Esempio n. 1
0
        private void PingReceived(byte[] data = null)
        {
            var pongBytes = WebSocketByteGenerator.Pong(data, false);

            Debug.Log("pingがきたのでpongを。");
            {
                try
                {
                    socketToken.socket.BeginSend(
                        pongBytes,
                        0,
                        pongBytes.Length,
                        SocketFlags.None,
                        result =>
                    {
                        var s   = (Socket)result.AsyncState;
                        var len = s.EndSend(result);
                        if (0 < len)
                        {
                            // do nothing.
                        }
                        else
                        {
                            Debug.LogError("send error:" + "pong failed by unknown reason.");
                            // // send failed.
                            // if (OnError != null)
                            // {
                            //     var error = new Exception("send error:" + "pong failed by unknown reason.");
                            //     OnError(WebuSocketErrorEnum.PONG_FAILED, error);
                            // }
                        }
                    },
                        socketToken.socket
                        );
                }
                catch (Exception e)
                {
                    Debug.Log("e:" + e);
                    // if (OnError != null)
                    // {
                    //     OnError(WebuSocketErrorEnum.PONG_FAILED, e);
                    // }
                    // Disconnect();
                }
            }

            Debug.Log("ping受けたことを書いてない");
            // if (OnPinged != null) OnPinged();
        }
Esempio n. 2
0
        public void Send(byte[] data)
        {
            if (socketToken.socketState != SocketState.OPENED)
            {
                WebuSocketErrorEnum ev    = WebuSocketErrorEnum.UNKNOWN_ERROR;
                Exception           error = null;
                switch (socketToken.socketState)
                {
                case SocketState.TLS_HANDSHAKING:
                case SocketState.WS_HANDSHAKING:
                {
                    ev    = WebuSocketErrorEnum.CONNECTING;
                    error = new Exception("send error:" + "not yet connected.");
                    break;
                }

                case SocketState.CLOSING:
                case SocketState.CLOSED:
                {
                    ev    = WebuSocketErrorEnum.ALREADY_DISCONNECTED;
                    error = new Exception("send error:" + "connection was already closed. please create new connection by new WebuSocket().");
                    break;
                }

                default:
                {
                    ev    = WebuSocketErrorEnum.CONNECTING;
                    error = new Exception("send error:" + "not yet connected.");
                    break;
                }
                }
                // if (OnError != null) OnError(ev, error);
                return;
            }

            var payloadBytes = WebSocketByteGenerator.SendBinaryData(data, false);

            {
                try
                {
                    socketToken.socket.BeginSend(
                        payloadBytes,
                        0,
                        payloadBytes.Length,
                        SocketFlags.None,
                        result =>
                    {
                        var s   = (Socket)result.AsyncState;
                        var len = s.EndSend(result);
                        if (0 < len)
                        {
                            // do nothing.
                        }
                        else
                        {
                            Debug.LogError("send error:" + "send failed by unknown reason.");
                            // // send failed.
                            // if (OnError != null)
                            // {
                            //     var error = new Exception("send error:" + "send failed by unknown reason.");
                            //     OnError(WebuSocketErrorEnum.SEND_FAILED, error);
                            // }
                        }
                    },
                        socketToken.socket
                        );
                }
                catch (Exception e)
                {
                    // disconnectをどう行うか。失敗をどうハンドルするか、今後考える必要がある。
                    // if (OnError != null)
                    // {
                    //     OnError(WebuSocketErrorEnum.SEND_FAILED, e);
                    // }
                    // Disconnect();
                }
            }
        }
