Beispiel #1
0
/*
 * OnClose gets called by the server at connection closing, once by
 * connection. This gives us the chance to unregister a new client and perform
 * client cleanup
 */
func (srv *Server) OnClose(c *network.Conn) {
	log.WithField("addr", c.GetRawConn().RemoteAddr()).Debug("Connection closed")

	// unregister the client before anything
	clientData := c.GetUserData().(ClientData)
	srv.clients.unregister(clientData.Id)

	if clientData.Joined {
		// client is still JOINED so that's a disconnection initiated externally
		// send a LEAVE to the rest of the world
		msg := messages.New(messages.LeaveId,
			messages.Leave{
				Id:     uint32(clientData.Id),
				Reason: "client disconnection",
			})
		srv.Broadcast(msg)
	} else {
		// the client was not marked as JOINED, so nobody knows about him
		// and we have nothing more to do
	}

	if srv.playerLeftCb != nil {
		// raise 'player left' external callback
		srv.playerLeftCb(clientData.Id)
	}
}
Beispiel #2
0
/*
 * register creates a new client, assigns it an id and returns it
 */
func (reg *ClientRegistry) register(client *network.Conn) uint32 {
	var clientId uint32

	// protect:
	// - increment the next available id
	// - client map write
	reg.mutex.Lock()

	// we have a new client, assign him an id.
	clientId = reg.allocId()
	reg.clients[clientId] = client

	// record the client id inside the connection, this is needed for later
	// retriving the clientId when we just have a connection
	clientData := ClientData{
		Id:     clientId,
		Name:   "",
		Joined: false,
	}
	client.SetUserData(clientData)

	// Note: for now we just stupidly increment the next available id.
	//        We will have other problems to solve before this overflows...
	reg.mutex.Unlock()

	log.WithFields(log.Fields{
		"client": clientData,
		"addr":   client.GetRawConn().RemoteAddr(),
	}).Info("Accepted a new client")

	return clientId
}
Beispiel #3
0
/*
 * OnIncomingMsg gets called by the server each time a message has been read
 * from the connection
 */
func (srv *Server) OnIncomingPacket(c *network.Conn, packet network.Packet) bool {
	clientData := c.GetUserData().(ClientData)
	raw := packet.(*messages.Message)

	log.WithFields(
		log.Fields{
			"clientData": clientData,
			"addr":       c.GetRawConn().RemoteAddr(),
			"type":       raw.Type.String(),
		}).Debug("Incoming message")

	// decode the raw message
	msg := srv.factory.Decode(raw)

	// get handler
	handler, ok := srv.msgHandlers[raw.Type]
	if ok {
		if err := handler(c, msg); err != nil {
			log.WithError(err).Error("Error handling message")
			return false
		}
	} else {

		switch raw.Type {

		case messages.PingId:

			// immediately reply pong
			ping := msg.(messages.Ping)
			pong := messages.New(messages.PongId,
				messages.Pong{
					Id:     ping.Id,
					Tstamp: time.Now().UnixNano() / int64(time.Millisecond),
				})
			if err := c.AsyncSendPacket(pong, time.Second); err != nil {
				log.WithError(err).Error("Error handling message")
				return false
			}

		case messages.JoinId:

			join := msg.(messages.Join)
			// JOIN is handled by the handshaker
			if srv.handshaker.Join(join, c) {
				// new client has been accepted
				if srv.playerJoinedCb != nil {
					// raise 'player joined' external callback
					srv.playerJoinedCb(clientData.Id, join.Type)
				}
			}
		}
	}

	return true
}