Beispiel #1
0
        private void Update()
        {
            switch (_readyState)
            {
            case ReadyState.OPEN:
            case ReadyState.CLOSING:
            case ReadyState.CONNECTING:
                if (!_context.IsValid())
                {
                    return;
                }

                _is_polling = true;
                do
                {
                    _is_servicing = false;
                    WSApi.lws_service(_context, 0);
                } while (_is_servicing);
                _is_polling = false;
                break;

            case ReadyState._CONSTRUCTED:
                Connect();
                break;
            }

            if (_is_context_destroying)
            {
                Destroy();
            }
        }
Beispiel #2
0
 private void SetClose()
 {
     if (_wsi.IsValid())
     {
         _is_closing = true;
         SetReadyState(ReadyState.CLOSING);
         WSApi.lws_callback_on_writable(_wsi);
         _wsi = lws.Null;
     }
     else
     {
         SetReadyState(ReadyState.CLOSED);
     }
 }
Beispiel #3
0
        // return -1 if error
        private int OnReceive(IntPtr @in, size_t len)
        {
            if (WSApi.lws_is_first_fragment(_wsi) == 1)
            {
                _buffer.writerIndex = 0;
            }
            _buffer.WriteBytes(@in, len);

            if (WSApi.lws_is_final_fragment(_wsi) == 1)
            {
                var is_binary = WSApi.lws_frame_is_binary(_wsi) == 1;
                if (is_binary)
                {
                    unsafe
                    {
                        fixed(byte *ptr = _buffer.data)
                        {
                            var val = JSApi.JS_NewArrayBufferCopy(_jsContext, ptr, _buffer.writerIndex);

                            CallScript("onmessage", val);
                            JSApi.JS_FreeValue(_jsContext, val);
                        }
                    }
                }
                else
                {
                    unsafe
                    {
                        _buffer.WriteByte(0); // make it null terminated
                        fixed(byte *ptr = _buffer.data)
                        {
                            var val = JSApi.JS_NewString(_jsContext, ptr);

                            CallScript("onmessage", val);
                            JSApi.JS_FreeValue(_jsContext, val);
                        }
                    }
                }
            }

            return(0);
        }
Beispiel #4
0
 // buffer: buffer for recv
 private WebSocket(ByteBuffer buffer, string url, List <string> protocols)
 {
     _url       = url;
     _buffer    = buffer;
     _protocols = protocols != null?protocols.ToArray() : new string[]
     {
         ""
     };
     _websockets.Add(this);
     do
     {
         if (_protocols != null && _protocols.Length > 0)
         {
             _context = WSApi.ulws_create(_protocols[0], _callback, 1024 * 4, 1024 * 4);
             if (_context.IsValid())
             {
                 SetReadyState(ReadyState._CONSTRUCTED);
                 break;
             }
         }
         SetReadyState(ReadyState.CLOSED);
     } while (false);
 }
Beispiel #5
0
        private void OnWrite()
        {
            if (_pending.Count > 0)
            {
                var packet   = _pending.Dequeue();
                var protocol = packet.is_binary ? lws_write_protocol.LWS_WRITE_BINARY : lws_write_protocol.LWS_WRITE_TEXT;
                var len      = packet.buffer.writerIndex - WSApi.LWS_PRE;

                unsafe
                {
                    fixed(byte *buf = packet.buffer.data)
                    {
                        WSApi.lws_write(_wsi, &buf[WSApi.LWS_PRE], len, protocol);
                    }
                }

                _bufferedAmount -= len;
                packet.Release();
                if (_pending.Count > 0)
                {
                    WSApi.lws_callback_on_writable(_wsi);
                }
            }
        }
Beispiel #6
0
        private static JSValue _js_send(JSContext ctx, JSValue this_obj, int argc, JSValue[] argv)
        {
            try
            {
                WebSocket self;
                if (!js_get_classvalue(ctx, this_obj, out self))
                {
                    throw new ThisBoundException();
                }
                if (argc == 0)
                {
                    throw new ParameterException("data", typeof(string), 0);
                }
                if (!self._wsi.IsValid() || !self._context.IsValid())
                {
                    return(JSApi.JS_ThrowInternalError(ctx, "websocket closed"));
                }

                if (argv[0].IsString())
                {
                    // send text data
                    size_t psize;
                    var    pointer = JSApi.JS_ToCStringLen(ctx, out psize, argv[0]);
                    if (pointer != IntPtr.Zero && psize > 0)
                    {
                        var buffer = ScriptEngine.AllocByteBuffer(ctx, psize + WSApi.LWS_PRE);
                        if (buffer != null)
                        {
                            buffer.WriteBytes(WSApi.LWS_PRE);
                            buffer.WriteBytes(pointer, psize);
                            self._pending.Enqueue(new Packet(false, buffer));
                            self._bufferedAmount += psize;
                            WSApi.lws_callback_on_writable(self._wsi);
                        }
                        else
                        {
                            JSApi.JS_FreeCString(ctx, pointer);
                            return(JSApi.JS_ThrowInternalError(ctx, "buf alloc failed"));
                        }
                    }
                    JSApi.JS_FreeCString(ctx, pointer);
                }
                else
                {
                    size_t psize;
                    var    pointer = JSApi.JS_GetArrayBuffer(ctx, out psize, argv[0]);
                    if (pointer != IntPtr.Zero && psize > 0)
                    {
                        var buffer = ScriptEngine.AllocByteBuffer(ctx, psize + WSApi.LWS_PRE);
                        if (buffer != null)
                        {
                            buffer.WriteBytes(WSApi.LWS_PRE);
                            buffer.WriteBytes(pointer, psize);
                            self._pending.Enqueue(new Packet(false, buffer));
                            self._bufferedAmount += psize;
                            WSApi.lws_callback_on_writable(self._wsi);
                        }
                        else
                        {
                            return(JSApi.JS_ThrowInternalError(ctx, "buf alloc failed"));
                        }
                    }
                    else
                    {
                        return(JSApi.JS_ThrowInternalError(ctx, "unknown buf type"));
                    }
                }

                return(JSApi.JS_UNDEFINED);
            }
            catch (Exception exception)
            {
                return(JSApi.ThrowException(ctx, exception));
            }
        }
