NPT_Result SetupResponse(NPT_HttpRequest& /*request*/, const NPT_HttpRequestContext& /*context*/, NPT_HttpResponse& response) { NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("text/html"); return NPT_SUCCESS; }
NPT_Result SetupResponse(NPT_HttpRequest& /*request*/, const NPT_HttpRequestContext& /*context*/, NPT_HttpResponse& response) { NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("text/html"); entity->SetTransferEncoding("chunked"); response.SetProtocol(NPT_HTTP_PROTOCOL_1_1); return NPT_SUCCESS; }
NPT_Result SetupResponse(NPT_HttpRequest& /*request*/, const NPT_HttpRequestContext& /*context*/, NPT_HttpResponse& response) { NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("text/html"); entity->SetInputStream("<html><body>Bye Bye!</body></html>"); KillRequest = true; 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); }
/*---------------------------------------------------------------------- | NPT_HttpLoggerConfigurator::SetupResponse +---------------------------------------------------------------------*/ NPT_Result NPT_HttpLoggerConfigurator::SetupResponse(NPT_HttpRequest& request, const NPT_HttpRequestContext& /*context*/, NPT_HttpResponse& response) { // we only support GET here if (request.GetMethod() != NPT_HTTP_METHOD_GET) return NPT_ERROR_HTTP_METHOD_NOT_SUPPORTED; // construct the response message NPT_String msg; msg = "<ul>"; NPT_List<NPT_LogConfigEntry>& config = LogManager.GetConfig(); NPT_List<NPT_LogConfigEntry>::Iterator cit = config.GetFirstItem(); for (; cit; ++cit) { NPT_LogConfigEntry& entry = (*cit); msg += "<li>"; msg += entry.m_Key; msg += "="; msg += entry.m_Value; msg += "</li>"; } msg += "</ul>"; msg += "<ul>"; NPT_List<NPT_Logger*>& loggers = LogManager.GetLoggers(); NPT_List<NPT_Logger*>::Iterator lit = loggers.GetFirstItem(); for (;lit;++lit) { NPT_Logger* logger = (*lit); msg += "<li>"; msg += logger->GetName(); msg += ", level="; msg += NPT_String::FromInteger(logger->GetLevel()); NPT_List<NPT_LogHandler*>& handlers = logger->GetHandlers(); NPT_List<NPT_LogHandler*>::Iterator hit = handlers.GetFirstItem(); msg += ", handlers="; for (;hit;++hit) { NPT_LogHandler* handler = (*hit); msg += handler->ToString(); } msg += "</li>"; } msg += "</ul>"; // setup the response body NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("text/html"); entity->SetInputStream(msg); return NPT_SUCCESS; }
// NPT_HttpRequetsHandler methods virtual NPT_Result SetupResponse(NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(context); NPT_HttpEntity* entity = response.GetEntity(); if (entity == NULL) return NPT_ERROR_INVALID_STATE; entity->SetContentType(m_MimeType); entity->SetInputStream(m_Body); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::IsBodyStreamSeekable +---------------------------------------------------------------------*/ bool PLT_HttpHelper::IsBodyStreamSeekable(NPT_HttpMessage* message) { NPT_HttpEntity* entity = message->GetEntity(); NPT_InputStreamReference stream; if (!entity || NPT_FAILED(entity->GetInputStream(stream))) return true; // try to get current position and seek there NPT_Position position; if (NPT_FAILED(stream->Tell(position)) || NPT_FAILED(stream->Seek(position))) { return false; } return true; }
bool CStreamCtrl::RecvHeaderData(NPT_HttpUrl url,NPT_DataBuffer& buffer) { NPT_HttpClient client; NPT_String rdUrl=url.ToString(); // first request NPT_HttpRequest request(url, NPT_HTTP_METHOD_GET, NPT_HTTP_PROTOCOL_1_1); NPT_HttpResponse* response = NULL; client.SendRequest(request, response); NPT_HttpEntity* entity = NULL; if (response && (entity = response->GetEntity())) { if (NPT_FAILED(entity->Load(buffer))) return false; } else return false; return true; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::GetBody(NPT_HttpMessage& message, NPT_String& body) { NPT_Result res; NPT_InputStreamReference stream; // get stream NPT_HttpEntity* entity = message.GetEntity(); if (!entity || NPT_FAILED(entity->GetInputStream(stream))) { return NPT_FAILURE; } // extract body NPT_StringOutputStream* output_stream = new NPT_StringOutputStream(&body); res = NPT_StreamToStreamCopy(*stream, *output_stream, 0, entity->GetContentLength()); delete output_stream; return res; }
/*---------------------------------------------------------------------- | ShowResponse +---------------------------------------------------------------------*/ static void ShowResponse(NPT_HttpResponse* response) { bool check_available = true;//true; // show entity NPT_HttpEntity* entity = response->GetEntity(); if (entity == NULL) return; NPT_Console::OutputF("ENTITY: length=%lld, type=%s, encoding=%s\n", entity->GetContentLength(), entity->GetContentType().GetChars(), entity->GetContentEncoding().GetChars()); NPT_DataBuffer buffer(65536); NPT_Result result; NPT_InputStreamReference input; entity->GetInputStream(input); NPT_TimeStamp start; NPT_System::GetCurrentTimeStamp(start); float total_read = 0.0f; for (;;) { NPT_Size bytes_read = 0; NPT_LargeSize available = 0; NPT_Size to_read = 65536; if (check_available) { input->GetAvailable(available); if ((NPT_Size)available < to_read) to_read = (NPT_Size)available; if (to_read == 0) { to_read = 1; NPT_TimeStamp sleep_time(0.01f); NPT_System::Sleep(sleep_time); } } result = input->Read(buffer.UseData(), to_read, &bytes_read); if (NPT_FAILED(result)) break; total_read += bytes_read; NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); NPT_TimeStamp duration = now-start; NPT_Console::OutputF("%6d avail, read %6d bytes, %6.3f KB/s\n", (int)available, bytes_read, (float)((total_read/1024.0)/(double)duration)); } }
/*---------------------------------------------------------------------- | PLT_Downloader::ProcessResponse +---------------------------------------------------------------------*/ NPT_Result PLT_Downloader::ProcessResponse(NPT_Result res, const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse* response) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(context); if (NPT_FAILED(res)) { NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_DOWNLOADING; NPT_HttpEntity* entity; NPT_InputStreamReference body; if (!response || !(entity = response->GetEntity()) || NPT_FAILED(entity->GetInputStream(body)) || body.IsNull()) { m_State = PLT_DOWNLOADER_ERROR; NPT_LOG_WARNING_2("No body %d for %s", res, m_URL.ToString().GetChars()); return NPT_FAILURE; } // Read body (no content length means until socket is closed) res = NPT_StreamToStreamCopy(*body.AsPointer(), *m_Output.AsPointer(), 0, entity->GetContentLength()); if (NPT_FAILED(res)) { NPT_LOG_WARNING_2("Downloader error %d for %s", res, m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_ERROR; return res; } NPT_LOG_INFO_1("Finished downloading %s", m_URL.ToString().GetChars()); m_State = PLT_DOWNLOADER_SUCCESS; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_HttpMessage::SetBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::SetBody(NPT_HttpMessage* message, NPT_InputStreamReference& stream, NPT_Size len) { if (len == 0) { NPT_CHECK_SEVERE(stream->GetAvailable(len)); } // get the entity NPT_HttpEntity* entity = message->GetEntity(); if (entity == NULL) { // no entity yet, create one message->SetEntity(entity = new NPT_HttpEntity()); } // set the entity body entity->SetInputStream(stream); entity->SetContentLength(len); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_MediaConnect::ProcessGetSCPD +---------------------------------------------------------------------*/ NPT_Result PLT_MediaConnect::ProcessGetSCPD(PLT_Service* service, NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response) { PLT_DeviceSignature signature = PLT_HttpHelper::GetDeviceSignature(request); // Override SCPD response by providing an SCPD without a Search action // to all devices except XBox or WMP which need it if (service->GetServiceType() == "urn:schemas-upnp-org:service:ContentDirectory:1" && signature != PLT_DEVICE_XBOX && signature != PLT_DEVICE_WMP && signature != PLT_DEVICE_SONOS) { NPT_HttpEntity* entity; PLT_HttpHelper::SetBody(response, (const char*) MS_ContentDirectorySCPD, &entity); entity->SetContentType("text/xml; charset=\"utf-8\""); return NPT_SUCCESS; } return PLT_MediaServer::ProcessGetSCPD(service, request, context, response); }
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; }
bool CStreamCtrl::RecvMediaData(NPT_HttpUrl url,int in_nStartPos, int in_nEndPos,NPT_DataBuffer& buffer) { NPT_HttpClient client; NPT_String rdUrl=url.ToString(); // first request NPT_HttpRequest request(url, NPT_HTTP_METHOD_GET, NPT_HTTP_PROTOCOL_1_1); char range[100]={0}; sprintf(range," bytes=%d-%d",in_nStartPos,in_nEndPos-1); request.GetHeaders().SetHeader(NPT_HTTP_HEADER_RANGE,range); NPT_HttpResponse* response = NULL; client.SendRequest(request, response); NPT_HttpEntity* entity = NULL; if (response && (entity = response->GetEntity())) { if (NPT_FAILED(entity->Load(buffer))) return false; } else return false; return true; }
/*---------------------------------------------------------------------- | PLT_Downloader::ProcessResponse +---------------------------------------------------------------------*/ NPT_Result PLT_Downloader::ProcessResponse(NPT_Result res, NPT_HttpRequest* request, const NPT_HttpRequestContext& context, NPT_HttpResponse* response) { NPT_COMPILER_UNUSED(request); NPT_COMPILER_UNUSED(context); if (NPT_FAILED(res)) { m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_DOWNLOADING; NPT_HttpEntity* entity; NPT_InputStreamReference body; if (!response || !(entity = response->GetEntity()) || NPT_FAILED(entity->GetInputStream(body)) || body.IsNull()) { m_State = PLT_DOWNLOADER_ERROR; return NPT_FAILURE; } // Read body (no content length means until socket is closed) res = NPT_StreamToStreamCopy(*body.AsPointer(), *m_Output.AsPointer(), 0, entity->GetContentLength()); if (NPT_FAILED(res)) { m_State = PLT_DOWNLOADER_ERROR; return res; } m_State = PLT_DOWNLOADER_SUCCESS; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServerSocketTask::SendResponseBody +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServerSocketTask::SendResponseBody(NPT_HttpResponse* response, NPT_OutputStream& output_stream) { NPT_HttpEntity* entity = response->GetEntity(); if (!entity) return NPT_SUCCESS; NPT_InputStreamReference body_stream; entity->GetInputStream(body_stream); if (body_stream.IsNull()) return NPT_SUCCESS; // check for chunked transfer encoding NPT_OutputStream* dest = &output_stream; if (entity->GetTransferEncoding() == NPT_HTTP_TRANSFER_ENCODING_CHUNKED) { dest = new NPT_HttpChunkedOutputStream(output_stream); } // send body NPT_LOG_FINE_1("sending body stream, %lld bytes", entity->GetContentLength()); NPT_LargeSize bytes_written = 0; NPT_Result result = NPT_StreamToStreamCopy(*body_stream, *dest, 0, entity->GetContentLength(), &bytes_written); /* passing 0 if content length is unknown will read until nothing is left */ if (NPT_FAILED(result)) { NPT_LOG_FINE_3("body stream only partially sent, %lld bytes (%d:%s)", bytes_written, result, NPT_ResultText(result)); } // flush to write out any buffered data left in chunked output if used dest->Flush(); // cleanup (this will send zero size chunk followed by CRLF) if (dest != &output_stream) delete dest; return result; }
/*---------------------------------------------------------------------- | PLT_HttpStreamRequestHandler::SetupResponse +---------------------------------------------------------------------*/ NPT_Result PLT_HttpStreamRequestHandler::SetupResponse(NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response) { PLT_LOG_HTTP_REQUEST(NPT_LOG_LEVEL_FINE, "PLT_HttpStreamRequestHandler::SetupResponse:", &request); if (request.GetMethod().Compare("GET") && request.GetMethod().Compare("HEAD")) { return NPT_FAILURE; } NPT_Reference<PLT_FrameBuffer> buffer; if (!m_StreamValidator.OnNewRequestAccept(request, context, response, buffer)) { return NPT_ERROR_NO_SUCH_ITEM; } response.SetProtocol(NPT_HTTP_PROTOCOL_1_0); response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONNECTION, "close"); response.GetHeaders().SetHeader("Cache-Control", "no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0"); response.GetHeaders().SetHeader("Pragma", "no-cache"); response.GetHeaders().SetHeader("Expires", "Tue, 4 Jan 2000 02:43:05 GMT"); // HEAD request has no entity or if status code is not 2xx if (!request.GetMethod().Compare("HEAD") || response.GetStatusCode()/100 != 2) return NPT_SUCCESS; NPT_HttpEntity* entity = response.GetEntity(); NPT_CHECK_POINTER_FATAL(entity); entity->SetContentType("multipart/x-mixed-replace;boundary=" BOUNDARY); NPT_InputStreamReference body(new PLT_InputFrameStream(buffer, BOUNDARY)); entity->SetInputStream(body, false); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | Test5 +---------------------------------------------------------------------*/ static bool Test5(NPT_HttpUrl url) { NPT_LOG_INFO("########### TEST 5 ######################"); NPT_HttpClient client; // first request NPT_HttpRequest request(url, NPT_HTTP_METHOD_POST, NPT_HTTP_PROTOCOL_1_1); NPT_HttpEntity* request_entity = new NPT_HttpEntity(); request_entity->SetInputStream("Testing"); request.SetEntity(request_entity); NPT_HttpResponse* response = NULL; client.SendRequest(request, response); NPT_HttpEntity* entity = NULL; if (response && (entity = response->GetEntity())) { NPT_DataBuffer buffer; if (NPT_FAILED(entity->Load(buffer))) return false; } // try again delete response; response = NULL; request_entity = new NPT_HttpEntity(); request_entity->SetInputStream("Testing2"); request.SetEntity(request_entity); client.SendRequest(request, response); entity = NULL; if (response && (entity = response->GetEntity())) { NPT_DataBuffer buffer; if (NPT_FAILED(entity->Load(buffer))) return false; } return true; }
/*---------------------------------------------------------------------- | PLT_HttpServerSocketTask::RespondToClient +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServerSocketTask::RespondToClient(NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse*& response) { NPT_Result result = NPT_ERROR_NO_SUCH_ITEM; // reset output params first response = NULL; // prepare the response body NPT_HttpEntity* body = new NPT_HttpEntity(); response = new NPT_HttpResponse(200, "OK", NPT_HTTP_PROTOCOL_1_1); response->SetEntity(body); // ask to setup the response result = SetupResponse(request, context, *response); // handle result if (result == NPT_ERROR_NO_SUCH_ITEM) { body->SetInputStream(PLT_HTTP_DEFAULT_404_HTML); body->SetContentType("text/html"); response->SetStatus(404, "Not Found"); } else if (result == NPT_ERROR_PERMISSION_DENIED) { body->SetInputStream(PLT_HTTP_DEFAULT_403_HTML); body->SetContentType("text/html"); response->SetStatus(403, "Forbidden"); } else if (result == NPT_ERROR_TERMINATED) { // mark that we want to exit delete response; response = NULL; } else if (NPT_FAILED(result)) { body->SetInputStream(PLT_HTTP_DEFAULT_500_HTML); body->SetContentType("text/html"); response->SetStatus(500, "Internal Error"); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | BtPlayerServer::SendControlForm +---------------------------------------------------------------------*/ NPT_Result BtPlayerServer::SendControlForm(NPT_HttpResponse& response, const char* msg) { // create the html document NPT_String html = "<html>"; // optional message if (msg && msg[0]) { html += "<"; html += msg; html += "><p>"; } // status html += "<p><b>State: </b>"; switch (m_DecoderState) { case BLT_DecoderServer::STATE_STOPPED: html += "[STOPPED]"; break; case BLT_DecoderServer::STATE_PLAYING: html += "[PLAYING]"; break; case BLT_DecoderServer::STATE_PAUSED: html += "[PAUSED]"; break; case BLT_DecoderServer::STATE_EOS: html += "[END OF STREAM]"; break; default: html += "[UNKNOWN]"; break; } html += "</p><p><b>Time Code: </b>"; html += NPT_String::Format("\"%02d:%02d:%02d\"", m_DecoderTimecode.h, m_DecoderTimecode.m, m_DecoderTimecode.s); html += "</p>"; html += "<p>"; html += "<b>Content Format: </b>"; if (m_StreamInfo.data_type) { html += m_StreamInfo.data_type; } html += "<br>"; // control form html += BT_CONTROL_FORM; html += "</html>"; // send the html document NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("text/html"); entity->SetInputStream(html); return NPT_SUCCESS; }
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; }
/*---------------------------------------------------------------------- | PLT_HttpServer::ServeStream +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::ServeStream(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context, NPT_HttpResponse& response, NPT_InputStreamReference& body, const char* content_type) { if (body.IsNull()) return NPT_FAILURE; // set date NPT_TimeStamp now; NPT_System::GetCurrentTimeStamp(now); response.GetHeaders().SetHeader("Date", NPT_DateTime(now).ToString(NPT_DateTime::FORMAT_RFC_1123), true); // get entity NPT_HttpEntity* entity = response.GetEntity(); NPT_CHECK_POINTER_FATAL(entity); // set the content type entity->SetContentType(content_type); // check for range requests const NPT_String* range_spec = request.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_RANGE); // setup entity body NPT_CHECK(NPT_HttpFileRequestHandler::SetupResponseBody(response, body, range_spec)); // set some default headers if (response.GetEntity()->GetTransferEncoding() != NPT_HTTP_TRANSFER_ENCODING_CHUNKED) { // set but don't replace Accept-Range header only if body is seekable NPT_Position offset; if (NPT_SUCCEEDED(body->Tell(offset)) && NPT_SUCCEEDED(body->Seek(offset))) { response.GetHeaders().SetHeader(NPT_HTTP_HEADER_ACCEPT_RANGES, "bytes", false); } } // set getcontentFeatures.dlna.org const NPT_String* value = request.GetHeaders().GetHeaderValue("getcontentFeatures.dlna.org"); if (value) { PLT_HttpRequestContext tmp_context(request, context); const char* dlna = PLT_ProtocolInfo::GetDlnaExtension(entity->GetContentType(), &tmp_context); if (dlna) response.GetHeaders().SetHeader("ContentFeatures.DLNA.ORG", dlna, false); } // transferMode.dlna.org value = request.GetHeaders().GetHeaderValue("transferMode.dlna.org"); if (value) { // Interactive mode not supported? /*if (value->Compare("Interactive", true) == 0) { response.SetStatus(406, "Not Acceptable"); return NPT_SUCCESS; }*/ response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", value->GetChars(), false); } else { response.GetHeaders().SetHeader("TransferMode.DLNA.ORG", "Streaming", false); } if (request.GetHeaders().GetHeaderValue("TimeSeekRange.dlna.org")) { response.SetStatus(406, "Not Acceptable"); return NPT_SUCCESS; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | ShowResponse +---------------------------------------------------------------------*/ static void ShowResponse(NPT_HttpResponse* response, ShowMode mode) { // show response info NPT_Debug("RESPONSE: protocol=%s, code=%d, reason=%s\n", response->GetProtocol().GetChars(), response->GetStatusCode(), response->GetReasonPhrase().GetChars()); // show headers NPT_HttpHeaders& headers = response->GetHeaders(); NPT_List<NPT_HttpHeader*>::Iterator header = headers.GetHeaders().GetFirstItem(); while (header) { NPT_Debug("%s: %s\n", (const char*)(*header)->GetName(), (const char*)(*header)->GetValue()); ++header; } // show entity NPT_HttpEntity* entity = response->GetEntity(); if (entity != NULL) { NPT_Debug("ENTITY: length=%lld, type=%s, encoding=%s\n", entity->GetContentLength(), entity->GetContentType().GetChars(), entity->GetContentEncoding().GetChars()); switch (mode) { case SHOW_MODE_LOAD: { NPT_DataBuffer body; NPT_Result result =entity->Load(body); if (NPT_FAILED(result)) { NPT_Debug("ERROR: failed to load entity (%d)\n", result); } else { NPT_Debug("BODY: loaded %d bytes\n", (int)body.GetDataSize()); // dump the body NPT_OutputStreamReference output; NPT_File standard_out(NPT_FILE_STANDARD_OUTPUT); standard_out.Open(NPT_FILE_OPEN_MODE_WRITE); standard_out.GetOutputStream(output); NPT_Debug("%s", (char *)body.GetData()); // ÔÝʱ²»Ö§³Ö // output->Write(body.GetData(), body.GetDataSize()); } break; } case SHOW_MODE_STREAM_BLOCKING: { NPT_DataBuffer buffer(4096); NPT_Result result; NPT_InputStreamReference input; entity->GetInputStream(input); do { NPT_Size bytes_read = 0; result = input->Read(buffer.UseData(), 4096, &bytes_read); NPT_Debug("read %d bytes\n", bytes_read); } while (NPT_SUCCEEDED(result)); break; } } } }
/*---------------------------------------------------------------------- | BtPlayerServer::SendStatus +---------------------------------------------------------------------*/ NPT_Result BtPlayerServer::SendStatus(NPT_HttpResponse& response, NPT_UrlQuery& query) { NPT_String json; // json start const char* json_callback = query.GetField("callback"); if (json_callback) { json += NPT_UrlQuery::UrlDecode(json_callback)+'('; } json += '{'; // state json += "\"state\": "; switch (m_DecoderState) { case BLT_DecoderServer::STATE_STOPPED: json += "\"STOPPED\""; break; case BLT_DecoderServer::STATE_PLAYING: json += "\"PLAYING\""; break; case BLT_DecoderServer::STATE_PAUSED: json += "\"PAUSED\""; break; case BLT_DecoderServer::STATE_EOS: json += "\"END OF STREAM\""; break; default: json += "\"UNKNOWN\""; break; } json += ','; // timecode json += NPT_String::Format("\"timecode\": \"%02d:%02d:%02d\", ", m_DecoderTimecode.h, m_DecoderTimecode.m, m_DecoderTimecode.s); // position json += NPT_String::Format("\"position\": %f, ", m_DecoderPosition); // stream info json += "\"streamInfo\": {"; if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_NOMINAL_BITRATE) { json += NPT_String::Format("\"nominalBitrate\": %d, ", m_StreamInfo.nominal_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_AVERAGE_BITRATE) { json += NPT_String::Format("\"averageBitrate\": %d, ", m_StreamInfo.average_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_INSTANT_BITRATE) { json += NPT_String::Format("\"instantBitrate\": %d, ", m_StreamInfo.instant_bitrate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_SIZE) { json += NPT_String::Format("\"size\": %d, ", m_StreamInfo.size); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_DURATION) { unsigned int seconds = m_StreamInfo.duration/1000; json += NPT_String::Format("\"duration\": \"%02d:%02d:%02d\", ", (seconds)/36000, (seconds%3600)/60, (seconds%60)); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_SAMPLE_RATE) { json += NPT_String::Format("\"sampleRate\": %d, ", m_StreamInfo.sample_rate); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_CHANNEL_COUNT) { json += NPT_String::Format("\"channelCount\": %d, ", m_StreamInfo.channel_count); } if (m_StreamInfo.mask & BLT_STREAM_INFO_MASK_DATA_TYPE) { json += NPT_String::Format("\"dataType\": \"%s\", ", m_StreamInfo.data_type); } json += "},"; // stream properties // json end json += '}'; if (json_callback) { json += ')'; } // send the html document NPT_HttpEntity* entity = response.GetEntity(); entity->SetContentType("application/json"); entity->SetInputStream(json); NPT_LOG_FINE_1("status: %s", json.GetChars()); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServerSocketTask::SendResponseHeaders +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServerSocketTask::SendResponseHeaders(NPT_HttpResponse* response, NPT_OutputStream& output_stream, bool& keep_alive) { // add any headers that may be missing NPT_HttpHeaders& headers = response->GetHeaders(); // get the request entity to set additional headers NPT_InputStreamReference body_stream; NPT_HttpEntity* entity = response->GetEntity(); if (entity && NPT_SUCCEEDED(entity->GetInputStream(body_stream))) { // set the content length if known if (entity->ContentLengthIsKnown()) { headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromIntegerU(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); } // transfer encoding const NPT_String& transfer_encoding = entity->GetTransferEncoding(); if (!transfer_encoding.IsEmpty()) { headers.SetHeader(NPT_HTTP_HEADER_TRANSFER_ENCODING, transfer_encoding); } } else if (!headers.GetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH)) { // force content length to 0 if there is no message body // (necessary for 1.1 or 1.0 with keep-alive connections) headers.SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, "0"); } const NPT_String* content_length = headers.GetHeaderValue(NPT_HTTP_HEADER_CONTENT_LENGTH); const NPT_String* transfer_encoding = headers.GetHeaderValue(NPT_HTTP_HEADER_TRANSFER_ENCODING); const NPT_String* connection_header = headers.GetHeaderValue(NPT_HTTP_HEADER_CONNECTION); if (keep_alive) { if (connection_header && connection_header->Compare("close") == 0) { keep_alive = false; } else { // the request says client supports keep-alive // but override if response has content-length header or // transfer chunked encoding keep_alive = content_length || (transfer_encoding && transfer_encoding->Compare(NPT_HTTP_TRANSFER_ENCODING_CHUNKED) == 0); } } // only write keep-alive header for 1.1 if it's close NPT_String protocol = response->GetProtocol(); if (protocol.Compare(NPT_HTTP_PROTOCOL_1_0, true) == 0 || !keep_alive) { headers.SetHeader(NPT_HTTP_HEADER_CONNECTION, keep_alive?"keep-alive":"close", true); } headers.SetHeader(NPT_HTTP_HEADER_SERVER, PLT_HTTP_DEFAULT_SERVER, false); // set but don't replace PLT_LOG_HTTP_RESPONSE(NPT_LOG_LEVEL_FINE, "PLT_HttpServerSocketTask::Write", response); // create a memory stream to buffer the headers NPT_MemoryStream header_stream; response->Emit(header_stream); // send the headers NPT_CHECK_WARNING(output_stream.WriteFully(header_stream.GetData(), header_stream.GetDataSize())); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_EventSubscriber::Notify +---------------------------------------------------------------------*/ NPT_Result PLT_EventSubscriber::Notify(NPT_List<PLT_StateVariable*>& vars) { // verify we have eventable variables bool foundVars = false; NPT_XmlElementNode* propertyset = new NPT_XmlElementNode("e", "propertyset"); NPT_CHECK_SEVERE(propertyset->SetNamespaceUri( "e", "urn:schemas-upnp-org:event-1-0")); NPT_List<PLT_StateVariable*>::Iterator var = vars.GetFirstItem(); while (var) { if ((*var)->IsSendingEvents()) { NPT_XmlElementNode* property = new NPT_XmlElementNode("e", "property"); propertyset->AddChild(property); PLT_XmlHelper::AddChildText(property, (*var)->GetName(), (*var)->GetValue()); foundVars = true; } ++var; } // no eventable state variables found! if (foundVars == false) { delete propertyset; return NPT_FAILURE; } // format the body with the xml NPT_String xml; if (NPT_FAILED(PLT_XmlHelper::Serialize(*propertyset, xml))) { delete propertyset; NPT_CHECK_FATAL(NPT_FAILURE); } delete propertyset; // parse the callback url NPT_HttpUrl url(m_CallbackURLs[0]); if (!url.IsValid()) { NPT_CHECK_FATAL(NPT_FAILURE); } // format request NPT_HttpRequest* request = new NPT_HttpRequest(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1); NPT_HttpEntity* entity; PLT_HttpHelper::SetBody(*request, xml, &entity); // add the extra headers entity->SetContentType("text/xml; charset=\"utf-8\""); PLT_UPnPMessageHelper::SetNT(*request, "upnp:event"); PLT_UPnPMessageHelper::SetNTS(*request, "upnp:propchange"); PLT_UPnPMessageHelper::SetSID(*request, m_SID); PLT_UPnPMessageHelper::SetSeq(*request, m_EventKey); // wrap around sequence to 1 if (++m_EventKey == 0) m_EventKey = 1; // start the task now if not started already if (!m_SubscriberTask) { // TODO: the subscriber task should inform subscriber if // a notification failed to be received so it can be removed // from the list of subscribers inside the device host m_SubscriberTask = new PLT_HttpClientSocketTask(request, true); // short connection time out in case subscriber is not alive NPT_HttpClient::Config config; config.m_ConnectionTimeout = 2000; m_SubscriberTask->SetHttpClientConfig(config); // add initial delay to make sure ctrlpoint receives response to subscription // before our first NOTIFY. Also make sure task is not auto-destroy // since we want to destroy it manually when the subscriber goes away. NPT_TimeInterval delay(0.05f); NPT_CHECK_FATAL(m_TaskManager->StartTask(m_SubscriberTask, NULL /*&delay*/, false)); } else { m_SubscriberTask->AddRequest(request); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }