internal static EngineIOPacket Decode(string Data) { try { EngineIOPacket Packet = new EngineIOPacket() { Type = (EngineIOPacketType)Data[0] - '0', IsText = true, IsBinary = false, }; if (Data.Length > 1) { Packet.Data = Data.Substring(1); Packet.RawData = Encoding.UTF8.GetBytes(Packet.Data); } return(Packet); } catch (Exception Exception) { EngineIOLogger.Error("Packet decoding failed. " + Data, Exception); return(CreateErrorPacket(Exception)); } }
internal static EngineIOPacket Decode(byte[] RawData) { try { Queue <byte> BufferQueue = new Queue <byte>(RawData); EngineIOPacket Packet = new EngineIOPacket() { Type = (EngineIOPacketType)BufferQueue.Dequeue(), IsText = false, IsBinary = true, }; if (BufferQueue.Count > 0) { Packet.RawData = BufferQueue.ToArray(); Packet.Data = BitConverter.ToString(Packet.RawData); } return(Packet); } catch (Exception Exception) { EngineIOLogger.Error("Packet decoding failed. " + RawData != null ? BitConverter.ToString(RawData) : string.Empty, Exception); return(CreateErrorPacket(Exception)); } }
private void Handshake(string TransportName, WebSocketContext Context) { void OnError() { Context.WebSocket.Close(CloseStatusCode.Abnormal, Exceptions.BAD_REQUEST.Message); } try { if (EngineIOHttpManager.IsWebSocket(TransportName)) { Handshake(Context.QueryString["sid"] ?? EngineIOSocketID.Generate(), new EngineIOWebSocket(Context)); } else { OnError(); } } catch (Exception Exception) { EngineIOLogger.Error(this, Exception); OnError(); } }
private void Handshake(string TransportName, HttpListenerRequest Request, HttpListenerResponse Response) { void OnError() { EngineIOHttpManager.SendErrorMessage(Request, Response, Exceptions.BAD_REQUEST); } try { if (EngineIOHttpManager.IsPolling(TransportName)) { EngineIOTransport Transport = new EngineIOPolling(Request); Transport.OnRequest(Request, Response); Handshake(EngineIOSocketID.Generate(), Transport); } else { OnError(); } } catch (Exception Exception) { EngineIOLogger.Error(this, Exception); OnError(); } }
private void Verify(WebSocketContext Context, Action <EngineIOException> Callback) { EngineIOException Return = null; bool AllowWebSocket = false; try { if ((Return = Verify(Context.QueryString, Context.Headers, EngineIOTransportType.websocket)) == null) { string SID = EngineIOHttpManager.GetSID(Context.QueryString); bool Contains = _Clients.ContainsKey(SID); if (!string.IsNullOrEmpty(SID)) { if (Contains && _Clients.TryGetValue(SID, out EngineIOSocket Socket)) { if (Socket.Transport is EngineIOPolling && Option.AllowUpgrade && Option.WebSocket && !(Socket.Upgrading || Socket.Upgraded)) { if (!(Socket.Upgrading || Socket.Upgraded)) { Socket.UpgradeTransport(new EngineIOWebSocket(Context)); AllowWebSocket = true; } else { Return = Exceptions.BAD_REQUEST; } } else { Return = Exceptions.BAD_REQUEST; } } else { Return = Exceptions.UNKNOWN_SID; } } else { if (Option.AllowWebSocket != null) { AllowWebSocket = true; Option.AllowWebSocket(Context, Callback); } } } } catch (Exception Exception) { EngineIOLogger.Error(this, Return = new EngineIOException("Unknown exception", Exception)); } finally { if (!AllowWebSocket) { Callback(Return); } } }
protected EngineIOTransport OnError(string Message, Exception Description) { EngineIOException Exception = new EngineIOException(Message, Description); EngineIOLogger.Error(this, Exception); Emit(Event.ERROR, Exception); return(this); }
private void Verify(HttpListenerRequest Request, Action <EngineIOException> Callback) { EngineIOException Return = null; bool AllowHttpRequest = false; try { if ((Return = Verify(Request.QueryString, Request.Headers, EngineIOTransportType.polling)) == null) { string SID = EngineIOHttpManager.GetSID(Request.QueryString); bool Contains = _Clients.ContainsKey(SID); if (string.IsNullOrEmpty(SID) || Contains) { if (Contains && !(_Clients[SID].Transport is EngineIOPolling)) { Return = Exceptions.BAD_REQUEST; } else if (EngineIOHttpManager.ParseMethod(Request.HttpMethod) == EngineIOHttpMethod.GET) { if (Option.AllowHttpRequest != null) { AllowHttpRequest = true; Option.AllowHttpRequest(Request, Callback); } } else if (string.IsNullOrEmpty(SID)) { Return = Exceptions.BAD_HANDSHAKE_METHOD; } } else { Return = Exceptions.UNKNOWN_SID; } } } catch (Exception Exception) { EngineIOLogger.Error(this, Return = new EngineIOException("Unknown exception", Exception)); } finally { if (!AllowHttpRequest) { Callback(Return); } } }
internal EngineIOTransport Send(params EngineIOPacket[] Packets) { if (Packets != null) { Writable = false; ThreadPool.QueueUserWorkItem((_) => { try { Semaphore.WaitOne(); if (ReadyState == EngineIOReadyState.OPEN) { try { foreach (EngineIOPacket Packet in Packets) { SendInternal(Packet); } } catch (Exception Exception) { EngineIOLogger.Error(this, Exception); } } else { EngineIOLogger.Error(this, new EngineIOException("Transport is not opened. ReadyState : " + ReadyState)); } Semaphore.Release(); Writable = true; } catch (Exception Exception) { OnError("Transport not sent.", Exception); } }); } return(this); }
private static EngineIOPacket[] Decode(Stream Stream, bool IsBinary) { List <EngineIOPacket> Result = new List <EngineIOPacket>(); object Temp = string.Empty; try { if (IsBinary) { using (MemoryStream MemoryStream = new MemoryStream()) { Stream.CopyTo(MemoryStream); Queue <byte> BufferQueue = new Queue <byte>(MemoryStream.ToArray()); if (BufferQueue.Contains(0xff)) { while (BufferQueue.Count > 0) { List <byte> RawBuffer = new List <byte>(); bool IsText = BufferQueue.Dequeue() == 0; StringBuilder Buffer = new StringBuilder(); int Size = 0; while (BufferQueue.Count > 0) { byte TempSize = BufferQueue.Dequeue(); if (TempSize < 0xff) { Buffer.Append(TempSize); } else { break; } } Size = int.Parse(Buffer.ToString()); Buffer.Clear(); for (int i = 0; i < Size; i++) { RawBuffer.Add(BufferQueue.Dequeue()); } if (IsText) { Result.Add(Decode(Encoding.UTF8.GetString(RawBuffer.ToArray()))); } else { Result.Add(Decode(RawBuffer.ToArray())); } } } } } else { using (StreamReader Reader = new StreamReader(Stream)) { string Content = (Temp = Reader.ReadToEnd()).ToString(); if (Content.Contains(':')) { while (Content.Length > 0) { StringBuilder Buffer = new StringBuilder(); int Size = 0; for (int i = 0; i < Content.Length; i++) { if (Content[i] != ':') { Buffer.Append(Content[i]); } else { break; } } Size = int.Parse(Buffer.ToString()); Content = Content.Substring(Buffer.Length + 1); Buffer.Clear(); for (int i = 0; i < Size; i++) { Buffer.Append(Content[i]); } Content = Content.Substring(Buffer.Length); string Data = Buffer.ToString(); if (Data.StartsWith("b")) { Result.Add(DecodeBase64String(Data)); } else { Result.Add(Decode(Data)); } } } } } } catch (Exception Exception) { EngineIOLogger.Error("Packet decoding failed. " + Temp, Exception); Result.Add(CreateErrorPacket(Exception)); } return(Result.ToArray()); }
internal void UpgradeTransport(EngineIOWebSocket Transport) { void OnTransportPacket(object Argument) { EngineIOPacket Packet = Argument as EngineIOPacket; if (Packet.Type == EngineIOPacketType.PING) { Transport.Send(EngineIOPacket.CreatePongPacket(Packet.Data)); Emit(Event.UPGRADING); ResetCheckTimer(); } else { Cleanup(); if (Packet.Type == EngineIOPacketType.UPGRADE && ReadyState != EngineIOReadyState.CLOSED) { this.Transport.Discard(); Upgraded = true; ClearTransport(); SetTransport(Transport); Emit(Event.UPGRADE); ResetPingTimer(); Flush(); if (ReadyState == EngineIOReadyState.CLOSING) { this.Transport.Close(() => { this.OnClose("Forced close."); }); } } else { Transport.Close(); } } } void Cleanup() { Upgrading = false; StopCheckTimer(); StopUpgradeTimer(); Transport.Off(EngineIOTransport.Event.PACKET, OnTransportPacket); Transport.Off(EngineIOTransport.Event.CLOSE, OnTransportClose); Transport.Off(EngineIOTransport.Event.ERROR, OnTransportError); } void OnTransportError(object Exception) { EngineIOLogger.Error(this, Exception as Exception); Cleanup(); Transport.Close(); } void OnTransportClose() { OnTransportError(new EngineIOException("Transport closed.")); } void OnClose() { OnTransportError(new EngineIOException("Socket closed.")); } Upgrading = true; StartUpgradeTimer(() => { Cleanup(); if (Transport.ReadyState == EngineIOReadyState.OPEN) { Transport.Close(); } }); Transport.On(EngineIOTransport.Event.PACKET, OnTransportPacket); Transport.Once(EngineIOTransport.Event.CLOSE, OnTransportClose); Transport.Once(EngineIOTransport.Event.ERROR, OnTransportError); Once(Event.CLOSE, OnClose); }