Пример #1
0
        public void HandleAckMessage(AckMessage ackMessage)
        {
            OutboundMessage outboundMessage = null;

            if (outboundMessagesBySequence.TryGetValue(ackMessage.AckedSequenceNumber, out outboundMessage))
            {
                outboundMessages.Remove(outboundMessage);
                outboundMessagesBySequence.Remove(ackMessage.AckedSequenceNumber);
                outboundMessagePool.Push(outboundMessage);
            }
            if (isResetPending && outboundMessages.FirstOrDefault(x => x.NeedsAck) == null)
            {
                if (IsVerbose)
                {
                    NeutrinoConfig.Log(node.Name + " drained all outbound - resetting sequence and sending queued");
                }
                isResetPending = false;
                nextSequence   = 0;
                foreach (byte[] buffer in pendingResetOutboundMessages)
                {
                    Enqueue(msgFactory.Read(buffer));
                }
                pendingResetOutboundMessages.Clear();
            }
        }
Пример #2
0
        private void HandleMessageReceived(IPEndPoint receivedFrom, byte[] buffer, int numBytesReceived)
        {
            NetworkPeer peer = null;

            if (peersByEndpoint.TryGetValue(receivedFrom, out peer))
            {
                peer.HandleMessageReceived(buffer, numBytesReceived);
            }
            else
            {
                if (NeutrinoConfig.LogLevel == NeutrinoLogLevel.Debug)
                {
                    NeutrinoConfig.Log("Received from potentially new peer at " + receivedFrom);
                }
                List <NetworkMessage> initialMessages = new List <NetworkMessage>(msgFactory.Read(buffer, numBytesReceived));
                var connectMsg = initialMessages.FirstOrDefault <NetworkMessage>(x => (x is ConnectMessage));
                if (connectMsg == null)
                {
                    NeutrinoConfig.Log("Ignoring peer who didn't send a ConnectMessage with his initial traffic");
                }
                else
                {
                    var newPeer = NeutrinoConfig.CreatePeer();
                    newPeer.Init(this, serverSocket, receivedFrom.Address, receivedFrom.Port, ((ConnectMessage)connectMsg).Nickname);
                    peersByEndpoint[(IPEndPoint)receivedFrom] = newPeer;
                    endpointsByPeer[newPeer] = (IPEndPoint)receivedFrom;
                    if (OnPeerConnected != null)
                    {
                        OnPeerConnected(newPeer);
                    }
                    newPeer.HandleMessageReceived(buffer, numBytesReceived);
                }
            }
        }
Пример #3
0
 private void BuildInstances(params Assembly[] messageAssemblies)
 {
     BuildInstances(typeof(NetworkMessage).Assembly);
     foreach (Assembly a in messageAssemblies)
     {
         BuildInstances(a);
     }
     NeutrinoConfig.Log("Built " + messages.Count + " registered network messages");
 }
Пример #4
0
 public void Dispose()
 {
     NeutrinoConfig.Log("Node shutting down...");
     if (serverSocket != null)
     {
         serverSocket.Close(1000);
         serverSocket = null;
         NeutrinoConfig.Log("Node shutdown");
     }
 }
Пример #5
0
 internal void DisconnectPeer(NetworkPeer peer)
 {
     if (NeutrinoConfig.LogLevel == NeutrinoLogLevel.Debug)
     {
         NeutrinoConfig.Log("Peer disconnected: " + peer);
     }
     if (OnPeerDisconnected != null)
     {
         OnPeerDisconnected(peer);
     }
     peersByEndpoint.Remove(peer.Endpoint);
     endpointsByPeer.Remove(peer);
 }
Пример #6
0
        public void Start()
        {
            NeutrinoConfig.Log("Node starting...");
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            if (ServerHostname == null)
            {
                serverSocket.Bind(new IPEndPoint(IPAddress.Any, ServerPort));
            }
            else
            {
                serverSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
                var addresses = Dns.GetHostAddresses(ServerHostname);
                if (addresses == null || addresses.Length == 0)
                {
                    throw new ApplicationException("Unable to resolve server [" + ServerHostname + "]");
                }
                else
                {
                    IPAddress address = addresses.FirstOrDefault <IPAddress>(x => x.AddressFamily == AddressFamily.InterNetwork);
                    if (address == null)
                    {
                        address = addresses.FirstOrDefault <IPAddress>(x => x.AddressFamily == AddressFamily.InterNetworkV6);
                    }
                    if (address == null)
                    {
                        throw new ApplicationException("Unable to find an IP address for server [" + ServerHostname + "]");
                    }
                    var serverPeer = NeutrinoConfig.CreatePeer();
                    serverPeer.Init(this, serverSocket, address, ServerPort, "Server");
                    IPEndPoint serverEndpoint = new IPEndPoint(address, ServerPort);
                    peersByEndpoint[serverEndpoint] = serverPeer;
                    endpointsByPeer[serverPeer]     = serverEndpoint;
                    if (OnPeerConnected != null)
                    {
                        OnPeerConnected(serverPeer);
                    }

                    var connectMsg = msgFactory.Get <ConnectMessage>();
                    connectMsg.Nickname = localNickname;
                    SendToAll(connectMsg);
                }
            }
            var asyncResult = serverSocket.BeginReceiveFrom(receiveBuffer, 0, NeutrinoConfig.MaxMessageSize, SocketFlags.None, ref receivedEndPoint, new AsyncCallback(HandleMessageReceived), null);

            if (asyncResult.CompletedSynchronously)
            {
                HandleMessageReceived(asyncResult);
            }
            NeutrinoConfig.Log("Node started");
        }
