Пример #1
0
        public void ConnectLocal(NetManager localServer)
        {
            if (Side != Side.Client)
            {
                throw new IncorrectManagerStateException("Only Client NetManagers can connect to local hosts");
            }

            if (ConnectionState != ConnectionState.Unconnected)
            {
                throw new IncorrectManagerStateException("Clients cannot connect to multiple hosts at once");
            }

            IsConnectedToLocalServer = true;
            ConnectionState          = ConnectionState.Connecting;
            InitialisationCount      = 1;        //udp handshake already done so initcount is 1
            _Clients.Add(new NetClient
            {
                Manager      = this,
                IsLocal      = true,
                LocalManager = localServer
            });

            ManagerEvent serverConnectionEvent = new ManagerEvent(ManagerEventType.RecievedLocalConnection, this);
            ManagerEvent clientConnectionEvent = new ManagerEvent(
                ManagerEventType.TcpConnectionComplete,
                new TcpConnectionCompleteEvent
            {
                Type      = ConnectionResult.Success,
                Exception = null
            }
                );

            localServer.EventQueue.Enqueue(serverConnectionEvent);
            EventQueue.Enqueue(clientConnectionEvent);
        }
Пример #2
0
        private async void AttemptAsyncConnection(IPEndPoint remoteEp)
        {
            ManagerEvent?connectionEvent = null;

            try
            {
                Task connectionAttempt = Tcp.ConnectAsync(remoteEp.Address, remoteEp.Port);
                Task timeout           = Task.Delay(ConnectionTimeout);

                if (await Task.WhenAny(connectionAttempt, timeout) == timeout)
                {
                    //connection timed out
                    //todo: check what happens if the connection succeeds post-timeout
                    connectionEvent = new ManagerEvent(
                        ManagerEventType.TcpConnectionComplete,
                        new TcpConnectionCompleteEvent
                    {
                        Type      = ConnectionResult.Timeout,
                        Exception = null
                    }
                        );
                }
            }
            catch (SocketException sockEx)
            {
                connectionEvent = new ManagerEvent(
                    ManagerEventType.TcpConnectionComplete,
                    new TcpConnectionCompleteEvent
                {
                    Type      = ConnectionResult.Errored,
                    Exception = sockEx
                }
                    );
            }

            if (connectionEvent == null)
            {
                connectionEvent = new ManagerEvent(
                    ManagerEventType.TcpConnectionComplete,
                    new TcpConnectionCompleteEvent
                {
                    Type      = ConnectionResult.Success,
                    Exception = null
                }
                    );
            }

            EventQueue.Enqueue(connectionEvent.Value);
            return;
        }
Пример #3
0
        private void CleanupAfterDisconnect()
        {
            ConnectionState          = ConnectionState.Unconnected;
            IsConnectedToLocalServer = false;
            UdpHandshakeGuid         = null;

            if (!Server.IsLocal)
            {
                Tcp.GetStream().Close();
                Tcp.Close();
            }

            _Clients.Clear();

            ManagerEvent disconnectEvent = new ManagerEvent(ManagerEventType.DisconnectedSelf);

            EventQueue.Enqueue(disconnectEvent);
        }
Пример #4
0
        private async void ServerTcpListenForClients()
        {
            while (PollingNet)
            {
                await Task.Delay(250);

                if (!TcpListener.Pending())
                {
                    continue;
                }

                //todo: make this cancel properly
                TcpClient newClient = await TcpListener.AcceptTcpClientAsync();

                ManagerEvent connectionEvent = new ManagerEvent(ManagerEventType.RecievedTcpConnection, newClient);
                EventQueue.Enqueue(connectionEvent);
            }
        }
