예제 #1
0
        public static void Connect(string host)
        {
            Client client = new Client(host, 9292, 9293);

            if (OnConnect != null)
            {
                NetworkBridge.Invoke(() => OnConnect(client, EventArgs.Empty));
            }
        }
예제 #2
0
        public static void Start(ServerConfiguration config)
        {
            Server server = new Server(config);

            if (OnStart != null)
            {
                NetworkBridge.Invoke(() => OnStart(server, EventArgs.Empty));
            }
        }
예제 #3
0
        public Client(string host, int tcpPort, int udpPort)
        {
            NetworkBridge.Log("Creating client...");

            Socket           = new Socket(host, tcpPort, udpPort);
            Current          = this;
            Side.NetworkSide = Side.Client;

            Thread tcpThread = new Thread(() => {
                Stream tcp = Socket.Tcp.GetStream();
                while (!Closed)
                {
                    // NetworkBridge.Log("Waiting to read TCP...");
                    byte[] raw  = new byte[Socket.PacketSize];
                    int read    = tcp.Read(raw, 0, raw.Length);
                    byte[] trim = new byte[read];
                    Array.Copy(raw, 0, trim, 0, trim.Length);

                    if (Closed)
                    {
                        break;
                    }

                    ByteBuffer bufIn = new ByteBuffer(trim);
                    // bufIn.Debug(0, bufIn.Length);
                    // NetworkBridge.Log("Sub-Buffers: ");
                    List <ByteBuffer> buffers = new List <ByteBuffer>();
                    while (bufIn.Pointer != bufIn.Length)
                    {
                        int len        = bufIn.ReadInt();
                        ByteBuffer buf = new ByteBuffer(bufIn.ReadBytes(len));
                        // buf.Debug(0, buf.Length);
                        buffers.Add(buf);
                    }
                    try {
                        // Debug.Log("Executing buffers: ");
                        foreach (ByteBuffer buffer in buffers)
                        {
                            // buffer.Debug(0, buffer.Length);
                            NetworkData.HandleClientData(buffer);
                        }
                    } catch (Exception e) {
                        NetworkBridge.Invoke(() => Debug.LogException(e));
                    }
                }
            });

            tcpThread.IsBackground = true;
            tcpThread.Start();

            Thread udpThread = new Thread(() => {
                while (IsConnected)
                {
                    byte[] raw       = Socket.Udp.Receive(ref Socket.UdpRemote);
                    ByteBuffer bufIn = new ByteBuffer(raw);
                    try {
                        NetworkData.HandleClientData(bufIn);
                    } catch (Exception e) {
                        Debug.LogException(e);
                    }
                }
            });

            udpThread.IsBackground = true;
            udpThread.Start();

            Thread authThread = new Thread(() => {
                Thread.Sleep(100);

                Out.WriteByte(NetworkData.Management);
                Out.WriteByte(NetworkData.Authenticate);
                WriteTcp();

                NetworkBridge.Log("Wrote authentication information.");
            });

            authThread.IsBackground = true;
            authThread.Start();

            OnAuthenticate += (sender, args) => {
                Thread updateThread = new Thread(() => {
                    while (IsConnected)
                    {
                        lock (UdpBuffers) {
                            if (UdpBuffers.Count > 0)
                            {
                                WriteUdp();
                                UdpBuffers.Clear();
                                PositionUpdates.Clear();
                                RotationUpdates.Clear();
                                ScaleUpdates.Clear();
                            }
                        }

                        Thread.Sleep((int)(1000 / (float)TickRate));
                    }
                });
                updateThread.IsBackground = true;
                updateThread.Start();
            };
        }