Esempio n. 3
0
        private WebuSocketResults ScanBuffer(byte[] encedBuffer, long bufferLength)
        {
            receivedDataSegments.Clear();

            int cursor      = 0;
            int lastDataEnd = 0;

            while (cursor < bufferLength)
            {
                // first byte = fin(1), rsv1(1), rsv2(1), rsv3(1), opCode(4)
                var opCode = (byte)(encedBuffer[cursor++] & WebSocketByteGenerator.OPFilter);

                // second byte = mask(1), length(7)
                if (bufferLength < cursor)
                {
                    break;
                }

                // ignore mask bit.
                int length = encedBuffer[cursor++] & 0x7f;
                switch (length)
                {
                case 126:
                {
                    // next 2 byte is length data.
                    if (bufferLength < cursor + 2)
                    {
                        break;
                    }

                    length = (
                        (encedBuffer[cursor++] << 8) +
                        (encedBuffer[cursor++])
                        );
                    break;
                }

                case 127:
                {
                    // next 8 byte is length data.
                    if (bufferLength < cursor + 8)
                    {
                        break;
                    }

                    length = (
                        (encedBuffer[cursor++] << (8 * 7)) +
                        (encedBuffer[cursor++] << (8 * 6)) +
                        (encedBuffer[cursor++] << (8 * 5)) +
                        (encedBuffer[cursor++] << (8 * 4)) +
                        (encedBuffer[cursor++] << (8 * 3)) +
                        (encedBuffer[cursor++] << (8 * 2)) +
                        (encedBuffer[cursor++] << 8) +
                        (encedBuffer[cursor++])
                        );
                    break;
                }

                default:
                {
                    // other.
                    break;
                }
                }

                // サーバ側はクライアントがセットしたdecKey分の4byteのデータを取り出す。
                if (bufferLength < cursor + 4)
                {
                    break;
                }

                var decKey = new byte[4];
                decKey[0] = encedBuffer[cursor++];
                decKey[1] = encedBuffer[cursor++];
                decKey[2] = encedBuffer[cursor++];
                decKey[3] = encedBuffer[cursor++];

                // read payload data.
                if (bufferLength < cursor + length)
                {
                    break;
                }

                // payload is fully contained!
                switch (opCode)
                {
                case WebSocketByteGenerator.OP_CONTINUATION:
                {
                    if (continuationBuffer == null)
                    {
                        continuationBuffer = new byte[baseReceiveBufferSize];
                    }
                    if (continuationBuffer.Length <= continuationBufferIndex + length)
                    {
                        Array.Resize(ref continuationBuffer, continuationBufferIndex + length);
                    }

                    // pool data to continuation buffer.
                    WebSocketByteGenerator.Unmasked(ref encedBuffer, decKey, cursor, length);
                    Buffer.BlockCopy(encedBuffer, cursor, continuationBuffer, continuationBufferIndex, length);
                    continuationBufferIndex += length;
                    break;
                }

                case WebSocketByteGenerator.OP_TEXT:
                case WebSocketByteGenerator.OP_BINARY:
                {
                    if (continuationBufferIndex == 0)
                    {
                        // unmask enced buffer.
                        WebSocketByteGenerator.Unmasked(ref encedBuffer, decKey, cursor, length);
                        receivedDataSegments.Enqueue(new ArraySegment <byte>(encedBuffer, cursor, length));
                    }
                    else
                    {
                        if (continuationBuffer.Length <= continuationBufferIndex + length)
                        {
                            Array.Resize(ref continuationBuffer, continuationBufferIndex + length);
                        }

                        WebSocketByteGenerator.Unmasked(ref encedBuffer, decKey, cursor, length);
                        Buffer.BlockCopy(encedBuffer, cursor, continuationBuffer, continuationBufferIndex, length);
                        continuationBufferIndex += length;

                        receivedDataSegments.Enqueue(new ArraySegment <byte>(continuationBuffer, 0, continuationBufferIndex));

                        // reset continuationBuffer index.
                        continuationBufferIndex = 0;
                    }
                    break;
                }

                case WebSocketByteGenerator.OP_CLOSE:
                {
                    CloseReceived();
                    break;
                }

                case WebSocketByteGenerator.OP_PING:
                {
                    /*
                     *  if client sent ping data with application data, open it.
                     */
                    if (0 < length)
                    {
                        var data = new byte[length];
                        WebSocketByteGenerator.Unmasked(ref encedBuffer, decKey, cursor, length);
                        Buffer.BlockCopy(encedBuffer, cursor, data, 0, length);
                        PingReceived(data);
                    }
                    else
                    {
                        PingReceived();
                    }
                    break;
                }

                case WebSocketByteGenerator.OP_PONG:
                {
                    /*
                     *  if client sent pong with application data, open it.
                     */
                    if (0 < length)
                    {
                        var data = new byte[length];
                        WebSocketByteGenerator.Unmasked(ref encedBuffer, decKey, cursor, length);
                        Buffer.BlockCopy(encedBuffer, cursor, data, 0, length);
                        // PongReceived(data);
                    }
                    else
                    {
                        // PongReceived();
                    }
                    Debug.LogError("pong received, but unable to handle it now.");
                    break;
                }

                default:
                {
                    break;
                }
                }

                cursor = cursor + length;

                // set end of data.
                lastDataEnd = cursor;
            }

            // finally return payload data indexies.
            return(new WebuSocketResults(receivedDataSegments, lastDataEnd));
        }
