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); }
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; }
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); }
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); } }
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); } }
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); }
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); } }
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); }
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); } }
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); } }