예제 #4
0
        public static void HandleClientData(ByteBuffer data)
        {
            byte type = data.ReadByte();

            if (type == Data)
            {
                byte dType = data.ReadByte();
                long id    = data.ReadLong();

                /* NetworkBehaviour obj = null;
                 * if(dType != InstantiateObject && !ClientRegistry.GetObject(id, out obj)) {
                 *   NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                 * } else {*/
                if (dType == InstantiateObject)
                {
                    bool hasAuthority = data.ReadBool();
                    // Debug.Log(hasAuthority);
                    string resourcePath = data.ReadString();
                    // Debug.Log(resourcePath);
                    Vector3    position = data.ReadVector3();
                    Quaternion rotation = data.ReadQuaternion();
                    Vector3    scale    = data.ReadVector3();
                    // Debug.Log(scale);
                    // data.Debug(data.Pointer, data.Length);
                    int    ptr    = data.Pointer;
                    object parent = null;
                    NetworkBridge.AwaitInvoke(() => {
                        try {
                            parent = data.ReadSceneObject();
                        } catch (System.IndexOutOfRangeException e) {
                            NetworkBridge.Warn("hasAuthority: " + hasAuthority);
                            NetworkBridge.Warn("resourcePath: " + resourcePath);
                            NetworkBridge.Warn("position: " + position);
                            NetworkBridge.Warn("rotation: " + position);
                            NetworkBridge.Warn("scale: " + position);
                            NetworkBridge.Warn("ptr: " + ptr);
                            NetworkBridge.Warn("len: " + data.Length);
                            NetworkBridge.Warn("byte: " + data.Bytes[ptr]);

                            data.Debug(0, data.Length);
                            throw e;
                        }
                    });
                    byte childCount = data.ReadByte();

                    long[] childIds = new long[childCount];
                    for (int i = 0; i < childCount; i++)
                    {
                        childIds[i] = data.ReadLong();
                    }

                    NetworkBridge.Invoke(() => {
                        Object resource = Resources.Load(resourcePath);
                        GameObject inst = (GameObject)Object.Instantiate(resource);
                        inst.name       = resource.name;

                        NetworkBehaviour net = inst.GetComponent <NetworkBehaviour>();

                        net.NetworkId            = id;
                        net.HasAuthority         = hasAuthority;
                        net.transform.UseNetwork = false;
                        net.transform.position   = position;
                        net.transform.rotation   = rotation;
                        net.transform.lossyScale = scale;

                        if (parent == null)
                        {
                            net.transform.SetParent((Transform)null);
                        }
                        else
                        {
                            if (parent is NetworkBehaviour)
                            {
                                net.transform.SetParent(((NetworkBehaviour)parent).transform);
                            }
                            else if (parent is Transform)
                            {
                                net.transform.SetParent((Transform)parent);
                            }
                        }

                        int i = 0;
                        foreach (Transform child in net.transform)
                        {
                            NetworkBehaviour c = child.GetComponent <NetworkBehaviour>();
                            if (c != null)
                            {
                                c.transform.UseNetwork = true;
                                c.HasAuthority         = hasAuthority;
                                ClientRegistry.Objects[c.NetworkId = childIds[i++]] = c;
                                c.NetworkAwake();
                            }
                        }

                        net.transform.UseNetwork   = true;
                        ClientRegistry.Objects[id] = net;
                        Debug.Log("Registered object with ID: " + id);
                        net.NetworkAwake();
                    });
                }
                else if (dType == DestroyObject)
                {
                    NetworkBehaviour obj = null;
                    if (!ClientRegistry.GetObject(id, out obj))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                        return;
                    }
                    NetworkBridge.Invoke(() => Object.Destroy(obj.gameObject));
                    ClientRegistry.Objects.Remove(id);
                }
                else if (dType == UpdateTransform)
                {
                    NetworkBehaviour obj = null;
                    if (!ClientRegistry.GetObject(id, out obj))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                        return;
                    }

                    if (obj.transform.AcceptUpdates && (!obj.HasAuthority || obj.transform.AcceptUpdatesWithAuthority))
                    {
                        NetworkBridge.Invoke(() => {
                            bool old = obj.transform.UseNetwork;
                            obj.transform.UseNetwork = false;
                            byte tType = data.ReadByte();
                            if (tType == Vector3Type)
                            {
                                Vector3 vec = data.ReadVector3();
                                byte vType  = data.ReadByte();
                                if (vType == 1)
                                {
                                    obj.transform.position = vec;
                                }
                                else if (vType == 2)
                                {
                                    obj.transform.lossyScale = vec;
                                }
                            }
                            else if (tType == QuaternionType)
                            {
                                obj.transform.rotation = data.ReadQuaternion();
                            }
                            else
                            {
                                Debug.LogWarning("Received malformed data packet with type: " + dType + ": invalid transformation object type id: " + tType);
                            }
                            obj.transform.UseNetwork = old;
                        });
                    }
                }
                else if (dType == UpdateParent)
                {
                    NetworkBehaviour obj = null;
                    if (!ClientRegistry.GetObject(id, out obj))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                        return;
                    }

                    if (obj.transform.AcceptUpdates && (!obj.HasAuthority || obj.transform.AcceptUpdatesWithAuthority))
                    {
                        NetworkBridge.Invoke(() => {
                            // ReadSceneObject needs to be called from an invocation to the bridge.
                            // is this safe?
                            object newParent        = data.ReadSceneObject();
                            bool worldPositionStays = data.ReadBool();

                            bool old = obj.transform.UseNetwork;
                            obj.transform.UseNetwork = false;
                            if (newParent == null)
                            {
                                obj.transform.SetParent((Transform)null, worldPositionStays);
                            }
                            else
                            {
                                if (newParent is NetworkBehaviour)
                                {
                                    obj.transform.SetParent(((NetworkBehaviour)newParent).transform, worldPositionStays);
                                }
                                else if (newParent is Transform)
                                {
                                    obj.transform.SetParent((Transform)newParent, worldPositionStays);
                                }
                            }
                            obj.transform.UseNetwork = old;
                        });
                    }
                }
                else if (dType == UpdateField)
                {
                    if (!Client.Current.IsAuthenticated)
                    {
                        data.Pointer = 0;
                        ExecuteLater.Add(data.CopyAll());
                    }
                    else
                    {
                        NetworkBehaviour obj = null;
                        if (!ClientRegistry.GetObject(id, out obj))
                        {
                            NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                            return;
                        }

                        string fieldName = data.ReadString();
                        byte   dataType  = data.ReadByte();
                        object value     = ReadObject(data, dataType);

                        NetworkBridge.Invoke(() => obj.SetLocal(fieldName, value, true));
                    }
                }
                else if (dType == InvokeRPC)
                {
                    NetworkBehaviour obj = null;
                    if (!ClientRegistry.GetObject(id, out obj))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                        return;
                    }

                    string   methodName = data.ReadString();
                    byte     argCount   = data.ReadByte();
                    object[] args       = new object[argCount];
                    for (int i = 0; i < argCount; i++)
                    {
                        args[i] = ReadObject(data, data.ReadByte());
                    }

                    NetworkBridge.Invoke(() => obj.InvokeLocalMethod(methodName, args));
                }
                else
                {
                    NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid type");
                }
            }
            else if (type == Management)
            {
                byte mType = data.ReadByte();

                if (mType == Authenticate)
                {
                    Client.Current.ClientId = data.ReadLong();
                    NetworkBridge.Log("Client ID: " + Client.Current.ClientId);
                    Client.Current.TickRate = data.ReadByte();
                    NetworkBridge.Log("Network tick rate: " + Client.Current.TickRate);
                }
                else if (mType == Disconnect)
                {
                    Client.Current.Socket.Close();
                }
                else if (mType == Complete)
                {
                    NetworkBridge.Log("Authentication complete.");
                    NetworkBridge.Invoke(() => {
                        Client.Current.NotifyAuthenticate();

                        foreach (ByteBuffer buf in ExecuteLater)
                        {
                            HandleClientData(buf);
                        }

                        ExecuteLater.Clear();
                    });
                }
                else
                {
                    NetworkBridge.Warn("Received malformed management packet with type: " + mType + ": invalid type");
                }
            }
            else if (type == QueryDatabase)
            {
                byte code = data.ReadByte();
                if (code == 0)
                {
                    long       id  = data.ReadLong();
                    int        len = data.ReadInt();
                    ByteBuffer ret = new ByteBuffer(len);
                    System.Array.Copy(data.Bytes, data.Pointer, ret.Bytes, 0, ret.Length);
                    NetworkBridge.Log("Query response: " + ret.Length + " bytes");

                    NetworkBridge.Invoke(() => {
                        Client.Queries[id](ret);
                        Client.Queries.Remove(id);
                    });
                }
                else
                {
                    NetworkBridge.Warn("Received malformed query packet: query unsuccessful");
                }
            }
            else
            {
                NetworkBridge.Warn("Received malformed packet with type: " + type + ": invalid type (not data or management)");
            }
        }
