/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseMetadata +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseMetadata(PLT_ActionReference& action, const char* object_id, const NPT_HttpRequestContext& context) { NPT_String didl; PLT_MediaObjectReference item; /* locate the file from the object ID */ NPT_String filepath; if (NPT_FAILED(GetFilePath(object_id, filepath))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } item = BuildFromFilePath( filepath, true, &context.GetLocalAddress()); if (item.IsNull()) return NPT_FAILURE; NPT_String filter; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); /* add didl header and footer */ didl = didl_header + tmp + didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", "1")); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", "1")); // update ID may be wrong here, it should be the one of the container? // TODO: We need to keep track of the overall updateID of the CDS NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_DeviceData::SetDescriptionDevice +---------------------------------------------------------------------*/ NPT_Result PLT_DeviceData::SetDescriptionDevice(PLT_DeviceDataReference& device, NPT_XmlElementNode* device_node, const NPT_HttpRequestContext& context) { NPT_Result res; device->m_LocalIfaceIp = context.GetLocalAddress().GetIpAddress(); NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "deviceType", device->m_DeviceType)); NPT_CHECK_SEVERE(PLT_XmlHelper::GetChildText(device_node, "UDN", device->m_UUID)); // remove uuid: prefix if (device->m_UUID.StartsWith("uuid:")) { device->m_UUID = ((const char*)device->m_UUID)+5; } // optional attributes PLT_XmlHelper::GetChildText(device_node, "friendlyName", device->m_FriendlyName); PLT_XmlHelper::GetChildText(device_node, "manufacturer", device->m_Manufacturer); PLT_XmlHelper::GetChildText(device_node, "manufacturerURL", device->m_ManufacturerURL); PLT_XmlHelper::GetChildText(device_node, "modelDescription", device->m_ModelDescription); PLT_XmlHelper::GetChildText(device_node, "modelName", device->m_ModelName); PLT_XmlHelper::GetChildText(device_node, "modelURL", device->m_ModelURL); PLT_XmlHelper::GetChildText(device_node, "modelNumber", device->m_ModelNumber); PLT_XmlHelper::GetChildText(device_node, "serialNumber", device->m_SerialNumber); // enumerate icons NPT_XmlElementNode* iconList = PLT_XmlHelper::GetChild(device_node, "iconList"); if (iconList) { NPT_Array<NPT_XmlElementNode*> icons; PLT_XmlHelper::GetChildren(iconList, icons, "icon"); for (NPT_Cardinal k=0 ; k<icons.GetItemCount(); k++) { PLT_DeviceIcon icon; NPT_String integer, height, depth; PLT_XmlHelper::GetChildText(icons[k], "mimetype", icon.m_MimeType); PLT_XmlHelper::GetChildText(icons[k], "url", icon.m_UrlPath); if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "width", integer))) NPT_ParseInteger32(integer, icon.m_Width); if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "height", integer))) NPT_ParseInteger32(integer, icon.m_Height); if(NPT_SUCCEEDED(PLT_XmlHelper::GetChildText(icons[k], "depth", integer))) NPT_ParseInteger32(integer, icon.m_Depth); device->m_Icons.Add(icon); } } // enumerate device services NPT_XmlElementNode* serviceList = PLT_XmlHelper::GetChild(device_node, "serviceList"); if (serviceList) { NPT_Array<NPT_XmlElementNode*> services; PLT_XmlHelper::GetChildren(serviceList, services, "service"); for( int k = 0 ; k < (int)services.GetItemCount(); k++) { NPT_String type, id, url; PLT_XmlHelper::GetChildText(services[k], "serviceType", type); PLT_XmlHelper::GetChildText(services[k], "serviceId", id); PLT_Service* service = new PLT_Service(device.AsPointer(), type, id, NULL); PLT_XmlHelper::GetChildText(services[k], "SCPDURL", url); service->SetSCPDURL(url); PLT_XmlHelper::GetChildText(services[k], "controlURL", url); service->SetControlURL(url); PLT_XmlHelper::GetChildText(services[k], "eventSubURL", url); service->SetEventSubURL(url); if (NPT_FAILED(res = device->AddService(service))) { delete service; return res; } } } // enumerate embedded devices NPT_XmlElementNode* deviceList = PLT_XmlHelper::GetChild(device_node, "deviceList"); if (deviceList) { NPT_Array<NPT_XmlElementNode*> devices; PLT_XmlHelper::GetChildren(deviceList, devices, "device"); for (int k = 0; k<(int)devices.GetItemCount(); k++) { // create an embedded device with same url base and leasetime as parent PLT_DeviceDataReference embedded_device(new PLT_DeviceData(device->m_URLDescription, "", device->m_LeaseTime)); NPT_CHECK_SEVERE(PLT_DeviceData::SetDescriptionDevice(embedded_device, devices[k], context)); device->AddEmbeddedDevice(embedded_device); } } // TODO: Parse extra DLNA stuff return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_FileMediaServer::OnBrowseDirectChildren +---------------------------------------------------------------------*/ NPT_Result PLT_FileMediaServer::OnBrowseDirectChildren(PLT_ActionReference& action, const char* object_id, const NPT_HttpRequestContext& context) { /* locate the file from the object ID */ NPT_String dir; if (NPT_FAILED(GetFilePath(object_id, dir))) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - ObjectID not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } /* retrieve the item type */ NPT_FileInfo info; NPT_Result res = NPT_File::GetInfo(dir, &info); if (NPT_FAILED(res)) { /* Object does not exist */ NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN failed for item %s", dir.GetChars()); action->SetError(800, "Can't retrieve info " + dir); return NPT_FAILURE; } if (info.m_Type != NPT_FileInfo::FILE_TYPE_DIRECTORY) { /* error */ NPT_LOG_WARNING("PLT_FileMediaServer::OnBrowse - BROWSEDIRECTCHILDREN not allowed on an item."); action->SetError(710, "item is not a container."); return NPT_FAILURE; } NPT_String filter; NPT_String startingInd; NPT_String reqCount; NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_UInt32 start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { action->SetError(412, "Precondition failed"); return NPT_FAILURE; } NPT_List<NPT_String> entries; res = NPT_File::ListDirectory(dir, entries, 0, 0); if (NPT_FAILED(res)) { NPT_LOG_WARNING_1("PLT_FileMediaServer::OnBrowseDirectChildren - failed to open dir %s", (const char*) dir); return res; } unsigned long cur_index = 0; unsigned long num_returned = 0; unsigned long total_matches = 0; NPT_String didl = didl_header; PLT_MediaObjectReference item; for (NPT_List<NPT_String>::Iterator it = entries.GetFirstItem(); it; ++it) { NPT_String& filename = *it; item = BuildFromFilePath( NPT_FilePath::Create(dir, filename), true, &context.GetLocalAddress()); if (!item.IsNull()) { if ((cur_index >= start_index) && ((num_returned < req_count) || (req_count == 0))) { NPT_String tmp; NPT_CHECK_SEVERE(PLT_Didl::ToDidl(*item.AsPointer(), filter, tmp)); didl += tmp; num_returned++; } cur_index++; total_matches++; } }; didl += didl_footer; NPT_CHECK_SEVERE(action->SetArgumentValue("Result", didl)); NPT_CHECK_SEVERE(action->SetArgumentValue("NumberReturned", NPT_String::FromInteger(num_returned))); NPT_CHECK_SEVERE(action->SetArgumentValue("TotalMatches", NPT_String::FromInteger(total_matches))); // 0 means we don't know how many we have but most browsers don't like that!! NPT_CHECK_SEVERE(action->SetArgumentValue("UpdateId", "1")); 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; }
/*---------------------------------------------------------------------- | CMediaCrawler::OnBrowseDevice +---------------------------------------------------------------------*/ NPT_Result CMediaCrawler::OnBrowseDevice(PLT_ActionReference& action, const char* server_uuid, const char* server_object_id, const NPT_HttpRequestContext& context) { NPT_Result res; PLT_DeviceDataReference device; { // look for device first const NPT_Lock<PLT_DeviceDataReferenceList>& devices = GetMediaServers(); NPT_AutoLock lock((NPT_Mutex&)devices); if (NPT_FAILED(NPT_ContainerFind(devices, PLT_DeviceDataFinder(server_uuid), device))) { /* error */ NPT_LOG_WARNING("CMediaCrawler::OnBrowseDevice - device not found."); action->SetError(701, "No Such Object."); return NPT_FAILURE; } } // look for args and convert them NPT_String browseFlagValue; NPT_String startingInd; NPT_String reqCount; NPT_String filter; NPT_String sort; NPT_CHECK_SEVERE(action->GetArgumentValue("BrowseFlag", browseFlagValue)); NPT_CHECK_SEVERE(action->GetArgumentValue("StartingIndex", startingInd)); NPT_CHECK_SEVERE(action->GetArgumentValue("RequestedCount", reqCount)); NPT_CHECK_SEVERE(action->GetArgumentValue("Filter", filter)); NPT_CHECK_SEVERE(action->GetArgumentValue("SortCriteria", sort)); unsigned long start_index, req_count; if (NPT_FAILED(startingInd.ToInteger(start_index)) || NPT_FAILED(reqCount.ToInteger(req_count))) { return NPT_FAILURE; } // create a container for our result // this will be filled in by OnBrowseResponse CMediaCrawlerBrowseInfoReference browse_info(new CMediaCrawlerBrowseInfo()); browse_info->shared_var.SetValue(0); // send off the browse packet. Note that this will // not block. The shared variable is used to block // until the response has been received. res = Browse(device, server_object_id, start_index, req_count, (browseFlagValue == "BrowseMetadata")?1:0, filter, sort, new CMediaCrawlerBrowseInfoReference(browse_info)); NPT_CHECK_SEVERE(res); // wait 30 secs for response res = browse_info->shared_var.WaitUntilEquals(1, 30000); NPT_CHECK_SEVERE(res); // did the browse fail? if (NPT_FAILED(browse_info->res)) { action->SetError(browse_info->code, ""); return NPT_FAILURE; } action->SetArgumentValue("Result", UpdateDidl(server_uuid, browse_info->didl, &context.GetLocalAddress())); action->SetArgumentValue("NumberReturned", browse_info->nr); action->SetArgumentValue("TotalMatches", browse_info->tm); action->SetArgumentValue("UpdateId", browse_info->uid); action->SetArgumentValue("ObjectID", FormatObjectId(server_uuid, browse_info->object_id)); return NPT_SUCCESS; }