public static bool CheckHandshake(Context context) { if(context.ReceivedByteCount > 8) { var AHandshake = new ClientHandshake(context.Header); // See if our header had the required information if (AHandshake.IsValid()) { // Optionally check Origin and Location if they're set. if (Origin != string.Empty && AHandshake.Origin != "http://" + Origin) { return false; } if (Location != string.Empty && AHandshake.Host != string.Format("{0}:{1}", Location, context.Server.Port)) { return false; } // Generate response handshake for the client var serverShake = GenerateResponseHandshake(AHandshake); // Send the response handshake SendServerHandshake(serverShake, context); return true; } } return false; }
/// <summary> /// Sends the specified data. /// </summary> /// <param name="data">The data.</param> /// <param name="context">The user context.</param> /// <param name="close">if set to <c>true</c> [close].</param> public override void Send(byte[] data, Context context, bool close = false) { AsyncCallback ACallback = EndSend; if (close) { ACallback = EndSendAndClose; } context.SendReady.Wait(); try { context.Connection.Client.BeginSend(data, 0, data.Length, SocketFlags.None, ACallback, context); } catch { context.SendReady.Release(); } }
/// <summary> /// Processes the header. /// </summary> /// <param name="context">The user context.</param> public void ProcessHeader(Context context) { string data = context.UserContext.Encoding.GetString(context.Buffer, 0, context.ReceivedByteCount); //Check first to see if this is a flash socket XML request. if (data == "<policy-file-request/>\0") { try { //if it is, we access the Access Policy Server instance to send the appropriate response. context.Server.AccessPolicyServer.SendResponse(context.Connection); } catch {} context.Dispose(); } else//If it isn't, process http/websocket header as normal. { context.Header = new Header(data); switch (context.Header.Protocol) { case Protocol.WebSocket: context.Handler = WebSocketHandler.Instance; break; case Protocol.FlashSocket: context.Handler = WebSocketHandler.Instance; break; default: context.Header.Protocol = Protocol.None; break; } if (context.Header.Protocol != Protocol.None) { context.Handler.HandleRequest(context); } else { context.UserContext.Send(Response.NotImplemented, true); } } }
/// <summary> /// Handles the initial request. /// Attempts to process the header that should have been sent. /// Otherwise, through magic and wizardry, the client gets disconnected. /// </summary> /// <param name="context">The user context.</param> public override void HandleRequest(Context context) { if (context.IsSetup) { context.Dispose(); } else { ProcessHeader(context); } }
public abstract void Send(byte[] data, Context context, bool close = false);
public abstract void HandleRequest(Context request);
/// <summary> /// Runs the client. /// Sets up the UserContext. /// Executes in it's own thread. /// Utilizes a semaphore(ReceiveReady) to limit the number of receive events active for this client to 1 at a time. /// </summary> /// <param name="result">The A result.</param> private void RunClient(IAsyncResult result) { TcpClient connection = null; try { if (_listener != null) { connection = _listener.EndAcceptTcpClient(result); } } catch (Exception e) { Log.Debug("Connect failed", e); } _connectReady.Release(); if (connection == null) { return; } _clientLock.Wait(); ClientCount++; _clientLock.Release(); using (var context = new Context()) { context.Server = this; context.Connection = connection; context.BufferSize = DefaultBufferSize; context.UserContext.ClientAddress = context.Connection.Client.RemoteEndPoint; context.UserContext.SetOnConnect(DefaultOnConnect); context.UserContext.SetOnDisconnect(DefaultOnDisconnect); context.UserContext.SetOnSend(DefaultOnSend); context.UserContext.SetOnReceive(DefaultOnReceive); context.UserContext.OnConnect(); try { while (context.Connection.Connected) { if (context.ReceiveReady.Wait(TimeOut)) { context.Connection.Client.BeginReceive(context.Buffer, 0, context.Buffer.Length, SocketFlags.None, DoReceive, context); } else { break; } } } catch (Exception e) { Log.Debug("Client Forcefully Disconnected", e); } } _clientLock.Wait(); ClientCount--; _clientLock.Release(); }
/// <summary> /// Initializes a new instance of the <see cref="UserContext"/> class. /// </summary> /// <param name="context">The user context.</param> public UserContext(Context context) { _context = context; Header = _context.Header; }
private static void SendServerHandshake(ServerHandshake aHandshake, Context context) { // generate a byte array representation of the handshake including the answer to the challenge byte[] handshakeBytes = context.UserContext.Encoding.GetBytes(aHandshake.ToString()); context.UserContext.SendRaw(handshakeBytes); }
/// <summary> /// Attempts to authenticates the specified user context. /// If authentication fails it kills the connection. /// </summary> /// <param name="context">The user context.</param> private void Authenticate(Context context) { if (WebSocketAuthentication.CheckHandshake(context)) { context.UserContext.Protocol = context.Header.Protocol; context.UserContext.RequestPath = context.Header.RequestPath; context.Header = null; context.IsSetup = true; } else { context.Dispose(); } }
/// <summary> /// Sends the specified data. /// </summary> /// <param name="data">The data.</param> /// <param name="context">The user context.</param> /// <param name="close">if set to <c>true</c> [close].</param> public override void Send(byte[] data, Context context, bool close = false) { var dataFrameBytes = new DataFrame(data).ToBytes(); AsyncCallback aCallback = EndSend; if (close) { aCallback = EndSendAndClose; } context.SendReady.Wait(); try { context.Connection.Client.BeginSend(dataFrameBytes, 0, dataFrameBytes.Length, SocketFlags.None, aCallback, context); } catch { context.SendReady.Release(); } }
/// <summary> /// Handles the request. /// </summary> /// <param name="context">The user context.</param> public override void HandleRequest(Context context) { if (context.IsSetup) { context.UserContext.DataFrame.Append(context.Buffer, context.ReceivedByteCount); if (context.UserContext.DataFrame.State == DataFrame.DataState.Complete) { context.UserContext.OnReceive(); } } else { Authenticate(context); } }