예제 #5
0
        public static void HandleServerData(ByteBuffer data, Socket client)
        {
            byte type = data.ReadByte();

            if (type == Data)
            {
                byte dType    = data.ReadByte();
                long clientId = data.ReadLong();

                if (client.SpecificUdp)
                {
                    Socket serverClient = ServerRegistry.GetClient(clientId);
                    if (serverClient.Udp == null)
                    {
                        serverClient.Udp       = client.Udp;
                        serverClient.UdpRemote = client.UdpRemote;
                    }
                }

                if (dType == InstantiateObject)
                {
                    string     resourcePath = data.ReadString();
                    Vector3    position     = data.ReadVector3();
                    Quaternion rotation     = data.ReadQuaternion();
                    Vector3    scale        = data.ReadVector3();
                    object     parent       = null;
                    NetworkBridge.AwaitInvoke(() => parent = data.ReadSceneObject());
                    bool here       = data.ReadBool();
                    byte childCount = data.ReadByte();

                    long[] ids = new long[childCount + 1];
                    for (int i = 0; i < ids.Length; i++)
                    {
                        ids[i] = Server.GenerateId();
                    }
                    long[] childIds = new long[childCount];
                    System.Array.Copy(ids, 1, childIds, 0, childCount);
                    NetworkBridge.Invoke(() => {
                        Debug.Log("Loading resource: " + resourcePath);
                        Object resource = Resources.Load(resourcePath);
                        GameObject inst = (GameObject)Object.Instantiate(resource);
                        inst.name       = resource.name;

                        NetworkBehaviour net = inst.GetComponent <NetworkBehaviour>();

                        IEnumerable <long> userIds = here ? ServerRegistry.GetClientIDs() : ServerRegistry.GetOtherClientIDs(clientId);
                        foreach (long userId in userIds)
                        {
                            Socket to = ServerRegistry.GetClient(userId);
                            lock (to.Buffer) {
                                to.Buffer.WriteByte(Data);
                                to.Buffer.WriteByte(InstantiateObject);
                                to.Buffer.WriteLong(ids[0]);
                                to.Buffer.WriteBool(!net.ServerOnly && userId == clientId);
                                to.Buffer.WriteString(resourcePath);
                                to.Buffer.WriteVector3(position);
                                to.Buffer.WriteQuaternion(rotation);
                                to.Buffer.WriteVector3(scale);
                                to.Buffer.WriteSceneObject(parent);
                                to.Buffer.WriteByte(childCount);
                                foreach (long id in childIds)
                                {
                                    to.Buffer.WriteLong(id);
                                }
                                to.WriteBufferTcp();
                            }
                        }

                        net.NetworkId            = ids[0];
                        net.transform.UseNetwork = false;
                        net.transform.position   = position;
                        net.transform.rotation   = rotation;
                        net.transform.lossyScale = scale;

                        if (parent == null)
                        {
                            net.transform.SetParent((Transform)null);
                        }
                        else
                        {
                            if (parent is ObjectRegistration)
                            {
                                net.transform.SetParent(((ObjectRegistration)parent).Object.transform);
                            }
                            else if (parent is Transform)
                            {
                                net.transform.SetParent((Transform)parent);
                            }
                        }

                        ServerRegistry.Objects[ids[0]] = new ObjectRegistration(net, clientId, resourcePath, false, childIds);
                        Debug.Log("Registered object with ID: " + ids[0] + ".");

                        int idCount = 0;
                        for (int i = 0; i < inst.transform.childCount; i++)
                        {
                            Transform child       = inst.transform.GetChild(i);
                            NetworkBehaviour cnet = child.GetComponent <NetworkBehaviour>();

                            if (cnet != null)
                            {
                                cnet.NetworkId            = childIds[idCount++];
                                cnet.transform.UseNetwork = true;
                                ServerRegistry.Objects[cnet.NetworkId] = new ObjectRegistration(net, clientId, resourcePath, true, new long[0]);
                                Debug.Log("Registered child with ID: " + cnet.NetworkId + ".");
                                cnet.NetworkAwake();
                            }
                        }

                        net.transform.UseNetwork = true;
                        net.NetworkAwake();
                    });
                }
                else if (dType == DestroyObject)
                {
                    long objectId = data.ReadLong();

                    ObjectRegistration obj = null;
                    if (!ServerRegistry.GetObject(objectId, out obj))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + objectId);
                    }
                    else
                    {
                        if (obj.ClientOwner == clientId)
                        {
                            Object.Destroy(obj.Object);
                            ServerRegistry.Objects.Remove(objectId);

                            foreach (long userId in ServerRegistry.GetClientIDs())
                            {
                                Socket to = ServerRegistry.GetClient(userId);
                                lock (to.Buffer) {
                                    to.Buffer.WriteByte(Data);
                                    to.Buffer.WriteByte(DestroyObject);
                                    to.Buffer.WriteLong(objectId);
                                    to.WriteBufferTcp();
                                }
                            }
                        }
                    }
                }
                else if (dType == UpdateTransform)
                {
                    long objectId = data.ReadLong();

                    ObjectRegistration reg = null;
                    if (!ServerRegistry.GetObject(objectId, out reg))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + objectId);
                    }
                    else
                    {
                        NetworkBehaviour obj = reg.Object;
                        if ((!obj.transform.RequiresAuthority || reg.ClientOwner == clientId) && obj.transform.AcceptUpdates)
                        {
                            NetworkBridge.Invoke(() => {
                                bool old = obj.transform.UseNetwork;
                                obj.transform.UseNetwork = true;
                                byte tType = data.ReadByte();
                                if (tType == Vector3Type)
                                {
                                    Vector3 vec = data.ReadVector3();
                                    byte vType  = data.ReadByte();
                                    if (vType == 1)
                                    {
                                        obj.transform.position = vec;
                                    }
                                    else if (vType == 2)
                                    {
                                        obj.transform.lossyScale = vec;
                                    }
                                }
                                else if (tType == QuaternionType)
                                {
                                    obj.transform.rotation = data.ReadQuaternion();
                                }
                                else
                                {
                                    Debug.LogWarning("Received malformed data packet with type: " + dType + ": invalid transformation object type id: " + tType);
                                }
                                obj.transform.UseNetwork = old;
                            });
                        }
                    }
                }
                else if (dType == UpdateParent)
                {
                    long id = data.ReadLong();

                    ObjectRegistration reg = null;
                    if (!ServerRegistry.GetObject(id, out reg))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                    }
                    else
                    {
                        NetworkBehaviour obj = reg.Object;

                        if ((!obj.transform.RequiresAuthority || reg.ClientOwner == clientId) && obj.transform.AcceptUpdates)
                        {
                            NetworkBridge.Invoke(() => {
                                object newParent        = data.ReadSceneObject();
                                bool worldPositionStays = data.ReadBool();

                                if (newParent == null)
                                {
                                    obj.transform.SetParent((Transform)null, worldPositionStays);
                                }
                                else
                                {
                                    if (newParent is ObjectRegistration)
                                    {
                                        obj.transform.SetParent(((ObjectRegistration)newParent).Object.transform, worldPositionStays);
                                    }
                                    else if (newParent is Transform)
                                    {
                                        obj.transform.SetParent((Transform)newParent, worldPositionStays);
                                    }
                                }
                            });
                        }
                        else
                        {
                            NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": missing authority");
                        }
                    }
                }
                else if (dType == UpdateField)
                {
                    long   id        = data.ReadLong();
                    bool   tcp       = data.ReadBool();
                    string fieldName = data.ReadString();
                    byte   dataType  = data.ReadByte();
                    object value     = ReadObject(data, dataType);

                    ObjectRegistration reg = null;
                    if (!ServerRegistry.GetObject(id, out reg))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                    }
                    else
                    {
                        Synchronized sync;
                        FieldInfo    field = reg.Object.GetLocal(fieldName, true, out sync);
                        if (field == null)
                        {
                            NetworkBridge.Log("Received malformed data packet with type: " + dType + ": invalid field");
                        }
                        else
                        {
                            if (!sync.RequiresAuthority || reg.ClientOwner == clientId)
                            {
                                NetworkBridge.Invoke(() => reg.Object.SetLocal(fieldName, value));

                                foreach (long userId in ServerRegistry.GetOtherClientIDs(clientId))
                                {
                                    Socket to = ServerRegistry.GetClient(userId);
                                    lock (to.Buffer) {
                                        to.Buffer.WriteByte(Data);
                                        to.Buffer.WriteByte(UpdateField);
                                        to.Buffer.WriteLong(id);
                                        to.Buffer.WriteString(fieldName);
                                        to.Buffer.WriteByte(dataType);
                                        WriteObject(value, to.Buffer);
                                        if (tcp)
                                        {
                                            to.WriteBufferTcp();
                                        }
                                        else
                                        {
                                            to.WriteBufferUdp();
                                        }
                                    }
                                }
                            }
                            else
                            {
                                NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": missing authority");
                            }
                        }
                    }
                }
                else if (dType == InvokeRPC)
                {
                    long     id         = data.ReadLong();
                    string   methodName = data.ReadString();
                    byte     argCount   = data.ReadByte();
                    object[] args       = new object[argCount];
                    for (int i = 0; i < argCount; i++)
                    {
                        args[i] = ReadObject(data, data.ReadByte());
                    }

                    ObjectRegistration reg = null;
                    if (!ServerRegistry.GetObject(id, out reg))
                    {
                        NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid object id: " + id);
                    }
                    else
                    {
                        RemoteMethod remote;
                        MethodInfo   method = reg.Object.GetLocalMethod(methodName, out remote);
                        if (method == null)
                        {
                            NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid method");
                        }
                        else
                        {
                            if (!remote.RequiresAuthority || reg.ClientOwner == clientId)
                            {
                                NetworkBridge.Invoke(() => reg.Object.InvokeLocalMethod(methodName, args));

                                // the server shouldn't make other clients invoke the RPC, so this code is broken!

                                /* foreach(long userId in ServerRegistry.GetOtherClientIDs(clientId)) {
                                 *  Socket to = ServerRegistry.Clients[userId];
                                 *  to.Buffer.WriteByte(Data);
                                 *  to.Buffer.WriteByte(InvokeRPC);
                                 *  to.Buffer.WriteLong(id);
                                 *  to.Buffer.WriteString(methodName);
                                 *  to.Buffer.WriteByte(argCount);
                                 *  foreach(object arg in args) {
                                 *      WriteObject(arg, to.Buffer);
                                 *  }
                                 *  to.WriteBufferTcp();
                                 * } */
                            }
                            else
                            {
                                NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": missing authority");
                            }
                        }
                    }
                }
                else
                {
                    NetworkBridge.Warn("Received malformed data packet with type: " + dType + ": invalid type");
                }
            }
            else if (type == Management)
            {
                byte mType = data.ReadByte();

                if (mType == Authenticate)
                {
                    long clientId = Server.GenerateId();
                    lock (client.Buffer) {
                        client.Buffer.WriteByte(Management);
                        client.Buffer.WriteByte(Authenticate);
                        client.Buffer.WriteLong(clientId);
                        client.Buffer.WriteByte((byte)Server.Current.Config.TickRate);
                        client.WriteBufferTcp();
                    }

                    lock (ServerRegistry.Clients) {
                        ServerRegistry.Clients[clientId] = client;
                        NetworkBridge.Log("Registered client with ID: " + clientId);
                    }

                    NetworkBridge.Invoke(() => {
                        foreach (long id in ServerRegistry.Objects.Keys)
                        {
                            ObjectRegistration reg = ServerRegistry.Objects[id];

                            if (!reg.IsChild)
                            {
                                Debug.Log("objid: " + id);
                                lock (client.Buffer) {
                                    client.Buffer.WriteByte(Data);
                                    client.Buffer.WriteByte(InstantiateObject);
                                    client.Buffer.WriteLong(id);
                                    client.Buffer.WriteBool(false);
                                    client.Buffer.WriteString(reg.ResourcePath);
                                    client.Buffer.WriteVector3(reg.Object.transform.position);
                                    client.Buffer.WriteQuaternion(reg.Object.transform.rotation);
                                    client.Buffer.WriteVector3(reg.Object.transform.lossyScale);

                                    Transform parent = reg.Object.transform.parent;

                                    /* NetworkBehaviour parentNet = null;
                                     * if(parent != null) {
                                     *  parentNet = parent.gameObject.GetComponent<NetworkBehaviour>();
                                     * } */
                                    client.Buffer.WriteSceneObject(parent);
                                    client.Buffer.WriteByte((byte)reg.ChildIds.Length);
                                    foreach (long cid in reg.ChildIds)
                                    {
                                        client.Buffer.WriteLong(cid);
                                    }
                                    client.WriteBufferTcp();
                                }
                            }

                            NetworkBehaviour net = reg.Object;
                            foreach (string key in net.FieldChanges.Keys)
                            {
                                object val = net.FieldChanges[key];

                                Debug.Log("field: " + key + " = " + val);

                                lock (client.Buffer) {
                                    client.Buffer.WriteByte(Data);
                                    client.Buffer.WriteByte(UpdateField);
                                    client.Buffer.WriteLong(id);
                                    client.Buffer.WriteString(key);
                                    client.Buffer.WriteByte(GetObjectType(val));
                                    WriteObject(val, client.Buffer);
                                    client.WriteBufferTcp();
                                }
                            }
                        }

                        NetworkBridge.Log("Sent all existing objects and their updated fields to client.");

                        lock (client.Buffer) {
                            client.Buffer.WriteByte(Management);
                            client.Buffer.WriteByte(Complete);
                            client.WriteBufferTcp();

                            NetworkBridge.Log("Sent Management/Complete message.");
                        }
                    });
                }
                else
                {
                    NetworkBridge.Warn("Received malformed management packet with type: " + mType + ": invalid type");
                }
            }
            else if (type == QueryDatabase)
            {
                long     id       = data.ReadLong();
                string   dataName = data.ReadString();
                byte     argCount = data.ReadByte();
                object[] args     = new object[argCount];
                for (int i = 0; i < argCount; i++)
                {
                    args[i] = ReadObject(data, data.ReadByte());
                }

                if (ServerDatabase.IsRegistered(dataName))
                {
                    NetworkBridge.Invoke(() => {
                        lock (client.Buffer) {
                            client.Buffer.WriteByte(QueryDatabase);
                            client.Buffer.WriteByte(0);
                            client.Buffer.WriteLong(id);
                            byte[] query = ServerDatabase.Request(dataName, args);
                            NetworkBridge.Log("Query: " + dataName + ": " + query.Length + " bytes");
                            client.Buffer.WriteInt(query.Length);
                            client.Buffer.WriteBytes(query);
                            client.WriteBufferTcp();
                        }
                    });
                }
                else
                {
                    NetworkBridge.Warn("Received malformed query packet: data not found: " + dataName);

                    NetworkBridge.Invoke(() => {
                        lock (client.Buffer) {
                            client.Buffer.WriteByte(QueryDatabase);
                            client.Buffer.WriteByte(1);
                            client.WriteBufferTcp();
                        }
                    });
                }
            }
            else
            {
                NetworkBridge.Warn("Received malformed packet with type: " + type + ": invalid type (not data or management");
            }
        }
