예제 #1
0
        int CreateAndBindSocket(out long socket, network_address address)
        {
            socket = -1;
            int errorcode = 0;
            int ret       = NativeBindings.network_create_and_bind(ref socket, ref address, ref errorcode);

            if (ret != 0)
            {
                return(errorcode);
            }
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            AllSockets.OpenSockets.Add(socket);
#endif
            if ((ret = NativeBindings.network_set_nonblocking(socket, ref errorcode)) != 0)
            {
                return(errorcode);
            }
            if ((ret = NativeBindings.network_set_send_buffer_size(socket, ushort.MaxValue, ref errorcode)) != 0)
            {
                return(errorcode);
            }
            if ((ret = NativeBindings.network_set_receive_buffer_size(socket, ushort.MaxValue, ref errorcode)) != 0)
            {
                return(errorcode);
            }
#if (UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN)
            // Avoid WSAECONNRESET errors when sending to an endpoint which isn't open yet (unclean connect/disconnects)
            NativeBindings.network_set_connection_reset(socket, 0);
#endif
            return(0);
        }
예제 #2
0
            unsafe int NativeReceive(ref UdpCHeader header, void *data, int length, ref network_address address)
            {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
                if (length <= 0)
                {
                    throw new ArgumentException("Can't receive into 0 bytes or less of buffer memory");
                }
#endif
                var iov = stackalloc network_iovec[2];

                fixed(byte *ptr = header.Data)
                {
                    iov[0].buf = ptr;
                    iov[0].len = UdpCHeader.Length;

                    iov[1].buf = data;
                    iov[1].len = length;
                }

                int errorcode = 0;
                var result    = NativeBindings.network_recvmsg(socket, iov, 2, ref address, ref errorcode);
                if (result == -1)
                {
                    if (errorcode == 10035 || errorcode == 35 || errorcode == 11)
                    {
                        return(0);
                    }

                    receiver.ReceiveErrorCode = errorcode;
                }
                return(result);
            }
예제 #3
0
        public unsafe int SendMessage(void *iov, int iov_len, ref network_address address)
        {
            if (m_LocalEndPoint[0].family != NetworkFamily.IPC || m_LocalEndPoint[0].port == 0)
            {
                m_LocalEndPoint[0] = IPCManager.Instance.CreateEndPoint();
            }

            return(IPCManager.Instance.SendMessageEx(m_LocalEndPoint[0], iov, iov_len, ref address));
        }
예제 #4
0
        unsafe int NativeReceive(ref UdpCHeader header, void *data, int length, ref network_address address)
        {
            if (length <= 0)
            {
                Debug.LogError("Can't receive into 0 bytes or less of buffer memory");
                return(0);
            }
            var iov = stackalloc network_iovec[2];

            fixed(byte *ptr = header.Data)
            {
                iov[0].buf = ptr;
                iov[0].len = UdpCHeader.Length;

                iov[1].buf = data;
                iov[1].len = length;
            }

            var result = m_NetworkInterface.ReceiveMessage(iov, 2, ref address);

            if (result == -1)
            {
                int err = Marshal.GetLastWin32Error();
                if (err == 10035 || err == 35 || err == 11)
                {
                    return(0);
                }

                Debug.LogError(string.Format("error on receive {0}", err));
                throw new SocketException(err);
            }

            if (result > 0)
            {
                DebugLog("NativeReceive Type=" + (UdpCProtocol)header.Type + " HdrLength=" + UdpCHeader.Length + " PayloadSize=" + length + " Result=" + result);
                string dump = "(";
                fixed(byte *ptr = header.Data)
                {
                    for (int i = 0; i < UdpCHeader.Length; ++i)
                    {
                        dump += ptr[i].ToString("X");
                    }
                }

                dump += ") ";
                for (int i = 0; i < result - UdpCHeader.Length; ++i)
                {
                    dump += ((byte *)data)[i].ToString("X");
                }
                DebugLog("Dump=" + dump);
            }

            return(result);
        }
예제 #5
0
        int SendPacket(UdpCProtocol type, network_address address)
        {
            var header = new UdpCHeader
            {
                Type = (byte)type
            };

            unsafe
            {
                return(NativeSend(ref header, null, 0, address));
            }
        }
예제 #6
0
        Connection GetConnection(network_address address)
        {
            for (int i = 0; i < m_ConnectionList.Length; i++)
            {
                if (address.ReallyEquals(m_ConnectionList[i].Address))
                {
                    return(m_ConnectionList[i]);
                }
            }

            return(Connection.Null);
        }
