Example #1
0
        private void OnAccept()
        {
            // 处理连接
            NetworkConnection c;

            while ((c = Driver.Accept()) != default)
            {
                // New connection can never have any events, if this one does - just close it
                if (c.PopEvent(Driver, out _) != NetworkEvent.Type.Empty)
                {
                    c.Disconnect(Driver);
                    continue;
                }

                Debug.Log($"Accepted a connection:{Driver.RemoteEndPoint(c).Address}");

                ++ConnectionCount;
                ++_connectionInstanceId;

                // 创建session
                var session = PostUpdateCommands.CreateEntity();
                PostUpdateCommands.AddComponent(session, new NetworkSnapshotAckComponent());
                PostUpdateCommands.AddComponent(session, new NetworkStreamConnection {
                    Value = c
                });
                PostUpdateCommands.AddComponent(session, new CommandTargetComponent());
                PostUpdateCommands.AddComponent(session, new NetworkIdComponent {
                    Value = _connectionInstanceId
                });
                PostUpdateCommands.AddBuffer <IncomingRpcDataStreamBufferComponent>(session);
                PostUpdateCommands.AddBuffer <IncomingCommandDataStreamBufferComponent>(session);
                var outBuffer = PostUpdateCommands.AddBuffer <OutgoingRpcDataStreamBufferComponent>(session);

                // 发送id
                _rpcQueue.Schedule(outBuffer, new RpcSetNetworkId {
                    id = _connectionInstanceId
                });
            }
        }
        public unsafe void Execute()
        {
            for (int index = 0; index < connections.Length; index++)
            {
                DataStreamReader stream;
                if (!connections[index].IsCreated)
                {
                    continue;
                }

                NetworkEvent.Type cmd;
                while ((cmd = driver.PopEventForConnection(connections[index], out stream)) !=
                       NetworkEvent.Type.Empty)
                {
                    if (cmd == NetworkEvent.Type.Data)
                    {
                        // First byte is the messageType
                        MessageType messageType = (MessageType)stream.ReadByte();

                        switch (messageType)
                        {
                        case MessageType.StartServer:
                        {
                            // Check if they are already connected or perhaps are already hosting, if so return
                            if (HasPeer(index) || connectionIndexToRoomID.ContainsKey(index))
                            {
                                return;
                            }

                            Client client = new Client
                            {
                                ConnectionId  = index,
                                IsServer      = true,
                                OutgoingBytes = 0,
                                ConnectTime   = DateTime.UtcNow
                            };
                            Room room = new Room
                            {
                                RoomId = GenerateRoomId(),
                                Server = client,
                            };

                            rooms.Add(room);
                            connectionIndexToRoomID.Add(index, room.RoomId);

                            NativeList <byte> ipv6AddressBuffer = new NativeList <byte>(16, Allocator.Temp);
                            NetworkEndPoint   ipAddress         = driver.RemoteEndPoint(connections[index]);

                            if (ipAddress.Family == NetworkFamily.Ipv6)
                            {
                                string ipv6Address = ipAddress.Address.Split(':')[0];
                                foreach (string n in ipv6Address.Split('.'))
                                {
                                    ipv6AddressBuffer.Add(Byte.Parse(n));
                                }
                            }
                            else if (ipAddress.Family == NetworkFamily.Ipv4)
                            {
                                string ipv4Address = ipAddress.Address.Split(':')[0];
                                foreach (byte b in new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255 })
                                {
                                    ipv6AddressBuffer.Add(b);
                                }
                                foreach (string n in ipv4Address.Split('.'))
                                {
                                    ipv6AddressBuffer.Add(Byte.Parse(n));
                                }
                            }
                            else
                            {
                                // TODO: Throw wrong type
                                ipv6AddressBuffer = default(NativeList <byte>);
                            }

                            ipAddress.SetRawAddressBytes(ipv6AddressBuffer, NetworkFamily.Ipv6);
                            serverAddressToRoomID.Add(ipAddress.Address, room.RoomId);

                            if (ServerBehaviour.Config.EnableRuntimeMetaLogging)
                            {
                                Console.WriteLine("[INFO] Server started from " + ipAddress.Address);
                            }

                            DataStreamWriter writer;
                            writer = driver.BeginSend(pipeline, connections[index]);

                            // Write the message type
                            writer.WriteByte((byte)MessageType.AddressReport);
                            // Write the Connection Id
                            writer.WriteInt(index);
                            // TODO: Throw if address is not 16 bytes. It should always be
                            // Write the address
                            writer.WriteBytes(ipv6AddressBuffer);
                            // Write the port
                            writer.WriteUShort(ipAddress.Port);

                            // Send connect to client
                            driver.EndSend(writer);

                            ipv6AddressBuffer.Dispose();
                        }
                        break;

                        case MessageType.ConnectToServer:
                        {
                            // Check if they are already connected or perhaps are already hosting, if so return
                            if (HasPeer(index) || connectionIndexToRoomID.ContainsKey(index))
                            {
                                return;
                            }

                            NativeArray <byte> addressBytes = new NativeArray <byte>(16, Allocator.Temp);
                            stream.ReadBytes(addressBytes);
                            ushort remotePort = stream.ReadUShort();

                            NetworkEndPoint endpoint = new NetworkEndPoint();
                            endpoint.SetRawAddressBytes(addressBytes, NetworkFamily.Ipv6);
                            endpoint.Port = remotePort;

                            if (ServerBehaviour.Config.EnableRuntimeMetaLogging)
                            {
                                Console.WriteLine("[INFO] Connection requested to address " + endpoint.Address);
                            }
                            if (serverAddressToRoomID.ContainsKey(endpoint.Address))
                            {
                                if (ServerBehaviour.Config.EnableRuntimeMetaLogging)
                                {
                                    Console.WriteLine("[INFO] Connection approved");
                                }

                                // Get the room they want to join
                                Room room = GetRoom(serverAddressToRoomID[endpoint.Address]);

                                // Create a client for them
                                Client client = new Client
                                {
                                    ConnectionId  = index,
                                    IsServer      = false,
                                    OutgoingBytes = 0,
                                    ConnectTime   = DateTime.UtcNow
                                };

                                // Handle the connect
                                HandleClientConnect(room, client);
                            }
                        }
                        break;

                        case MessageType.Data:
                        {
                            foreach (Room room in rooms)
                            {
                                if (HasPeer(room, index, out bool isServer))
                                {
                                    // Found a matching client in room
                                    if (isServer)
                                    {
                                        // The server is sending data

                                        int destination = stream.ReadInt();

                                        // Safety check. Make sure who they want to send to ACTUALLY belongs to their room
                                        if (HasPeer(room, destination, out isServer) && !isServer)
                                        {
                                            Send(room, destination, index, stream);
                                        }
                                    }
                                    else
                                    {
                                        // A client is sending data

                                        Send(room, room.ServerConnectionId, index, stream);
                                    }
                                }
                            }
                        }
                        break;

                        case MessageType.ClientDisconnect:
                        {
                            int clientConnectionId = stream.ReadInt();

                            if (ServerBehaviour.Config.EnableRuntimeMetaLogging)
                            {
                                Console.WriteLine("[INFO] Client disconnect request");
                            }

                            foreach (Room room in rooms)
                            {
                                if (room.ServerConnectionId == clientConnectionId && HandleClientDisconnect(room, clientConnectionId, true))
                                {
                                    // Only disconnect one. A peer can only be in 1 room
                                    break;
                                }
                            }
                        }
                        break;
                        }
                    }
                    else if (cmd == NetworkEvent.Type.Disconnect)
                    {
                        Console.WriteLine("[INFO] Client disconnected from server");
                        connections[index] = default(NetworkConnection);
                    }
                }
            }
        }