Пример #7
0
        internal void Update()
        {
            outboundQueue.Send();
            int ticksSinceActivity = Environment.TickCount - previousActivityTimeTicks;

            if (ticksSinceActivity >= NeutrinoConfig.PeerTimeoutMillis)
            {
                if (NeutrinoConfig.LogLevel == NeutrinoLogLevel.Debug)
                {
                    NeutrinoConfig.Log("Disconnecting peer " + this + " because of inactivity for " + ticksSinceActivity + " millis");
                }
                Disconnect();
            }
        }
Пример #8
0
        private void ProcessMessage(NetworkMessage msg)
        {
            ResetNetworkIdsMessage resetMsg = msg as ResetNetworkIdsMessage;

            if (resetMsg != null)
            {
                Array.Clear(idempotentSequenceNumbers, 0, idempotentSequenceNumbers.Length);
                if (pendingOutOfSequenceMessages.Count != 0)
                {
                    NeutrinoConfig.LogError(node.Name + " there were still pending messages when resetting id's!");
                    pendingOutOfSequenceMessages.Clear();
                }
            }
            node.OnReceived(msg);
        }
Пример #9
0
 public void Enqueue(NetworkMessage msg)
 {
     if (isResetPending && msg.IsGuaranteed)
     {
         if (IsVerbose)
         {
             NeutrinoConfig.Log(node.Name + " reset pending enqueuing for later: " + msg);
         }
         byte[] buffer = new byte[NeutrinoConfig.MaxMessageSize];
         msg.Write(buffer);
         pendingResetOutboundMessages.Add(buffer);
     }
     else
     {
         var outboundMessage = outboundMessagePool.Pop();
         Assign(msg, outboundMessage);
         outboundMessages.Add(outboundMessage);
     }
 }
Пример #10
0
        public void Update()
        {
            lock (readyBuffers)
            {
                buffersToProcess.AddRange(readyBuffers);
                readyBuffers.Clear();
            }
            foreach (var bufferToProcess in buffersToProcess)
            {
                HandleMessageReceived(bufferToProcess.Endpoint, bufferToProcess.Buffer, bufferToProcess.NumBytesReceived);
                receivedBuffers.Push(bufferToProcess);
            }
            buffersToProcess.Clear();
#if DEBUG
            lock (receivedBuffersForShuffling)
            {
                for (int i = receivedBuffersForShuffling.Count - 1; i >= 0; i--)
                {
                    var deferred = receivedBuffersForShuffling[i];
                    if (deferred.TimeToReceiveTicks <= Environment.TickCount)
                    {
                        NeutrinoConfig.LogWarning(Name + " injecting shuffled receipt...");
                        HandleMessageReceived(deferred.Endpoint, deferred.ReceivedBuffer, deferred.ReceivedBuffer.Length);
                        receivedBuffersForShuffling.RemoveAt(i);
                    }
                }
            }
#endif
            foreach (NetworkPeer c in peersByEndpoint.Values)
            {
                c.Update();
                if (!c.IsConnected)
                {
                    peersPendingDisconnect.Add(c);
                }
            }
            foreach (NetworkPeer c in peersPendingDisconnect)
            {
                DisconnectPeer(c);
            }
            peersPendingDisconnect.Clear();
        }
Пример #11
0
        private void BuildInstances(Assembly messageAssembly)
        {
            Type networkMsgType = typeof(NetworkMessage);

            foreach (Type t in messageAssembly.GetTypes())
            {
                if (t.IsSubclassOf(networkMsgType) && !messagesByType.ContainsKey(t))
                {
                    if (messages.Count == Byte.MaxValue)
                    {
                        throw new ApplicationException("The maximum number of network messages has been reached - you need to use fewer message types in this project");
                    }
                    var msg = (NetworkMessage)t.GetConstructor(Type.EmptyTypes).Invoke(Utility.emptyArgs);
                    msg.Id           = (byte)messages.Count;
                    messages[msg.Id] = msg;
                    messagesByType[msg.GetType()] = msg;
                    NeutrinoConfig.Log("Registered message type " + msg.GetType() + " as Id " + msg.Id);
                }
            }
        }