예제 #7
0
        unsafe int NativeSend(ref UdpCHeader header, void *payload, int payloadSize, network_address remote)
        {
            var iov = stackalloc network_iovec[2];
            int result;

            fixed(byte *ptr = header.Data)
            {
                iov[0].buf = ptr;
                iov[0].len = UdpCHeader.Length;

                iov[1].buf = payload;
                iov[1].len = payloadSize;

                result = m_NetworkInterface.SendMessage(iov, 2, ref remote);
            }

            DebugLog("NativeSend Type=" + (UdpCProtocol)header.Type + " HdrLength=" + UdpCHeader.Length + " PayloadSize=" + payloadSize + " Result=" + result);
            string dump = "(";

            fixed(byte *ptr = header.Data)
            {
                for (int i = 0; i < UdpCHeader.Length; ++i)
                {
                    dump += ptr[i].ToString("X");
                }
            }

            dump += ") ";
            for (int i = 0; i < payloadSize; ++i)
            {
                dump += ((byte *)payload)[i].ToString("X");
            }
            DebugLog("Dump=" + dump);

            if (result == -1)
            {
                int error = Marshal.GetLastWin32Error();
                throw new SocketException(error);
            }

            return(result);
        }
예제 #8
0
            public unsafe void Execute()
            {
                var address = new network_address {
                    length = network_address.Length
                };
                var header = new UdpCHeader();
                var stream = receiver.GetDataStream();

                receiver.ReceiveCount     = 0;
                receiver.ReceiveErrorCode = 0;

                while (true)
                {
                    int dataStreamSize = receiver.GetDataStreamSize();
                    if (receiver.DynamicDataStreamSize())
                    {
                        while (dataStreamSize + NetworkParameterConstants.MTU - UdpCHeader.Length >= stream.Length)
                        {
                            stream.ResizeUninitialized(stream.Length * 2);
                        }
                    }
                    else if (dataStreamSize >= stream.Length)
                    {
                        return;
                    }
                    var result = NativeReceive(ref header, (byte *)stream.GetUnsafePtr() + dataStreamSize,
                                               Math.Min(NetworkParameterConstants.MTU - UdpCHeader.Length, stream.Length - dataStreamSize), ref address);
                    if (result <= 0)
                    {
                        return;
                    }

                    var endpoint = default(NetworkInterfaceEndPoint);
                    endpoint.dataLength = UnsafeUtility.SizeOf <network_address>();
                    UnsafeUtility.MemCpy(endpoint.data, &address, endpoint.dataLength);
                    receiver.ReceiveCount += receiver.AppendPacket(endpoint, header, result);
                }
            }
예제 #9
0
        public static unsafe network_address ToNetworkAddress(NetworkEndPoint ep)
        {
            switch (ep.family)
            {
            case NetworkFamily.UdpIpv4:
                return(SocketExtension.MarshalIpV4Address(ep.address, ep.port));

            case NetworkFamily.IPC:
                network_address addr = default(network_address);
                // TODO: Double check this works on ios as well.
#if (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
                addr.family.sa_family = (byte)AddressFamily.Unspecified;
#else
                addr.family.sa_family = (ushort)AddressFamily.Unspecified;
#endif
                addr.ipc_handle = *(int *)ep.address;
                addr.length     = 6;
                return(addr);

            default:
                throw new NotImplementedException();
            }
        }
