public Connection(Socket socket, Server server) { this.socket = socket; this.server = server; server.AllocateBuffers (out receive_buffer, out send_buffer); }
public Record (Socket socket, Buffers receive_buffer) : this() { if (socket == null) throw new ArgumentNullException ("socket"); CompatArraySegment<byte> header_buffer = receive_buffer.EnforceHeaderLength (HeaderSize); // Read the 8 byte record header. NRecord.ReceiveAll (socket, header_buffer, HeaderSize); // Read the values from the data. version = header_buffer [0]; type = (RecordType) header_buffer [1]; request_id = NRecord.ReadUInt16 (header_buffer, 2); BodyLength = NRecord.ReadUInt16 (header_buffer, 4); byte padding_length = header_buffer [6]; CompatArraySegment<byte> body_buffer = receive_buffer.EnforceBodyLength (BodyLength); // Read the record data, and throw an exception if the // complete data cannot be read. if (BodyLength > 0) NRecord.ReceiveAll (socket, body_buffer, BodyLength); CompatArraySegment<byte> padding_buffer = receive_buffer.EnforcePaddingLength (padding_length); if(padding_length > 0) NRecord.ReceiveAll(socket, padding_buffer, padding_length); buffers = receive_buffer; Logger.Write (LogLevel.Debug, Strings.Record_Received, Type, RequestID, BodyLength); }
public static Record Receive (Socket socket, Buffers buffers) { if (socket == null) throw new ArgumentNullException ("socket"); CompatArraySegment<byte> header_buffer = buffers.EnforceHeaderLength (HEADER_SIZE); // Read the 8 byte record header. ReceiveAll (socket, header_buffer, HEADER_SIZE); // Read the values from the data. var version = header_buffer [0]; var type = (RecordType) header_buffer [1]; var requestID = ReadUInt16 (header_buffer, 2); var bodyLength = ReadUInt16 (header_buffer, 4); byte padding_length = header_buffer [6]; CompatArraySegment<byte> body_buffer = buffers.EnforceBodyLength (bodyLength); // Read the record data, and throw an exception if the // complete data cannot be read. if (bodyLength > 0) ReceiveAll (socket, body_buffer, bodyLength); CompatArraySegment<byte> padding_buffer = buffers.EnforcePaddingLength (padding_length); if(padding_length > 0) ReceiveAll(socket, padding_buffer, padding_length); Logger.Write (LogLevel.Debug, Strings.Record_Received, type, requestID, bodyLength); return new Record (version, type, requestID, bodyLength, buffers); }
public Server(Socket socket) { if (socket == null) throw new ArgumentNullException ("socket"); this.listen_socket = socket; }
public Server (Socket socket) { if (socket == null) throw new ArgumentNullException ("socket"); BigBufferManager = new BufferManager (4 * 1024); //4k SmallBufferManager = new BufferManager (8); backend = new GenericServer<ConnectionProxy> (socket, new ServerProxy (this)); backend.RequestReceived += RequestReceived; }
public Connection(Socket socket, Server server) { if (socket == null) throw new ArgumentNullException ("socket"); if (server == null) throw new ArgumentNullException ("server"); this.socket = socket; this.server = server; server.AllocateBuffers (out receive_buffer, out send_buffer); }
public Connection (Socket socket, Server server) { if (socket == null) throw new ArgumentNullException ("socket"); if (server == null) throw new ArgumentNullException ("server"); this.socket = socket; this.server = server; receive_buffers = new Buffers(server.BigBufferManager, server.SmallBufferManager); send_buffers = new Buffers (server.BigBufferManager, server.SmallBufferManager); }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="Record" /> by reading the contents from a specified /// socket. /// </summary> /// <param name="socket"> /// A <see cref="Socket" /> object to receive the record data /// from. /// </param> /// <remarks> /// To improve performance, consider using a buffer and /// <see cref="Record(Socket,byte[])" /> instead. /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="socket" /> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="socket" /> does not contain a complete /// record. /// </exception> public Record (Socket socket) : this (socket, null) { }
internal ConnectionProxy OnAccept (Socket socket) { return new ConnectionProxy (new Connection (socket, this)); }
public void Send (Socket socket) { var padding_size = (byte) ((8 - (BodyLength % 8)) % 8); CompatArraySegment<byte> header = Content.EnforceHeaderLength (HEADER_SIZE); header [0] = Version; header [1] = (byte) Type; header [2] = (byte) (RequestID >> 8); header [3] = (byte) (RequestID & 0xFF); header [4] = (byte) (BodyLength >> 8); header [5] = (byte) (BodyLength & 0xFF); header [6] = padding_size; CompatArraySegment<byte> padding = Content.EnforcePaddingLength (padding_size); for (int i = 0; i < padding_size; i ++) padding [i] = 0; Logger.Write (LogLevel.Debug, Strings.Record_Sent, Type, RequestID, BodyLength); SendAll (socket, header, HEADER_SIZE); SendAll (socket, Content.Body, BodyLength); SendAll (socket, padding, padding_size); }
public void Run() { Logger.Write (LogLevel.Notice, Strings.Connection_BeginningRun); if (socket == null) { Logger.Write (LogLevel.Notice, Strings.Connection_NoSocketInRun); return; } do { Record record; try { record = new Record (socket, receive_buffer); } catch (System.Net.Sockets.SocketException) { StopRun (Strings.Connection_RecordNotReceived); Stop (); break; } Request request = GetRequest (record.RequestID); HandleRequest (record, request); } while (!stop && (UnfinishedRequests || keep_alive)); if (requests.Count == 0) { lock (connection_teardown_lock) { try { if (socket != null) socket.Close (); } catch (System.Net.Sockets.SocketException e) { // Ignore: "The descriptor is not a socket" // error from UnmanagedSocket.Close if (e.ErrorCode != 10038) throw; // Rethrow other errors } finally { socket = null; } if (!stop) server.EndConnection (this); if (receive_buffer != null && send_buffer != null) { server.ReleaseBuffers (receive_buffer, send_buffer); receive_buffer = null; send_buffer = null; } } } Logger.Write (LogLevel.Notice, Strings.Connection_EndingRun); }
public Connection(Socket socket) { if (socket == null) throw new ArgumentNullException ("socket"); this.socket = socket; }
internal static void ReceiveAll (Socket socket, CompatArraySegment<byte> data, int length) { if (length <= 0) return; int total = 0; while (total < length) { total += socket.Receive (data.Array, total + data.Offset, length - total, System.Net.Sockets.SocketFlags.None); } }
public Record (Socket socket, byte[] buffer) : this (socket, new Buffers (buffer, HeaderSize, buffer.Length - HeaderSize - 8)) { }
void CloseSocket () { try { if (socket != null) socket.Close (); } catch (System.Net.Sockets.SocketException e) { // Ignore: "The descriptor is not a socket" // error from UnmanagedSocket.Close if (e.ErrorCode != 10038) throw; // Rethrow other errors } catch (ObjectDisposedException){ // Ignore: already closed } finally { socket = null; } }
/// <summary> /// Sends a FastCGI record with the data from the current /// instance over a given socket. /// </summary> /// <param name="socket"> /// A <see cref="Socket" /> object to send the data over. /// </param> /// <param name="buffer"> /// A <see cref="byte[]" /> to write the record to or <see /// langword="null" /> to create a temporary buffer during /// the send. /// </param> /// <remarks> /// If <paramref name="buffer" /> is of insufficient size to /// write to the buffer, a temporary buffer will be created. /// </remarks> public void Send (Socket socket, byte [] buffer) { byte padding_size = (byte) ((8 - (body_length % 8)) % 8); int total_size = 8 + body_length + padding_size; byte[] data = (buffer != null && buffer.Length > total_size) ? buffer : new byte [total_size]; data [0] = version; data [1] = (byte) type; data [2] = (byte) (request_id >> 8); data [3] = (byte) (request_id & 0xFF); data [4] = (byte) (body_length >> 8); data [5] = (byte) (body_length & 0xFF); data [6] = padding_size; Array.Copy (this.data, body_index, data, 8, body_length); for (int i = 0; i < padding_size; i ++) data [8 + body_length + i] = 0; Logger.Write (LogLevel.Debug, Strings.Record_Sent, Type, RequestID, body_length); SendAll (socket, data, total_size); }
/// <summary> /// Constructs and initializes a new instance of <see /// cref="Record" /> by reading the contents from a specified /// socket. /// </summary> /// <param name="socket"> /// A <see cref="Socket" /> object to receive the record data /// from. /// </param> /// <param name="buffer"> /// A <see cref="byte[]" /> containing the buffer to use when /// receiving from the socket or <see langword="null" /> to /// create the buffers on the fly. /// </param> /// <remarks> /// <para>If <paramref name="buffer" /> is not <see /// langword="null" />, the suggested size is <see /// cref="SuggestedBufferSize" />. If the size of the buffer /// is insufficient to read the data, a sufficiently sized /// array will be created on a per-instance basis.</para> /// <note type="caution"> /// <para>If a buffer is used, the new instance /// is only valid until the same buffer is used again. /// Therefore, use an extra degree of caution when using /// this constructor.</para> /// </note> /// </remarks> /// <exception cref="ArgumentNullException"> /// <paramref name="socket" /> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="socket" /> does not contain a complete /// record. /// </exception> public Record (Socket socket, byte [] buffer) { if (socket == null) throw new ArgumentNullException ("socket"); byte[] header_buffer = (buffer != null && buffer.Length > 8) ? buffer : new byte [HeaderSize]; byte padding_length; // Read the 8 byte record header. ReceiveAll (socket, header_buffer, HeaderSize); // Read the values from the data. version = header_buffer [0]; type = (RecordType) header_buffer [1]; request_id = ReadUInt16 (header_buffer, 2); body_length = ReadUInt16 (header_buffer, 4); padding_length = header_buffer [6]; int total_length = body_length + padding_length; data = (buffer != null && buffer.Length >= total_length) ? buffer : new byte [total_length]; body_index = 0; // Read the record data, and throw an exception if the // complete data cannot be read. if (total_length > 0) ReceiveAll (socket, data, total_length); Logger.Write (LogLevel.Debug, Strings.Record_Received, Type, RequestID, BodyLength); }
public void EndRequest(ushort requestID, int appStatus, ProtocolStatus protocolStatus) { EndRequestBody body = new EndRequestBody (appStatus, protocolStatus); if (IsConnected) new Record (1, RecordType.EndRequest, requestID, body.GetData ()).Send (socket); int index = GetRequestIndex (requestID); if (index >= 0) { lock (request_lock) { requests.RemoveAt (index); } } lock (connection_teardown_lock) { if (requests.Count == 0 && (!keep_alive || stop)) { if (socket != null) { try { socket.Close (); } finally { socket = null; } } if (!stop) server.EndConnection (this); if (receive_buffer != null && send_buffer != null) { server.ReleaseBuffers (receive_buffer, send_buffer); receive_buffer = null; send_buffer = null; } } } }
public void Run() { Logger.Write (LogLevel.Notice, Strings.Connection_BeginningRun); if (socket == null) { Logger.Write (LogLevel.Notice, Strings.Connection_NoSocketInRun); return; } do { Record record; try { record = new Record (socket, receive_buffer); } catch (System.Net.Sockets.SocketException) { StopRun (Strings.Connection_RecordNotReceived); Stop (); break; } Request request = GetRequest (record.RequestID); switch (record.Type) { // Creates a new request. case RecordType.BeginRequest: // If a request with the given ID // already exists, there's a bug in the // client. Abort. if (request != null) { StopRun (Strings.Connection_RequestAlreadyExists); break; } // If there are unfinished requests // and multiplexing is disabled, inform // the client and don't begin the // request. if (!server.MultiplexConnections && UnfinishedRequests) { EndRequest (record.RequestID, 0, ProtocolStatus.CantMultiplexConnections); break; } // If the maximum number of requests is // reached, inform the client and don't // begin the request. if (!server.CanRequest) { EndRequest (record.RequestID, 0, ProtocolStatus.Overloaded); break; } BeginRequestBody body = new BeginRequestBody (record); // If the role is "Responder", and it is // supported, create a ResponderRequest. if (body.Role == Role.Responder && server.SupportsResponder) request = new ResponderRequest (record.RequestID, this); // If the request is null, the role is // not supported. Inform the client and // don't begin the request. if (request == null) { Logger.Write (LogLevel.Warning, Strings.Connection_RoleNotSupported, body.Role); EndRequest (record.RequestID, 0, ProtocolStatus.UnknownRole); break; } lock (request_lock) { requests.Add (request); } keep_alive = (body.Flags & BeginRequestFlags.KeepAlive) != 0; break; // Gets server values. case RecordType.GetValues: byte [] response_data; // Look up the data from the server. try { IDictionary<string,string> pairs_in = NameValuePair.FromData (record.GetBody ()); IDictionary<string,string> pairs_out = server.GetValues (pairs_in.Keys); response_data = NameValuePair.GetData (pairs_out); } catch { response_data = new byte [0]; } SendRecord (RecordType.GetValuesResult, record.RequestID, response_data); break; // Sends params to the request. case RecordType.Params: if (request == null) { StopRun (Strings.Connection_RequestDoesNotExist, record.RequestID); break; } request.AddParameterData (record.GetBody ()); break; // Sends standard input to the request. case RecordType.StandardInput: if (request == null) { StopRun (Strings.Connection_RequestDoesNotExist, record.RequestID); break; } request.AddInputData (record); break; // Sends file data to the request. case RecordType.Data: if (request == null) { StopRun (Strings.Connection_RequestDoesNotExist, record.RequestID); break; } request.AddFileData (record); break; // Aborts a request when the server aborts. case RecordType.AbortRequest: if (request == null) break; request.Abort ( Strings.Connection_AbortRecordReceived); break; // Informs the client that the record type is // unknown. default: Logger.Write (LogLevel.Warning, Strings.Connection_UnknownRecordType, record.Type); SendRecord (RecordType.UnknownType, record.RequestID, new UnknownTypeBody ( record.Type).GetData ()); break; } } while (!stop && (UnfinishedRequests || keep_alive)); if (requests.Count == 0) { lock (connection_teardown_lock) { try { if (socket != null) socket.Close (); } catch (System.Net.Sockets.SocketException e) { // Ignore: "The descriptor is not a socket" // error from UnmanagedSocket.Close if (e.ErrorCode != 10038) throw; // Rethrow other errors } finally { socket = null; } if (!stop) server.EndConnection (this); if (receive_buffer != null && send_buffer != null) { server.ReleaseBuffers (receive_buffer, send_buffer); receive_buffer = null; send_buffer = null; } } } Logger.Write (LogLevel.Notice, Strings.Connection_EndingRun); }
/// <summary> /// Sends a FastCGI record with the data from the current /// instance over a given socket. /// </summary> /// <param name="socket"> /// A <see cref="Socket" /> object to send the data over. /// </param> public void Send (Socket socket) { Send (socket, null); }
public void Send (Socket socket, byte [] buffer) { Send(socket); }
private static void SendAll (Socket socket, byte [] data, int length) { if (length <= 0) return; int total = 0; while (total < length) { total += socket.Send (data, total, length - total, System.Net.Sockets.SocketFlags.None); } }
public void Send(Socket socket) { var padding_size = (byte) ((8 - (BodyLength % 8)) % 8); CompatArraySegment<byte> header = buffers.EnforceHeaderLength (HeaderSize); header [0] = version; header [1] = (byte) type; header [2] = (byte) (request_id >> 8); header [3] = (byte) (request_id & 0xFF); header [4] = (byte) (BodyLength >> 8); header [5] = (byte) (BodyLength & 0xFF); header [6] = padding_size; CompatArraySegment<byte> padding = buffers.EnforcePaddingLength (padding_size); for (int i = 0; i < padding_size; i ++) padding [i] = 0; Logger.Write (LogLevel.Debug, Strings.Record_Sent, Type, RequestID, BodyLength); NRecord.SendAll (socket, header, HeaderSize); NRecord.SendAll (socket, buffers.Body, BodyLength); NRecord.SendAll (socket, padding, padding_size); }
public Record (Socket socket) : this (socket, new Buffers()) { }
internal static void SendAll (Socket socket, CompatArraySegment<byte>? data, int length) { if (length <= 0 || data == null) return; int total = 0; while (total < length) { total += socket.Send (data.Value.Array, data.Value.Offset + total, length - total, System.Net.Sockets.SocketFlags.None); } }