Beispiel #1
0
// wsHandler is a WebSocket server that handles requests from the WebSocket client in the form of:
// 1. { 'cmd': 'register', 'roomid': $ROOM, 'clientid': $CLIENT' },
// which binds the WebSocket client to a client ID and room ID.
// A client should send this message only once right after the connection is open.
// or
// 2. { 'cmd': 'send', 'msg': $MSG }, which sends the message to the other client of the room.
// It should be sent to the server only after 'regiser' has been sent.
// The message may be cached by the server if the other client has not joined.
//
// Unexpected messages will cause the WebSocket connection to be closed.
func (c *Collider) wsHandler(ws *websocket.Conn) {
	var rid, cid string

	registered := false

	var msg wsClientMsg
loop:
	for {
		err := ws.SetReadDeadline(time.Now().Add(time.Duration(wsReadTimeoutSec) * time.Second))
		if err != nil {
			c.wsError("ws.SetReadDeadline error: "+err.Error(), ws)
			break
		}

		err = websocket.JSON.Receive(ws, &msg)
		if err != nil {
			if err.Error() != "EOF" {
				c.wsError("websocket.JSON.Receive error: "+err.Error(), ws)
			}
			break
		}

		switch msg.Cmd {
		case "register":
			if registered {
				c.wsError("Duplicated register request", ws)
				break loop
			}
			if msg.RoomID == "" || msg.ClientID == "" {
				c.wsError("Invalid register request: missing 'clientid' or 'roomid'", ws)
				break loop
			}
			if err = c.roomTable.register(msg.RoomID, msg.ClientID, ws); err != nil {
				c.wsError(err.Error(), ws)
				break loop
			}
			registered, rid, cid = true, msg.RoomID, msg.ClientID
			c.dash.incrWs()

			defer c.roomTable.deregister(rid, cid)
			break
		case "send":
			if !registered {
				c.wsError("Client not registered", ws)
				break loop
			}
			if msg.Msg == "" {
				c.wsError("Invalid send request: missing 'msg'", ws)
				break loop
			}
			c.roomTable.send(rid, cid, msg.Msg)
			break
		default:
			c.wsError("Invalid message: unexpected 'cmd'", ws)
			break
		}
	}
	// This should be unnecessary but just be safe.
	ws.Close()
}
Beispiel #2
0
func setDeadlines(ws *websocket.Conn) {
	if err := ws.SetDeadline(time.Now().Add(100 * time.Hour)); err != nil {
		log.Fatal(err)
	}
	if err := ws.SetReadDeadline(time.Now().Add(100 * time.Hour)); err != nil {
		log.Fatal(err)
	}
	if err := ws.SetWriteDeadline(time.Now().Add(100 * time.Hour)); err != nil {
		log.Fatal(err)
	}
}
Beispiel #3
0
func CalcServer(ws *websocket.Conn) {
	defer ws.Close()

	ws.SetReadDeadline(time.Now().Add(time.Second * time.Duration(*Timeout)))
	timeout := time.NewTimer(time.Second * time.Duration(*Timeout))

	for {
		select {
		case <-timeout.C:
			log.Printf("timeout exceeded for connection")
			return

		default:
			var req []byte
			err := websocket.Message.Receive(ws, &req)
			if err != nil {
				log.Printf("error receiving %s", err)
			}

			var request network.Request
			err = proto.Unmarshal(req, &request)
			if err != nil {
				log.Printf("error unmarshalling request: %s", err)
				return
			}

			log.Printf("recevied: %s", request)

			task := Task{ws, request.Id}

			calc := rpn.New(base.New(strings.NewReader(request.Expression)))
			expr, err := calc.Parse()
			if err != nil {
				log.Printf("could not parse expression: %s", err)
				task.error(err)
				return
			}

			result, err := expr.Evaluate()
			if err != nil {
				log.Printf("could not evaluate expression: %s", err)
				task.error(err)
				return
			}

			log.Printf("calculated result: %f", result)

			task.success(result)

			return
		}
	}
}
Beispiel #4
0
func (hd *wshandler) Handle(conn *websocket.Conn) {

	log.LogInfo("new websocket client: ", conn.RemoteAddr())

	if !App.MustAppReady {
		log.LogError("must app not ready")
		conn.Close()
		return
	}

	r := &s2c.Rpc{}
	r.Sender = proto.String(App.Name)

	h, p, err := GetLogin()
	if err != nil {
		e := &s2c.Error{}
		e.ErrorNo = proto.Int32(share.ERROR_NOLOGIN)
		b, err := proto.Marshal(e)
		if err != nil {
			conn.Close()
			log.LogFatalf(err)
		}

		r.Servicemethod = proto.String("Login.Error")
		r.Data = b
		data, err := proto.Marshal(r)
		if err != nil {
			log.LogFatalf(err)
			return
		}
		out, _ := util.CreateMsg(nil, data, share.S2C_RPC)
		err = websocket.Message.Send(conn, out)
		if err != nil {
			conn.Close()
			log.LogError(err)
			return
		}
	} else {
		l := &s2c.Login{}
		l.Host = proto.String(h)
		l.Port = proto.Int32(int32(p))
		b, err := proto.Marshal(l)
		if err != nil {
			conn.Close()
			log.LogFatalf(err)
		}
		log.LogInfo("client choose login:"******":", p)

		r.Servicemethod = proto.String("Login.LoginInfo")
		r.Data = b
		data, err := proto.Marshal(r)
		if err != nil {
			log.LogFatalf(err)
			return
		}
		out, _ := util.CreateMsg(nil, data, share.S2C_RPC)
		err = websocket.Message.Send(conn, out)
		if err != nil {
			conn.Close()
			log.LogError(err)
			return
		}
	}
	conn.SetReadDeadline(time.Now().Add(time.Second * 10))
	websocket.Message.Receive(conn, hd.ignore[:])
	log.LogMessage("client close: ", conn.RemoteAddr())
	conn.Close()
}
// Subscriber Handle is the websocket handle for sub request.
func SubscribeHandle(ws *websocket.Conn) {
	addr := ws.Request().RemoteAddr
	params := ws.Request().URL.Query()
	// get subscriber key
	key := params.Get("key")
	if key == "" {
		ws.Write(ParamReply)
		log.Warn("<%s> key param error", addr)
		return
	}
	// get heartbeat second
	heartbeatStr := params.Get("heartbeat")
	i, err := strconv.Atoi(heartbeatStr)
	if err != nil {
		ws.Write(ParamReply)
		log.Error("<%s> user_key:\"%s\" heartbeat argument error(%v)", addr, key, err)
		return
	}
	if i < minHearbeatSec {
		ws.Write(ParamReply)
		log.Warn("<%s> user_key:\"%s\" heartbeat argument error, less than %d", addr, key, minHearbeatSec)
		return
	}
	heartbeat := i + delayHeartbeatSec
	token := params.Get("token")
	version := params.Get("ver")
	log.Info("<%s> subscribe to key = %s, heartbeat = %d, token = %s, version = %s", addr, key, heartbeat, token, version)
	// fetch subscriber from the channel
	c, err := UserChannel.Get(key, true)
	if err != nil {
		log.Warn("<%s> user_key:\"%s\" can't get a channel (%s)", addr, key, err)
		if err == ErrChannelKey {
			ws.Write(NodeReply)
		} else {
			ws.Write(ChannelReply)
		}
		return
	}
	// auth token
	if ok := c.AuthToken(key, token); !ok {
		ws.Write(AuthReply)
		log.Error("<%s> user_key:\"%s\" auth token \"%s\" failed", addr, key, token)
		return
	}
	// add a conn to the channel
	connElem, err := c.AddConn(key, &Connection{Conn: ws, Proto: WebsocketProto, Version: version})
	if err != nil {
		log.Error("<%s> user_key:\"%s\" add conn error(%v)", addr, key, err)
		return
	}
	// blocking wait client heartbeat
	reply := ""
	begin := time.Now().UnixNano()
	end := begin + Second
	for {
		// more then 1 sec, reset the timer
		if end-begin >= Second {
			if err = ws.SetReadDeadline(time.Now().Add(time.Second * time.Duration(heartbeat))); err != nil {
				log.Error("<%s> user_key:\"%s\" websocket.SetReadDeadline() error(%v)", addr, key, err)
				break
			}
			begin = end
		}
		if err = websocket.Message.Receive(ws, &reply); err != nil {
			log.Error("<%s> user_key:\"%s\" websocket.Message.Receive() error(%v)", addr, key, err)
			break
		}
		if reply == Heartbeat {
			if _, err = ws.Write(HeartbeatReply); err != nil {
				log.Error("<%s> user_key:\"%s\" write heartbeat to client error(%s)", addr, key, err)
				break
			}
			log.Debug("<%s> user_key:\"%s\" receive heartbeat", addr, key)
		} else {
			log.Warn("<%s> user_key:\"%s\" unknown heartbeat protocol", addr, key)
			break
		}
		end = time.Now().UnixNano()
	}
	// remove exists conn
	if err := c.RemoveConn(key, connElem); err != nil {
		log.Error("<%s> user_key:\"%s\" remove conn error(%v)", addr, key, err)
	}
	return
}