// Called by the UPnP Remote I/O Microstack
// Implements the SetPeerOverride call, lets a CP connect this RIO client to
// a new URI. If this RIO client is currently connected, it will disconnect and
// switch to the new URI.
void UpnpRemoteIOClient_RemoteIO_SetPeerOverride(void* upnptoken,char* PeerConnection)
{
	struct parser_result* ParsedAddress = NULL;
	char* RemoteIOSessionPath = NULL;
	char* RemoteIOSessionAddress = NULL;
	int address = 0;

	
	if (upnptoken && (PeerConnection == NULL || (int)strlen(PeerConnection) < 7))
	{
		UpnpResponse_Error(upnptoken,700,"Invalid PeerConnection");
		return;
	}

	sem_wait(&RemoteIOLock);
	if (RIO->PeerConnection == NULL || strcmp(RIO->PeerConnection,PeerConnection) != 0)
	{
		if (RIO->PeerConnection != NULL)
		{
			// Disconnect the socket
			ILibAsyncSocket_Disconnect(RIO->Session);
			free(RIO->PeerConnection);
		}

		// Set the new session URI
		RIO->PeerConnection = (char*)malloc((int)strlen(PeerConnection) + 1);
		strcpy(RIO->PeerConnection,PeerConnection);

		// Event the new connection
		UpnpSetState_RemoteIOClient_RemoteIO_PeerConnection(RIO->RIOmicroStack,RIO->PeerConnection);

		// Connect session
		ParseUri(RIO->PeerConnection,&RemoteIOSessionAddress,&RIO->SessionPort,&RemoteIOSessionPath);
		free(RemoteIOSessionPath);

		ParsedAddress = ILibParseString(RemoteIOSessionAddress,0,(int)strlen(RemoteIOSessionAddress),".",1);

		address  = atoi(ParsedAddress->FirstResult->data);
		address += atoi(ParsedAddress->FirstResult->NextResult->data) << 8;
		address += atoi(ParsedAddress->FirstResult->NextResult->NextResult->data) << 16;
		address += atoi(ParsedAddress->FirstResult->NextResult->NextResult->NextResult->data) << 24;

		ILibAsyncSocket_ConnectTo(RIO->Session,0,address,RIO->SessionPort,NULL,NULL);
		ILibDestructParserResults(ParsedAddress);
		free(RemoteIOSessionAddress);
		sem_post(&RemoteIOLock);

		// Event the user
		if (RemoteIOConnectionChanged != NULL) RemoteIOConnectionChanged(RIO->PeerConnection);
	}
	else 
	{
		sem_post(&RemoteIOLock);
	}
	
	if(upnptoken) {UpnpResponse_RemoteIOClient_RemoteIO_SetPeerOverride(upnptoken);}
}
// Called by the UPnP Remote I/O Microstack
// Implements the RegisterChannel call, lets the CP un-register a RIO channel.
void UpnpRemoteIOClient_ChannelManager_UnregisterChannel(void* upnptoken,char* PeerConnection)
{
	// Scan the channel list for an existing channel
	struct RemoteIOChannel* channelprevious = NULL;
	struct RemoteIOChannel* channelindex = RIO->ChannelList;

	printf("UnRegisterChannel: %s\r\n",PeerConnection);

	if (PeerConnection == NULL)
	{
		if (upnptoken != NULL) UpnpResponse_Error(upnptoken,800,"Invalid PeerConnection URI");
		return;
	}

	sem_wait(&RemoteIOLock);
	while (channelindex != NULL)
	{
		// Look for a match
		if (strcmp(channelindex->uri,PeerConnection) == 0) break;
		channelprevious = channelindex;
		channelindex = channelindex->next;
	}

	// Delete the channel from the list, and free the channel struct
	if (channelindex != NULL)
	{
		ILibLifeTime_Remove(RIO->RIOLifeTime,channelindex);

		if (channelprevious == NULL)
		{
			RIO->ChannelList = channelindex->next;
		}
		else
		{
			channelprevious->next = channelindex->next;
		}
		free(channelindex->name);
		free(channelindex->uri);
		free(channelindex);

		// Set the channels to be evented
		if (RIO->EventModerationSet == 0)
		{
			ILibLifeTime_Add(RIO->RIOLifeTime,NULL,2,&RemoteIO_EventChannelList, NULL);
			RIO->EventModerationSet = 1;
		}
	}
	
	if (upnptoken != NULL) UpnpResponse_RemoteIOClient_ChannelManager_UnregisterChannel(upnptoken);

	sem_post(&RemoteIOLock);
}
示例#3
0
// Called by the UPnP Remote I/O Microstack
// Implements the ForceDisconnect call, lets a CP connect this RIO client
// to a URI if, and only if, this RIO client is not currently connected.
void UpnpRemoteIO_SetPeerInterlock(void* upnptoken,char* PeerConnection)
{
	struct parser_result* ParsedAddress = NULL;
	char* RemoteIOSessionPath = NULL;
	char* RemoteIOSessionAddress = NULL;
	int address = 0;

	if (PeerConnection == NULL || (int)strlen(PeerConnection) < 7)
	{
		UpnpResponse_Error(upnptoken,700,"Invalid PeerConnection");
		return;
	}

	sem_wait(&RemoteIOLock);
	if (RIO->PeerConnection == NULL)
	{
		RIO->PeerConnection = (char*)RIO_MALLOC((int)strlen(PeerConnection) + 1);
		strcpy(RIO->PeerConnection,PeerConnection);

		// Event the new connection
		UpnpSetState_RemoteIO_PeerConnection(RIO->RIOmicroStack,RIO->PeerConnection);

		// Connect session
		ParseUri(RIO->PeerConnection,&RemoteIOSessionAddress,&RIO->SessionPort,&RemoteIOSessionPath);
		RIO_FREE(RemoteIOSessionPath);

		ParsedAddress = ILibParseString(RemoteIOSessionAddress,0,(int)strlen(RemoteIOSessionAddress),".",1);

		address  = atoi(ParsedAddress->FirstResult->data);
		address += atoi(ParsedAddress->FirstResult->NextResult->data) << 8;
		address += atoi(ParsedAddress->FirstResult->NextResult->NextResult->data) << 16;
		address += atoi(ParsedAddress->FirstResult->NextResult->NextResult->NextResult->data) << 24;

		ILibConnectTo(RIO->Session,0,address,RIO->SessionPort);
		ILibDestructParserResults(ParsedAddress);
		RIO_FREE(RemoteIOSessionAddress);
		UpnpResponse_RemoteIO_SetPeerInterlock(upnptoken,RIO->PeerConnection);
		sem_post(&RemoteIOLock);

		// Event the user
		if (RemoteIOConnectionChanged != NULL) RemoteIOConnectionChanged(RIO->PeerConnection);
	}
	else
	{
		UpnpResponse_RemoteIO_SetPeerInterlock(upnptoken,RIO->PeerConnection);
		sem_post(&RemoteIOLock);
	}
}
void UpnpConnectionManager_GetCurrentConnectionInfo(void* upnptoken,int ConnectionID)
{
	/*
	 *	HTTP connections are stateless, from the perspective of UPnP AV.
	 *	This is largely because we can't really monitor connection lifetime
	 *	of HTTP traffic in the UPnP AV sense, without risking memory leaks.
	 *
	 *	TODO: Low priority - Add support for connection-lifetime aware protocols.
	 */

	#ifdef _DEBUG
	printf("UPnP Invoke: UpnpConnectionManager_GetCurrentConnectionInfo(%u);\r\n",ConnectionID);
	#endif

	UpnpResponse_Error(upnptoken, (int) MSL_Error_ConnectionDoesNotExist, MSL_ErrorMsg_ConnectionDoesNotExist);
}
/* see header file */
void MSL_ForResponse_RespondError(struct MSL_CdsQuery *cdsQuery, int errorCode, const char *errorMsg)
{
	ASSERT(cdsQuery != NULL);

	UpnpResponse_Error(cdsQuery->UpnpToken, errorCode, errorMsg);
}
void UpnpContentDirectory_Browse(void* upnptoken,char* ObjectID,char* BrowseFlag,char* Filter,unsigned int StartingIndex,unsigned int RequestedCount,char* SortCriteria)
{
	struct MSL_CdsQuery *browseArgs;
	int errorCode;
	const char *errorMsg;
	enum MSL_Enum_QueryTypes browseChildren;
	int size;

	#ifdef _DEBUG
	printf("UPnP Invoke: UpnpContentDirectory_Browse();\r\n");
	#endif

	/*
	 *	Validate arguments.
	 */

	errorCode = 0;
	errorMsg = NULL;
	if (stricmp(BrowseFlag, CDS_STRING_BROWSE_DIRECT_CHILDREN) == 0)
	{
		browseChildren = MSL_Query_BrowseDirectChildren;
	}
	else if (stricmp(BrowseFlag, CDS_STRING_BROWSE_METADATA) == 0)
	{
		browseChildren = MSL_Query_BrowseMetadata;
	}
	else
	{
		fprintf(stderr, "WARNING: UpnpContentDirectory_Browse(): Possible error with generated microstack. Encountered BrowseFlag='%s'\r\n", BrowseFlag);
		errorCode = MSL_ERROR_CODE_INVALID_BROWSEFLAG;
		errorMsg = MSL_ERROR_MSG_INVALID_BROWSEFLAG;
	}

	if ((errorCode != 0) || (errorMsg != NULL))
	{
		/* ensure that the error code and message map to something */
		if (errorCode == 0) { errorCode = MSL_ERROR_CODE_INTERNAL; }
		if (errorMsg == NULL) {	errorMsg = MSL_ERROR_MSG_INTERNAL; }

		UpnpResponse_Error(upnptoken, errorCode, errorMsg);
	}
	else
	{
		/*
		 *	Input arguments valid at UPnP layer.
		 *	Create an MSL_CdsQuery object and execute
		 *	the browse callback so that application can return results.
		 */

		browseArgs = (struct MSL_CdsQuery*) MSL_MALLOC (sizeof(struct MSL_CdsQuery));
		memset(browseArgs, 0, sizeof(struct MSL_CdsQuery));

		browseArgs->QueryType = browseChildren;
		
		size = (int) strlen(Filter)+1;
		browseArgs->Filter = (char*) MSL_MALLOC(size);
		memcpy(browseArgs->Filter, Filter, size);

		browseArgs->MediaServerObject = MSL_TheMslObj;
		
		size = (int) strlen(ObjectID)+1;
		browseArgs->ObjectID = (char*) MSL_MALLOC(size);
		memcpy(browseArgs->ObjectID, ObjectID, size);
		/* Be sure to unescape it first. */
		ILibInPlaceXmlUnEscape(browseArgs->ObjectID);

		browseArgs->RequestedCount = RequestedCount;

		size = (int) strlen(SortCriteria)+1;
		browseArgs->SortCriteria = (char*) MSL_MALLOC(size);
		memcpy(browseArgs->SortCriteria, SortCriteria, size);

		browseArgs->StartingIndex = StartingIndex;

		browseArgs->UpnpToken = upnptoken;
		browseArgs->UserObject = NULL;

		browseArgs->IpAddrList = NULL;
		MSL_Helper_PopulateIpInfo(MSL_TheMslObj, browseArgs);

		if (MSL_Callback_OnQuery != NULL)
		{
			MSL_Callback_OnQuery(browseArgs);
		}
	}
}
// Called by the UPnP Remote I/O Microstack
// Implements the RegisterChannel call, lets the CP register a new RIO channels for a
// certain amont of time. The CP must re-register the channel from time-to-time to
// prevent the channel from expiring.
void UpnpRemoteIOClient_ChannelManager_RegisterChannel(void* upnptoken,char* Name,char* PeerConnection,int Timeout)
{
	// Scan the channel list for an existing channel
	struct RemoteIOChannel* channelindex = RIO->ChannelList;
	struct RemoteIOChannel* newchannel;

	printf("RegisterChannel[%s] (%d): %s\r\n",PeerConnection,Timeout,Name);

	if (PeerConnection == NULL)
	{
		if (upnptoken != NULL) UpnpResponse_Error(upnptoken,800,"Invalid PeerConnection URI");
		return;
	}

	sem_wait(&RemoteIOLock);

	while (channelindex != NULL)
	{
		// Look for a match
		if (strcmp(channelindex->uri,PeerConnection) == 0) break;
		channelindex = channelindex->next;
	}

	if (channelindex != NULL)
	{
		// Update the expiration time
		ILibLifeTime_Remove(RIO->RIOLifeTime,channelindex);
		#ifdef _WIN32_WCE
			channelindex->expiration = (GetTickCount() / 1000) + Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,channelindex,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#elif WIN32
			channelindex->expiration = (GetTickCount() / 1000) + Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,channelindex,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#elif _POSIX
			gettimeofday(&(channelindex->expiration),NULL);
			(channelindex->expiration).tv_sec += (int)Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,channelindex,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#endif
	}
	else
	{
		// Add a new channel to the channel list
		newchannel = (struct RemoteIOChannel*)malloc(sizeof(struct RemoteIOChannel));
		newchannel->name = (char*)malloc(strlen(Name)+1);
		strcpy(newchannel->name,Name);
		newchannel->uri = (char*)malloc(strlen(PeerConnection)+1);
		strcpy(newchannel->uri,PeerConnection);
		#ifdef _WIN32_WCE
			newchannel->expiration = (GetTickCount() / 1000) + Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,newchannel,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#elif WIN32
			newchannel->expiration = (GetTickCount() / 1000) + Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,newchannel,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#elif _POSIX
			gettimeofday(&(newchannel->expiration),NULL);
			(newchannel->expiration).tv_sec += (int)Timeout;
			ILibLifeTime_Add(RIO->RIOLifeTime,newchannel,Timeout,&RemoteIO_ChannelExpireSink, NULL);
		#endif
		newchannel->next = RIO->ChannelList;
		RIO->ChannelList = newchannel;

		// Set the channels to be evented
		if (RIO->EventModerationSet == 0)
		{
			ILibLifeTime_Add(RIO->RIOLifeTime,NULL,2,&RemoteIO_EventChannelList, NULL);
			RIO->EventModerationSet = 1;
		}
	}

	UpnpResponse_RemoteIOClient_ChannelManager_RegisterChannel(upnptoken);

	sem_post(&RemoteIOLock);
}