/* * Check for messages and also deal with new connections and disconnects etc */ private bool ReceiveAndProcessEvents(out int connectionId, out TransportEvent transportEvent, out byte[] data, int chan) { data = null; //first check if we have received any new connections and return them as an event if (steamNewConnections.Count > 0) { if (LogFilter.Debug || debug) { Debug.Log("Handling a new connection from queue"); } connectionId = steamNewConnections.Dequeue(); try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; steamClient.timeIdle = 0; if (steamClient.state == SteamClient.ConnectionState.CONNECTING) { if (LogFilter.Debug || debug) { Debug.Log("Set connection state to connected"); } steamClient.state = SteamClient.ConnectionState.CONNECTED; } } catch (KeyNotFoundException) { //shouldnt happen - ignore } transportEvent = TransportEvent.Connected; return(true); } //first check if we have received any new disconnects and return them as an event if (steamDisconnectedConnections.Count > 0) { if (LogFilter.Debug || debug) { Debug.Log("Handling a disconnect from queue"); } SteamClient steamClient = steamDisconnectedConnections.Dequeue(); connectionId = steamClient.connectionID; transportEvent = TransportEvent.Disconnected; //at this point we have completly disconnected from the client so stop accepting further messages from this client SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); return(true); } //this is a buffer that may have been received at the same time as a new connection if (serverReceiveBufferPending != null) { if (LogFilter.Debug || debug) { Debug.Log("Handling a postponed message"); } //we have a packet received and already in the buffer waiting to be returned connectionId = serverReceiveBufferPendingConnectionID; transportEvent = TransportEvent.Data; data = serverReceiveBufferPending; //clear our buffered variables serverReceiveBufferPendingConnectionID = -1; serverReceiveBufferPending = null; return(true); } //finally look for new packets return(Receive(out connectionId, out transportEvent, out data, chan)); }
/** * Check for internal networked messages like disconnect request */ private void handleInternalMessages() { if (lastInternalMessageFrame == Time.frameCount) { return; //already processed this frame } lastInternalMessageFrame = Time.frameCount; int connectionId; Byte[] data; while (ReceiveInternal(out connectionId, out data)) { if (LogFilter.Debug || debug) { Debug.Log("handleInternalMessages Got a message"); } try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; if (steamClient.state == SteamClient.ConnectionState.CONNECTED || steamClient.state == SteamClient.ConnectionState.CONNECTING) { NetworkReader reader = new NetworkReader(data); byte message = reader.ReadByte(); switch (message) { case (byte)InternalMessages.CONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received a request to Connect from " + steamClient.steamID); } //if we are a server and have spaces then accept the request to connect, else reject if (mode == Mode.SERVER && getNumberOfActiveConnection() < maxConnections) { //we have to queue this connection up so we can let the ReceiveFromHost method return the new connection steamNewConnections.Enqueue(connectionId); //send a message back to the client to confirm they have connected successfully SteamNetworking.SendP2PPacket(steamClient.steamID, acceptConnectMsgBuffer, (uint)acceptConnectMsgBuffer.Length, sendMethods[Channels.DefaultReliable], (int)SteamChannels.SEND_INTERNAL); } else { if (LogFilter.Debug || debug) { Debug.LogWarning("Rejected connect from " + steamClient.steamID + ". Active Connections: " + getNumberOfActiveConnection() + ", maxConnections: " + maxConnections); } SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); } steamClient.timeIdle = 0; break; case (byte)InternalMessages.ACCEPT_CONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received an accept to connect to " + steamClient.steamID); } //if we are a client and received this message from the server we are trying to connect to then connect, else reject if (mode == Mode.CLIENT && steamClient.steamID == steamClientServer.steamID) { //we have to queue this connection up so we can let the ReceiveFromHost method return the new connection steamNewConnections.Enqueue(connectionId); } else { Debug.LogError("Received an ACCEPT_CONNECT from wrong person"); SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); } steamClient.timeIdle = 0; break; case (byte)InternalMessages.DISCONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received an instruction to Disconnect from " + steamClient.steamID); } //requested to disconnect if (mode == Mode.CLIENT || mode == Mode.SERVER) { //disconnect this client closeSteamConnection(steamClient); } break; } } else { Debug.LogWarning("Received message for non connected client ?"); } } catch (KeyNotFoundException) { //shouldnt happen - ignore Debug.LogError("Received internal message from unknown.. connect?"); } } //check all connections to check they are healthy foreach (var connection in steamConnectionMap) { SteamClient steamClient = connection.Value; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { if (steamClient.timeIdle > (NetworkTime.PingFrequency + connectedTimeoutBuffer)) { //idle too long - disconnect Debug.LogWarning("Connection " + steamClient.connectionID + " timed out - going to disconnect"); internalDisconnect(steamClient); continue; } //If client then this will Not be called if the scene is loading. We dont want to count idle time if loading the scene for this reason //If Server then this will be called so we need to not count idle time for clients who are not "ready" as they are loading the scene and unable to communicate. The connect timeout will catch people that disconnect during scene load if (mode == Mode.CLIENT || (mode == Mode.SERVER && (!NetworkServer.connections.ContainsKey(steamClient.connectionID) || NetworkServer.connections[steamClient.connectionID].isReady))) { steamClient.timeIdle += Time.deltaTime; } } } }
/** * Check for internal networked messages like ping or disconnect request */ private void handleInternalMessages() { if (lastInternalMessageFrame == Time.frameCount) { return; //already processed this frame } lastInternalMessageFrame = Time.frameCount; int connectionId; TransportEvent transportEvent; Byte[] data; while (ReceiveInternal(out connectionId, out data)) { try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { float senderTime; NetworkReader reader = new NetworkReader(data); switch (reader.ReadByte()) { case (byte)InternalMessages.PING: //ping .. send a pong senderTime = reader.ReadSingle(); sendInternalPong(steamClient, senderTime); break; case (byte)InternalMessages.PONG: //pong .. update when we last received a pong senderTime = reader.ReadSingle(); steamClient.lastPong = Time.time; double rtt = LocalTime() - senderTime; _rtt.Add(rtt); break; case (byte)InternalMessages.DISCONNECT: if (LogFilter.Debug) { Debug.LogWarning("Received an instruction to Disconnect"); } //requested to disconnect if (mode == Mode.CLIENT || mode == Mode.SERVER) { //disconnect this client closeSteamConnection(steamClient); } break; } } } catch (KeyNotFoundException) { //shouldnt happen - ignore } } //check all connections to check they are healthy foreach (var connection in steamConnectionMap) { SteamClient steamClient = connection.Value; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { if (Time.time - steamClient.lastPong > PONG_TIMEOUT) { //idle too long - disconnect Debug.LogError("Connection " + steamClient.connectionID + " timed out - going to disconnect"); internalDisconnect(steamClient); continue; } if (Time.time - steamClient.lastPing > PING_FREQUENCY) { //time to ping sendInternalPing(steamClient); } } } }