예제 #6
0
        public Server(ServerConfiguration config)
        {
            Config = config;

            TcpServer = new TcpListener(IPAddress.Any, config.TcpPort);
            UdpServer = new UdpClient(config.UdpPort);

            NetworkBridge.Log("Started TCP and UDP servers.");

            Current = this;

            Thread tcpThread = new Thread(() => {
                TcpServer.Start();

                while (!Closed)
                {
                    TcpClient client = TcpServer.AcceptTcpClient();
                    NetworkBridge.Log("Accepted TCP client.");

                    Socket socket = new Socket(client, null);
                    Stream tcp    = client.GetStream();

                    if (Closed)  // disconnect socket that connected after server closed: is this necessary?
                    {
                        NetworkBridge.Log("Kicked client.");
                        lock (socket.Buffer) {
                            socket.Buffer.WriteByte(NetworkData.Management);
                            socket.Buffer.WriteByte(NetworkData.Disconnect);
                            socket.WriteBufferTcp();
                        }
                        return;
                    }

                    Thread tcpClientThread = new Thread(() => {
                        while (!Closed)
                        {
                            byte[] raw = new byte[Socket.PacketSize];
                            int read   = tcp.Read(raw, 0, raw.Length);

                            if (Closed)
                            {
                                NetworkBridge.Log("Kicked client.");
                                lock (socket.Buffer) {
                                    socket.Buffer.WriteByte(NetworkData.Management);
                                    socket.Buffer.WriteByte(NetworkData.Disconnect);
                                    socket.WriteBufferTcp();
                                }
                                return;
                            }

                            byte[] trimmed = new byte[read];
                            Array.Copy(raw, trimmed, read);

                            ByteBuffer bufIn          = new ByteBuffer(trimmed);
                            List <ByteBuffer> buffers = new List <ByteBuffer>();
                            while (bufIn.Pointer != bufIn.Length)
                            {
                                int len           = bufIn.ReadInt();
                                ByteBuffer buffer = new ByteBuffer(bufIn.ReadBytes(len));
                                buffers.Add(buffer);
                            }
                            try {
                                foreach (ByteBuffer buffer in buffers)
                                {
                                    NetworkData.HandleServerData(buffer, socket);
                                }
                            } catch (Exception e) {
                                NetworkBridge.Invoke(() => Debug.LogException(e));
                            }
                        }
                    });
                    tcpClientThread.IsBackground = true;
                    tcpClientThread.Start();
                }
            });

            tcpThread.IsBackground = true;
            tcpThread.Start();

            Thread udpThread = new Thread(() => {
                IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0);
                while (!Closed)
                {
                    byte[] raw = UdpServer.Receive(ref remote);

                    Socket socket    = new Socket(null, UdpServer);
                    socket.UdpRemote = remote;

                    if (Closed)
                    {
                        return;
                    }

                    ByteBuffer bufIn = new ByteBuffer(raw);
                    byte bufferCount = bufIn.ReadByte();
                    // NetworkBridge.Log("Received " + bufferCount + " buffer(s) of UDP data.");
                    for (int i = 0; i < bufferCount; i++)
                    {
                        byte bufferLength = bufIn.ReadByte();
                        byte[] buffer     = bufIn.ReadBytes(bufferLength);
                        try {
                            NetworkData.HandleServerData(new ByteBuffer(buffer), socket);
                        } catch (Exception e) {
                            NetworkBridge.Invoke(() => UnityEngine.Debug.LogException(e));
                        }
                    }
                }
            });

            udpThread.IsBackground = true;
            udpThread.Start();

            Side.NetworkSide = Side.Server;
        }