void Initialize(ushort port)
        {
            // initialize native layer
            int initialize = NativeBindings.network_initialize();

            if (initialize == 0)
            {
                Debug.Log("network_initialized");

                // create the socket and listen on IPv6 and IPv4 via DualMode
                int             error   = 0;
                byte[]          bytes   = IPAddress.IPv6Any.GetAddressBytes();
                NetworkEndPoint address = NetworkEndPoint.CreateIPv6(bytes, port);
                if (NativeBindings.network_create_socket(ref listener, ref address, ref error) == 0)
                {
                    // try to enable dual mode to support both IPv6 and IPv4
                    if (NativeBindings.network_set_dualmode(listener, 1, ref error) != 0)
                    {
                        Debug.LogError("network_set_dualmode failed: " + (NativeError)error);
                    }

                    // bind the socket
                    if (NativeBindings.network_bind(listener, ref address, ref error) == 0)
                    {
                        // configure the socket
                        ConfigureSocket(listener);
                    }
                    else
                    {
                        Debug.LogError("network_bind failed: " + (NativeError)error);
                    }
                }
                else
                {
                    Debug.LogError("network_create_socket failed: " + (NativeError)error);
                }
            }
            else
            {
                Debug.LogError("network_initialize failed: " + initialize);
            }
        }
        // try to accept the next connection
        bool AcceptNext(out long socket)
        {
            socket = -1;
            int             error         = 0;
            NetworkEndPoint clientAddress = new NetworkEndPoint();

            if (NativeBindings.network_accept(listener, ref socket, ref clientAddress, ref error) == 0)
            {
                //Debug.Log("network_accept: " + socket + " address=" + clientAddress);
                return(true);
            }
            // log error if unusual
            // (ignore EWOULDBLOCK, which is expected for nonblocking sockets)
            // (http://www.workers.com.br/manuais/53/html/tcp53/mu/mu-7.htm)
            else if ((NativeError)error != NativeError.EWOULDBLOCK)
            {
                Debug.LogError("network_accept failed: " + (NativeError)error);
            }

            return(false);
        }
        // the connect thread function
        void ConnectThreadFunction(NetworkEndPoint address)
        {
            // absolutely must wrap with try/catch, otherwise thread
            // exceptions are silent
            try
            {
                // connect (blocking)
                int error = 0;
                if (NativeBindings.network_connect(socket, ref address, ref error) == 0)
                {
                    // configure the socket
                    ConfigureSocket(socket);

                    // connect successful
                    // AFTER configuring the socket. so that we don't call recv
                    // while still blocking!
                    Debug.Log("[Client] connected!");
                    lock (this) { _Connected = true; }
                }
                // log errors if failed.
                // (ECONNABORTED is expected if we call Disconnect while connecting)
                else if ((NativeError)error != NativeError.ECONNABORTED)
                {
                    Debug.LogError("network_connect failed: " + (NativeError)error);
                }
            }
            catch (Exception exception)
            {
                // something went wrong. probably important.
                Debug.LogError("[Client] Connect Exception: " + exception);
            }
            finally
            {
                // we definitely aren't connecting anymore. either it worked or
                // it failed.
                lock (this) { _Connecting = false; }
            }
        }
 // client's ip is sometimes needed by the server, e.g. for bans
 public unsafe string GetClientAddress(int connectionId)
 {
     // find the connection
     if (clients.TryGetValue(connectionId, out ClientToken token) &&
         token.socket != -1)
     {
         int error = 0;
         // NetworkEndPoint NEEDS to be created with length, otherwise
         // data array is empty and get_peer_address won't write into it
         NetworkEndPoint address = new NetworkEndPoint {
             length = sizeof(NetworkEndPoint)
         };
         if (NativeBindings.network_get_peer_address(token.socket, ref address, ref error) == 0)
         {
             return(address.Ip);
         }
         else
         {
             Debug.LogError("network_get_socket_address failed: " + (NativeError)error);
         }
     }
     return("");
 }
        public void Connect(string hostname, ushort port)
        {
            // not if already started
            if (Connecting || Connected)
            {
                return;
            }

            // create 'N' content buffers
            contentBuffers = new byte[MaxReceivesPerTickPerConnection][];
            for (int i = 0; i < contentBuffers.Length; ++i)
            {
                // create content buffer depending on configured MaxMessageSize
                contentBuffers[i] = new byte[MaxMessageSize];
            }

            // reset state
            lastConnected = false;
            contentSize   = 0;

            // resolve host name (if hostname. otherwise it returns the IP)
            // and connect to the first available address (IPv4 or IPv6)
            // => GetHostAddresses is BLOCKING (for a very short time). we could
            //    move it to the ConnectThread, but it's hardly worth the extra
            //    code since we would have to create the socket in ConnectThread
            //    too, which would require us to use locks around socket every-
            //    where. it's better to live with a <1s block (if any).
            try
            {
                IPAddress[] addresses = Dns.GetHostAddresses(hostname);
                if (addresses.Length > 0)
                {
                    // try to parse the IP
                    string ip = addresses[0].ToString();
                    if (NetworkEndPoint.TryParse(ip, port, out NetworkEndPoint address))
                    {
                        // create the socket
                        int error = 0;
                        if (NativeBindings.network_create_socket(ref socket, ref address, ref error) == 0)
                        {
                            // note: no need to enable DualMode because we
                            // connect to IPv4 or IPv6 depending on 'hostname'
                            // and then we don't reuse the socket.

                            // we are connecting
                            _Connecting = true; // thread isn't running, no lock needed!
                            Debug.Log("[Client] connecting to: " + ip);

                            // connect is blocking. let's call it in the thread and
                            // return immediately.
                            connectThread = new Thread(() => { ConnectThreadFunction(address); });
                            connectThread.IsBackground = true;
                            connectThread.Start();
                        }
                        else
                        {
                            Debug.LogError("network_create_socket failed: " + (NativeError)error);
                        }
                    }
                    else
                    {
                        Debug.LogError("[Client] Connect: failed to parse ip: " + ip + " port: " + port);
                    }
                }
                // it's not an error. just an invalid host so log a warning.
                else
                {
                    Debug.LogWarning("[Client] Connect: failed to resolve host: " + hostname + " (no address found)");
                }
            }
            catch (SocketException exception)
            {
                // it's not an error. just an invalid host so log a warning.
                Debug.LogWarning("[Client] Connect: failed to resolve host: " + hostname + " reason: " + exception);
            }
        }