Ejemplo n.º 1
0
 public void dropClient(Client who)
 {
     _debug("[SS] Dropping client " + who.Guid.ToString());
     _onLostClient(who);
 }
Ejemplo n.º 2
0
 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);
 }
Ejemplo n.º 3
0
 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);
 }
Ejemplo n.º 4
0
 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);
 }
Ejemplo n.º 5
0
 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);
 }
Ejemplo n.º 6
0
 private void _send(byte[] data, Client to)
 {
     socket.Send(data, data.Length, to.observedAddress);
     to.lastCommunication = DateTime.Now;
 }
Ejemplo n.º 7
0
        private void _onLostClient(Client client)
        {
            clients.Remove(client);

            foreach (var existingClient in clients)
            {
                _sendPeerLeftMessage(existingClient, client);
            }
            if (onClientLeft != null) onClientLeft(client);
        }
Ejemplo n.º 8
0
        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); }
        }
Ejemplo n.º 9
0
 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);
 }
Ejemplo n.º 10
0
 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);
 }