Beispiel #7
0
        private async void Connect()
        {
            if (_readyState != ReadyState._CONSTRUCTED)
            {
                return;
            }
            SetReadyState(ReadyState._DNS);
            var uri            = new Uri(_url);
            var ssl_type       = uri.Scheme == "ws" ? ulws_ssl_type.ULWS_DEFAULT : ulws_ssl_type.ULWS_USE_SSL_ALLOW_SELFSIGNED;
            var protocol_names = QuickJS.Utils.TextUtils.GetNullTerminatedBytes(string.Join(",", _protocols));
            var path           = QuickJS.Utils.TextUtils.GetNullTerminatedBytes(uri.AbsolutePath);
            var host           = QuickJS.Utils.TextUtils.GetNullTerminatedBytes(uri.DnsSafeHost);
            var port           = uri.Port;

            switch (uri.HostNameType)
            {
            case UriHostNameType.IPv4:
            case UriHostNameType.IPv6:
            {
                var address = QuickJS.Utils.TextUtils.GetNullTerminatedBytes(uri.DnsSafeHost);
                SetReadyState(ReadyState.CONNECTING);
                unsafe
                {
                    fixed(byte *protocol_names_ptr = protocol_names)
                    fixed(byte *host_ptr    = host)
                    fixed(byte *address_ptr = address)
                    fixed(byte *path_ptr    = path)
                    {
                        WSApi.ulws_connect(_context, protocol_names_ptr, ssl_type, host_ptr, address_ptr, path_ptr, port);
                    }
                }
            }
            break;

            default:
            {
                var entry = await Dns.GetHostEntryAsync(uri.DnsSafeHost);

                if (_readyState != ReadyState._DNS)
                {
                    // already closed
                    return;
                }
                SetReadyState(ReadyState.CONNECTING);
                try
                {
                    var ipAddress = Select(entry.AddressList);
                    var address   = QuickJS.Utils.TextUtils.GetNullTerminatedBytes(ipAddress.ToString());
                    unsafe
                    {
                        fixed(byte *protocol_names_ptr = protocol_names)
                        fixed(byte *host_ptr    = host)
                        fixed(byte *address_ptr = address)
                        fixed(byte *path_ptr    = path)
                        {
                            WSApi.ulws_connect(_context, protocol_names_ptr, ssl_type, host_ptr, address_ptr, path_ptr, port);
                        }
                    }
                }
                catch (Exception exception)
                {
                    // UnityEngine.Debug.LogErrorFormat("{0}", exception);
                    SetReadyState(ReadyState.CLOSED);
                    OnError(exception);
                }
            }
            break;
            }
        }
Beispiel #8
0
        public static int _callback(lws wsi, lws_callback_reasons reason, IntPtr user, IntPtr @in, size_t len)
        {
            var context   = WSApi.lws_get_context(wsi);
            var websocket = GetWebSocket(context);

            if (websocket == null)
            {
                return(-1);
            }

            switch (reason)
            {
            case lws_callback_reasons.LWS_CALLBACK_CHANGE_MODE_POLL_FD:
            {
                return(0);
            }

            case lws_callback_reasons.LWS_CALLBACK_CLIENT_RECEIVE:
            {
                websocket._is_servicing = true;
                return(websocket.OnReceive(@in, len));
            }

            case lws_callback_reasons.LWS_CALLBACK_CLIENT_WRITEABLE:
            {
                websocket._is_servicing = true;
                if (websocket._is_closing)
                {
                    WSApi.lws_close_reason(wsi, lws_close_status.LWS_CLOSE_STATUS_NORMAL, "");
                    return(-1);
                }
                websocket.OnWrite();
                return(0);
            }

            case lws_callback_reasons.LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
            {
                return(0);
            }

            case lws_callback_reasons.LWS_CALLBACK_CLIENT_ESTABLISHED:
            {
                websocket._is_servicing = true;
                websocket._wsi          = wsi;
                websocket.OnConnect();         // _on_connect(websocket, lws_get_protocol(wsi)->name);
                return(0);
            }

            case lws_callback_reasons.LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
            {
                websocket._is_servicing = true;
                websocket.OnError(@in, len);
                websocket.Destroy();
                return(-1);
            }

            case lws_callback_reasons.LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
            {
                websocket._is_servicing = true;
                websocket.OnCloseRequest(@in, len);
                return(0);
            }

            case lws_callback_reasons.LWS_CALLBACK_CLIENT_CLOSED:
            {
                websocket.SetClose();         // _duk_lws_close(websocket);
                websocket.Destroy();
                websocket.OnClose();
                return(0);
            }

            default:
            {
                return(0);
            }
            }
        }