private async void SIOSocketReader()
    {
        bool haveIEverBeenConnected = false;

        while (!cTokenSrc.Token.IsCancellationRequested)
        {
            var message = "";
            var binary  = new List <byte>();

READ:
            var buffer = new byte[1024];
            WebSocketReceiveResult res = null;

            try
            {
                res = await Socket.ReceiveAsync(new ArraySegment <byte>(buffer), cTokenSrc.Token);

                if (cTokenSrc.Token.IsCancellationRequested)
                {
                    return;
                }
            }
            catch
            {
                if (Status != SIOStatus.CONNECTED)
                {
                    return;                                //Yeah, we already know. Wait for reconnect
                }
                //Something went wrong
                if (cTokenSrc.Token.IsCancellationRequested)
                {
                    return;
                }
                if (Status == SIOStatus.CONNECTED)
                {
                    Socket.Abort();
                }
                Status = SIOStatus.ERROR;
                SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent((haveIEverBeenConnected ? "disconnect" : (ReconnectAttempts > 0 ? "reconnect_error" : "connect_error")), (Socket.State == WebSocketState.CloseReceived || Socket.State == WebSocketState.Closed ? "transport close" : "transport error")); }));
                return;
            }

            if (res == null)
            {
                goto READ; //we got nothing. Wait for data.
            }
            if (res.MessageType == WebSocketMessageType.Close)
            {
                if (cTokenSrc.Token.IsCancellationRequested || Status != SIOStatus.CONNECTED)
                {
                    return;
                }
                Status = SIOStatus.ERROR;
                SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent((haveIEverBeenConnected ? "disconnect" : (ReconnectAttempts > 0 ? "reconnect_error" : "connect_error")), "transport close"); }));
                return;
            }
            else if (res.MessageType == WebSocketMessageType.Text)
            {
                if (!res.EndOfMessage)
                {
                    message += Encoding.UTF8.GetString(buffer).TrimEnd('\0');
                    goto READ;
                }
                message += Encoding.UTF8.GetString(buffer).TrimEnd('\0');

#if VERBOSE
                SocketIOManager.LogDebug("WS < " + message);
#endif

                SocketPacket packet = Decoder.Decode(message);

                switch (packet.enginePacketType)
                {
                case EnginePacketType.OPEN:
                    SocketOpenData sockData = JsonUtility.FromJson <SocketOpenData>(packet.json);
                    SocketID     = null;
                    pingInterval = sockData.pingInterval;
                    pingTimeout  = sockData.pingTimeout;

                    //Serialize Payload
                    string payload = "";
                    if (authPayload != null)
                    {
                        payload = authPayload.GetPayloadJSON();
                    }

                    //Hey Server, how are you today?
                    EmitPacket(new SocketPacket(EnginePacketType.MESSAGE, SocketPacketType.CONNECT, 0, "/", -1, payload));

                    SIODispatcher.Instance.Enqueue(new Action(() =>
                    {
                        RaiseSIOEvent("open");
                    }));
                    break;

                case EnginePacketType.CLOSE:
                    SIODispatcher.Instance.Enqueue(new Action(() =>
                    {
                        RaiseSIOEvent("close");
                    }));
                    break;

                case EnginePacketType.MESSAGE:
                    if (packet.socketPacketType == SocketPacketType.EVENT && packet.json == "")
                    {
                        buffer  = null;
                        message = "";
                        continue;
                    }

                    if (packet.socketPacketType == SocketPacketType.CONNECT)
                    {
                        //Extract socket id
                        string tmpExtractionSubstr = packet.json.Substring(packet.json.IndexOf("sid\":") + 4).Trim();
                        tmpExtractionSubstr = tmpExtractionSubstr.Substring(tmpExtractionSubstr.IndexOf("\"") + 1, tmpExtractionSubstr.IndexOf("}") - 1);
                        SocketID            = tmpExtractionSubstr.Substring(0, tmpExtractionSubstr.IndexOf("\""));

                        //invoke "connect" event
                        Status = SIOStatus.CONNECTED;
                        if (ReconnectAttempts > 0)
                        {
                            SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("reconnect", null); }));
                        }
                        SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("connect", null); }));
                        haveIEverBeenConnected = true;
                        ReconnectAttempts      = 0;
                    }
                    else if (packet.socketPacketType == SocketPacketType.DISCONNECT)
                    {
                        SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("disconnect", "io server disconnect"); }));
                        FinishOperation();
                    }
                    else if (packet.socketPacketType == SocketPacketType.ACK)
                    {
                        SocketIOManager.LogWarning("ACK is not supported by this library.");
                    }
                    else if (packet.socketPacketType == SocketPacketType.EVENT)
                    {
                        SIOEventStructure e = Parser.Parse(packet.json);
                        SIODispatcher.Instance.Enqueue(new Action(() =>
                        {
                            RaiseSIOEvent(e.eventName, e.data);
                        }));
                    }
                    break;

                case EnginePacketType.PING:
                    lastPing = DateTime.Now;
                    EmitPacket(new SocketPacket(EnginePacketType.PONG));
                    break;

                default:
                    SocketIOManager.LogWarning("Unhandled SIO packet: " + message);
                    break;
                }
            }
            else
            {
                if (!res.EndOfMessage)
                {
                    goto READ;
                }
                SocketIOManager.LogWarning("Received binary message");
            }
            buffer = null;
        }
    }
