summaryrefslogtreecommitdiff
path: root/upnp/contentdirectory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'upnp/contentdirectory.cpp')
-rw-r--r--upnp/contentdirectory.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/upnp/contentdirectory.cpp b/upnp/contentdirectory.cpp
new file mode 100644
index 0000000..954f001
--- /dev/null
+++ b/upnp/contentdirectory.cpp
@@ -0,0 +1,306 @@
+/*
+ * File: contentdirectory.cpp
+ * Author: savop
+ *
+ * Created on 21. August 2009, 16:12
+ */
+
+#include <upnp/ixml.h>
+#include <upnp/upnptools.h>
+#include "upnp/contentdirectory.h"
+#include "../common.h"
+#include "util.h"
+
+cContentDirectory::cContentDirectory(UpnpDevice_Handle DeviceHandle, cMediaDatabase* MediaDatabase)
+: cUpnpService(DeviceHandle) {
+ this->mMediaDatabase = MediaDatabase;
+}
+
+cContentDirectory::~cContentDirectory() {}
+
+int cContentDirectory::subscribe(Upnp_Subscription_Request* Request){
+ IXML_Document* PropertySet = NULL;
+
+ /* The system update ID */
+ UpnpAddToPropertySet(&PropertySet, "SystemUpdateID", itoa(this->mMediaDatabase->getSystemUpdateID()));
+ /* The container update IDs as CSV list */
+ UpnpAddToPropertySet(&PropertySet, "ContainerUpdateIDs", this->mMediaDatabase->getContainerUpdateIDs());
+ /* The transfer IDs, which are not supported, i.e. empty */
+ UpnpAddToPropertySet(&PropertySet, "TransferIDs", "");
+ // Accept subscription
+ int ret = UpnpAcceptSubscriptionExt(this->mDeviceHandle, Request->UDN, Request->ServiceId, PropertySet, Request->Sid);
+
+ if(ret != UPNP_E_SUCCESS){
+ ERROR("Subscription failed (Error code: %d)", ret);
+ }
+
+ ixmlDocument_free(PropertySet);
+ return ret;
+}
+
+void cContentDirectory::Action(){
+ static int Retry = 5;
+ MESSAGE(VERBOSE_CDS, "Start Content directory thread");
+ while(this->Running()){
+ IXML_Document* PropertySet = NULL;
+ UpnpAddToPropertySet(&PropertySet, "SystemUpdateID", itoa(this->mMediaDatabase->getSystemUpdateID()));
+ int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet);
+ ixmlDocument_free(PropertySet);
+
+ if(ret != UPNP_E_SUCCESS){
+ Retry--;
+ ERROR("State change notification failed (Error code: %d)",ret);
+ ERROR("%d of %d notifications failed", (5-Retry), 5);
+ }
+ else {
+ Retry = 5;
+ }
+ if (!Retry){
+ ERROR("Maximum retries of notifications reached. Stopping...");
+ this->Cancel();
+ }
+ // Sleep 2 seconds
+ cCondWait::SleepMs(2000);
+ }
+}
+
+int cContentDirectory::execute(Upnp_Action_Request* Request){
+ if (Request == NULL) {
+ ERROR("CMS Action Handler - request is null");
+ return UPNP_E_BAD_REQUEST;
+ }
+
+ if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_BROWSE))
+ return this->browse(Request);
+ if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SEARCHCAPABILITIES))
+ return this->getSearchCapabilities(Request);
+ if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SORTCAPABILITIES))
+ return this->getSortCapabilities(Request);
+ if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SYSTEMUPDATEID))
+ return this->getSystemUpdateID(Request);
+
+ return UPNP_E_BAD_REQUEST;
+}
+
+
+int cContentDirectory::browse(Upnp_Action_Request* Request){
+ MESSAGE(VERBOSE_CDS, "Browse requested by %s.", inet_ntoa(Request->CtrlPtIPAddr));
+
+ char* ObjectID = NULL;
+ if(this->parseStringValue(Request->ActionRequest, "ObjectID", &ObjectID)){
+ ERROR("Invalid arguments. ObjectID missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ char* BrowseFlag = NULL;
+ bool BrowseMetadata = false;
+ if(this->parseStringValue(Request->ActionRequest, "BrowseFlag", &BrowseFlag)){
+ ERROR("Invalid arguments. Browse flag missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+ if(!strcasecmp(BrowseFlag, "BrowseMetadata")){
+ BrowseMetadata = true;
+ }
+ else if(!strcasecmp(BrowseFlag, "BrowseDirectChildren")){
+ BrowseMetadata = false;
+ }
+ else {
+ ERROR("Invalid argument. Browse flag invalid");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ char* Filter = NULL;
+ if(this->parseStringValue(Request->ActionRequest, "Filter", &Filter)){
+ ERROR("Invalid arguments. Filter missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ int StartingIndex = 0;
+ if(this->parseIntegerValue(Request->ActionRequest, "StartingIndex", &StartingIndex)){
+ ERROR("Invalid arguments. Starting index missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ int RequestedCount = 0;
+ if(this->parseIntegerValue(Request->ActionRequest, "RequestedCount", &RequestedCount)){
+ ERROR("Invalid arguments. Requested count missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ char* SortCriteria = NULL;
+ if(this->parseStringValue(Request->ActionRequest, "SortCriteria", &SortCriteria)){
+ ERROR("Invalid arguments. Sort criteria missing or wrong");
+ this->setError(Request, UPNP_SOAP_E_INVALID_ARGS);
+ return Request->ErrCode;
+ }
+
+ cUPnPResultSet* ResultSet;
+
+ int ret = this->mMediaDatabase->browse(&ResultSet, ObjectID, BrowseMetadata, Filter, StartingIndex, RequestedCount, SortCriteria);
+ if(ret!=UPNP_E_SUCCESS){
+ ERROR("Error while browsing. Code: %d", ret);
+ this->setError(Request, ret);
+ return Request->ErrCode;
+ }
+
+ char* escapedResult = NULL;
+ escapeXMLCharacters(ResultSet->mResult, &escapedResult);
+
+ if(!escapedResult){
+ ERROR("Escaping XML data failed");
+ this->setError(Request, UPNP_SOAP_E_ACTION_FAILED);
+ return Request->ErrCode;
+ }
+
+ cString Result = cString::sprintf(
+ "<u:%sResponse xmlns:u=\"%s\"> \
+ <Result>%s</Result> \
+ <NumberReturned>%d</NumberReturned> \
+ <TotalMatches>%d</TotalMatches> \
+ <UpdateID>%d</UpdateID> \
+ </u:%sResponse>",
+ Request->ActionName,
+ UPNP_CDS_SERVICE_TYPE,
+ escapedResult,
+ ResultSet->mNumberReturned,
+ ResultSet->mTotalMatches,
+ this->mMediaDatabase->getSystemUpdateID(),
+ Request->ActionName
+ );
+
+ Request->ActionResult = ixmlParseBuffer(Result);
+ Request->ErrCode = UPNP_E_SUCCESS;
+
+ free(escapedResult);
+
+ return Request->ErrCode;
+
+}
+
+int cContentDirectory::getSystemUpdateID(Upnp_Action_Request* Request){
+ cString Result = cString::sprintf(
+ "<u:%sResponse xmlns:u=\"%s\"> \
+ <Id>%d</Id> \
+ </u:%sResponse>",
+ Request->ActionName,
+ UPNP_CDS_SERVICE_TYPE,
+ this->mMediaDatabase->getSystemUpdateID(),
+ Request->ActionName
+ );
+
+ Request->ActionResult = ixmlParseBuffer(Result);
+ Request->ErrCode = UPNP_E_SUCCESS;
+
+ return Request->ErrCode;
+}
+
+int cContentDirectory::getSearchCapabilities(Upnp_Action_Request* Request){
+ MESSAGE(VERBOSE_CDS, "Sorry, no search capabilities yet");
+
+ cString Result = cString::sprintf(
+ "<u:%sResponse xmlns:u=\"%s\"> \
+ <SearchCaps>%s</SearchCaps> \
+ </u:%sResponse>",
+ Request->ActionName,
+ UPNP_CDS_SERVICE_TYPE,
+ UPNP_CDS_SEARCH_CAPABILITIES,
+ Request->ActionName
+ );
+
+ Request->ActionResult = ixmlParseBuffer(Result);
+ Request->ErrCode = UPNP_E_SUCCESS;
+
+ return Request->ErrCode;
+}
+
+int cContentDirectory::getSortCapabilities(Upnp_Action_Request* Request){
+ MESSAGE(VERBOSE_CDS, "Sorry, no sort capabilities yet");
+
+ cString Result = cString::sprintf(
+ "<u:%sResponse xmlns:u=\"%s\"> \
+ <SortCaps>%s</SortCaps> \
+ </u:%sResponse>",
+ Request->ActionName,
+ UPNP_CDS_SERVICE_TYPE,
+ UPNP_CDS_SORT_CAPABILITIES,
+ Request->ActionName
+ );
+
+ Request->ActionResult = ixmlParseBuffer(Result);
+ Request->ErrCode = UPNP_E_SUCCESS;
+
+ return Request->ErrCode;
+}
+
+void cContentDirectory::setError(Upnp_Action_Request* Request, int Error){
+ Request->ErrCode = Error;
+ switch(Error){
+ case UPNP_CDS_E_BAD_METADATA:
+ strn0cpy(Request->ErrStr,_("Bad metadata"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_CANT_PROCESS_REQUEST:
+ strn0cpy(Request->ErrStr,_("Cannot process the request"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_DEST_RESOURCE_ACCESS_DENIED:
+ strn0cpy(Request->ErrStr,_("Destination resource access denied"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_INVALID_CURRENT_TAG:
+ strn0cpy(Request->ErrStr,_("Invalid current tag"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_INVALID_NEW_TAG:
+ strn0cpy(Request->ErrStr,_("Invalid new tag"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_INVALID_SEARCH_CRITERIA:
+ strn0cpy(Request->ErrStr,_("Invalid or unsupported search criteria"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_INVALID_SORT_CRITERIA:
+ strn0cpy(Request->ErrStr,_("Invalid or unsupported sort criteria"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_NO_SUCH_CONTAINER:
+ strn0cpy(Request->ErrStr,_("No such container"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_NO_SUCH_DESTINATION_RESOURCE:
+ strn0cpy(Request->ErrStr,_("No such destination resource"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_NO_SUCH_FILE_TRANSFER:
+ strn0cpy(Request->ErrStr,_("No such file transfer"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_NO_SUCH_OBJECT:
+ strn0cpy(Request->ErrStr,_("No such objectID"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_NO_SUCH_SOURCE_RESOURCE:
+ strn0cpy(Request->ErrStr,_("No such source resource"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_PARAMETER_MISMATCH:
+ strn0cpy(Request->ErrStr,_("Parameter mismatch"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_READ_ONLY_TAG:
+ strn0cpy(Request->ErrStr,_("Read only tag"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_REQUIRED_TAG:
+ strn0cpy(Request->ErrStr,_("Required tag"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_RESOURCE_ACCESS_DENIED:
+ strn0cpy(Request->ErrStr,_("Resource access denied"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_RESTRICTED_OBJECT:
+ strn0cpy(Request->ErrStr,_("Restricted object"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_RESTRICTED_PARENT:
+ strn0cpy(Request->ErrStr,_("Restricted parent"),LINE_SIZE);
+ break;
+ case UPNP_CDS_E_TRANSFER_BUSY:
+ strn0cpy(Request->ErrStr,_("Transfer busy"),LINE_SIZE);
+ break;
+ default:
+ cUpnpService::setError(Request, Error);
+ break;
+ }
+ return;
+} \ No newline at end of file