Beispiel #1
0
func (server *Server) serveHTTP(w http.ResponseWriter, r *http.Request, tr *itime.Timer) {
	var (
		b    *Bucket
		ok   bool
		hb   time.Duration // heartbeat
		key  string
		cb   string
		err  error
		trd  *itime.TimerData
		conn net.Conn
		rwr  *bufio.ReadWriter
		hj   http.Hijacker
		// no client send
		ch = NewChannel(1, define.NoRoom)
	)
	if key, cb, hb, err = server.authHTTP(r, ch); err != nil {
		http.Error(w, "auth failed", http.StatusForbidden)
		return
	}
	if hj, ok = w.(http.Hijacker); !ok {
		log.Error("w.(http.Hijacker) type assection failed")
		http.Error(w, "not support", http.StatusInternalServerError)
		return
	}
	if conn, rwr, err = hj.Hijack(); err != nil {
		log.Error("hj.Hijack() error(%v)", err)
		http.Error(w, "not support", http.StatusInternalServerError)
		return
	}
	// register key->channel
	b = server.Bucket(key)
	b.Put(key, ch, tr)
	// hanshake ok start dispatch goroutine
	server.dispatchHTTP(rwr, cb, ch, hb)
	tr.Del(trd)
	conn.Close()
	b.Del(key)
	// don't use close chan, Signal can be reused
	// if chan full, writer goroutine next fetch from chan will exit
	// if chan empty, send a 0(close) let the writer exit
	if err = server.operator.Disconnect(key, ch.RoomId); err != nil {
		log.Error("%s operator do disconnect error(%v)", key, err)
	}
	if Debug {
		log.Debug("%s serverconn goroutine exit", key)
	}
	return
}
Beispiel #2
0
func (server *Server) serveHTTP(w http.ResponseWriter, r *http.Request, tr *Timer) {
	var (
		b    *Bucket
		ch   *Channel
		hb   time.Duration // heartbeat
		key  string
		cb   string
		err  error
		trd  *TimerData
		conn net.Conn
		rwr  *bufio.ReadWriter
		hj   http.Hijacker
		p    = new(Proto)
		ok   bool
	)
	if key, cb, hb, err = server.authHTTP(r, p); err != nil {
		http.Error(w, "auth failed", http.StatusForbidden)
		return
	}
	if hj, ok = w.(http.Hijacker); !ok {
		log.Error("w.(http.Hijacker) type assection failed")
		http.Error(w, "not support", http.StatusInternalServerError)
		return
	}
	if conn, rwr, err = hj.Hijack(); err != nil {
		log.Error("hj.Hijack() error(%v)", err)
		http.Error(w, "not support", http.StatusInternalServerError)
		return
	}
	if trd, err = tr.Add(hb, conn); err != nil {
		log.Error("handshake: timer.Add() error(%v)", err)
		if err = conn.Close(); err != nil {
			log.Error("handshake: conn.Close() error(%v)", err)
		}
		return
	}
	// TODO how to reuse channel
	// register key->channel
	b = server.Bucket(key)
	// no client send
	ch = NewChannel(0, 1)
	b.Put(key, ch)
	// hanshake ok start dispatch goroutine
	server.dispatchHTTP(rwr, cb, ch)
	// dialog finish
	// revoke the subkey
	// revoke the remote subkey
	// close the net.Conn
	// read & write goroutine
	// return channel to bucket's free list
	if err = conn.Close(); err != nil {
		log.Error("conn.Close() error(%v)", err)
	}
	b.Del(key)
	tr.Del(trd)
	// don't use close chan, Signal can be reused
	// if chan full, writer goroutine next fetch from chan will exit
	// if chan empty, send a 0(close) let the writer exit
	if err = server.operator.Disconnect(key); err != nil {
		log.Error("%s operator do disconnect error(%v)", key, err)
	}
	log.Debug("%s serverconn goroutine exit", key)
	return
}