Esempio n. 4
0
        private void OnReceived(object unused, SocketAsyncEventArgs args)
        {
            var token = (ServerSocketToken)args.UserToken;

            if (args.SocketError != SocketError.Success)
            {
                lock (lockObj)
                {
                    switch (token.socketState)
                    {
                    case SocketState.CLOSING:
                    case SocketState.CLOSED:
                    {
                        // already closing, ignore.
                        return;
                    }

                    default:
                    {
                        Debug.LogError("receive error:" + args.SocketError.ToString() + " size:" + args.BytesTransferred);
                        // // show error, then close or continue receiving.
                        // if (OnError != null)
                        // {
                        //     var error = new Exception("receive error:" + args.SocketError.ToString() + " size:" + args.BytesTransferred);
                        //     OnError(WebuSocketErrorEnum.RECEIVE_FAILED, error);
                        // }
                        // Disconnect();
                        return;
                    }
                    }
                }
            }

            if (args.BytesTransferred == 0)
            {
                // Debug.LogError("failed to receive. args.BytesTransferred = 0." + " args.SocketError:" + args.SocketError);
                // if (OnError != null)
                // {
                //     var error = new Exception("failed to receive. args.BytesTransferred = 0." + " args.SocketError:" + args.SocketError);
                //     OnError(WebuSocketErrorEnum.RECEIVE_FAILED, error);
                // }
                // Disconnect();
                return;
            }

            switch (token.socketState)
            {
            case SocketState.WS_HANDSHAKING:
            {
                var receivedData = new byte[args.BytesTransferred];
                Buffer.BlockCopy(args.Buffer, 0, receivedData, 0, receivedData.Length);


                var index  = 0;
                var length = args.BytesTransferred;
                if (webSocketHandshakeResult == null)
                {
                    webSocketHandshakeResult = new byte[args.BytesTransferred];
                }
                else
                {
                    index = webSocketHandshakeResult.Length;
                    // already hold some bytes, and should expand for holding more decrypted data.
                    Array.Resize(ref webSocketHandshakeResult, webSocketHandshakeResult.Length + length);
                }
                Buffer.BlockCopy(args.Buffer, 0, webSocketHandshakeResult, index, length);


                if (0 < webSocketHandshakeResult.Length)
                {
                    // clients.Add(new Client(stream, clientRequestHeaders, clientSecret));

                    var lineEndCursor = ReadUpgradeLine(webSocketHandshakeResult, 0, webSocketHandshakeResult.Length);
                    if (lineEndCursor != -1)
                    {
                        var baseStr = Encoding.UTF8.GetString(webSocketHandshakeResult);
                        var lines   = baseStr.Replace("\r\n", "\n").Split('\n');

                        var clientRequestHeaders = new Dictionary <string, string>();
                        foreach (var line in lines)
                        {
                            if (line.Length == 0 || string.IsNullOrEmpty(line))
                            {
                                continue;
                            }

                            // ignore fixed info.
                            switch (line)
                            {
                            case "GET / HTTP/1.1":
                            case "Upgrade: websocket":
                            case "Connection: Upgrade":
                            case "Sec-WebSocket-Version: 13":
                                // ignore.
                                break;

                            default:
                                if (line.StartsWith("Host:"))
                                {
                                    continue;
                                }

                                if (line.StartsWith("Sec-WebSocket-Key: "))
                                {
                                    clientSecret = line.Substring("Sec-WebSocket-Key: ".Length);
                                    continue;
                                }

                                // rest is request header parameters.
                                if (line.Contains(":"))
                                {
                                    var keyAndVal = line.Split(':');
                                    clientRequestHeaders[keyAndVal[0]] = keyAndVal[1];
                                }
                                break;
                            }
                        }

                        if (string.IsNullOrEmpty(clientSecret))
                        {
                            Debug.LogError("received connection is not valid.");
                            return;
                        }

                        // foreach (var a in clientRequestHeaders)
                        // {
                        //     Debug.Log("a:" + a.Key + " v:" + a.Value);
                        // }

                        /*
                         *  Sec-WebSocket-Key(key) の末尾の空白を覗いた値を準備
                         *  key に固定値 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" を連結
                         *  sha1 を取得
                         *  base64 に変換
                         */

                        var acceptedSecret = WebSocketByteGenerator.GenerateExpectedAcceptedKey(clientSecret);

                        // generate response.
                        var responseStr =
                            @"HTTP/1.1 101 Switching Protocols
Server: webusocket
Date: " + DateTime.UtcNow +
                            @"Connection: upgrade
Upgrade: websocket
Sec-WebSocket-Accept: " + acceptedSecret + "\r\n\r\n";
                        var responseBytes = Encoding.UTF8.GetBytes(responseStr);

                        token.socket.BeginSend(
                            responseBytes,
                            0,
                            responseBytes.Length,
                            SocketFlags.None,
                            result =>
                            {
                                var s   = (Socket)result.AsyncState;
                                var len = s.EndSend(result);

                                var clientId = Guid.NewGuid().ToString();

                                token.socketState      = SocketState.OPENED;
                                this.RequestHeaderDict = clientRequestHeaders;

                                if (OnConnected != null)
                                {
                                    OnConnected(this);
                                }

                                var afterHandshakeDataIndex = lineEndCursor + 1;        // after last crlf.


                                /*
                                 *  ready buffer data.
                                 */
                                wsBuffer   = new byte[baseReceiveBufferSize];
                                wsBufIndex = 0;


                                /*
                                 *  if end cursor of handshake is not equal to holded data length, received data is already contained.
                                 */
                                if (webSocketHandshakeResult.Length == afterHandshakeDataIndex)
                                {
                                    // no extra data exists.

                                    // ready for receiving websocket data.
                                    ReadyReceivingNewData(token);
                                    return;
                                }
                                else
                                {
                                    wsBufLength = webSocketHandshakeResult.Length - afterHandshakeDataIndex;

                                    if (wsBuffer.Length < wsBufLength)
                                    {
                                        Array.Resize(ref wsBuffer, wsBufLength);
                                    }

                                    Buffer.BlockCopy(webSocketHandshakeResult, afterHandshakeDataIndex, wsBuffer, 0, wsBufLength);

                                    ReadBuffer(token);
                                }
                            },
                            socketToken.socket
                            );
                        return;
                    }
                }

                // continue receiveing websocket handshake data.
                ReadyReceivingNewData(token);
                return;
            }

            case SocketState.OPENED:
            {
                var additionalLen = args.BytesTransferred;

                if (wsBuffer.Length < wsBufIndex + additionalLen)
                {
                    Array.Resize(ref wsBuffer, wsBufIndex + additionalLen);
                    // resizeイベント発生をどう出すかな〜〜
                }

                Buffer.BlockCopy(args.Buffer, 0, wsBuffer, wsBufIndex, additionalLen);
                wsBufLength = wsBufLength + additionalLen;

                ReadBuffer(token);
                return;
            }

            default:
            {
                Debug.LogError("fatal error, could not detect error, receive condition is strange, token.socketState:" + token.socketState);
                // var error = new Exception("fatal error, could not detect error, receive condition is strange, token.socketState:" + token.socketState);
                // if (OnError != null) OnError(WebuSocketErrorEnum.RECEIVE_FAILED, error);
                // Disconnect();
                return;
            }
            }
        }