Пример #5
0
        private async void ServerTcpListenToClient(NetClient client)
        {
            NetworkStream clientStream = client.Tcp.GetStream();

            while (client.PollingNet)             //todo: make sure this dies right
            {
                await Task.Delay(50);

                if (!clientStream.DataAvailable)
                {
                    continue;
                }

                byte[] lenData      = new byte[sizeof(ushort)];
                int    lenBytesRead = await clientStream.ReadAsync(lenData, 0, sizeof(ushort));

                if (lenBytesRead < sizeof(ushort))                 //bad data
                {
                    continue;
                }

                ushort len = BitConverter.ToUInt16(lenData, 0);

                byte[] data          = new byte[len];
                int    dataBytesRead = await clientStream.ReadAsync(data, 0, data.Length);

                if (dataBytesRead != len)                 //bad data
                {
                    continue;
                }

                //data is fine! move it to the main thread
                Packet packet = new Packet
                {
                    SendMode = SendMode.Tcp,
                    Data     = data,
                    Client   = client
                };
                ManagerEvent dataEvent = new ManagerEvent(ManagerEventType.RecievedData, packet);
                EventQueue.Enqueue(dataEvent);
            }
        }
Пример #6
0
        private void CleanupDisconnectedClient(NetClient client, string reason)
        {
            _Clients.Remove(client);
            client.PollingNet = false;

            if (!client.IsLocal)
            {
                client.Tcp.GetStream().Close();
                client.Tcp.Close();
            }

            TcpClientDisconnectEvent tcpDisconnectEvent = new TcpClientDisconnectEvent
            {
                Client = client,
                Reason = reason
            };

            ManagerEvent disconnectEvent = new ManagerEvent(ManagerEventType.ClientDisconnected, tcpDisconnectEvent);

            EventQueue.Enqueue(disconnectEvent);
        }
Пример #7
0
        private async void ClientUdpListen()
        {
            while (PollingNet)
            {
                await Task.Delay(50);

                if (Udp.Available == 0)
                {
                    continue;
                }

                byte[] data = new byte[0];
                try
                {
                    //todo: possibly check the ep here to see if it matches the host ep? unsure if necessary
                    data = (await Udp.ReceiveAsync()).Buffer;
                }
                catch (SocketException ex)
                {
                    //deal with this later
                }

                if (data.Length < sizeof(ushort))                 //bad data
                {
                    continue;
                }

                //send data to main thread
                Packet packet = new Packet
                {
                    SendMode = SendMode.Udp,
                    Data     = data
                };
                ManagerEvent dataEvent = new ManagerEvent(ManagerEventType.RecievedData, packet);
                EventQueue.Enqueue(dataEvent);
            }
        }
Пример #8
0
        public static NetManager CreateClient()
        {
            NetManager createdManager = new NetManager();

            createdManager.Udp  = new UdpClient();
            createdManager.Side = Side.Client;

            //this could be done with a custom channel for serialization and validation and shit but what's even the point lol
            createdManager.Channels[UDP_HANDSHAKE_CHANNEL_INDEX].OnRecieveRaw += (byte[] data, NetClient sender) =>
            {
                if (data.Length != sizeof(byte) + 16)
                {
                    return;
                }

                UdpHandshakeUpdateEvent updateEvent;
                if (data[0] == 0)                         //not completed
                {
                    byte[] guidData = new byte[16];
                    Array.Copy(data, 1, guidData, 0, guidData.Length);

                    updateEvent = new UdpHandshakeUpdateEvent
                    {
                        Complete = false,
                        GuidData = guidData
                    };
                }
                else
                {
                    updateEvent = new UdpHandshakeUpdateEvent
                    {
                        Complete = true
                    }
                };

                ManagerEvent handshakeEvent = new ManagerEvent(ManagerEventType.UdpHandshakeUpdate, updateEvent);
                createdManager.EventQueue.Enqueue(handshakeEvent);
            };

            createdManager.Channels[DISCONNECT_CHANNEL_INDEX].OnRecieveRaw +=
                (byte[] data, NetClient sender) => createdManager.Disconnect(Encoding.Unicode.GetString(data));

            createdManager.Channels[CHANNEL_INDEX_SYNC_CHANNEL_INDEX].OnRecieveSerialized += (object objData, NetClient sender) =>
            {
                SyncableStringArray data = (SyncableStringArray)objData;

                if (data.ID != createdManager.ChannelSyncGuid)
                {
                    return;
                }

                if (data.SendingIndexes)
                {
                    for (int i = 0; i < createdManager.Channels.Count; i++)
                    {
                        createdManager.Channels[i].ID = (ushort)data.Indexes[i];
                    }

                    createdManager.IncrementInitialisationState();
                }
                else
                {
                    foreach (SyncableStringArray.OptionalString channel in data.Items)
                    {
                        createdManager.CreateChannel(channel.String);
                    }
                }
            };

            return(createdManager);
        }