Exemple #2
0
    private async void SIOSocketReader()
    {
        while (!cTokenSrc.Token.IsCancellationRequested)
        {
            var message = "";
            var binary  = new List <byte>();

READ:
            var buffer = new byte[1024];
            WebSocketReceiveResult res = null;

            try
            {
                res = await Socket.ReceiveAsync(new ArraySegment <byte>(buffer), cTokenSrc.Token);

                if (cTokenSrc.Token.IsCancellationRequested)
                {
                    return;
                }
            }
            catch
            {
                //Something went wrong
                if (cTokenSrc.Token.IsCancellationRequested)
                {
                    return;
                }
                Status = SIOStatus.ERROR;
                SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("disconnect", "transport error"); }));
                Socket.Abort();
                break;
            }

            if (res == null)
            {
                goto READ; //we got nothing. Wait for data.
            }
            if (res.MessageType == WebSocketMessageType.Close)
            {
                Status = SIOStatus.DISCONNECTED;
                Close();
                SIODispatcher.Instance.Enqueue(new Action(() => { RaiseSIOEvent("disconnect", "io server disconnect"); }));
                return;
            }
            else if (res.MessageType == WebSocketMessageType.Text)
            {
                if (!res.EndOfMessage)
                {
                    message += Encoding.UTF8.GetString(buffer).TrimEnd('\0');
                    goto READ;
                }
                message += Encoding.UTF8.GetString(buffer).TrimEnd('\0');

                SocketPacket packet = Decoder.Decode(message);

                switch (packet.enginePacketType)
                {
                case EnginePacketType.OPEN:
                    SocketOpenData sockData = JsonUtility.FromJson <SocketOpenData>(packet.json);
                    SocketID     = sockData.sid;
                    pingInterval = sockData.pingInterval;
                    pingTimeout  = sockData.pingTimeout;

                    //Hey Server, how are you today?
                    EmitPacket(new SocketPacket(EnginePacketType.MESSAGE, SocketPacketType.CONNECT, 0, "/", -1, ""));

                    SIODispatcher.Instance.Enqueue(new Action(() =>
                    {
                        RaiseSIOEvent("open");
                    }));

                    ReconnectAttempts = 0;
                    break;

                case EnginePacketType.CLOSE:
                    SIODispatcher.Instance.Enqueue(new Action(() =>
                    {
                        RaiseSIOEvent("close");
                    }));
                    break;

                case EnginePacketType.MESSAGE:
                    if (packet.json == "")
                    {
                        buffer  = null;
                        message = "";
                        continue;
                    }

                    if (packet.socketPacketType == SocketPacketType.ACK)
                    {
                        SocketIOManager.LogWarning("ACK is not supported by this library.");
                    }

                    if (packet.socketPacketType == SocketPacketType.EVENT)
                    {
                        SIOEventStructure e = Parser.Parse(packet.json);
                        SIODispatcher.Instance.Enqueue(new Action(() =>
                        {
                            RaiseSIOEvent(e.eventName, e.data);
                        }));
                    }
                    break;

                case EnginePacketType.PING:
                    lastPing = DateTime.Now;
                    EmitPacket(new SocketPacket(EnginePacketType.PONG));
                    break;

                default:
                    SocketIOManager.LogWarning("Unhandled SIO packet: " + message);
                    break;
                }
            }
            else
            {
                if (!res.EndOfMessage)
                {
                    goto READ;
                }
                SocketIOManager.LogWarning("Received binary message");
            }
            buffer = null;
        }
    }