Example #1
0
/*----------------------------------------------------------------------
|   PLT_HttpServer::ServeFile
+---------------------------------------------------------------------*/
NPT_Result 
PLT_HttpServer::ServeFile(const NPT_HttpRequest&        request, 
                          const NPT_HttpRequestContext& context,
                          NPT_HttpResponse&             response,
                          NPT_String                    file_path) 
{
    NPT_InputStreamReference stream;
    NPT_File                 file(file_path);
    NPT_FileInfo             file_info;
    
    // prevent hackers from accessing files outside of our root
    if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0) ||
        NPT_FAILED(NPT_File::GetInfo(file_path, &file_info))) {
        return NPT_ERROR_NO_SUCH_ITEM;
    }
    
    // check for range requests
    const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE);
    
    // handle potential 304 only if range header not set
    NPT_DateTime  date;
    NPT_TimeStamp timestamp;
    if (NPT_SUCCEEDED(PLT_UPnPMessageHelper::GetIfModifiedSince((NPT_HttpMessage&)request, date)) &&
        !range_spec) {
        date.ToTimeStamp(timestamp);
        
        NPT_LOG_INFO_5("File %s timestamps: request=%d (%s) vs file=%d (%s)", 
                       (const char*)request.GetUrl().GetPath(),
                       (NPT_UInt32)timestamp.ToSeconds(),
                       (const char*)date.ToString(),
                       (NPT_UInt32)file_info.m_ModificationTime,
                       (const char*)NPT_DateTime(file_info.m_ModificationTime).ToString());
        
        if (timestamp >= file_info.m_ModificationTime) {
            // it's a match
            NPT_LOG_FINE_1("Returning 304 for %s", request.GetUrl().GetPath().GetChars());
            response.SetStatus(304, "Not Modified", NPT_HTTP_PROTOCOL_1_1);
            return NPT_SUCCESS;
        }
    }
    
    // open file
    if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || 
        NPT_FAILED(file.GetInputStream(stream))        ||
        stream.IsNull()) {
        return NPT_ERROR_NO_SUCH_ITEM;
    }
    
    // set Last-Modified and Cache-Control headers
    if (file_info.m_ModificationTime) {
        NPT_DateTime last_modified = NPT_DateTime(file_info.m_ModificationTime);
        response.GetHeaders().SetHeader("Last-Modified", last_modified.ToString(NPT_DateTime::FORMAT_RFC_1123), true);
        response.GetHeaders().SetHeader("Cache-Control", "max-age=0,must-revalidate", true);
        //response.GetHeaders().SetHeader("Cache-Control", "max-age=1800", true);
    }
    
    PLT_HttpRequestContext tmp_context(request, context);
    return ServeStream(request, context, response, stream, PLT_MimeType::GetMimeType(file_path, &tmp_context));
}
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::ProcessFileRequest
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::ProcessFileRequest(NPT_HttpRequest&  request, 
                                        NPT_HttpResponse& response, 
                                        NPT_SocketInfo&   client_info)
{
    NPT_COMPILER_UNUSED(client_info);

    NPT_LOG_FINE("PLT_FileMediaServer::ProcessFileRequest Received Request:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    response.GetHeaders().SetHeader("Accept-Ranges", "bytes");

    if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
        response.SetStatus(500, "Internal Server Error");
        return NPT_SUCCESS;
    }

    // File requested
    NPT_String path = m_FileBaseUri.GetPath();
    NPT_String strUri = NPT_Uri::PercentDecode(request.GetUrl().GetPath());

    NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
    NPT_String file_path = query.GetField("path");

    // hack for XBMC support for 360, we urlencoded the ? to that the 360 doesn't strip out the query
    // but then the query ends being parsed as part of the path
    int index = strUri.Find("path=");
    if (index>0) file_path = strUri.Right(strUri.GetLength()-index-5);
    if (file_path.GetLength() == 0) goto failure;

    // HACK for wmp: somehow they inverse our slashes !
    // do it only if we're on windows
    if (m_DirDelimiter == "\\") {
        file_path.Replace('/', '\\');
    }

    if (path.Compare(strUri.Left(path.GetLength()), true) == 0) {
        NPT_Integer start, end;
        PLT_HttpHelper::GetRange(&request, start, end);

        return PLT_FileServer::ServeFile(m_Path + file_path, &response, start, end, !request.GetMethod().Compare("HEAD"));
    } 

    // Album Art requested
    path = m_AlbumArtBaseUri.GetPath();
    if (path.Compare(strUri.Left(path.GetLength()), true) == 0) {
        return OnAlbumArtRequest(m_Path + file_path, response);
    } 

failure:
    response.SetStatus(404, "File Not Found");
    return NPT_SUCCESS;
}
Example #3
0
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::ProcessHttpRequest
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::ProcessHttpRequest(NPT_HttpRequest&              request, 
                                        const NPT_HttpRequestContext& context,
                                        NPT_HttpResponse&             response)
{
    if (request.GetUrl().GetPath().StartsWith(m_FileBaseUri.GetPath()) || 
        request.GetUrl().GetPath().StartsWith(m_AlbumArtBaseUri.GetPath())) {
        return ProcessFileRequest(request, context, response);
    }

    return PLT_MediaServer::ProcessHttpRequest(request, context, response);
}
Example #4
0
/*----------------------------------------------------------------------
|   PLT_HttpClient::Connect
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpClient::Connect(NPT_Socket* connection, NPT_HttpRequest& request, NPT_Timeout timeout)
{
    // get the address of the server
    NPT_IpAddress server_address;
    NPT_CHECK_SEVERE(server_address.ResolveName(request.GetUrl().GetHost(), timeout));
    NPT_SocketAddress address(server_address, request.GetUrl().GetPort());

    // connect to the server
    NPT_LOG_FINER_2("Connecting to %s:%d\n", (const char*)request.GetUrl().GetHost(), request.GetUrl().GetPort());
    NPT_CHECK_SEVERE(connection->Connect(address, timeout));

    return NPT_SUCCESS;
}
Example #5
0
/*----------------------------------------------------------------------
|   CMediaCrawler::ProcessFileRequest
+---------------------------------------------------------------------*/
NPT_Result 
CMediaCrawler::ProcessFileRequest(NPT_HttpRequest&  request, 
                                  NPT_HttpResponse& response,
                                  NPT_SocketInfo&   info)
{
    NPT_COMPILER_UNUSED(info);

    NPT_LOG_FINE("CMediaCrawler::ProcessFileRequest Received Request:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
        response.SetStatus(500, "Internal Server Error");
        return NPT_SUCCESS;
    }

    // add the user agent header, some stupid media servers like YME needs it
    if (!request.GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT)) {
        request.GetHeaders().SetHeader(NPT_HTTP_HEADER_USER_AGENT, 
            "Platinum/" PLT_PLATINUM_VERSION_STRING);
    }

    // File requested
    NPT_HttpResponse* out_response = NULL;
    NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
    const char* url = query.GetField("url");
    if (url) {
        // look for handler
        CStreamHandler* handler = NULL;
        NPT_ContainerFind(m_StreamHandlers, CStreamHandlerFinder(NULL, url), handler);
        if (handler && NPT_SUCCEEDED(handler->ProcessFileRequest(request, out_response)) && out_response) {
            // copy response code and reason
            response.SetStatus(out_response->GetStatusCode(), out_response->GetReasonPhrase());

            // copy headers
            NPT_List<NPT_HttpHeader*>::Iterator headers = out_response->GetHeaders().GetHeaders().GetFirstItem();
            while (headers) {
                response.GetHeaders().SetHeader((*headers)->GetName(), (*headers)->GetValue());
                ++headers;
            }
            response.SetEntity(new NPT_HttpEntity(response.GetHeaders()));
            
            // update inputstream
            NPT_HttpEntity* out_entity;
            if ((out_entity = out_response->GetEntity()) != NULL) {
                NPT_InputStreamReference inputstream;
                out_entity->GetInputStream(inputstream);
                if (!inputstream.IsNull()) {
                    // set the stream but do not update the content length
                    response.GetEntity()->SetInputStream(inputstream, false);
                }
            }

            delete out_response;
            return NPT_SUCCESS;
        }
    }

    response.SetStatus(404, "File Not Found");
    return NPT_SUCCESS;
}
Example #6
0
/*----------------------------------------------------------------------
|   PLT_FileMediaServer::ProcessFileRequest
+---------------------------------------------------------------------*/
NPT_Result 
PLT_FileMediaServer::ProcessFileRequest(NPT_HttpRequest&              request, 
                                        const NPT_HttpRequestContext& context,
                                        NPT_HttpResponse&             response)
{
    NPT_LOG_FINE("PLT_FileMediaServer::ProcessFileRequest Received Request:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    response.GetHeaders().SetHeader("Accept-Ranges", "bytes");

    if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) {
        response.SetStatus(500, "Internal Server Error");
        return NPT_SUCCESS;
    }

    // Extract uri path from url
    NPT_String uri_path = NPT_Uri::PercentDecode(request.GetUrl().GetPath());
    
    // extract file path from query
    NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
    NPT_String file_path = query.GetField("path");

    // hack for XBMC support for 360, we urlencoded the ? to that the 360 doesn't strip out the query
    // but then the query ends being parsed as part of the path
    int index = uri_path.Find("path=");
    if (index>0) file_path = uri_path.Right(uri_path.GetLength()-index-5);
    if (file_path.GetLength() == 0) goto failure;
    
    NPT_CHECK_LABEL_WARNING(ServeFile(request, 
                                      context, 
                                      response, 
                                      uri_path, 
                                      file_path),
                            failure);

    return NPT_SUCCESS;

failure:
    response.SetStatus(404, "File Not Found");
    return NPT_SUCCESS;
}
Example #7
0
    NPT_Result SetupResponse(NPT_HttpRequest&  request, 
                             NPT_HttpResponse& response,
                             NPT_SocketInfo&   /*info*/) {
        NPT_String msg = "<HTML>";
        msg += "PATH=";
        msg += request.GetUrl().GetPath();
        msg += " <P><UL>";
        if (request.GetUrl().HasQuery()) {
            NPT_HttpUrlQuery query(request.GetUrl().GetQuery());
            for (NPT_List<NPT_HttpUrlQuery::Field>::Iterator it = query.GetFields().GetFirstItem();
                 it;
                 ++it) {
                 NPT_HttpUrlQuery::Field& field = *it;
                 msg += "<LI>";
                 msg += field.m_Name;
                 msg += " = ";
                 msg += field.m_Value;
                 msg += " </LI>";
            }
        }
        msg += "</UL></HTML>";

        if (request.GetMethod() == NPT_HTTP_METHOD_POST) {
            NPT_DataBuffer request_body;
            request.GetEntity()->Load(request_body);
            NPT_Debug("REQUEST: body = %d bytes\n", request_body.GetDataSize());
            NPT_Debug("REQUEST: content type = %s\n", request.GetEntity()->GetContentType().GetChars());
            if (request.GetEntity()->GetContentType().StartsWith("text") ||
                request.GetEntity()->GetContentType() == "application/x-www-form-urlencoded") {
                NPT_String body_string;
                body_string.Assign((char*)request_body.GetData(), request_body.GetDataSize());
                NPT_Debug("%s", body_string.GetChars());
            }
        }

        NPT_HttpEntity* entity = response.GetEntity();
        entity->SetContentType("text/html");
        entity->SetInputStream(msg);

        return NPT_SUCCESS;
    }
