private static void HttpListener_RequestReceived(object sender, RequestEventArgs e) { IHttpRequest request = e.Request; IHttpClientContext context = sender as IHttpClientContext; foreach (var module in Modules) { if (module.Execute(request.Uri.AbsolutePath, request, out string result)) { context.Respond(result ?? string.Empty); return; } } context.Respond(string.Empty); }
public void SendResponse(List <LLEventQueueEvent> eventsToSend) { if (Request == null || Response == null) { ConnectionOpen = false; m_log.Warn("Cannot send response, connection is closed"); return; } Response.Connection = Request.Connection; if (eventsToSend != null) { OSDArray responseArray = new OSDArray(eventsToSend.Count); // Put all of the events in an array for (int i = 0; i < eventsToSend.Count; i++) { LLEventQueueEvent currentEvent = eventsToSend[i]; OSDMap eventMap = new OSDMap(2); eventMap.Add("message", OSD.FromString(currentEvent.Name)); eventMap.Add("body", currentEvent.Body); responseArray.Add(eventMap); } // Create a map containing the events array and the id of this response OSDMap responseMap = new OSDMap(2); responseMap.Add("events", responseArray); responseMap.Add("id", OSD.FromInteger(CurrentID++)); // Serialize the events and send the response string responseBody = OSDParser.SerializeLLSDXmlString(responseMap); m_log.Debug("Sending " + responseArray.Count + " events over the event queue"); Context.Respond(HttpHelper.HTTP11, HttpStatusCode.OK, "OK", responseBody, "application/xml"); } else { //m_log.Debug("Sending a timeout response over the event queue"); // The 502 response started as a bug in the LL event queue server implementation, // but is now hardcoded into the protocol as the code to use for a timeout Context.Respond(HttpHelper.HTTP10, HttpStatusCode.BadGateway, "Upstream error:", "Upstream error:", null); } ConnectionOpen = false; }
private void OnIncomingRequest(object source, RequestEventArgs args) { IHttpClientContext client = (IHttpClientContext)source; IHttpRequest request = args.Request; client.Respond("Hello world!"); ++_currentThreadCount; _testEvent.Set(); }
protected void HandleHTTPRequest(IHttpClientContext context, IHttpRequest request) { Uri uri = request.Uri; string hostName = uri.Host; string pathAndQuery = uri.PathAndQuery; try { // Handle different HTTP methods here if (request.Method == "NOTIFY") { foreach (DeviceConnection connection in _connectedDevices.Values) { if (!NetworkHelper.HostNamesEqual(hostName, NetworkHelper.IPAddrToHostName(connection.GENAClientController.EventNotificationEndpoint.Address))) { continue; } if (pathAndQuery == connection.GENAClientController.EventNotificationPath) { IHttpResponse response = request.CreateResponse(context); response.Status = connection.GENAClientController.HandleUnicastEventNotification(request); response.Send(); return; } } } else { context.Respond(HttpHelper.HTTP11, HttpStatusCode.MethodNotAllowed, null); return; } // Url didn't match context.Respond(HttpHelper.HTTP11, HttpStatusCode.NotFound, null); return; } catch (Exception) // Don't log the exception here - we don't care about not being able to send the return value to the client { IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.InternalServerError; response.Send(); return; } }
void SendResponse(IHttpClientContext context, IHttpRequest request, IHttpResponse response, List <EventQueueEvent> eventsToSend) { response.Connection = request.Connection; if (eventsToSend != null) { OSDArray responseArray = new OSDArray(eventsToSend.Count); // Put all of the events in an array for (int i = 0; i < eventsToSend.Count; i++) { EventQueueEvent currentEvent = eventsToSend[i]; OSDMap eventMap = new OSDMap(2); eventMap.Add("message", OSD.FromString(currentEvent.Name)); eventMap.Add("body", currentEvent.Body); responseArray.Add(eventMap); } // Create a map containing the events array and the id of this response OSDMap responseMap = new OSDMap(2); responseMap.Add("events", responseArray); responseMap.Add("id", OSD.FromInteger(currentID++)); // Serialize the events and send the response string responseBody = OSDParser.SerializeLLSDXmlString(responseMap); Logger.Log.Debug("[EventQueue] Sending " + responseArray.Count + " events over the event queue"); context.Respond(HttpHelper.HTTP11, HttpStatusCode.OK, "OK", responseBody, "application/xml"); } else { //Logger.Log.Debug("[EventQueue] Sending a timeout response over the event queue"); // The 502 response started as a bug in the LL event queue server implementation, // but is now hardcoded into the protocol as the code to use for a timeout context.Respond(HttpHelper.HTTP10, HttpStatusCode.BadGateway, "Upstream error:", "Upstream error:", null); } }
private void OnRequest(object source, RequestEventArgs args) { IHttpClientContext context = (IHttpClientContext)source; IHttpRequest request = args.Request; // Respond is a small convenience function that let's you send one string to the browser. // you can also use the Send, SendHeader and SendBody methods to have total control. if (request.Uri.AbsolutePath == "/hello") { context.Respond("Hello to you too!"); } else if (request.UriParts.Length == 1 && request.UriParts[0] == "goodbye") { IHttpResponse response = request.CreateResponse(context); StreamWriter writer = new StreamWriter(response.Body); writer.WriteLine("Goodbye to you too!"); writer.Flush(); response.Send(); } }
/// <summary> /// Received from a <see cref="IHttpClientContext"/> when a request have been parsed successfully. /// </summary> /// <param name="source"><see cref="IHttpClientContext"/> that received the request.</param> /// <param name="args">The request.</param> private void OnRequest(object source, RequestEventArgs args) { _current = this; IHttpClientContext context = (IHttpClientContext)source; IHttpRequest request = args.Request; if (_requestQueue.ShouldQueue) { // Do not use unfinished _requestQueue: //_requestQueue.Enqueue(context, request); context.Respond("HTTP/1.0", HttpStatusCode.ServiceUnavailable, HttpStatusCode.ServiceUnavailable.ToString(), "Request Queue is full", "text/plain"); return; } ProcessRequestWrapper(context, request); // no need to lock, if all threads are busy, // someone is bound to trigger the thread correctly =) // Update: Trigger body does not (yet) have any implementation. //_requestQueue.Trigger(); }
private void ProcessRequest(IHttpClientContext context, IHttpRequest request) { IHttpResponse response = request.CreateResponse(context); try { foreach (IRule rule in _rules) { if (!rule.Process(request, response)) continue; response.Send(); return; } // load cookies if the exist. RequestCookies cookies = request.Headers["cookie"] != null ? new RequestCookies(request.Headers["cookie"]) : new RequestCookies(string.Empty); request.SetCookies(cookies); IHttpSession session; if (cookies[_sessionCookieName] != null) { string sessionCookie = cookies[_sessionCookieName].Value; // there's a bug somewhere which messes up headers which can render the session cookie useless. // therefore let's consider the session cookie as not set if that have happened. if (sessionCookie.Length > 40) { _logWriter.Write(this, LogPrio.Error, "Session cookie is invalid: " + sessionCookie); cookies.Remove(_sessionCookieName); _sessionStore.Remove(sessionCookie); // free the session cookie (and thus generating a new one). session = _sessionStore.Create(); } else session = _sessionStore.Load(sessionCookie) ?? _sessionStore.Create(sessionCookie); } else session = _sessionStore.Create(); HandleRequest(context, request, response, session); } catch (Exception err) { if (_exceptionHandler == null) #if DEBUG throw; #else { WriteLog(LogPrio.Fatal, err.Message); return; } #endif _exceptionHandler(this, err); Exception e = err; while (e != null) { if (e is SocketException) return; e = e.InnerException; } try { #if DEBUG context.Respond("HTTP/1.0", HttpStatusCode.InternalServerError, "Internal server error", err.ToString(), "text/plain"); #else context.Respond("HTTP/1.0", HttpStatusCode.InternalServerError, "Internal server error"); #endif } catch (Exception err2) { LogWriter.Write(this, LogPrio.Fatal, "Failed to respond on message with Internal Server Error: " + err2); } } }
private void ProcessRequest(IHttpClientContext context, IHttpRequest request) { IHttpResponse response = request.CreateResponse(context); try { foreach (IRule rule in _rules) { if (!rule.Process(request, response)) { continue; } response.Send(); return; } // load cookies if the exist. RequestCookies cookies = request.Headers["cookie"] != null ? new RequestCookies(request.Headers["cookie"]) : new RequestCookies(string.Empty); request.SetCookies(cookies); IHttpSession session; if (cookies[_sessionCookieName] != null) { string sessionCookie = cookies[_sessionCookieName].Value; // there's a bug somewhere which f***s up headers which can render the session cookie useless. // therefore let's consider the session cookie as not set if that have happened. if (sessionCookie.Length > 40) { LogWriter.Write(this, LogPrio.Error, "Session cookie is invalid: " + sessionCookie); cookies.Remove(_sessionCookieName); _sessionStore.Remove(sessionCookie); // free the session cookie (and thus generating a new one). session = _sessionStore.Create(); } else { session = _sessionStore.Load(sessionCookie) ?? _sessionStore.Create(sessionCookie); } } else { session = _sessionStore.Create(); } HandleRequest(context, request, response, session); } catch (Exception err) { if (_exceptionHandler == null) #if DEBUG { throw; } #else { WriteLog(LogPrio.Fatal, err.Message); return; } #endif _exceptionHandler(this, err); Exception e = err; while (e != null) { if (e is SocketException) { return; } e = e.InnerException; } try { #if DEBUG context.Respond("HTTP/1.0", HttpStatusCode.InternalServerError, "Internal server error", err.ToString(), "text/plain"); #else context.Respond("HTTP/1.0", HttpStatusCode.InternalServerError, "Internal server error"); #endif } catch (Exception err2) { LogWriter.Write(this, LogPrio.Fatal, "Failed to respond on message with Internal Server Error: " + err2); } } }
/// <summary> /// Handles all kinds of HTTP over TCP requests - Description, Control and Event subscriptions. /// </summary> /// <param name="context">HTTP client context of the current request.</param> /// <param name="request">HTTP request to handle.</param> protected void HandleHTTPRequest_NoLock(IHttpClientContext context, IHttpRequest request) { Uri uri = request.Uri; string hostName = uri.Host; string pathAndQuery = uri.LocalPath; // Unfortunately, Uri.PathAndQuery doesn't decode characters like '{' and '}', so we use the Uri.LocalPath property try { DvService service; ICollection<EndpointConfiguration> endpoints; lock (_serverData.SyncObj) endpoints = _serverData.UPnPEndPoints; foreach (EndpointConfiguration config in endpoints) { if (!NetworkHelper.HostNamesEqual(hostName, NetworkHelper.IPAddrToHostName(config.EndPointIPAddress))) continue; // Common check for supported encodings string acceptEncoding = request.Headers.Get("ACCEPT-ENCODING") ?? string.Empty; // Handle different HTTP methods here if (request.Method == "GET") { // GET of descriptions if (pathAndQuery.StartsWith(config.DescriptionPathBase)) { string acceptLanguage = request.Headers.Get("ACCEPT-LANGUAGE"); CultureInfo culture = GetFirstCultureOrDefault(acceptLanguage, CultureInfo.InvariantCulture); string description = null; DvDevice rootDevice; lock (_serverData.SyncObj) if (config.RootDeviceDescriptionPathsToRootDevices.TryGetValue(pathAndQuery, out rootDevice)) description = rootDevice.BuildRootDeviceDescription(_serverData, config, culture); else if (config.SCPDPathsToServices.TryGetValue(pathAndQuery, out service)) description = service.BuildSCPDDocument(config, _serverData); if (description != null) { IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.OK; response.ContentType = "text/xml; charset=utf-8"; if (!string.IsNullOrEmpty(acceptLanguage)) response.AddHeader("CONTENT-LANGUAGE", culture.ToString()); using (MemoryStream responseStream = new MemoryStream(UPnPConsts.UTF8_NO_BOM.GetBytes(description))) CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream); SafeSendResponse(response); return; } } } else if (request.Method == "POST") { // POST of control messages if (config.ControlPathsToServices.TryGetValue(pathAndQuery, out service)) { string contentType = request.Headers.Get("CONTENT-TYPE"); string userAgentStr = request.Headers.Get("USER-AGENT"); IHttpResponse response = request.CreateResponse(context); int minorVersion; if (string.IsNullOrEmpty(userAgentStr)) minorVersion = 0; else if (!ParserHelper.ParseUserAgentUPnP1MinorVersion(userAgentStr, out minorVersion)) { response.Status = HttpStatusCode.BadRequest; SafeSendResponse(response); return; } string mediaType; Encoding encoding; if (!EncodingUtils.TryParseContentTypeEncoding(contentType, Encoding.UTF8, out mediaType, out encoding)) throw new ArgumentException("Unable to parse content type"); if (mediaType != "text/xml") { // As specified in (DevArch), 3.2.1 response.Status = HttpStatusCode.UnsupportedMediaType; SafeSendResponse(response); return; } response.AddHeader("DATE", DateTime.Now.ToUniversalTime().ToString("R")); response.AddHeader("SERVER", UPnPConfiguration.UPnPMachineInfoHeader); response.AddHeader("CONTENT-TYPE", "text/xml; charset=\"utf-8\""); string result; HttpStatusCode status; try { CallContext callContext = new CallContext(request, context, config); status = SOAPHandler.HandleRequest(service, request.Body, encoding, minorVersion >= 1, callContext, out result); } catch (Exception e) { UPnPConfiguration.LOGGER.Warn("Action invocation failed", e); result = SOAPHandler.CreateFaultDocument(501, "Action failed"); status = HttpStatusCode.InternalServerError; } response.Status = status; using (MemoryStream responseStream = new MemoryStream(encoding.GetBytes(result))) CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream); SafeSendResponse(response); return; } } else if (request.Method == "SUBSCRIBE" || request.Method == "UNSUBSCRIBE") { GENAServerController gsc; lock (_serverData.SyncObj) gsc = _serverData.GENAController; if (gsc.HandleHTTPRequest(request, context, config)) return; } else { context.Respond(HttpHelper.HTTP11, HttpStatusCode.MethodNotAllowed, null); return; } } // Url didn't match context.Respond(HttpHelper.HTTP11, HttpStatusCode.NotFound, null); } catch (Exception e) { UPnPConfiguration.LOGGER.Error("UPnPServer: Error handling HTTP request '{0}'", e, uri); IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.InternalServerError; SafeSendResponse(response); } }
void SendResponse(IHttpClientContext context, IHttpRequest request, IHttpResponse response, List<EventQueueEvent> eventsToSend) { response.Connection = request.Connection; if (eventsToSend != null) { OSDArray responseArray = new OSDArray(eventsToSend.Count); // Put all of the events in an array for (int i = 0; i < eventsToSend.Count; i++) { EventQueueEvent currentEvent = eventsToSend[i]; OSDMap eventMap = new OSDMap(2); eventMap.Add("message", OSD.FromString(currentEvent.Name)); eventMap.Add("body", currentEvent.Body); responseArray.Add(eventMap); } // Create a map containing the events array and the id of this response OSDMap responseMap = new OSDMap(2); responseMap.Add("events", responseArray); responseMap.Add("id", OSD.FromInteger(currentID++)); // Serialize the events and send the response string responseBody = OSDParser.SerializeLLSDXmlString(responseMap); Logger.Log.Debug("[EventQueue] Sending " + responseArray.Count + " events over the event queue"); context.Respond(HttpHelper.HTTP11, HttpStatusCode.OK, "OK", responseBody, "application/xml"); } else { //Logger.Log.Debug("[EventQueue] Sending a timeout response over the event queue"); // The 502 response started as a bug in the LL event queue server implementation, // but is now hardcoded into the protocol as the code to use for a timeout context.Respond(HttpHelper.HTTP10, HttpStatusCode.BadGateway, "Upstream error:", "Upstream error:", null); } }
protected void HandleHTTPRequest(IHttpClientContext context, IHttpRequest request) { Uri uri = request.Uri; string hostName = uri.Host; string pathAndQuery = uri.PathAndQuery; try { // Handle different HTTP methods here if (request.Method == "NOTIFY") { foreach (DeviceConnection connection in _connectedDevices.Values) { if (!NetworkHelper.HostNamesEqual(hostName, NetworkHelper.IPAddrToHostName(connection.GENAClientController.EventNotificationEndpoint.Address))) continue; if (pathAndQuery == connection.GENAClientController.EventNotificationPath) { IHttpResponse response = request.CreateResponse(context); response.Status = connection.GENAClientController.HandleUnicastEventNotification(request); response.Send(); return; } } } else { context.Respond(HttpHelper.HTTP11, HttpStatusCode.MethodNotAllowed, null); return; } // Url didn't match context.Respond(HttpHelper.HTTP11, HttpStatusCode.NotFound, null); } catch (Exception) // Don't log the exception here - we don't care about not being able to send the return value to the client { IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.InternalServerError; response.Send(); } }
/// <summary> /// Handles all kinds of HTTP over TCP requests - Description, Control and Event subscriptions. /// </summary> /// <param name="context">HTTP client context of the current request.</param> /// <param name="request">HTTP request to handle.</param> protected void HandleHTTPRequest_NoLock(IHttpClientContext context, IHttpRequest request) { Uri uri = request.Uri; string hostName = uri.Host; string pathAndQuery = uri.LocalPath; // Unfortunately, Uri.PathAndQuery doesn't decode characters like '{' and '}', so we use the Uri.LocalPath property try { DvService service; ICollection <EndpointConfiguration> endpoints; lock (_serverData.SyncObj) endpoints = _serverData.UPnPEndPoints; foreach (EndpointConfiguration config in endpoints) { if (!NetworkHelper.HostNamesEqual(hostName, NetworkHelper.IPAddrToHostName(config.EndPointIPAddress))) { continue; } // Common check for supported encodings string acceptEncoding = request.Headers.Get("ACCEPT-ENCODING") ?? string.Empty; // Handle different HTTP methods here if (request.Method == "GET") { // GET of descriptions if (pathAndQuery.StartsWith(config.DescriptionPathBase)) { string acceptLanguage = request.Headers.Get("ACCEPT-LANGUAGE"); CultureInfo culture = GetFirstCultureOrDefault(acceptLanguage, CultureInfo.InvariantCulture); string description = null; DvDevice rootDevice; lock (_serverData.SyncObj) if (config.RootDeviceDescriptionPathsToRootDevices.TryGetValue(pathAndQuery, out rootDevice)) { description = rootDevice.BuildRootDeviceDescription(_serverData, config, culture); } else if (config.SCPDPathsToServices.TryGetValue(pathAndQuery, out service)) { description = service.BuildSCPDDocument(config, _serverData); } if (description != null) { IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.OK; response.ContentType = "text/xml; charset=utf-8"; if (!string.IsNullOrEmpty(acceptLanguage)) { response.AddHeader("CONTENT-LANGUAGE", culture.ToString()); } using (MemoryStream responseStream = new MemoryStream(UPnPConsts.UTF8_NO_BOM.GetBytes(description))) CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream); SafeSendResponse(response); return; } } } else if (request.Method == "POST") { // POST of control messages if (config.ControlPathsToServices.TryGetValue(pathAndQuery, out service)) { string contentType = request.Headers.Get("CONTENT-TYPE"); string userAgentStr = request.Headers.Get("USER-AGENT"); IHttpResponse response = request.CreateResponse(context); int minorVersion; if (string.IsNullOrEmpty(userAgentStr)) { minorVersion = 0; } else if (!ParserHelper.ParseUserAgentUPnP1MinorVersion(userAgentStr, out minorVersion)) { response.Status = HttpStatusCode.BadRequest; SafeSendResponse(response); return; } string mediaType; Encoding encoding; if (!EncodingUtils.TryParseContentTypeEncoding(contentType, Encoding.UTF8, out mediaType, out encoding)) { throw new ArgumentException("Unable to parse content type"); } if (mediaType != "text/xml") { // As specified in (DevArch), 3.2.1 response.Status = HttpStatusCode.UnsupportedMediaType; SafeSendResponse(response); return; } response.AddHeader("DATE", DateTime.Now.ToUniversalTime().ToString("R")); response.AddHeader("SERVER", UPnPConfiguration.UPnPMachineInfoHeader); response.AddHeader("CONTENT-TYPE", "text/xml; charset=\"utf-8\""); string result; HttpStatusCode status; try { CallContext callContext = new CallContext(request, context, config); status = SOAPHandler.HandleRequest(service, request.Body, encoding, minorVersion >= 1, callContext, out result); } catch (Exception e) { UPnPConfiguration.LOGGER.Warn("Action invocation failed", e); result = SOAPHandler.CreateFaultDocument(501, "Action failed"); status = HttpStatusCode.InternalServerError; } response.Status = status; using (MemoryStream responseStream = new MemoryStream(encoding.GetBytes(result))) CompressionHelper.WriteCompressedStream(acceptEncoding, response, responseStream); SafeSendResponse(response); return; } } else if (request.Method == "SUBSCRIBE" || request.Method == "UNSUBSCRIBE") { GENAServerController gsc; lock (_serverData.SyncObj) gsc = _serverData.GENAController; if (gsc.HandleHTTPRequest(request, context, config)) { return; } } else { context.Respond(HttpHelper.HTTP11, HttpStatusCode.MethodNotAllowed, null); return; } } // Url didn't match context.Respond(HttpHelper.HTTP11, HttpStatusCode.NotFound, null); } catch (Exception e) { UPnPConfiguration.LOGGER.Error("UPnPServer: Error handling HTTP request '{0}'", e, uri); IHttpResponse response = request.CreateResponse(context); response.Status = HttpStatusCode.InternalServerError; SafeSendResponse(response); } }
void ProcessRequest(IHttpClientContext context, IHttpRequest request) { LogWriter.Write(this, LogPrio.Trace, "Processing request..."); IHttpResponse response = request.CreateResponse(context); try { // load cookies if they exist. RequestCookies cookies = request.Headers["cookie"] != null ? new RequestCookies(request.Headers["cookie"]) : new RequestCookies(string.Empty); request.SetCookies(cookies); // Create a request signature HttpRequestSignature signature = new HttpRequestSignature(request); // Look for a signature match in our handlers bool found = false; for (int i = 0; i < _requestHandlers.Length; i++) { HttpRequestHandler handler = _requestHandlers[i]; if (signature == handler.Signature) { FireRequestCallback(context, request, response, handler.Callback); found = true; break; } } if (!found) { // No registered handler matched this request's signature if (_notFoundHandler != null) { FireRequestCallback(context, request, response, _notFoundHandler); } else { // Send a default 404 response try { response.Status = HttpStatusCode.NotFound; response.Reason = String.Format("No request handler registered for Method=\"{0}\", Content-Type=\"{1}\", Path=\"{2}\"", signature.Method, signature.ContentType, signature.Path); string notFoundResponse = "<html><head><title>Page Not Found</title></head><body><h3>" + response.Reason + "</h3></body></html>"; byte[] buffer = System.Text.Encoding.UTF8.GetBytes(notFoundResponse); response.Body.Write(buffer, 0, buffer.Length); response.Send(); } catch (Exception) { } } } } catch (Exception err) { ThrowException(err); bool errorResponse = true; Exception e = err; while (e != null) { if (e is SocketException) { errorResponse = false; break; } e = e.InnerException; } if (errorResponse) { try { #if DEBUG context.Respond(HttpHelper.HTTP11, HttpStatusCode.InternalServerError, "Internal server error", err.ToString(), "text/plain"); #else context.Respond(HttpHelper.HTTP10, HttpStatusCode.InternalServerError, "Internal server error"); #endif } catch (Exception err2) { LogWriter.Write(this, LogPrio.Fatal, "Failed to respond on message with Internal Server Error: " + err2); } } } request.Clear(); LogWriter.Write(this, LogPrio.Trace, "...done processing request."); }