/*---------------------------------------------------------------------- | 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)); }
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; }
/*---------------------------------------------------------------------- | 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_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; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::GetContentRange +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::GetContentRange(const NPT_HttpResponse& response, NPT_Position& start, NPT_Position& end, NPT_LargeSize& length) { const NPT_String* range = response.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_CONTENT_RANGE); NPT_CHECK_POINTER(range); start = (NPT_Position)-1; end = (NPT_Position)-1; length = (NPT_LargeSize)-1; char s[32], e[32], l[32]; s[0] = '\0'; e[0] = '\0'; l[0] = '\0'; int ret = sscanf(*range, "bytes %31[^-]-%31s[^/]/%31s", s, e, l); if (ret < 3) { return NPT_FAILURE; } if (s[0] != '\0') { NPT_ParseInteger64(s, start); } if (e[0] != '\0') { NPT_ParseInteger64(e, end); } if (l[0] != '\0') { NPT_ParseInteger64(l, length); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpSender::SendSsdp +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpSender::SendSsdp(NPT_HttpResponse& response, const char* usn, const char* target, NPT_UdpSocket& socket, bool notify, const NPT_SocketAddress* addr /* = NULL */) { NPT_CHECK_SEVERE(FormatPacket(response, usn, target, socket, notify)); // logging NPT_LOG_FINE("Sending SSDP:"); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &response); // use a memory stream to write all the data NPT_MemoryStream stream; NPT_Result res = response.Emit(stream); if (NPT_FAILED(res)) return res; // copy stream into a data packet and send it NPT_LargeSize size; stream.GetSize(size); if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE; NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size); return socket.Send(packet, addr); }
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; }
/*---------------------------------------------------------------------- | 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; }
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; }
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; }
/*---------------------------------------------------------------------- | NPT_HttpResponse::ToLog +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::ToLog(NPT_LoggerReference logger, int level, const NPT_HttpResponse& response) { NPT_COMPILER_UNUSED(logger); NPT_COMPILER_UNUSED(level); NPT_StringOutputStreamReference stream(new NPT_StringOutputStream); NPT_OutputStreamReference output = stream; response.GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output)); NPT_LOG_L4(logger, level, "\n%s %d %s\n%s", (const char*)response.GetProtocol(), response.GetStatusCode(), (const char*)response.GetReasonPhrase(), (const char*)stream->GetString()); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }
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; }
// 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; }
/*---------------------------------------------------------------------- | 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_FileMediaServer::OnAlbumArtRequest +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnAlbumArtRequest(NPT_HttpResponse& response, NPT_String file_path) { NPT_LargeSize total_len; NPT_File file(file_path); NPT_InputStreamReference stream; // prevent hackers from accessing files outside of our root if ((file_path.Find("/..") >= 0) || (file_path.Find("\\..") >= 0)) { return NPT_FAILURE; } if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) { goto filenotfound; } else { NPT_String extension = NPT_FilePath::FileExtension(file_path); if (extension.GetLength() == 0) { goto filenotfound; } PLT_MetadataHandler* metadataHandler = NULL; char* caData; int caDataLen; NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, PLT_MetadataHandlerFinder(extension), metadataHandler); if (NPT_FAILED(ret) || metadataHandler == NULL) { goto filenotfound; } // load the metadatahandler and read the cover art if (NPT_FAILED(metadataHandler->Load(*stream)) || NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) { goto filenotfound; } PLT_HttpHelper::SetContentType(response, "application/octet-stream"); PLT_HttpHelper::SetBody(response, caData, caDataLen); delete caData; return NPT_SUCCESS; } filenotfound: response.SetStatus(404, "File Not Found"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpHelper::SetContentRange +---------------------------------------------------------------------*/ NPT_Result PLT_HttpHelper::SetContentRange(NPT_HttpResponse& response, NPT_Position start, NPT_Position end, NPT_LargeSize length) { if (start == (NPT_Position)-1 || end == (NPT_Position)-1 || length == (NPT_Size)-1) { NPT_LOG_WARNING_3("Content Range is exactly -1? (start=%d, end=%d, length=%d)", start, end, length); } NPT_String range = "bytes "; range += NPT_String::FromIntegerU(start); range += '-'; range += NPT_String::FromIntegerU(end); range += '/'; range += NPT_String::FromIntegerU(length); response.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, range); return NPT_SUCCESS; }
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; }
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; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnAlbumArtRequest +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnAlbumArtRequest(NPT_String filepath, NPT_HttpResponse& response) { NPT_Size total_len; NPT_File file(filepath); NPT_InputStreamReference stream; if (NPT_FAILED(file.Open(NPT_FILE_OPEN_MODE_READ)) || NPT_FAILED(file.GetInputStream(stream)) || NPT_FAILED(stream->GetSize(total_len)) || (total_len == 0)) { goto filenotfound; } else { const char* extension = PLT_MediaItem::GetExtFromFilePath(filepath, m_DirDelimiter); if (extension == NULL) { goto filenotfound; } PLT_MetadataHandler* metadataHandler = NULL; char* caData; int caDataLen; NPT_Result ret = NPT_ContainerFind(m_MetadataHandlers, PLT_MetadataHandlerFinder(extension), metadataHandler); if (NPT_FAILED(ret) || metadataHandler == NULL) { goto filenotfound; } // load the metadatahandler and read the cover art if (NPT_FAILED(metadataHandler->Load(*stream)) || NPT_FAILED(metadataHandler->GetCoverArtData(caData, caDataLen))) { goto filenotfound; } PLT_HttpHelper::SetContentType(&response, "application/octet-stream"); PLT_HttpHelper::SetBody(&response, caData, caDataLen); delete caData; return NPT_SUCCESS; } filenotfound: response.SetStatus(404, "File Not Found"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }
void serveStreamAdv(AbortableTask *task, const MediaStore::FileDetail& detail, AdvStreamReader *reader, const FrontEnd::RequestContext& reqCtx, const NPT_HttpRequest *req, NPT_HttpResponse& resp, HttpOutput *httpOutput, NPT_Size bufferSize) { bool isGetMethod = req->GetMethod().Compare("GET") == 0; bool isHeadMethod = req->GetMethod().Compare("HEAD") == 0; if (isGetMethod || isHeadMethod) { NPT_Result nr; NPT_UInt64 offset, length; NPT_HttpHeader *hdrRange = req->GetHeaders().GetHeader("RANGE"); if (hdrRange) { if (!parseRangeHeader(hdrRange->GetValue(), detail.m_size, offset, length)) { setStatusCode(resp, 416); httpOutput->writeResponseHeader(resp); return; } setStatusCode(resp, 206); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, NPT_String::Format("bytes %s-%s/%s", NPT_String::FromIntegerU(offset).GetChars(), NPT_String::FromIntegerU(offset + length - 1).GetChars(), NPT_String::FromIntegerU(detail.m_size).GetChars())); } else { offset = 0; length = detail.m_size; setStatusCode(resp, 200); } resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, detail.m_mimeType); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromIntegerU(length)); resp.GetHeaders().SetHeader("Last-Modified", NPT_DateTime(detail.m_modificationTime).ToString(NPT_DateTime::FORMAT_RFC_1123)); resp.GetHeaders().SetHeader("Accept-Ranges", "bytes"); resp.GetHeaders().SetHeader("EXT", ""); if (reqCtx.transferMode != FrontEnd::TM_None) { const char *transferMode = "Streaming"; switch (reqCtx.transferMode) { case FrontEnd::TM_Background: transferMode = "Background"; break; case FrontEnd::TM_Interactive: transferMode = "Interactive"; break; } resp.GetHeaders().SetHeader("transferMode.dlna.org", transferMode); } if (reqCtx.getcontentFeaturesReq) { NPT_String contentFeatures("DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"); resp.GetHeaders().SetHeader("contentFeatures.dlna.org", contentFeatures); } httpOutput->writeResponseHeader(resp); if (isGetMethod) { bool abortFlag = false; ServeFileAbortCallback abortCallback(&abortFlag, reader); if (task->registerAbortCallback(&abortCallback)) { reader->seek(offset); NPT_DataBuffer buffer(bufferSize); NPT_UInt64 cbRemain = length; for (;;) { if (abortFlag) { break; } if (cbRemain == 0) { break; } NPT_Size cbRead; NPT_Size cbToRead = cbRemain; if (cbToRead > buffer.GetBufferSize()) { cbToRead = buffer.GetBufferSize(); } nr = reader->read(buffer.UseData(), buffer.GetBufferSize(), &cbRead); if (NPT_FAILED(nr)) { /*if (nr == NPT_ERROR_EOS) { } else { }*/ break; } if (abortFlag) { break; } if (cbRead > 0) { cbRemain -= cbRead; httpOutput->writeData(buffer.GetData(), cbRead); } } task->unregisterAbortCallback(&abortCallback); } } } else { setStatusCode(resp, 405); resp.GetHeaders().SetHeader("Allow", "GET, HEAD"); httpOutput->writeResponseHeader(resp); } }
void FrontEnd::HttpOutputImpl::writeResponseHeader(const NPT_HttpResponse& response) { m_frontEnd->onHttpResponseHeader(m_socketInfo, &response); response.Emit(*m_outputStream); m_outputStream->Flush(); }
/*---------------------------------------------------------------------- | 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; }
void serveFile2(AbortableTask *task, const NPT_String& filePath, const NPT_String& mimeType, const FrontEnd::RequestContext& reqCtx, const NPT_HttpRequest *req, NPT_HttpResponse& resp, HttpOutput *httpOutput) { #if 1 NPT_File f(filePath); NPT_FileInfo fileInfo; if (NPT_FAILED(f.GetInfo(fileInfo)) || fileInfo.m_Type != NPT_FileInfo::FILE_TYPE_REGULAR || NPT_FAILED(f.Open(NPT_FILE_OPEN_MODE_READ))) { setStatusCode(resp, 404); httpOutput->writeResponseHeader(resp); return; } NPT_InputStreamReference fileInput; f.GetInputStream(fileInput); serveStream(task, fileInput.AsPointer(), fileInfo.m_ModificationTime, mimeType, reqCtx, req, resp, httpOutput); #else bool isGetMethod = req->GetMethod().Compare("GET") == 0; bool isHeadMethod = req->GetMethod().Compare("HEAD") == 0; if (isGetMethod || isHeadMethod) { NPT_Result nr; NPT_File f(filePath); NPT_FileInfo fileInfo; if (NPT_FAILED(f.GetInfo(fileInfo)) || fileInfo.m_Type != NPT_FileInfo::FILE_TYPE_REGULAR || NPT_FAILED(f.Open(NPT_FILE_OPEN_MODE_READ))) { setStatusCode(resp, 404); httpOutput->writeResponseHeader(resp); return; } NPT_InputStreamReference fileInput; f.GetInputStream(fileInput); NPT_UInt64 offset, length; NPT_HttpHeader *hdrRange = req->GetHeaders().GetHeader("RANGE"); if (hdrRange) { if (!parseRangeHeader(hdrRange->GetValue(), fileInfo.m_Size, offset, length)) { setStatusCode(resp, 416); httpOutput->writeResponseHeader(resp); return; } setStatusCode(resp, 206); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_RANGE, NPT_String::Format("bytes %s-%s/%s", NPT_String::FromIntegerU(offset).GetChars(), NPT_String::FromIntegerU(offset + length - 1).GetChars(), NPT_String::FromIntegerU(fileInfo.m_Size).GetChars())); fileInput->Seek(offset); } else { offset = 0; length = fileInfo.m_Size; setStatusCode(resp, 200); } resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_TYPE, mimeType); resp.GetHeaders().SetHeader(NPT_HTTP_HEADER_CONTENT_LENGTH, NPT_String::FromIntegerU(length)); resp.GetHeaders().SetHeader("Last-Modified", NPT_DateTime(fileInfo.m_ModificationTime).ToString(NPT_DateTime::FORMAT_RFC_1123)); resp.GetHeaders().SetHeader("Accept-Ranges", "bytes"); resp.GetHeaders().SetHeader("EXT", ""); if (reqCtx.transferMode != FrontEnd::TM_None) { const char *transferMode = "Streaming"; switch (reqCtx.transferMode) { case FrontEnd::TM_Background: transferMode = "Background"; break; case FrontEnd::TM_Interactive: transferMode = "Interactive"; break; } resp.GetHeaders().SetHeader("transferMode.dlna.org", transferMode); } if (reqCtx.getcontentFeaturesReq) { NPT_String contentFeatures("DLNA.ORG_OP=01;DLNA.ORG_CI=0;DLNA.ORG_FLAGS=01700000000000000000000000000000"); resp.GetHeaders().SetHeader("contentFeatures.dlna.org", contentFeatures); } httpOutput->writeResponseHeader(resp); if (isGetMethod) { bool abortFlag = false; ServeFileAbortCallback abortCallback(&abortFlag); if (task->registerAbortCallback(&abortCallback)) { NPT_DataBuffer buffer(4096); NPT_UInt64 cbRemain = length; for (;;) { if (abortFlag) { break; } if (cbRemain == 0) { break; } NPT_Size cbRead; NPT_UInt64 cbToRead = cbRemain; if (cbToRead > buffer.GetBufferSize()) { cbToRead = buffer.GetBufferSize(); } nr = fileInput->Read(buffer.UseData(), buffer.GetBufferSize(), &cbRead); if (NPT_FAILED(nr)) { /*if (nr == NPT_ERROR_EOS) { } else { }*/ break; } if (abortFlag) { break; } if (cbRead > 0) { cbRemain -= cbRead; httpOutput->writeData(buffer.GetData(), cbRead); } } task->unregisterAbortCallback(&abortCallback); } } } else { setStatusCode(resp, 405); resp.GetHeaders().SetHeader("Allow", "GET, HEAD"); httpOutput->writeResponseHeader(resp); } #endif }
/*---------------------------------------------------------------------- | 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; }
int SimpleDMR::onAction(const ServiceDecl *serviceDecl, const ActionDecl *actionDecl, AbortableTask *task, const FrontEnd::InterfaceContext *ifctx, const FrontEnd::RequestContext& reqCtx, const NPT_HttpRequest *req, const NPT_List<NPT_String>& inputArgNames, const NPT_List<NPT_String>& inputArgValues, NPT_List<NPT_String>& outputArgValues) { WriteLocker locker(m_stateLock); if (NPT_String::Compare(serviceDecl->serviceId, "urn:upnp-org:serviceId:AVTransport") == 0) { if (NPT_String::Compare(actionDecl->name, "SetAVTransportURI") == 0) { if (inputArgValues.GetItemCount() != 3) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } NPT_HttpClient httpClient; NPT_HttpRequest req(*inputArgValues.GetItem(1), NPT_HTTP_METHOD_GET, NPT_HTTP_PROTOCOL_1_1); Helper::setupHttpRequest(req); NPT_HttpResponse *resp; NPT_Result nr; HttpClientAbortCallback abortCallback(&httpClient); if (task->registerAbortCallback(&abortCallback)) { nr = httpClient.SendRequest(req, resp); task->unregisterAbortCallback(&abortCallback); } else { return 715; } if (NPT_FAILED(nr)) { return 716; } PtrHolder<NPT_HttpResponse> resp1(resp); if (resp->GetStatusCode() != 200) { return 716; } NPT_HttpHeader *hdrContentType = resp->GetHeaders().GetHeader(NPT_HTTP_HEADER_CONTENT_TYPE); if (!hdrContentType) { return 714; } setVar(DMRVAR_AVTransportURI, *inputArgValues.GetItem(1)); setVar(DMRVAR_AVTransportURIMetaData, *inputArgValues.GetItem(2)); setVar(DMRVAR_CurrentTrackMetaData, *inputArgValues.GetItem(2)); m_callback->doDmrOpen(this, *inputArgValues.GetItem(1), hdrContentType->GetValue(), *inputArgValues.GetItem(2)); return 0; } if (NPT_String::Compare(actionDecl->name, "GetMediaInfo") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } *outputArgValues.GetItem(0) = m_avtVars[DMRVAR_NumberOfTracks - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(1) = m_avtVars[DMRVAR_CurrentMediaDuration - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(2) = m_avtVars[DMRVAR_AVTransportURI - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(3) = m_avtVars[DMRVAR_AVTransportURIMetaData - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(4) = m_avtVars[DMRVAR_NextAVTransportURI - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(5) = m_avtVars[DMRVAR_NextAVTransportURIMetaData - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(6) = m_avtVars[DMRVAR_PlaybackStorageMedium - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(7) = m_avtVars[DMRVAR_RecordStorageMedium - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(8) = m_avtVars[DMRVAR_RecordMediumWriteStatus - DMRVAR_BaseIndexAVT]; return 0; } if (NPT_String::Compare(actionDecl->name, "GetTransportInfo") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } *outputArgValues.GetItem(0) = m_avtVars[DMRVAR_TransportState - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(1) = m_avtVars[DMRVAR_TransportStatus - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(2) = m_avtVars[DMRVAR_TransportPlaySpeed - DMRVAR_BaseIndexAVT]; return 0; } if (NPT_String::Compare(actionDecl->name, "GetPositionInfo") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } *outputArgValues.GetItem(0) = m_avtVars[DMRVAR_CurrentTrack - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(1) = m_avtVars[DMRVAR_CurrentTrackDuration - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(2) = m_avtVars[DMRVAR_CurrentTrackMetaData - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(3) = m_avtVars[DMRVAR_CurrentTrackURI - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(4) = m_avtVars[DMRVAR_RelativeTimePosition - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(5) = m_avtVars[DMRVAR_AbsoluteTimePosition - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(6) = m_avtVars[DMRVAR_RelativeCounterPosition - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(7) = m_avtVars[DMRVAR_AbsoluteCounterPosition - DMRVAR_BaseIndexAVT]; return 0; } if (NPT_String::Compare(actionDecl->name, "GetDeviceCapabilities") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } *outputArgValues.GetItem(0) = m_avtVars[DMRVAR_PossiblePlaybackStorageMedia - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(1) = m_avtVars[DMRVAR_PossibleRecordStorageMedia - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(2) = m_avtVars[DMRVAR_PossibleRecordQualityModes - DMRVAR_BaseIndexAVT]; return 0; } if (NPT_String::Compare(actionDecl->name, "GetTransportSettings") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } *outputArgValues.GetItem(0) = m_avtVars[DMRVAR_CurrentPlayMode - DMRVAR_BaseIndexAVT]; *outputArgValues.GetItem(1) = m_avtVars[DMRVAR_CurrentRecordQualityMode - DMRVAR_BaseIndexAVT]; return 0; } if (NPT_String::Compare(actionDecl->name, "Stop") == 0) { m_callback->doDmrStop(this); return 0; } if (NPT_String::Compare(actionDecl->name, "Play") == 0) { m_callback->doDmrPlay(this); return 0; } if (NPT_String::Compare(actionDecl->name, "Pause") == 0) { m_callback->doDmrPause(this); return 0; } if (NPT_String::Compare(actionDecl->name, "Seek") == 0) { if (inputArgValues.GetItemCount() != 3) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 718; } const NPT_String& seekMode = *inputArgValues.GetItem(1); const NPT_String& seekTarget = *inputArgValues.GetItem(2); if (seekMode.Compare("TRACK_NR") == 0) { // TODO: } else if (seekMode.Compare("REL_TIME") == 0) { NPT_UInt64 pos; if (NPT_FAILED(Helper::parseTrackDurationString(seekTarget, pos))) { // Illegal seek target return 711; } m_callback->doDmrSeekTo(this, pos); } else { // Seek mode not supported return 710; } return 0; } if (NPT_String::Compare(actionDecl->name, "Next") == 0) { return 0; } if (NPT_String::Compare(actionDecl->name, "Previous") == 0) { return 0; } return 602; } if (NPT_String::Compare(serviceDecl->serviceId, "urn:upnp-org:serviceId:RenderingControl") == 0) { if (NPT_String::Compare(actionDecl->name, "ListPresets") == 0) { if (inputArgValues.GetItemCount() != 1) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 702; } *outputArgValues.GetItem(0) = m_rcsVars[DMRVAR_PresetNameList - DMRVAR_BaseIndexRCS]; return 0; } if (NPT_String::Compare(actionDecl->name, "SelectPreset") == 0) { return 0; } if (NPT_String::Compare(actionDecl->name, "GetMute") == 0) { if (inputArgValues.GetItemCount() != 2) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 702; } *outputArgValues.GetItem(0) = m_rcsVars[DMRVAR_Mute - DMRVAR_BaseIndexRCS]; return 0; } if (NPT_String::Compare(actionDecl->name, "SetMute") == 0) { if (inputArgValues.GetItemCount() != 3) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 702; } const NPT_String& desiredMute = *inputArgValues.GetItem(2); m_callback->doDmrSetMute(this, desiredMute.Compare("true", true) == 0 || desiredMute.Compare("1") == 0); return 0; } if (NPT_String::Compare(actionDecl->name, "GetVolume") == 0) { if (inputArgValues.GetItemCount() != 2) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 702; } *outputArgValues.GetItem(0) = m_rcsVars[DMRVAR_Volume - DMRVAR_BaseIndexRCS]; return 0; } if (NPT_String::Compare(actionDecl->name, "SetVolume") == 0) { if (inputArgValues.GetItemCount() != 3) { // Invalid Args return 402; } if (inputArgValues.GetFirstItem()->Compare("0") != 0) { // Invalid InstanceID return 702; } const NPT_String& desiredVolume = *inputArgValues.GetItem(2); int volume; if (NPT_FAILED(NPT_ParseInteger(desiredVolume, volume))) { // Invalid Args return 402; } m_callback->doDmrSetVolume(this, volume); return 0; } return 602; } if (NPT_String::Compare(serviceDecl->serviceId, "urn:upnp-org:serviceId:ConnectionManager") == 0) { if (NPT_String::Compare(actionDecl->name, "GetProtocolInfo") == 0) { NPT_String v; if (getStateValue(serviceDecl->serviceId, "SourceProtocolInfo", v)) { *outputArgValues.GetItem(0) = v; } if (getStateValue(serviceDecl->serviceId, "SinkProtocolInfo", v)) { *outputArgValues.GetItem(1) = v; } return 0; } if (NPT_String::Compare(actionDecl->name, "GetCurrentConnectionIDs") == 0) { NPT_String v; if (getStateValue(serviceDecl->serviceId, "SourceProtocolInfo", v)) { *outputArgValues.GetItem(0) = v; } return 0; } if (NPT_String::Compare(actionDecl->name, "GetCurrentConnectionInfo") == 0) { *outputArgValues.GetItem(0) = "0"; *outputArgValues.GetItem(1) = "0"; *outputArgValues.GetItem(2) = ""; *outputArgValues.GetItem(3) = ""; *outputArgValues.GetItem(4) = "-1"; *outputArgValues.GetItem(5) = "Input"; // or "Output"? WTF! *outputArgValues.GetItem(6) = "OK"; return 0; } return 602; } return 501; }
/*---------------------------------------------------------------------- | 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; }