From 724cb5e3783311f6b8c808852dbe2de59f2399b0 Mon Sep 17 00:00:00 2001 From: Denis Loh Date: Mon, 25 Jan 2010 12:10:01 +0100 Subject: Fixed small bug which leads to an empty TV folder --- upnp/connectionmanager.cpp | 393 +++++++++++++++++++++++++++++++++++++++++++++ upnp/contentdirectory.cpp | 306 +++++++++++++++++++++++++++++++++++ upnp/service.cpp | 118 ++++++++++++++ 3 files changed, 817 insertions(+) create mode 100644 upnp/connectionmanager.cpp create mode 100644 upnp/contentdirectory.cpp create mode 100644 upnp/service.cpp (limited to 'upnp') diff --git a/upnp/connectionmanager.cpp b/upnp/connectionmanager.cpp new file mode 100644 index 0000000..4d1f97b --- /dev/null +++ b/upnp/connectionmanager.cpp @@ -0,0 +1,393 @@ +/* + * File: connectionmanager.cpp + * Author: savop + * + * Created on 21. August 2009, 18:35 + */ + +#include +#include +#include +#include +#include "upnp/connectionmanager.h" +#include "../common.h" +#include "upnp/dlna.h" + +cVirtualConnection::cVirtualConnection() : mRcsID(-1) {} + +cConnectionManager::cConnectionManager(UpnpDevice_Handle DeviceHandle) : cUpnpService(DeviceHandle) { + this->mVirtualConnections = new cList; + this->mDefaultConnection = this->createVirtualConnection(); + this->mSupportedProtocols = cDlna::getInstance()->getSupportedProtocols(); +} + +cConnectionManager::~cConnectionManager() { + delete this->mDefaultConnection; + delete this->mVirtualConnections; +} + +int cConnectionManager::subscribe(Upnp_Subscription_Request* Request){ + IXML_Document* PropertySet = NULL; + /* The protocol infos which this server supports */ + UpnpAddToPropertySet(&PropertySet, "SourceProtocolInfo", this->mSupportedProtocols); + /* Not set, this field is only used by Media Renderers */ + UpnpAddToPropertySet(&PropertySet, "SinkProtocolInfo", ""); + /* The current connection IDs of all virtual connections */ + const char* IDs = this->getConnectionIDsCVS(); + if(!IDs){ + return UPNP_E_INTERNAL_ERROR; + } + UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); + // 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; +} + +int cConnectionManager::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_CMS_ACTION_GETPROTOCOLINFO)) + return this->getProtocolInfo(Request); + if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_GETCURRENTCONNECTIONIDS)) + return this->getCurrentConnectionIDs(Request); + if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_GETCURRENTCONNECTIONINFO)) + return this->getCurrentConnectionInfo(Request); + if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_PREPAREFORCONNECTION)) + return this->prepareForConnection(Request); + if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_CONNECTIONCOMPLETE)) + return this->connectionComplete(Request); + + return UPNP_E_BAD_REQUEST; +} + +int cConnectionManager::getProtocolInfo(Upnp_Action_Request* Request){ + MESSAGE(VERBOSE_CMS, "Protocol info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); + cString Result = cString::sprintf( + " \ + %s \ + \ + ", + Request->ActionName, + UPNP_CMS_SERVICE_TYPE, + *this->mSupportedProtocols, + Request->ActionName + ); + Request->ActionResult = ixmlParseBuffer(Result); + Request->ErrCode = UPNP_E_SUCCESS; + return Request->ErrCode; +} + +int cConnectionManager::getCurrentConnectionIDs(Upnp_Action_Request* Request){ + MESSAGE(VERBOSE_CMS, "Current connection IDs requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); + cString Result; + const char* IDs = this->getConnectionIDsCVS(); + if(!IDs){ + Request->ErrCode = UPNP_E_INTERNAL_ERROR; + return Request->ErrCode; + } + Result = cString::sprintf( + " \ + %s \ + ", + Request->ActionName, + UPNP_CMS_SERVICE_TYPE, + IDs, + Request->ActionName + ); + Request->ActionResult = ixmlParseBuffer(Result); + Request->ErrCode = UPNP_E_SUCCESS; + return Request->ErrCode; +} + +int cConnectionManager::getCurrentConnectionInfo(Upnp_Action_Request* Request){ + MESSAGE(VERBOSE_CMS, "Current connection info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); + int ConnectionID; + + if(this->parseIntegerValue(Request->ActionRequest, "ConnectionID", &ConnectionID) != 0){ + ERROR("Invalid arguments. ConnectionID missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + cVirtualConnection* Connection; + for(Connection = this->mVirtualConnections->First(); Connection && Connection->mConnectionID != ConnectionID; Connection = this->mVirtualConnections->Next(Connection)){} + + if(Connection){ + cString Result = cString::sprintf( + "\ + %s\ + %s\ + %d\ + %s\ + %d\ + %d\ + %s\ + ", + Request->ActionName, + UPNP_CMS_SERVICE_TYPE, + *Connection->mRemoteProtocolInfo, + *Connection->mRemoteConnectionManager, + -1, + cVirtualConnection::getDirectionString(OUTPUT), + Connection->mRcsID, + Connection->mAVTransportID, + cVirtualConnection::getStatusString(Connection->mStatus), + Request->ActionName + ); + Request->ActionResult = ixmlParseBuffer(Result); + Request->ErrCode = UPNP_E_SUCCESS; + } + else { + ERROR("No valid connection found with given ID=%d!", ConnectionID); + this->setError(Request, 706); + } + + return Request->ErrCode; + +} + +int cConnectionManager::prepareForConnection(Upnp_Action_Request* Request){ + MESSAGE(VERBOSE_CMS, "Request for a new connection by %s.", inet_ntoa(Request->CtrlPtIPAddr)); + //char* Result = NULL; + char* RemoteProtocolInfo = NULL; + char* PeerConnectionManager = NULL; + int PeerConnectionID = 0; + char* DirectionStr = NULL; + int Direction; + + if(this->parseStringValue(Request->ActionRequest, "RemoteProtocolInfo", &RemoteProtocolInfo) != 0){ + ERROR("Invalid argument RemoteProtocolInfo: Missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + if(this->parseStringValue(Request->ActionRequest, "PeerConnectionManager", &PeerConnectionManager) != 0){ + ERROR("Invalid argument PeerConnectionManager: Missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + if(this->parseStringValue(Request->ActionRequest, "Direction", &DirectionStr) != 0 && (Direction = cVirtualConnection::getDirection(DirectionStr)) == -1){ + ERROR("Invalid argument Direction: Missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + if(this->parseIntegerValue(Request->ActionRequest, "PeerConnectionID", &PeerConnectionID) != 0){ + ERROR("Invalid argument PeerConnectionID: Missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + + /* TODO: + Create Connection + Notify AVTransport that a new connection was established + Send back the response */ + this->setError(Request, UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED); + return Request->ErrCode; +} + +int cConnectionManager::connectionComplete(Upnp_Action_Request* Request){ + MESSAGE(VERBOSE_CMS, "Request for closing an open connection by %s.", inet_ntoa(Request->CtrlPtIPAddr)); + //char* Result = NULL; + int ConnectionID; + + if(this->parseIntegerValue(Request->ActionRequest, "ConnectionID", &ConnectionID) != 0){ + ERROR("Invalid argument ConnectionID: Missing or wrong"); + this->setError(Request, 402); + return Request->ErrCode; + } + + // TODO: + // Close and clear any open resources + // Close and delete the connection + // Free other resources left + this->setError(Request, UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED); + return Request->ErrCode; +} + +//bool cConnectionManager::setProtocolInfo(const char* ProtocolInfo){ +// if(strcmp(this->mSupportedProtocols, ProtocolInfo)){ +// // ProtocolInfo changed, save and invoke a event notification +// this->mSupportedProtocols = ProtocolInfo; +// +// IXML_Document* PropertySet = NULL; +// UpnpAddToPropertySet(&PropertySet, "SourceProtocolInfo", this->mSupportedProtocols); +// int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); +// ixmlDocument_free(PropertySet); +// +// if(ret != UPNP_E_SUCCESS){ +// ERROR("State change notification failed (Error code: %d)",ret); +// return false; +// } +// } +// return true; +//} + +cVirtualConnection* cConnectionManager::createVirtualConnection(const char* RemoteProtocolInfo, const char* RemoteConnectionManager, int RemoteConnectionID, eDirection Direction){ + static int lastConnectionID = 0; + MESSAGE(VERBOSE_CMS, "Create virtual connection"); + if(lastConnectionID == 2147483647) lastConnectionID = 1; + cVirtualConnection* Connection = new cVirtualConnection; + // AVT is available + Connection->mAVTransportID = 0; + // The ProtocolInfo of the remote device (i.e. Media Renderer) + Connection->mRemoteProtocolInfo = RemoteProtocolInfo; + // The responsible connection manager + Connection->mRemoteConnectionManager = RemoteConnectionManager; + // The virtual connection direction is output + Connection->mDirection = Direction; + // The remote connection ID, -1 says ID is unknown + Connection->mRemoteConnectionID = RemoteConnectionID; + // Connection status, assume that its ok. + Connection->mStatus = OK; + // new assigned ConnectionID + Connection->mConnectionID = lastConnectionID++; + + // Notify the subscribers + IXML_Document* PropertySet = NULL; + const char* IDs = this->getConnectionIDsCVS(); + if(!IDs){ + return NULL; + } + UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); + int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); + ixmlDocument_free(PropertySet); + + if(ret != UPNP_E_SUCCESS){ + ERROR("State change notification failed (Error code: %d)",ret); + return NULL; + } + MESSAGE(VERBOSE_CMS, "Notification of connection creation sent"); + this->mVirtualConnections->Add(Connection); + return Connection; +} + +bool cConnectionManager::destroyVirtualConnection(int ConnectionID){ + if(ConnectionID == 0){ + ERROR("Cannot delete default connection with ID 0!"); + return false; + } + + cVirtualConnection* Connection; + for(Connection = this->mVirtualConnections->First(); Connection && Connection->mConnectionID != ConnectionID; Connection = this->mVirtualConnections->Next(Connection)){} + + if(Connection){ + this->mVirtualConnections->Del(Connection); + // Notify the subscribers + IXML_Document* PropertySet = NULL; + const char* IDs = this->getConnectionIDsCVS(); + if(!IDs){ + return false; + } + UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); + int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); + ixmlDocument_free(PropertySet); + + if(ret != UPNP_E_SUCCESS){ + ERROR("State change notification failed (Error code: %d)",ret); + return false; + } + return true; + } + ERROR("No connection with ID=%d found!", ConnectionID); + return false; +} + +const char* cConnectionManager::getConnectionIDsCVS(){ + cString IDs; + for(cVirtualConnection* Connection = this->mVirtualConnections->First(); Connection; Connection = this->mVirtualConnections->Next(Connection)){ + IDs = cString::sprintf("%s,%d", (*IDs)?*IDs:"", Connection->mConnectionID); + } + return IDs; +} + +void cConnectionManager::setError(Upnp_Action_Request* Request, int Error){ + Request->ErrCode = Error; + switch(Error){ + case 701: + strn0cpy(Request->ErrStr,_("Incompatible protocol info"),LINE_SIZE); + break; + case 702: + strn0cpy(Request->ErrStr,_("Incompatible directions"),LINE_SIZE); + break; + case 703: + strn0cpy(Request->ErrStr,_("Insufficient network resources"),LINE_SIZE); + break; + case 704: + strn0cpy(Request->ErrStr,_("Local restrictions"),LINE_SIZE); + break; + case 705: + strn0cpy(Request->ErrStr,_("Access denied"),LINE_SIZE); + break; + case 706: + strn0cpy(Request->ErrStr,_("Invalid connection reference"),LINE_SIZE); + break; + case 707: + strn0cpy(Request->ErrStr,_("Not in network"),LINE_SIZE); + break; + default: + cUpnpService::setError(Request, Error); + break; + } +} + +const char* cVirtualConnection::getDirectionString(eDirection Direction){ + switch(Direction){ + case INPUT: + return "Input"; + case OUTPUT: + return "Output"; + default: + return NULL; + } +} + +const char* cVirtualConnection::getStatusString(eConnectionStatus Status){ + switch(Status){ + case OK: + return "OK"; + case CONTENT_FORMAT_MISMATCH: + return "ContentFormatMismatch"; + case INSUFFICIENT_BANDWIDTH: + return "InsufficientBandwidth"; + case UNRELIABLE_CHANNEL: + return "UnreliableChannel"; + case UNKNOWN: + return "Unknown"; + default: + return NULL; + } +} + +int cVirtualConnection::getConnectionStatus(const char* eConnectionStatus){ + if(!strcasecmp(eConnectionStatus,"OK")) + return OK; + if(!strcasecmp(eConnectionStatus,"ContentFormatMismatch")) + return CONTENT_FORMAT_MISMATCH; + if(!strcasecmp(eConnectionStatus,"InsufficientBandwidth")) + return INSUFFICIENT_BANDWIDTH; + if(!strcasecmp(eConnectionStatus,"UnreliableChannel")) + return UNRELIABLE_CHANNEL; + if(!strcasecmp(eConnectionStatus,"Unknown")) + return UNKNOWN; + return -1; +} + +int cVirtualConnection::getDirection(const char* Direction){ + if(!strcasecmp(Direction, "Output")) + return OUTPUT; + if(!strcasecmp(Direction, "Input")) + return INPUT; + return -1; +} \ No newline at end of file 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 +#include +#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( + " \ + %s \ + %d \ + %d \ + %d \ + ", + 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( + " \ + %d \ + ", + 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( + " \ + %s \ + ", + 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( + " \ + %s \ + ", + 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 diff --git a/upnp/service.cpp b/upnp/service.cpp new file mode 100644 index 0000000..4d17af1 --- /dev/null +++ b/upnp/service.cpp @@ -0,0 +1,118 @@ +/* + * File: upnpservice.cpp + * Author: savop + * + * Created on 21. August 2009, 18:38 + */ + +#include "upnp/service.h" +#include "../common.h" +#include "util.h" + +cUpnpService::cUpnpService(UpnpDevice_Handle DeviceHandle) { + this->mDeviceHandle = DeviceHandle; +} + +int cUpnpService::parseIntegerValue(IN IXML_Document* Document, IN const char* Item, OUT int* Value){ + char* Val = NULL; + int Error = 0; + + Val = ixmlGetFirstDocumentItem(Document, Item, &Error); + + if(Error != 0){ + ERROR("Error while parsing integer value for item=%s", Item); + Error = -1; + } + else if(!Value){ + WARNING("Value %s empty!", Item); + *Value = 0; + } + else { + *Value = atoi(Val); + free(Val); + } + return Error; +} + +int cUpnpService::parseStringValue(IN IXML_Document* Document, IN const char* Item, OUT char** Value){ + char* Val = NULL; + int Error = 0; + + Val = ixmlGetFirstDocumentItem(Document, Item, &Error); + + if(Error != 0){ + ERROR("Error while parsing string value for item=%s", Item); + Error = -1; + } + else if(!Val){ + WARNING("Value %s empty!", Item); + *Value = NULL; + } + else { + *Value = strdup(Val); + free(Val); + } + + return Error; +} + +void cUpnpService::setError(Upnp_Action_Request* Request, int Error){ + Request->ErrCode = Error; + switch(Error){ + case UPNP_SOAP_E_INVALID_ACTION: + strn0cpy(Request->ErrStr,_("Invalid action"),LINE_SIZE); + break; + case UPNP_SOAP_E_INVALID_ARGS: + strn0cpy(Request->ErrStr,_("Invalid args"),LINE_SIZE); + break; + case UPNP_SOAP_E_INVALID_VAR: + strn0cpy(Request->ErrStr,_("Invalid var"),LINE_SIZE); + break; + case UPNP_SOAP_E_ACTION_FAILED: + strn0cpy(Request->ErrStr,_("Action failed"),LINE_SIZE); + break; + case UPNP_SOAP_E_ARGUMENT_INVALID: + strn0cpy(Request->ErrStr,_("Argument value invalid"),LINE_SIZE); + break; + case UPNP_SOAP_E_ARGUMENT_OUT_OF_RANGE: + strn0cpy(Request->ErrStr,_("Argument value out of range"),LINE_SIZE); + break; + case UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED: + strn0cpy(Request->ErrStr,_("Optional action not implemented"),LINE_SIZE); + break; + case UPNP_SOAP_E_OUT_OF_MEMORY: + strn0cpy(Request->ErrStr,_("Out of memory"),LINE_SIZE); + break; + case UPNP_SOAP_E_HUMAN_INTERVENTION: + strn0cpy(Request->ErrStr,_("Human intervention required"),LINE_SIZE); + break; + case UPNP_SOAP_E_STRING_TO_LONG: + strn0cpy(Request->ErrStr,_("String argument to long"),LINE_SIZE); + break; + case UPNP_SOAP_E_NOT_AUTHORIZED: + strn0cpy(Request->ErrStr,_("Action not authorized"),LINE_SIZE); + break; + case UPNP_SOAP_E_SIGNATURE_FAILURE: + strn0cpy(Request->ErrStr,_("Signature failure"),LINE_SIZE); + break; + case UPNP_SOAP_E_SIGNATURE_MISSING: + strn0cpy(Request->ErrStr,_("Signature missing"),LINE_SIZE); + break; + case UPNP_SOAP_E_NOT_ENCRYPTED: + strn0cpy(Request->ErrStr,_("Not encrypted"),LINE_SIZE); + break; + case UPNP_SOAP_E_INVALID_SEQUENCE: + strn0cpy(Request->ErrStr,_("Invalid sequence"),LINE_SIZE); + break; + case UPNP_SOAP_E_INVALID_CONTROL_URL: + strn0cpy(Request->ErrStr,_("Invalid control URL"),LINE_SIZE); + break; + case UPNP_SOAP_E_NO_SUCH_SESSION: + strn0cpy(Request->ErrStr,_("No such session"),LINE_SIZE); + break; + case UPNP_SOAP_E_OUT_OF_SYNC: + default: + strn0cpy(Request->ErrStr,_("Unknown error code. Contact the device manufacturer"),LINE_SIZE); + break; + } +} \ No newline at end of file -- cgit v1.2.3