예제 #1
0
        public WebuSocket(
            string url,
            int baseReceiveBufferSize,
            Action OnConnected = null,
            Action <Queue <ArraySegment <byte> > > OnMessage = null,
            Action OnPinged = null,
            Action <WebuSocketCloseEnum> OnClosed              = null,
            Action <WebuSocketErrorEnum, Exception> OnError    = null,
            Dictionary <string, string> additionalHeaderParams = null
            )
        {
            this.webSocketConnectionId = Guid.NewGuid().ToString();
            this.baseReceiveBufferSize = baseReceiveBufferSize;

            this.base64Key = WebSocketByteGenerator.GeneratePrivateBase64Key();

            var requstBytesAndHostAndPort = GenerateRequestData(url, additionalHeaderParams, base64Key);

            this.endPoint = new IPEndPoint(IPAddress.Parse(requstBytesAndHostAndPort.host), requstBytesAndHostAndPort.port);

            this.OnConnected = OnConnected;
            this.OnMessage   = OnMessage;
            this.OnPinged    = OnPinged;
            this.OnClosed    = OnClosed;
            this.OnError     = OnError;

            StartConnectAsync(requstBytesAndHostAndPort.requestDataBytes);
        }
예제 #2
0
        public void Ping(Action OnPonged)
        {
            this.OnPonged = OnPonged;
            var pingBytes = WebSocketByteGenerator.Ping();

            socketToken.sendArgs.SetBuffer(pingBytes, 0, pingBytes.Length);
            if (!socketToken.socket.SendAsync(socketToken.sendArgs))
            {
                OnSend(socketToken.socket, socketToken.sendArgs);
            }
        }
예제 #3
0
        private void PingReceived()
        {
            if (OnPinged != null)
            {
                OnPinged();
            }

            var pongBytes = WebSocketByteGenerator.Pong();

            socketToken.sendArgs.SetBuffer(pongBytes, 0, pongBytes.Length);
            if (!socketToken.socket.SendAsync(socketToken.sendArgs))
            {
                OnSend(socketToken.socket, socketToken.sendArgs);
            }
        }
예제 #4
0
        private void StartCloseAsync()
        {
            var closeEventArgs = new SocketAsyncEventArgs();

            closeEventArgs.UserToken    = socketToken;
            closeEventArgs.AcceptSocket = socketToken.socket;

            var closeData = WebSocketByteGenerator.CloseData();

            closeEventArgs.SetBuffer(closeData, 0, closeData.Length);

            closeEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(OnDisconnected);

            if (!socketToken.socket.SendAsync(closeEventArgs))
            {
                OnDisconnected(socketToken.socket, closeEventArgs);
            }
        }
예제 #5
0
        public void Send(byte[] data)
        {
            if (socketToken.socketState != SocketState.OPENED)
            {
                WebuSocketErrorEnum ev    = WebuSocketErrorEnum.UNKNOWN_ERROR;
                Exception           error = null;
                switch (socketToken.socketState)
                {
                case SocketState.OPENING: {
                    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;
                }
                }
                if (OnError != null)
                {
                    OnError(ev, error);
                }
                return;
            }

            var payloadBytes = WebSocketByteGenerator.SendBinaryData(data);

            socketToken.sendArgs.SetBuffer(payloadBytes, 0, payloadBytes.Length);
            if (!socketToken.socket.SendAsync(socketToken.sendArgs))
            {
                OnSend(socketToken.socket, socketToken.sendArgs);
            }
        }
예제 #6
0
        private void OnReceived(object unused, SocketAsyncEventArgs args)
        {
            var token = (SocketToken)args.UserToken;

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

                default: {
                    // 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);
                    }

                    // connection is already closed.
                    if (!IsSocketConnected(token.socket))
                    {
                        if (OnClosed != null)
                        {
                            OnClosed(WebuSocketCloseEnum.CLOSED_WHILE_RECEIVING);
                        }
                        Disconnect();
                        return;
                    }

                    // continue receiving data. go to below.
                    break;
                }
                }
            }

            if (args.BytesTransferred == 0)
            {
                throw new Exception("failed to receive. args.BytesTransferred = 0.");
            }

            // update as read completed.
            token.readableDataLength = token.readableDataLength + args.BytesTransferred;

            switch (token.socketState)
            {
            case SocketState.OPENING: {
                var lineEndCursor = ReadUpgradeLine(args.Buffer, 0, token.readableDataLength);
                if (lineEndCursor != -1)
                {
                    var protocolData = new SwitchingProtocolData(Encoding.UTF8.GetString(args.Buffer, 0, lineEndCursor));
                    var expectedKey  = WebSocketByteGenerator.GenerateExpectedAcceptedKey(base64Key);

                    if (protocolData.securityAccept != expectedKey)
                    {
                        if (OnError != null)
                        {
                            var error = new Exception("WebSocket Key Unmatched.");
                            OnError(WebuSocketErrorEnum.CONNECTION_KEY_UNMATCHED, error);
                        }
                    }
                    token.socketState = SocketState.OPENED;

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

                    ReadyReceivingNewData(token);
                    return;
                }

                // should read next.
                ReceivingRestDataWithoutSort(token);
                return;
            }

            case SocketState.OPENED: {
                var result = ScanBuffer(token.receiveBuffer, token.readableDataLength);

                // read completed datas.
                if (0 < result.segments.Count)
                {
                    OnMessage(result.segments);
                }

                // if the last result index is matched to whole length, receive finished.
                if (result.lastDataTail == token.readableDataLength)
                {
                    ReadyReceivingNewData(token);
                    return;
                }

                // rest data exists.

                var alreadyReceivedDataLength = token.receiveBuffer.Length - result.lastDataTail;

                // should read rest.
                ReceivingRestData(token, result.lastDataTail, alreadyReceivedDataLength);
                return;
            }

            default: {
                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(true);
                return;
            }
            }
        }