Пример #1
0
 /// <summary>
 /// The constructor of this class. You dont have to use this by your own, NoIIS will handle this for you.
 /// </summary>
 /// <param name="request">The client's request.</param>
 /// <param name="response">Your response to the client's request.</param>
 public NoIISContext(NoIISRequest request, NoIISResponse response)
 {
     this.request  = request;
     this.response = response;
 }
Пример #2
0
        private static async void clientThread(HttpListener listener)
        {
            try
            {
                // Will wait for the next client request:
                var context = await listener.GetContextAsync();

                // Filter-out any requests which are to huge:
                if (context.Request.ContentLength64 > NoIISServer.maxRequestSizeBytes)
                {
                    Console.WriteLine("A request was to huge: {0} bytes.", context.Request.ContentLength64);
                    context.Response.Abort();
                    return;
                }

                // Read the client's address:
                var clientAddress = context.Request.RemoteEndPoint.Address.ToString();

                // Is this address known?
                if (!NoIISServer.clients.ContainsKey(clientAddress))
                {
                    // Unknown:
                    NoIISServer.createAndStoreClientProfile(clientAddress);
                }

                //
                // In the meanwhile the maintenance thread could take action. Scenario: This client is known
                // but was not visiting for the allowed time span. One moment after the previous check, the
                // allowed time span expires and the maintenance thread deletes the entry. In such a case,
                // an exception will be throwed. Is this the case, we add a new client profile. This is
                // fine and a valid case.
                //

                Client clientProfile;
                try {
                    // Read the client's profile:
                    clientProfile = NoIISServer.clients[clientAddress];
                } catch (KeyNotFoundException) {
                    // Valide case. Create a new entry:
                    NoIISServer.createAndStoreClientProfile(clientAddress);

                    // Read it again. It is not possible that the case occurs again:
                    clientProfile = NoIISServer.clients[clientAddress];
                }

                // Is this client blocked?
                if (clientProfile.Blocked)
                {
                    Console.WriteLine("A blocked client tried to access: {0}.", clientAddress);
                    context.Response.Abort();
                    return;
                }

                // File this visit. It is intended to do so after the block check.
                // Otherwise, an attacker could use this fact to flood the memory
                // with visits:
                NoIISServer.clientVisits[clientAddress].Enqueue(DateTime.UtcNow);
                clientProfile.LastVisitUTC = DateTime.UtcNow;

                // Store the changed time. This could happens parallel with several
                // threads. Thus, it is not atomic. This behaviour is intended! Only
                // the roughly time is necessary.
                NoIISServer.clients[clientAddress] = clientProfile;

                try
                {
                    // Create the NoIIS request:
                    var request = new NoIISRequest(context, NoIISServer.tempFolder);

                    // Create the NoIIS response:
                    var response = new NoIISResponse(context);

                    // Create the NoIIS context with request and response:
                    var webContext = new NoIISContext(request, response);

                    // Search for a handler inside all factories which matches the request:
                    var foundHandler = false;
                    foreach (var factory in NoIISServer.factories)
                    {
                        // Does this factory is able to deliver a handler for this request?
                        var handler = factory.GetHandler(webContext, request.RequestType, request.Path, string.Empty);

                        // Case: Yes, we have found the first handler:
                        if (handler != null)
                        {
                            // Let the handler process the request:
                            handler.ProcessRequest(webContext);
                            foundHandler = true;

                            // We only use the first matching handler:
                            break;
                        }
                    }

                    // Case: No handler was found
                    if (!foundHandler)
                    {
                        Console.WriteLine("No handler found for the URL '{0}'.", request.RawUrl);
                        response.StatusCode = 404;
                    }

                    try
                    {
                        response.Dispose();
                    }
                    catch
                    {
                    }

                    try
                    {
                        request.Dispose();
                    }
                    catch
                    {
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("Exception while processing request: {0}", e.Message);
                    Console.WriteLine(e.StackTrace);

                    try
                    {
                        context.Response.Abort();
                    }
                    catch
                    {
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception while accepting request: {0}", e.Message);
                Console.WriteLine(e.StackTrace);
            }
            finally
            {
                NoIISServer.semaphoreClients.Release();
            }
        }