Пример #9
0
        public void SendRaw(SendMode sendMode, byte[] data, NetChannel channel, NetClient reciever)
        {
            if (reciever.IsLocal)
            {
                //faking a send to a local client by just directly queueing the event
                byte[] id       = BitConverter.GetBytes(channel.ID);
                byte[] sentData = new byte[sizeof(ushort) + data.Length];

                Array.Copy(id, 0, sentData, 0, id.Length);
                Array.Copy(data, 0, sentData, 2, data.Length);

                //create recieve event for other manager
                Packet packet = new Packet
                {
                    SendMode = SendMode.Tcp,
                    Data     = sentData,
                };

                if (Side == Side.Client)
                {
                    packet.Client = LocalServersideClient;
                }

                ManagerEvent recieveEvent = new ManagerEvent(ManagerEventType.RecievedData, packet);

                //enqueue
                reciever.LocalManager.EventQueue.Enqueue(recieveEvent);
                return;
            }
            else if (sendMode == SendMode.Tcp)
            {
                //packet length first, then channel id, then data
                int    length        = sizeof(ushort) + data.Length;
                byte[] lengthEncoded = BitConverter.GetBytes((ushort)length);
                byte[] id            = BitConverter.GetBytes(channel.ID);

                byte[] sentData = new byte[length + sizeof(ushort)];
                Array.Copy(lengthEncoded, 0, sentData, 0, lengthEncoded.Length);
                Array.Copy(id, 0, sentData, 2, id.Length);
                Array.Copy(data, 0, sentData, 4, data.Length);

                NetworkStream stream;
                if (Side == Side.Server)
                {
                    stream = reciever.Tcp.GetStream();
                }
                else
                {
                    stream = Tcp.GetStream();
                }

                stream.Write(sentData, 0, sentData.Length);
                stream.Flush();
            }
            else
            {
                //channel id, then data
                byte[] id       = BitConverter.GetBytes(channel.ID);
                byte[] sentData = new byte[sizeof(ushort) + data.Length];

                Array.Copy(id, 0, sentData, 0, id.Length);
                Array.Copy(data, 0, sentData, 2, data.Length);

                Udp.Send(sentData, sentData.Length, reciever.EP);
            }
        }
Пример #10
0
        private async void ServerUdpListen()
        {
            while (PollingNet)
            {
                //await Task.Delay(50);
                //if (Udp.Available == 0)
                //	continue;

                IPEndPoint ep   = null;
                byte[]     data = new byte[0];

                try
                {
                    UdpReceiveResult asyncResult = await Udp.ReceiveAsync();

                    ep   = asyncResult.RemoteEndPoint;
                    data = asyncResult.Buffer;
                }
                catch (SocketException ex)
                {
                    //todo deal with this
                }

                if (data.Length < sizeof(ushort))                 //bad data
                {
                    continue;
                }

                //check if it's a udp handshake packet and emit the necessary event if it is
                //this has to be done here since we need the client's EP before it's already been resolved
                ushort channel = BitConverter.ToUInt16(data, 0);
                if (channel == UDP_HANDSHAKE_CHANNEL_INDEX)
                {
                    if (data.Length != sizeof(ushort) + 16 /*sizeof(Guid) isn't possible*/)
                    {
                        continue;
                    }

                    //create guid from bytes
                    byte[] guidArray = new byte[16];
                    Array.Copy(data, 2, guidArray, 0, guidArray.Length);

                    Guid guid = new Guid(guidArray);

                    //create event
                    UdpHandshakeAttemptEvent attemptEvent = new UdpHandshakeAttemptEvent
                    {
                        Guid     = guid,
                        SenderEP = ep
                    };

                    ManagerEvent guidEvent = new ManagerEvent(ManagerEventType.RecievedUdpHandshakeAttempt, attemptEvent);
                    EventQueue.Enqueue(guidEvent);

                    continue;
                }

                Packet packet = new Packet
                {
                    SendMode = SendMode.Udp,
                    Data     = data,
                    EP       = ep
                };
                ManagerEvent dataEvent = new ManagerEvent(ManagerEventType.RecievedData, packet);
                EventQueue.Enqueue(dataEvent);
            }
        }