예제 #10
0
        unsafe int ProcessPackets(BitStream bs)
        {
            var address = new network_address();

            address.length = sizeof(network_address);
            var header = new UdpCHeader();

            while (true)
            {
                if (bs.WriteCapacity <= 0)
                {
                    return(0);
                }
                var sliceOffset = bs.GetBytesWritten();
                var result      = NativeReceive(ref header, bs.UnsafeDataPtr + sliceOffset,
                                                Math.Min(NetworkParameterConstants.MTU, bs.WriteCapacity), ref address);
                if (result <= 0)
                {
                    return(result);
                }

                switch ((UdpCProtocol)header.Type)
                {
                case UdpCProtocol.ConnectionRequest:
                {
                    if (!Listening)
                    {
                        continue;
                    }

                    Connection c;
                    if ((c = GetConnection(address)) == Connection.Null || c.State == NetworkConnection.State.Destroyed)
                    {
                        int id;
                        if (!m_FreeList.AquireConnectionId(out id))
                        {
                            SendPacket(UdpCProtocol.ConnectionReject, address);
                            continue;
                        }

                        int ver = m_ConnectionList[id].Version;
                        c = new Connection()
                        {
                            Id          = id,
                            Version     = ver,
                            State       = NetworkConnection.State.Connected,
                            Address     = address,
                            Attempts    = 1,
                            LastAttempt = Timer.ElapsedMilliseconds
                        };
                        SetConnection(c);
                        AddConnection(c.Id);
                    }
                    else
                    {
                        c.Attempts++;
                        c.LastAttempt = Timer.ElapsedMilliseconds;
                        SetConnection(c);
                    }

                    SendPacket(UdpCProtocol.ConnectionAccept, new NetworkConnection {
                            m_NetworkId = c.Id, m_NetworkVersion = c.Version
                        });
                }
                break;

                case UdpCProtocol.ConnectionReject:
                {
                    // m_EventQ.Enqueue(Id, (int)NetworkEvent.Connect);
                }
                break;

                case UdpCProtocol.ConnectionAccept:
                {
                    Connection c = GetConnection(address);
                    if (c != Connection.Null)
                    {
                        if (c.State == NetworkConnection.State.Connected)
                        {
                            //DebugLog("Dropping connect request for an already connected endpoint [" + address + "]");
                            continue;
                        }
                        if (c.State == NetworkConnection.State.Connecting)
                        {
                            c.State = NetworkConnection.State.Connected;
                            UpdateConnection(c);
                            AddConnection(c.Id);
                        }
                    }
                }
                break;

                case UdpCProtocol.Disconnect:
                {
                    DebugLog("Disconnect packet received from " + address);
                    Connection c = GetConnection(address);
                    if (c != Connection.Null)
                    {
                        RemoveConnection(c);
                        AddDisconnection(c.Id);
                    }
                }
                break;

                case UdpCProtocol.Data:
                {
                    Connection c = GetConnection(address);
                    if (c == Connection.Null)
                    {
                        continue;
                    }

                    c.LastAttempt = Timer.ElapsedMilliseconds;
                    UpdateConnection(c);

                    if (c.State == NetworkConnection.State.Connecting)
                    {
                        c.State = NetworkConnection.State.Connected;
                        UpdateConnection(c);
                        AddConnection(c.Id);
                    }

                    var length = result - UdpCHeader.Length;
                    bs.IncreaseWritePtr(length);

                    m_EventQueue.PushEvent(new NetworkEvent
                        {
                            connectionId = c.Id,
                            type         = NetworkEvent.Type.Data,
                            offset       = sliceOffset,
                            size         = length
                        });
                }
                break;
                }
            }
        }
예제 #11
0
        public unsafe int ReceiveMessageEx(NetworkEndPoint local, void *iov, int iov_len, ref network_address remote)
        {
            var vec = stackalloc network_iovec[iov_len];

            int             totalLength = 0;
            NetworkEndPoint from;

            for (int i = 0; i < iov_len; i++)
            {
                int length;
                int result;

                vec[i] = UnsafeUtility.ReadArrayElement <network_iovec>(iov, i);

                if ((result = RecvFrom(local, vec[i].buf, out length, out from)) < 0)
                {
                    return(result);
                }

                Assert.IsTrue(from.family == NetworkFamily.IPC);
                vec[i].len   = length;
                totalLength += length;

                // TODO: Double check this works on ios as well.
#if (UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX)
                remote.family.sa_family = (byte)AddressFamily.Unspecified;
#else
                remote.family.sa_family = (ushort)AddressFamily.Unspecified;
#endif
                remote.ipc_handle = *(int *)from.address;
                remote.length     = 6;
            }

            return(totalLength);
        }
예제 #12
0
        public unsafe int SendMessageEx(NetworkEndPoint local, void *iov, int iov_len, ref network_address address)
        {
            var             vec = stackalloc network_iovec[iov_len];
            NetworkEndPoint endpoint;

            if (!TryGetEndPointByHandle(address.ipc_handle, out endpoint))
            {
                return(-1);
            }

            for (int i = 0; i < iov_len; i++)
            {
                vec[i] = UnsafeUtility.ReadArrayElement <network_iovec>(iov, i);
            }

            int length = 0;

            for (int i = 0; i < iov_len; i++)
            {
                int result;
                if ((result = SendTo(local, vec[i].buf, vec[i].len, endpoint)) < 0)
                {
                    return(result);
                }
                length += result;
            }

            return(length);
        }
예제 #13
0
 public unsafe int SendMessage(void *iov, int iov_len, ref network_address address)
 {
     return(SocketExtension.SendMessageEx(m_SocketHandle, iov, iov_len, ref address));
 }
예제 #14
0
 public unsafe int ReceiveMessage(void *iov, int iov_len, ref network_address address)
 {
     Assert.IsTrue(m_LocalEndPoint[0].family == NetworkFamily.IPC && m_LocalEndPoint[0].port != 0);
     return(IPCManager.Instance.ReceiveMessageEx(m_LocalEndPoint[0], iov, iov_len, ref address));
 }