Пример #12
0
 private void Assign(NetworkMessage msg, OutboundMessage target)
 {
     target.ContainedMessageType = msg.GetType();
     if (msg.IsGuaranteed)
     {
         target.SequenceNumber = nextSequence++;
         outboundMessagesBySequence[target.SequenceNumber] = target;
         msg.SequenceNumber = target.SequenceNumber;
     }
     target.PayloadLength     = msg.Write(target.Payload);
     target.NeedsAck          = msg.IsGuaranteed;
     target.PreviousSendTicks = Environment.TickCount - resendGuaranteedPeriodTicks - 1;
     if (!(msg is ResetNetworkIdsMessage) && nextSequence == maxGuaranteedBeforeReset)
     {
         if (IsVerbose)
         {
             NeutrinoConfig.Log(node.Name + " reached max sequence - resetting...");
         }
         Enqueue(msgFactory.Get <ResetNetworkIdsMessage>());
         isResetPending = true;
     }
 }
Пример #13
0
        private void HandleMessageReceived(IAsyncResult result)
        {
            if (serverSocket != null)
            {
                try
                {
#if DEBUG
                    if (SimulatedPacketLossRate > 0.0 && (randomGenerator.NextDoublePositive() <= SimulatedPacketLossRate))
                    {
                        NeutrinoConfig.LogWarning("SIMULATING PACKET LOSS!");
                        receivedEndPoint = new IPEndPoint(IPAddress.Any, 0);
                        IAsyncResult asyncResult = serverSocket.BeginReceiveFrom(receiveBuffer, 0, NeutrinoConfig.MaxMessageSize, SocketFlags.None, ref receivedEndPoint, new AsyncCallback(HandleMessageReceived), null);
                        if (asyncResult.CompletedSynchronously)
                        {
                            HandleMessageReceived(asyncResult);
                        }
                        return;
                    }
                    else if (SimulatedPacketShuffleRate > 0.0 && (randomGenerator.NextDoublePositive() <= SimulatedPacketShuffleRate))
                    {
                        NeutrinoConfig.LogWarning("SIMULATING PACKET OUT OF ORDER!");
                        int    numReceived        = serverSocket.EndReceiveFrom(result, ref receivedEndPoint);
                        byte[] receivedForShuffle = new byte[numReceived];
                        Array.Copy(receiveBuffer, receivedForShuffle, numReceived);
                        lock (receivedBuffersForShuffling)
                        {
                            receivedBuffersForShuffling.Add(new DeferredReceivable()
                            {
                                ReceivedBuffer     = receivedForShuffle,
                                TimeToReceiveTicks = Environment.TickCount + (int)(randomGenerator.NextDoublePositive() * 100.0),
                                Endpoint           = (IPEndPoint)receivedEndPoint
                            });
                        }
                        receivedEndPoint = new IPEndPoint(IPAddress.Any, 0);
                        IAsyncResult asyncResult = serverSocket.BeginReceiveFrom(receiveBuffer, 0, NeutrinoConfig.MaxMessageSize, SocketFlags.None, ref receivedEndPoint, new AsyncCallback(HandleMessageReceived), null);
                        if (asyncResult.CompletedSynchronously)
                        {
                            HandleMessageReceived(asyncResult);
                        }
                        return;
                    }
#endif
                    int numBytesReceived = serverSocket.EndReceiveFrom(result, ref receivedEndPoint);
                    var receivedBuffer   = receivedBuffers.Pop();
                    Array.Copy(receiveBuffer, receivedBuffer.Buffer, numBytesReceived);
                    receivedBuffer.NumBytesReceived = numBytesReceived;
                    receivedBuffer.Endpoint         = (IPEndPoint)receivedEndPoint;
                    lock (readyBuffers)
                        readyBuffers.Add(receivedBuffer);
                }
                catch (Exception ex)
                {
                    NeutrinoConfig.LogError("Error handling message: " + ex);
                }

                // TBD: When tests are complete, test whether we need to reallocate here?
                receivedEndPoint = new IPEndPoint(IPAddress.Any, 0);
                IAsyncResult repeatAsyncResult = serverSocket.BeginReceiveFrom(receiveBuffer, 0, NeutrinoConfig.MaxMessageSize, SocketFlags.None, ref receivedEndPoint, new AsyncCallback(HandleMessageReceived), null);
                if (repeatAsyncResult.CompletedSynchronously)
                {
                    HandleMessageReceived(repeatAsyncResult);
                }
            }
        }