/*----------------------------------------------------------------------
|   CUPnPRenderer::ProcessHttpRequest
+---------------------------------------------------------------------*/
NPT_Result
CUPnPRenderer::ProcessHttpGetRequest(NPT_HttpRequest&              request,
                                  const NPT_HttpRequestContext& context,
                                  NPT_HttpResponse&             response)
{
    // get the address of who sent us some data back
    NPT_String  ip_address = context.GetRemoteAddress().GetIpAddress().ToString();
    NPT_String  method     = request.GetMethod();
    NPT_String  protocol   = request.GetProtocol();
    NPT_HttpUrl url        = request.GetUrl();

    if (url.GetPath() == "/thumb") {
        NPT_HttpUrlQuery query(url.GetQuery());
        NPT_String filepath = query.GetField("path");
        if (!filepath.IsEmpty()) {
            NPT_HttpEntity* entity = response.GetEntity();
            if (entity == NULL) return NPT_ERROR_INVALID_STATE;

            // check the method
            if (request.GetMethod() != NPT_HTTP_METHOD_GET &&
                request.GetMethod() != NPT_HTTP_METHOD_HEAD) {
                response.SetStatus(405, "Method Not Allowed");
                return NPT_SUCCESS;
            }

            // prevent hackers from accessing files outside of our root
            if ((filepath.Find("/..") >= 0) || (filepath.Find("\\..") >=0)) {
                return NPT_FAILURE;
            }
#if 1
            std::string path;
            //url
#else
            // open the file
            CStdString path = CURL::Decode((const char*) filepath);
#endif
            NPT_File file(path.c_str());
            NPT_Result result = file.Open(NPT_FILE_OPEN_MODE_READ);
            if (NPT_FAILED(result)) {
                response.SetStatus(404, "Not Found");
                return NPT_SUCCESS;
            }
            NPT_InputStreamReference stream;
            file.GetInputStream(stream);
            entity->SetContentType(GetMimeType(filepath));
            entity->SetInputStream(stream, true);

            return NPT_SUCCESS;
        }
    }

    return PLT_MediaRenderer::ProcessHttpGetRequest(request, context, response);
}
/*----------------------------------------------------------------------
|   PLT_HttpHelper::ToLog
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpHelper::ToLog(NPT_LoggerReference    logger, 
                      int                    level, 
                      const NPT_HttpRequest& request)
{
    NPT_COMPILER_UNUSED(logger);
    NPT_COMPILER_UNUSED(level);

    NPT_StringOutputStreamReference stream(new NPT_StringOutputStream);
    NPT_OutputStreamReference output = stream;
    request.GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output));

    NPT_LOG_L4(logger, level, "\n%s %s %s\n%s", 
        (const char*)request.GetMethod(), 
        (const char*)request.GetUrl().ToRequestString(true), 
        (const char*)request.GetProtocol(),
        (const char*)stream->GetString());
    return NPT_SUCCESS;
}
Example #10
0
NPT_Result CHttpServer::SetupResponse(NPT_HttpRequest&              request, 
                              const NPT_HttpRequestContext& context,
                              NPT_HttpResponse&             response) 
{
    NPT_String prefix = NPT_String::Format("PLT_HttpServer::SetupResponse %s request from %s for \"%s\"", 
        (const char*) request.GetMethod(),
        (const char*) context.GetRemoteAddress().ToString(),
        (const char*) request.GetUrl().ToString());

    NPT_List<NPT_HttpRequestHandler*> handlers = FindRequestHandlers(request);
    if (handlers.GetItemCount() == 0) return NPT_ERROR_NO_SUCH_ITEM;

    // ask the handler to setup the response
    NPT_Result result = (*handlers.GetFirstItem())->SetupResponse(request, context, response);
    
    // DLNA compliance
    UPNPMessageHelper::SetDate(response);
    if (request.GetHeaders().GetHeader("Accept-Language")) {
        response.GetHeaders().SetHeader("Content-Language", "en");
    }
    return result;
}
Example #11
0
/*----------------------------------------------------------------------
|   PLT_HttpClient::SendRequest
+---------------------------------------------------------------------*/
NPT_Result
PLT_HttpClient::SendRequest(NPT_OutputStreamReference& output_stream, 
                            NPT_HttpRequest&           request, 
                            NPT_Timeout                timeout)
{
    NPT_COMPILER_UNUSED(timeout);

    // connect to the server
    NPT_LOG_FINE("Sending:");
    PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &request);

    // add any headers that may be missing
    NPT_HttpHeaders& headers = request.GetHeaders();
    //headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, "close");
    if (!headers.GetHeader(NPT_HTTP_HEADER_USER_AGENT)) {
        headers.SetHeader(NPT_HTTP_HEADER_USER_AGENT, 
            "Platinum/" PLT_PLATINUM_VERSION_STRING);
    }

    // set host only if not already set
    if (!headers.GetHeader(NPT_HTTP_HEADER_HOST)) {
        NPT_String host = request.GetUrl().GetHost();
        if (request.GetUrl().GetPort() != NPT_HTTP_DEFAULT_PORT) {
            host += ":";
            host += NPT_String::FromInteger(request.GetUrl().GetPort());
        }
        headers.SetHeader(NPT_HTTP_HEADER_HOST, host);
    }

    // get the request entity to set additional headers
    NPT_InputStreamReference body_stream;
    NPT_HttpEntity* entity = request.GetEntity();
    if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) {
        // content length
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, 
            NPT_String::FromInteger(entity->GetContentLength()));

        // content type
        NPT_String content_type = entity->GetContentType();
        if (!content_type.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, content_type);
        }

        // content encoding
        NPT_String content_encoding = entity->GetContentEncoding();
        if (!content_encoding.IsEmpty()) {
            headers.SetHeader(NPT_HTTP_HEADER_CONTENT_ENCODING, content_encoding);
        }
    } else {
        // force content length to 0 is there is no message body
        headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
    }

    // create a memory stream to buffer the headers
    NPT_MemoryStream header_stream;

    // emit the request headers into the header buffer
    request.Emit(header_stream);

    // send the headers
    NPT_CHECK_SEVERE(output_stream->WriteFully(header_stream.GetData(), header_stream.GetDataSize()));

    // send request body
    if (!body_stream.IsNull() && entity->GetContentLength()) {
        NPT_CHECK_SEVERE(NPT_StreamToStreamCopy(*body_stream.AsPointer(), *output_stream.AsPointer()));
    }

    // flush the output stream so that everything is sent to the server
    output_stream->Flush();

    return NPT_SUCCESS;
}
Example #12
0
/*----------------------------------------------------------------------
|    BtPlayerServer::SetupResponse
+---------------------------------------------------------------------*/
NPT_Result 
BtPlayerServer::SetupResponse(NPT_HttpRequest&              request,
                              const NPT_HttpRequestContext& /*context*/,
                              NPT_HttpResponse&             response)
{
    const NPT_Url&    url  = request.GetUrl();
    const NPT_String& path = url.GetPath();
    NPT_UrlQuery      query;
    
    // parse the query part, if any
    if (url.HasQuery()) {
        query.Parse(url.GetQuery());
    }
    
    // lock the player 
    NPT_AutoLock lock(m_Lock);
    
    // handle form requests
    if (path == "/") {
        response.GetHeaders().SetHeader("Location", "/control/ajax");
        response.SetStatus(301, "Moved Permanently");
        return BLT_SUCCESS;
    }

    // handle form requests
    if (path == "/control/form") {
        return SendControlForm(response, NULL);
    }
    
    // handle status requests
    if (path == "/player/status") {
        return SendStatus(response, query);
    }
    
    // handle commands
    const char* mode_field = query.GetField("mode");
    const char* form_msg = "OK";
    bool use_form = false;
    if (mode_field && NPT_StringsEqual(mode_field, "form")) {
        use_form = true;
    }
    if (path == "/player/set-input") {
        const char* name_field = query.GetField("name");
        if (name_field) {
            NPT_String name = NPT_UrlQuery::UrlDecode(name_field);
            m_Player.SetInput(name);
        } else {
            form_msg = "INVALID PARAMETERS";
        }
    } else if (path == "/player/set-output") {
        const char* name_field = query.GetField("name");
        if (name_field) {
            NPT_String name = NPT_UrlQuery::UrlDecode(name_field);
            m_Player.SetOutput(name);
        } else {
            form_msg = "INVALID PARAMETERS";
        }
    } else if (path == "/player/play") {
        m_Player.Play();
    } else if (path == "/player/pause") {
        m_Player.Pause();
    } else if (path == "/player/stop") {
        m_Player.Stop();
    } else if (path == "/player/seek") {
        const char* timecode_field = query.GetField("timecode");
        const char* position_field = query.GetField("position");
        if (timecode_field) {
            NPT_String timecode = NPT_UrlQuery::UrlDecode(timecode_field);
            DoSeekToTimecode(timecode);
        } else if (position_field) {
            unsigned int position;
            if (NPT_SUCCEEDED(NPT_ParseInteger(position_field, position))) {
                m_Player.SeekToPosition(position, 100);
            }
        } else {
            form_msg = "INVALID PARAMETER";
        }
    } else if (path == "/player/set-volume") {
        const char* volume_field = query.GetField("volume");
        if (volume_field) {
            unsigned int volume;
            if (NPT_SUCCEEDED(NPT_ParseInteger(volume_field, volume))) {
                m_Player.SetVolume((float)volume/100.0f);
            }
        } else {
            form_msg = "INVALID PARAMETER";
        }
    }
    
    if (use_form) {
        return SendControlForm(response, form_msg);
    } else {
        NPT_HttpEntity* entity = response.GetEntity();
        entity->SetContentType("application/json");
        entity->SetInputStream("{}");
        return NPT_SUCCESS;
    }

    printf("BtPlayerServer::SetupResponse - command not found\n");
    
    response.SetStatus(404, "Command Not Found");
    return NPT_SUCCESS;
}
Example #13
0
void FrontEnd::processSsdpSearch(SsdpServerTask *task, Interface *intf, const NPT_DataBuffer& data, const NPT_SocketAddress& fromAddr)
{
	do {
		NPT_HttpRequest *req;
		NPT_InputStreamReference inputStream0(new NPT_MemoryStream(data.GetData(), data.GetDataSize()));
		NPT_BufferedInputStream inputStream(inputStream0);
		if (NPT_FAILED(NPT_HttpRequest::Parse(inputStream, NULL, req))) {
			break;
		}

		PtrHolder<NPT_HttpRequest> req1(req);
		if (req->GetMethod().Compare("M-SEARCH") != 0 || req->GetProtocol().Compare(NPT_HTTP_PROTOCOL_1_1) != 0 || req->GetUrl().GetPath().Compare("*") != 0) {
			break;
		}

		NPT_HttpHeader *hdrMan = req->GetHeaders().GetHeader("MAN");
		if (!hdrMan || hdrMan->GetValue().Compare("\"ssdp:discover\"") != 0) {
			break;
		}

		NPT_HttpHeader *hdrHost = req->GetHeaders().GetHeader("HOST");
		if (!hdrHost || (hdrHost->GetValue().Compare("239.255.255.250:1900") != 0 && hdrHost->GetValue().Compare("239.255.255.250") != 0)) {
			break;
		}

		int mx;
		NPT_HttpHeader *hdrMX = req->GetHeaders().GetHeader("MX");
		if (!hdrMX || NPT_FAILED(NPT_ParseInteger(hdrMX->GetValue(), mx)) || mx < 1) {
			break;
		}

		if (mx > 120) {
			mx = 120;
		}

		NPT_HttpHeader *hdrST = req->GetHeaders().GetHeader("ST");
		if (!hdrST) {
			break;
		}

		NPT_List<MatchContext*> matchList;

		NPT_UdpSocket sock(NPT_SOCKET_FLAG_CANCELLABLE);
		sock.Bind(NPT_SocketAddress(intf->m_context.m_ifAddr, 0));
		NPT_SharedVariable waitVar;
		waitVar.SetValue(0);

		{
			ReadLocker locker(m_dsLock);
			for (NPT_Ordinal i = 0; i < m_deviceImplList.GetItemCount(); i++) {
				NPT_List<DeviceImplInfo*>::Iterator it = m_deviceImplList.GetItem(i);
				DeviceImplInfo *info = *it;
				MatchContext *matchContext = new MatchContext();
				if (info->m_deviceImpl->match(hdrST->GetValue(), matchContext->matches)) {
					matchList.Add(matchContext);
					matchContext->deviceUuid = info->m_deviceImpl->uuid();
					matchContext->expireSeconds = info->m_deviceImpl->m_expireSeconds;
					matchContext->descPath = info->m_deviceImpl->m_descPath;
					matchContext->httpRoot = info->m_context.m_httpRoot;
				} else {
					delete matchContext;
				}
			}
		}

		SsdpSearchAbortCallback abortCallback(&sock, &waitVar);
		if (task->registerAbortCallback(&abortCallback)) {

			for (NPT_Ordinal i = 0; i < matchList.GetItemCount(); i++) {
				MatchContext *matchContext = *matchList.GetItem(i);

				NPT_String location = NPT_String::Format("http://%s:%d%s%s", intf->m_context.m_ifAddr.ToString().GetChars(), intf->m_context.m_httpPort, matchContext->httpRoot.GetChars(), matchContext->descPath.GetChars());

				bool broken = false;

				for (NPT_Ordinal j = 0; j < matchContext->matches.GetItemCount(); j++) {
					NPT_List<DeviceImplMatch>::Iterator it2 = matchContext->matches.GetItem(j);

					NPT_Timeout timeout = NPT_System::GetRandomInteger() % (mx * 1000);
					// TODO: wait or not ???
					timeout = 0;
					if (NPT_SUCCEEDED(waitVar.WaitWhileEquals(0, timeout))) {
						break;
					}

					{
						ReadLocker locker(m_dsLock);
						if (m_deviceImplIndex.HasKey(matchContext->deviceUuid)) {
							NPT_TimeStamp ts;
							NPT_System::GetCurrentTimeStamp(ts);
							NPT_String dateStr = NPT_DateTime(ts).ToString(NPT_DateTime::FORMAT_RFC_1123);
							NPT_String resp = NPT_String::Format("HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=%d\r\nDATE: %s\r\nEXT: \r\nLOCATION: %s\r\nSERVER: %s\r\nST: %s\r\nUSN: %s\r\nCUSTOM:%s\r\n\r\n",
														matchContext->expireSeconds, dateStr.GetChars(), location.GetChars(), m_serverHeader.GetChars(), it2->m_st.GetChars(), it2->m_usn.GetChars(), m_DevName.GetChars());
							NPT_DataBuffer packet(resp.GetChars(), resp.GetLength(), false);
							sock.Send(packet, &fromAddr);
						}
					}
				}

				if (broken) {
					break;
				}
			}

			task->unregisterAbortCallback(&abortCallback);
		}

		matchList.Apply(NPT_ObjectDeleter<MatchContext>());
	} while (false);
}
Example #14
0
void FrontEnd::httpConnectorOnNewClient(HttpServerTask *task, Interface *intf, NPT_Socket *client)
{
	NPT_Result nr;
	NPT_InputStreamReference inputStream0;
	nr = client->GetInputStream(inputStream0);
	if (NPT_FAILED(nr)) {
		return;
	}

	NPT_OutputStreamReference outputStream;
	nr = client->GetOutputStream(outputStream);
	if (NPT_FAILED(nr)) {
		return;
	}

	NPT_BufferedInputStreamReference inputStream(new NPT_BufferedInputStream(inputStream0));

	NPT_HttpRequest *req;

	nr = NPT_HttpRequest::Parse(*inputStream.AsPointer(), NULL, req);
	if (NPT_FAILED(nr)) {
		return;
	}

	// TODO: validate "HOST" ???

	RequestContext reqCtx;
	reqCtx.clientHint = CH_Unknown;
	reqCtx.transferMode = TM_None;
	reqCtx.getcontentFeaturesReq = false;

	NPT_HttpHeader *hdrUserAgent = req->GetHeaders().GetHeader(NPT_HTTP_HEADER_USER_AGENT);
	if (hdrUserAgent) {
		if (hdrUserAgent->GetValue().Find("xbox", 0, true) >= 0) {
			NPT_LOG_INFO_1("XBox found [User-Agent: %s]", hdrUserAgent->GetValue().GetChars());
			reqCtx.clientHint = CH_XBox;
		}
	}

	NPT_HttpHeader *hdrTransferMode = req->GetHeaders().GetHeader("transferMode.dlna.org");
	if (hdrTransferMode) {
		const NPT_String& transferMode = hdrTransferMode->GetValue();
		if (transferMode.Compare("Streaming", true) == 0) {
			reqCtx.transferMode = TM_Streaming;
		} else if (transferMode.Compare("Interactive", true) == 0) {
			reqCtx.transferMode = TM_Interactive;
		} else if (transferMode.Compare("Background", true) == 0) {
			reqCtx.transferMode = TM_Background;
		} else {
			reqCtx.transferMode = TM_Unknown;
		}
	}

	NPT_HttpHeader *hdrGetContentFeatures = req->GetHeaders().GetHeader("getcontentFeatures.dlna.org");
	if (hdrGetContentFeatures) {
		NPT_String getContentFeatures = hdrGetContentFeatures->GetValue();
		if (getContentFeatures.Trim().Compare("1") == 0) {
			reqCtx.getcontentFeaturesReq = true;
		}
	}

	NPT_SocketInfo si;
	client->GetInfo(si);
	onHttpRequestHeader(si, req);

	PtrHolder<NPT_HttpRequest> req1(req);
	NPT_String reqPath(req->GetUrl().GetPath());

	NPT_TimeStamp ts;
	NPT_System::GetCurrentTimeStamp(ts);
	NPT_String dateStr = NPT_DateTime(ts).ToString(NPT_DateTime::FORMAT_RFC_1123);

	NPT_HttpResponse *resp = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_1);
	PtrHolder<NPT_HttpResponse> resp1(resp);
	resp->GetHeaders().SetHeader(NPT_HTTP_HEADER_SERVER, m_serverHeader);
	resp->GetHeaders().SetHeader("Date", dateStr);
	resp->GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0");
	resp->GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, "text/xml");

	HttpOutput *httpOutput = new HttpOutputImpl(this, si, outputStream);
	PtrHolder<HttpOutput> httpOutput1(httpOutput);

	{
		ReadLocker locker(m_cpLock);
		for (NPT_Ordinal i = 0; i < m_controlPointList.GetItemCount(); i++) {
			NPT_List<ControlPointInfo*>::Iterator it = m_controlPointList.GetItem(i);
			ControlPointInfo *info = *it;
			if (reqPath.StartsWith(info->m_context.m_httpRoot)) {
				NPT_InputStream *input = inputStream.AsPointer();
				inputStream.Detach();
				httpOutput1.detach();
				resp1.detach();
				req1.detach();
				task->detach();
				return info->m_controlPoint->processHttpRequest(&intf->m_context, reqPath.SubString(info->m_context.m_httpRoot.GetLength()), reqCtx, req, resp, input, httpOutput, client);
			}
		}
	}

	{
		ReadLocker locker(m_dsLock);
		for (NPT_Ordinal i = 0; i < m_deviceImplList.GetItemCount(); i++) {
			NPT_List<DeviceImplInfo*>::Iterator it = m_deviceImplList.GetItem(i);
			DeviceImplInfo *info = *it;
			if (reqPath.StartsWith(info->m_context.m_httpRoot)) {
				NPT_InputStream *input = inputStream.AsPointer();
				inputStream.Detach();
				httpOutput1.detach();
				resp1.detach();
				req1.detach();
				task->detach();
				return info->m_deviceImpl->processHttpRequest(&intf->m_context, reqPath.SubString(info->m_context.m_httpRoot.GetLength()), reqCtx, req, resp, input, httpOutput, client);
			}
		}
	}

	setStatusCode(*resp, 404);
	httpOutput->writeResponseHeader(*resp);
	httpOutput->flush();

}
    NPT_Result SetupResponse(NPT_HttpRequest&              request, 
                             const NPT_HttpRequestContext& context,
                             NPT_HttpResponse&             response) {
        NPT_String msg = "<HTML>";
        msg += "PATH=";
        msg += request.GetUrl().GetPath();
        msg += "<P><B>Local Address:</B> ";
        msg += context.GetLocalAddress().ToString();
        msg += "<P>";
        msg += "<B>Remote Address:</B> ";
        msg += context.GetRemoteAddress().ToString();
        msg += "<P><UL>";
        if (request.GetUrl().HasQuery()) {
            NPT_UrlQuery query(request.GetUrl().GetQuery());
            for (NPT_List<NPT_UrlQuery::Field>::Iterator it = query.GetFields().GetFirstItem();
                 it;
                 ++it) {
                 NPT_UrlQuery::Field& field = *it;
                 msg += "<LI>";
                 msg += field.m_Name;
                 msg += " = ";
                 msg += field.m_Value;
                 msg += " </LI>";
                 
                 // check for a 'delay' field
                 if (field.m_Name == "delay") {
                    NPT_UInt32 delay = 0;
                    field.m_Value.ToInteger(delay);
                    NPT_Debug("DELAY: %d seconds\n", delay);
                    NPT_System::Sleep(NPT_TimeInterval((float)delay));
                 }
            }
        }
        msg += "</UL></HTML>";

        
        if (request.GetMethod() == NPT_HTTP_METHOD_POST) {
            NPT_DataBuffer request_body;
            request.GetEntity()->Load(request_body);
            NPT_Debug("REQUEST: body = %d bytes\n", request_body.GetDataSize());
            NPT_Debug("REQUEST: content type = %s\n", request.GetEntity()->GetContentType().GetChars());
            if (request.GetEntity()->GetContentType().StartsWith("text") ||
                request.GetEntity()->GetContentType() == "application/x-www-form-urlencoded") {
                NPT_String body_string;
                body_string.Assign((char*)request_body.GetData(), request_body.GetDataSize());
                NPT_Debug("%s", body_string.GetChars());
            }
        }

        NPT_HttpEntity* entity = response.GetEntity();
        entity->SetContentType("text/html");
        NPT_MemoryStreamReference memory_stream(
            new NPT_MemoryStream((const void*)msg.GetChars(), msg.GetLength()));
        entity->SetInputStream(memory_stream, !m_Chunked);
        
        if (m_Chunked) {
            entity->SetTransferEncoding(NPT_HTTP_TRANSFER_ENCODING_CHUNKED);
        }
        
        return NPT_SUCCESS;
    }