public void dropClient(Client who) { _debug("[SS] Dropping client " + who.Guid.ToString()); _onLostClient(who); }
private void _sendKeepalive(Client to) { var ackID = nextAckID++; var datagram = new WriteOnlyDatagram(); datagram.WriteUInt((uint)ServerToClientMessage.Keepalive, 8); datagram.WriteUInt((uint)ackID, 32); _sendCriticalDatagram(to, datagram.BufferAsArray, ackID); }
private void _sendPeerLeftMessage(Client to, Client about) { var ackID = nextAckID++; var datagram = new WriteOnlyDatagram(); datagram.WriteUInt((uint)ServerToClientMessage.PeerLeft, 8); datagram.WriteUInt((uint)ackID, 32); datagram.WriteBytes(about.Guid.ToByteArray()); _sendCriticalDatagram(to, datagram.BufferAsArray, ackID); }
private void _sendAckMessage(Client to, uint ackID) { var ackDatagram = new WriteOnlyDatagram(); ackDatagram.WriteUInt((uint)ServerToClientMessage.Acknowledge, 8); ackDatagram.WriteUInt(ackID, 32); _send(ackDatagram.BufferAsArray, to); }
private void _sendCriticalDatagram(Client to, byte[] data, uint ackID, Action onSuccess = null) { var criticalDatagram = new CriticalDatagram { to = to, data = data, ackID = ackID, lastSendAttempt = System.DateTime.MinValue, sendAttempts = 0, onSuccess = onSuccess, }; criticalDatagrams.Add(criticalDatagram); }
private void _send(byte[] data, Client to) { socket.Send(data, data.Length, to.observedAddress); to.lastCommunication = DateTime.Now; }
private void _onLostClient(Client client) { clients.Remove(client); foreach (var existingClient in clients) { _sendPeerLeftMessage(existingClient, client); } if (onClientLeft != null) onClientLeft(client); }
public void update() { try { while (socket.Available > 0) { IPEndPoint observedEndpoint = new IPEndPoint(IPAddress.Any, 0); byte[] bytes = null; try { bytes = socket.Receive(ref observedEndpoint); } catch (System.Net.Sockets.SocketException except) { _debug("[SS] Receive threw an exception. Socket Error : " + except.SocketErrorCode); continue; } _debug("[SS] Incoming message of length " + bytes.Length.ToString() + " : " + BitConverter.ToString(bytes)); _debug("[SS] It appears to have come from " + observedEndpoint.ToString()); var datagram = new ReadOnlyDatagram(bytes); uint messageType = 0; uint ackID = 0; if (!datagram.ReadUInt(out messageType, 8)) goto OnBadMessage; if (!datagram.ReadUInt(out ackID, 32)) goto OnBadMessage; var sendingClient = clients.FirstOrDefault((client) => { return client.observedAddress.Equals(observedEndpoint); }); switch ((ClientToServerMessage)messageType) { case ClientToServerMessage.Join: { if (sendingClient != null) { _sendAckMessage(sendingClient, ackID); break; } var newClient = new Client(); newClient.observedAddress = observedEndpoint; newClient.Guid = Guid.NewGuid(); newClient.lastCommunication = DateTime.Now; _sendAckMessage(newClient, ackID); _debug("[SS] A client with observed address " + observedEndpoint.ToString() + " has joined the session."); foreach (var existingClient in clients) { _sendPeerJoinedMessage(existingClient, newClient); _sendPeerJoinedMessage(newClient, existingClient); } clients.Add(newClient); if (onClientJoined != null) onClientJoined(newClient); } break; case ClientToServerMessage.Acknowledge: { var criticalDatagram = criticalDatagrams.FirstOrDefault((crit) => { return crit.ackID == ackID; }); if (criticalDatagram != null) { if (!criticalDatagram.to.observedAddress.Equals(observedEndpoint)) { _debug("[SS] The observed endpoint of the ack reply does not match the known observed endpoint of the peer the datagram was sent to."); break; } if (criticalDatagram.onSuccess != null) { try { criticalDatagram.onSuccess(); } catch (Exception) { } } criticalDatagrams.Remove(criticalDatagram); } } break; case ClientToServerMessage.Datagram: { if (sendingClient == null) { _debug("[SS] I received a datagram from an unknown client with address " + observedEndpoint.ToString() +"."); break; } if (ackID != 0) { _sendAckMessage(sendingClient, ackID); if (sendingClient.newDatagramReceived(ackID) == RemotePeer.DatagramResponse.Ignore) break; } _debug("[SS] I received a datagram from client " + sendingClient.Guid.ToString() + ". It was " + (bytes.Length - 5).ToString() + " bytes long."); if (bytes.Length - 5 <= 0) goto OnBadMessage; byte[] data = new byte[bytes.Length - 5]; if (!datagram.ReadBytes(data, (uint)(bytes.Length - 5))) goto OnBadMessage; if (onDatagramReceived != null) onDatagramReceived(sendingClient, data); } break; } continue; OnBadMessage: { _debug("[SS] I received a bad message."); } } var now = DateTime.Now; for (int i = 0; i < criticalDatagrams.Count; ) { var criticalDatagram = criticalDatagrams[i]; var timeDelta = now - criticalDatagram.lastSendAttempt; if (timeDelta.TotalMilliseconds > millisecondsBeforeRetry) { if (criticalDatagram.sendAttempts >= retryAttempts) { _debug("[SS] I was not able to deliver critical packet " + criticalDatagram.ackID + "."); criticalDatagrams.RemoveAt(i); _onLostClient(criticalDatagram.to); continue; } criticalDatagram.sendAttempts += 1; _debug("[SS] I am trying to send critical packet " + criticalDatagram.ackID + ". [" + criticalDatagram.sendAttempts + " attempts]"); criticalDatagram.lastSendAttempt = now; _send(criticalDatagram.data, criticalDatagram.to); } ++i; } foreach (var client in clients) { var timeDelta = now - client.lastCommunication; if (timeDelta.TotalMilliseconds > keepaliveRate) _sendKeepalive(client); } } catch (Exception e) { _debug(e.Message + "\n" + e.StackTrace); } }
public void sendDatagram(Client to, byte[] data) { var datagram = new WriteOnlyDatagram(); datagram.WriteUInt((uint)ServerToClientMessage.Datagram, 8); datagram.WriteUInt(0, 32); datagram.WriteBytes(data); _send(datagram.BufferAsArray, to); }
public void sendCriticalDatagram(Client to, byte[] data, Action onSuccess = null) { var ackID = nextAckID++; var datagram = new WriteOnlyDatagram(); datagram.WriteUInt((uint)ServerToClientMessage.Datagram, 8); datagram.WriteUInt(ackID, 32); datagram.WriteBytes(data); _sendCriticalDatagram(to, datagram.BufferAsArray, ackID, onSuccess); }