Example #1
0
 public Connection(Socket socket, Server server)
 {
     this.socket = socket;
     this.server = server;
     server.AllocateBuffers (out receive_buffer,
         out send_buffer);
 }
Example #2
0
		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);
		}
Example #3
0
		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);
		}
Example #4
0
        public Server(Socket socket)
        {
            if (socket == null)
                throw new ArgumentNullException ("socket");

            this.listen_socket = socket;
        }
Example #5
0
		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;
		}
Example #6
0
        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);
        }
Example #7
0
		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);
		}
Example #8
0
		/// <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)
		{
		}
Example #9
0
		internal ConnectionProxy OnAccept (Socket socket)
		{
			return new ConnectionProxy (new Connection (socket, this));
		}
Example #10
0
		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);
		}
Example #11
0
        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);
        }
Example #12
0
 public Connection(Socket socket)
 {
     if (socket == null)
         throw new ArgumentNullException ("socket");
     this.socket = socket;
 }
Example #13
0
		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);
			}
		}
Example #14
0
		public Record (Socket socket, byte[] buffer) : this (socket, new Buffers (buffer, HeaderSize, buffer.Length - HeaderSize - 8))
		{
		}
Example #15
0
		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;
			}
		}
Example #16
0
		/// <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);
		}
Example #17
0
		/// <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);
		}
Example #18
0
        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;
                    }
                }
            }
        }
Example #19
0
        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);
        }
Example #20
0
		/// <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);
		}
Example #21
0
		public void Send (Socket socket, byte [] buffer)
		{
			Send(socket);
		}
Example #22
0
		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);
			}
		}
Example #23
0
		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);
		}
Example #24
0
		public Record (Socket socket) : this (socket, new Buffers())
		{
		}
Example #25
0
		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);
			}
		}