//---------------------------------------------------------------------------------- /// <summary> /// Overridden function to disconnect by mask index instead. /// </summary> /// <param name="nMaskIndex">index of peer to be kicked.</param> //---------------------------------------------------------------------------------- public void DisconnectPeer(int nMaskIndex) { ClientConnectedInfo client = null; //Unfortunately we have to a linear search in order to find it this way. foreach (ClientConnectedInfo clientInfo in m_UdpClients.Values) { if (clientInfo.NetworkID == nMaskIndex) { client = clientInfo; break; } } if (client != null) { m_UdpClients.Remove(client.Address); client.Client.Close(); lock (m_connectionLock) m_ConnectedClientsMask &= ~nMaskIndex; if (ClientDisconnectedCallback != null) { ClientDisconnectedCallback(nMaskIndex); } } }
//---------------------------------------------------------------------------------- /// <summary> /// Kick a peer of the network. /// </summary> /// <param name="address">address of peer to be kicked.</param> //---------------------------------------------------------------------------------- public void DisconnectPeer(IPAddress address) { ClientConnectedInfo clientInfo = m_UdpClients[address]; int nMaskIndex = clientInfo.NetworkID; //remove address from connections. m_UdpClients.Remove(address); clientInfo.Client.Close(); //update connected mask. lock (m_connectionLock) m_ConnectedClientsMask &= ~nMaskIndex; //invoke callback to tell the local machine of event. if (ClientDisconnectedCallback != null) { ClientDisconnectedCallback(nMaskIndex); } }
//---------------------------------------------------------------------------------- /// <summary> /// Processes the send queue and send all queued packets for the network. NOTE: This is done on a seperate thread. /// </summary> /// <param name="queue"></param> //---------------------------------------------------------------------------------- private void ProcessSendQueue(object queue) { lock (m_SendQueueLock) { if (m_OrderedSendQueue.Count > 0) { while (m_OrderedSendQueue.Count > 0) { NetworkSendItem item = m_OrderedSendQueue.Dequeue(); NetworkDataPacket packet = item.Packet; IPEndPoint endpoint = null; //serialise the packet to be sent. byte[] data = SerializePacket(packet); int nConnectionMask; int nCounter = 50; int nSpins = 0; m_AckClientsMask = 0; if (item.IPAdress != null) { endpoint = new IPEndPoint(item.IPAdress, m_nUdpPort); } if (endpoint == null) { //send the packet to all connected clients. foreach (ClientConnectedInfo clientInfo in m_UdpClients.Values) { clientInfo.Client.BeginSend(data, data.Length, SendCompleteCallback, clientInfo.Client); } //We don't obtain a double nested lock on the AckMask as //we want the thread to overwrite as necessary lock (m_connectionLock) nConnectionMask = m_ConnectedClientsMask; //We hold execution here until all acks have come back. while (0 != (m_AckClientsMask ^ nConnectionMask)) { ++nSpins; if (nSpins > nCounter) { //if a certain amount of time passes and not all replies have come back. // disconnect that client. int nDisconnectionMask = m_ConnectedClientsMask ^ m_AckClientsMask; for (int i = 0; i < 32; ++i) { if (0 != (m_ConnectedClientsMask & i)) { DisconnectPeer(i); } } } //We need to keep updating this every cycle to check if anything has changed. lock (m_connectionLock) nConnectionMask = m_ConnectedClientsMask; } } else { //This is if we are only sending an inorder packet to a single client. ClientConnectedInfo clientInfo = m_UdpClients[endpoint.Address]; clientInfo.Client.BeginSend(data, data.Length, SendCompleteCallback, clientInfo.Client); //We hold execution here till we get a response.. //if we dont we assume the client has disconnected. while (0 != (m_AckClientsMask & clientInfo.NetworkID)) { ++nSpins; if (nSpins > nCounter) { DisconnectPeer(clientInfo.Address); } } } } } } }