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); } } }
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(); } }
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"); }
public void Dispose() { NeutrinoConfig.Log("Node shutting down..."); if (serverSocket != null) { serverSocket.Close(1000); serverSocket = null; NeutrinoConfig.Log("Node shutdown"); } }
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); }
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"); }
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(); } }
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); } }
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); } } }
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; } }