Exemple #1
0
/************************************************************************
* Function : genaUnSubscribe
*																	
* Parameters:														
*	IN UpnpClient_Handle client_handle: UPnP client handle
*	IN SID in_sid: The subscription ID
*
* Description:														
*	This function unsubscribes a SID. It first validates the SID and 
*	client_handle,copies the subscription, sends UNSUBSCRIBE http request 
*	to service processes request and finally removes the subscription
*
* Returns: int
*	return UPNP_E_SUCCESS if service response is OK else 
*	returns appropriate error
***************************************************************************/
int
genaUnSubscribe( IN UpnpClient_Handle client_handle,
                 IN const Upnp_SID in_sid )
{
    client_subscription *sub;
    int return_code = GENA_SUCCESS;
    struct Handle_Info *handle_info;
    client_subscription sub_copy;
    http_parser_t response;

    HandleLock(  );

    // validate handle and sid

    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        return GENA_E_BAD_HANDLE;
    }

    if( ( sub =
          GetClientSubClientSID( handle_info->ClientSubList, in_sid ) )
        == NULL ) {
        HandleUnlock(  );
        return GENA_E_BAD_SID;
    }

    return_code = copy_client_subscription( sub, &sub_copy );

    HandleUnlock(  );

    return_code = gena_unsubscribe( sub_copy.EventURL, sub_copy.ActualSID,
                                    &response );

    if( return_code == 0 ) {
        httpmsg_destroy( &response.msg );
    }

    free_client_subscription( &sub_copy );

    HandleLock(  );

    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        return GENA_E_BAD_HANDLE;
    }

    RemoveClientSubClientSID( &handle_info->ClientSubList, in_sid );

    HandleUnlock(  );

    return return_code;
}
//-----------------------------------------------------------------------------
// Purpose: Calculates the center of an edge.
// Input  : pEdge - 
//-----------------------------------------------------------------------------
void CSSolid::CalcEdgeCenter(CSSEdge *pEdge)
{
	SSHANDLEINFO hi;

	GetHandleInfo(&hi, pEdge->hvStart);
	Vector &pt1 = m_Vertices[hi.iIndex].pos;

	GetHandleInfo(&hi, pEdge->hvEnd);
	Vector &pt2 = m_Vertices[hi.iIndex].pos;

	for (int i = 0; i < 3; i++)
	{
		pEdge->ptCenter[i] = (pt1[i] + pt2[i]) / 2.0f;
	}
}
int genaUnSubscribe(
	UpnpClient_Handle client_handle,
	const UpnpString *in_sid)
{
	ClientSubscription *sub = NULL;
	int return_code = GENA_SUCCESS;
	struct Handle_Info *handle_info;
	ClientSubscription *sub_copy = UpnpClientSubscription_new();
	http_parser_t response;

	/* validate handle and sid */
	HandleLock();
	if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		HandleUnlock();
		return_code = GENA_E_BAD_HANDLE;
		goto exit_function;
	}
	sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid);
	if (sub == NULL) {
		HandleUnlock();
		return_code = GENA_E_BAD_SID;
		goto exit_function;
	}
	UpnpClientSubscription_assign(sub_copy, sub);
	HandleUnlock();

	return_code = gena_unsubscribe(
		UpnpClientSubscription_get_EventURL(sub_copy),
		UpnpClientSubscription_get_ActualSID(sub_copy),
		&response);
	if (return_code == 0) {
		httpmsg_destroy(&response.msg);
	}
	free_client_subscription(sub_copy);

	HandleLock();
	if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		HandleUnlock();
		return_code = GENA_E_BAD_HANDLE;
		goto exit_function;
	}
	RemoveClientSubClientSID(&handle_info->ClientSubList, in_sid);
	HandleUnlock();

exit_function:
	UpnpClientSubscription_delete(sub_copy);
	return return_code;
}
BOOL CSSolid::SplitFace(SSHANDLE h1, SSHANDLE h2)
{
	SSHANDLEINFO hi;
	GetHandleInfo(&hi, h1);

	if(m_nFaces == MAX_FACES-1)
		return FALSE;

	BOOL bRvl = FALSE;

	if(hi.Type == shtEdge)
	{
		// edge-based face split
		bRvl = SplitFaceByEdges((CSSEdge*) hi.pData, 
			(CSSEdge*) GetHandleData(h2));
	}
	else if(hi.Type == shtVertex)
	{
		// vertex-based face split
		bRvl = SplitFaceByVertices((CSSVertex*) hi.pData, 
			(CSSVertex*) GetHandleData(h2));
	}

	return bRvl;
}
// Create point list, but return indices instead of positions ->
PINT CSSolid::CreatePointIndexList(CSSFace & face, PINT piPoints)
{
	PINT pts;
	int nPts = 0;

	if(piPoints)
		pts = piPoints;
	else
		pts = new int[face.nEdges+1];

	SSHANDLEINFO hi;

	for(int i = 0; i < face.nEdges; i++)
	{
		// calc next edge so we can see which is the next clockwise point
		int iNextEdge = i+1;
		if(iNextEdge == face.nEdges)
			iNextEdge = 0;

		CSSEdge * edgeCur = (CSSEdge*) GetHandleData(face.Edges[i]);
		CSSEdge * edgeNext = (CSSEdge*)  GetHandleData(face.Edges[iNextEdge]);

		SSHANDLE hVertex = GetConnectionVertex(edgeCur, edgeNext);
		ASSERT(hVertex);

		GetHandleInfo(&hi, hVertex);
		pts[i] = hi.iIndex;
	}

	return pts;
}
// 2D Hit Test ->
SSHANDLE CSSolid::HitTest(CPoint pt, SSHANDLEINFO *pInfo)
{
	SSHANDLE hnd = 0;

	// do a hit test on all handles:
	if(m_bShowVertices)	for(int i = 0; i < m_nVertices; i++)
	{
		CSSVertex &v = m_Vertices[i];
		if(PtInRect(&v.m_r, pt))
		{
			hnd = v.id;
			break;
		}
	}

	if(!hnd && m_bShowEdges) for(int i = 0; i < m_nEdges; i++)
	{
		CSSEdge &e = m_Edges[i];
		if(PtInRect(&e.m_r, pt))
		{
			hnd = e.id;
			break;
		}
	}

	if(hnd && pInfo)
		GetHandleInfo(pInfo, hnd);

	return hnd;
}
PVOID CSSolid::GetHandleData(SSHANDLE id)
{
	SSHANDLEINFO hi;
	if(!GetHandleInfo(&hi, id))
		return NULL;
	return hi.pData;
}
/*!
 * \brief This is a thread function to send the renewal just before the
 * subscription times out.
 */
static void GenaAutoRenewSubscription(
	/*! [in] Thread data(upnp_timeout *) needed to send the renewal. */
	IN void *input)
{
	upnp_timeout *event = (upnp_timeout *) input;
        struct Upnp_Event_Subscribe *sub_struct = (struct Upnp_Event_Subscribe *)event->Event;
	void *cookie;
	Upnp_FunPtr callback_fun;
	struct Handle_Info *handle_info;
	int send_callback = 0;
	int eventType = 0;
	int timeout = 0;
	int errCode = 0;
	UpnpString *tmpSID = UpnpString_new();

	if (AUTO_RENEW_TIME == 0) {
		UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "GENA SUB EXPIRED");
		sub_struct->ErrCode = UPNP_E_SUCCESS;
		send_callback = 1;
		eventType = UPNP_EVENT_SUBSCRIPTION_EXPIRED;
	} else {
		UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENA AUTO RENEW");
		timeout = sub_struct->TimeOut;
		UpnpString_set_String(tmpSID, sub_struct->Sid);
		errCode = genaRenewSubscription(
			event->handle,
			tmpSID,
			&timeout);
		sub_struct->ErrCode = errCode;
		sub_struct->TimeOut = timeout;
		if (errCode != UPNP_E_SUCCESS &&
		    errCode != GENA_E_BAD_SID &&
		    errCode != GENA_E_BAD_HANDLE) {
			send_callback = 1;
			eventType = UPNP_EVENT_AUTORENEWAL_FAILED;
		}
	}

	if (send_callback) {
		HandleReadLock();
		if( GetHandleInfo( event->handle, &handle_info ) != HND_CLIENT ) {
			HandleUnlock();
			free_upnp_timeout(event);
			goto end_function;
		}
		UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "HANDLE IS VALID");

		/* make callback */
		callback_fun = handle_info->Callback;
		cookie = handle_info->Cookie;
		HandleUnlock();
		callback_fun(eventType, event->Event, cookie);
	}

	free_upnp_timeout(event);

end_function:
	UpnpString_delete(tmpSID);
	return;
}
Exemple #9
0
/************************************************************************
* Function : GenaAutoRenewSubscription									
*																	
* Parameters:														
*	IN void *input: Thread data(upnp_timeout *) needed to send the renewal
*
* Description:														
*	This is a thread function to send the renewal just before the 
*	subscription times out.
*
* Returns: VOID
*	
***************************************************************************/
static void
GenaAutoRenewSubscription( IN void *input )
{
    upnp_timeout *event = ( upnp_timeout * ) input;
    void *cookie;
    Upnp_FunPtr callback_fun;
    struct Handle_Info *handle_info;
    struct Upnp_Event_Subscribe *sub_struct =
        ( struct Upnp_Event_Subscribe * )
        event->Event;

    int send_callback = 0;
    int eventType = 0;

    if( AUTO_RENEW_TIME == 0 ) {
        DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                             "GENA SUB EXPIRED" ) );
        sub_struct->ErrCode = UPNP_E_SUCCESS;
        send_callback = 1;
        eventType = UPNP_EVENT_SUBSCRIPTION_EXPIRED;
    } else {
        DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                             "GENA AUTO RENEW" ) );
        if( ( ( sub_struct->ErrCode = genaRenewSubscription( event->handle,
                                                             sub_struct->
                                                             Sid,
                                                             &sub_struct->
                                                             TimeOut ) ) !=
              UPNP_E_SUCCESS )
            && ( sub_struct->ErrCode != GENA_E_BAD_SID )
            && ( sub_struct->ErrCode != GENA_E_BAD_HANDLE ) ) {
            send_callback = 1;
            eventType = UPNP_EVENT_AUTORENEWAL_FAILED;
        }
    }
    if( send_callback ) {
        HandleLock(  );
        if( GetHandleInfo( event->handle, &handle_info ) != HND_CLIENT ) {
            HandleUnlock(  );
            free_upnp_timeout( event );
            return;
        }
        DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                             "HANDLE IS VALID" ) );
        callback_fun = handle_info->Callback;
        cookie = handle_info->Cookie;
        HandleUnlock(  );
        //make callback

        callback_fun( eventType, event->Event, cookie );
    }

    free_upnp_timeout( event );
}
// Move handle(s) to a new location ->
void CSSolid::MoveSelectedHandles(const Vector &Delta)
{
	SSHANDLE MoveVertices[128];
	int nMoveVertices = 0;

	SSHANDLEINFO hi;
	
	for(int i = 0; i < m_nVertices; i++)
	{
		if(m_Vertices[i].m_bSelected)
			MoveVertices[nMoveVertices++] = m_Vertices[i].id;
	}

	for(i = 0; i < m_nEdges; i++)
	{
		CSSEdge* pEdge = &m_Edges[i];

		if(!pEdge->m_bSelected)	// make sure it's selected
			continue;

		// add edge's vertices to the movement list
		BOOL bAddStart = TRUE, bAddEnd = TRUE;
		for(int i2 = 0; i2 < nMoveVertices; i2++)
		{
			if(pEdge->hvStart == MoveVertices[i2])
				bAddStart = FALSE;	// already got this one
			if(pEdge->hvEnd == MoveVertices[i2])
				bAddEnd = FALSE;	// already got this one
		}

		if(bAddStart)
			MoveVertices[nMoveVertices++] = pEdge->hvStart;
		if(bAddEnd)
			MoveVertices[nMoveVertices++] = pEdge->hvEnd;
	}

	// move vertices now
	for(i = 0; i < nMoveVertices; i++)
	{
		GetHandleInfo(&hi, MoveVertices[i]);
		CSSVertex* pVertex = (CSSVertex*) hi.pData;
		SetVertexPosition(hi.iIndex, pVertex->pos[0] + Delta[0], pVertex->pos[1] + Delta[1], pVertex->pos[2] + Delta[2]);
	}

	// calculate center of moved edges
	int nEdges;
	CSSEdge ** ppEdges = FindAffectedEdges(MoveVertices, nMoveVertices, nEdges);
	for(i = 0; i < nEdges; i++)
	{
		CalcEdgeCenter(ppEdges[i]);
	}
}
Exemple #11
0
/************************************************************************
* Function : genaUnregisterClient									
*																	
* Parameters:														
*	IN UpnpClient_Handle client_handle: Handle containing all the control
*			point related information
*
* Description:														
*	This function unsubcribes all the outstanding subscriptions and cleans
*	the subscription list. This function is called when control point 
*	unregisters.
*
* Returns: int
*	return UPNP_E_SUCCESS if successful else returns appropriate error
***************************************************************************/
int
genaUnregisterClient( IN UpnpClient_Handle client_handle )
{
    client_subscription sub_copy;
    int return_code = UPNP_E_SUCCESS;
    struct Handle_Info *handle_info = NULL;
    http_parser_t response;

    while( TRUE ) {
        HandleLock(  );
        if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
            HandleUnlock(  );
            return GENA_E_BAD_HANDLE;
        }

        if( handle_info->ClientSubList == NULL ) {
            return_code = UPNP_E_SUCCESS;
            break;
        }

        return_code = copy_client_subscription( handle_info->ClientSubList,
                                                &sub_copy );
        if( return_code != HTTP_SUCCESS ) {
            break;
        }

        RemoveClientSubClientSID( &handle_info->ClientSubList,
                                  sub_copy.sid );

        HandleUnlock(  );

		return_code = gena_unsubscribe( sub_copy.EventURL,
										sub_copy.ActualSID, &response );
		if( return_code == 0 ) {
			httpmsg_destroy( &response.msg );
		}

        free_client_subscription( &sub_copy );
    }

    freeClientSubList( handle_info->ClientSubList );
    HandleUnlock(  );
    return return_code;
}
int genaUnregisterClient(UpnpClient_Handle client_handle)
{
	ClientSubscription *sub_copy = UpnpClientSubscription_new();
	int return_code = UPNP_E_SUCCESS;
	struct Handle_Info *handle_info = NULL;
	http_parser_t response;

	while (TRUE) {
		HandleLock();

		if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
			HandleUnlock();
			return_code = GENA_E_BAD_HANDLE;
			goto exit_function;
		}
		if (handle_info->ClientSubList == NULL) {
			return_code = UPNP_E_SUCCESS;
			break;
		}
		UpnpClientSubscription_assign(sub_copy, handle_info->ClientSubList);
		RemoveClientSubClientSID(
			&handle_info->ClientSubList,
			UpnpClientSubscription_get_SID(sub_copy));

		HandleUnlock();

		return_code = gena_unsubscribe(
			UpnpClientSubscription_get_EventURL(sub_copy),
			UpnpClientSubscription_get_ActualSID(sub_copy),
			&response);
		if (return_code == 0) {
			httpmsg_destroy(&response.msg);
		}
		free_client_subscription(sub_copy);
	}

	freeClientSubList(handle_info->ClientSubList);
	HandleUnlock();

exit_function:
	UpnpClientSubscription_delete(sub_copy);
	return return_code;
}
Exemple #13
0
/*!
 * \brief Unregisters a device.
 *
 * \return UPNP_E_SUCCESS on success, GENA_E_BAD_HANDLE on failure.
 */
int genaUnregisterDevice(
	/*! [in] Device handle. */
	UpnpDevice_Handle device_handle)
{
	int ret = 0;
	struct Handle_Info *handle_info;

	HandleLock();
	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		UpnpPrintf(UPNP_CRITICAL, GENA, __FILE__, __LINE__,
			"genaUnregisterDevice: BAD Handle: %d\n",
			device_handle);
		ret = GENA_E_BAD_HANDLE;
	} else {
		freeServiceTable(&handle_info->ServiceTable);
		ret = UPNP_E_SUCCESS;
	}
	HandleUnlock();

	return ret;
}
Exemple #14
0
/* We take ownership of propertySet and will free it */
static int genaNotifyAllCommon(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	DOMString propertySet)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *finger = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN NOTIFY ALL COMMON");

	/* Keep this allocation first */
	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if( servId_copy == NULL ) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
	} else {
		service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
		if (service != NULL) {
			finger = GetFirstSubscription(service);
			while (finger) {
				ThreadPoolJob *job = NULL;
				ListNode *node;

				thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
				if (thread_struct == NULL) {
					line = __LINE__;
					ret = UPNP_E_OUTOF_MEMORY;
					break;
				}

				(*reference_count)++;
				thread_struct->reference_count = reference_count;
				thread_struct->UDN = UDN_copy;
				thread_struct->servId = servId_copy;
				thread_struct->headers = headers;
				thread_struct->propertySet = propertySet;
				memset(thread_struct->sid, 0,
					sizeof(thread_struct->sid));
				strncpy(thread_struct->sid, finger->sid,
					sizeof(thread_struct->sid) - 1);
				thread_struct->ctime = time(0);
				thread_struct->device_handle = device_handle;

				maybeDiscardEvents(&finger->outgoing);
				job = (ThreadPoolJob *)malloc(sizeof(ThreadPoolJob));
				if (job == NULL) {
					line = __LINE__;
					ret = UPNP_E_OUTOF_MEMORY;
					break;
				}
				memset(job, 0, sizeof(ThreadPoolJob));
				TPJobInit(job, (start_routine)genaNotifyThread, thread_struct);
				TPJobSetFreeFunction(job, (free_routine)free_notify_struct);
				TPJobSetPriority(job, MED_PRIORITY);
				node = ListAddTail(&finger->outgoing, job);

				/* If there is only one element on the list (which we just
				   added), need to kickstart the threadpool */
				if (ListSize(&finger->outgoing) == 1) {
					ret = ThreadPoolAdd(&gSendThreadPool, job, NULL);
					if (ret != 0) {
						line = __LINE__;
						if (ret == EOUTOFMEM) {
							line = __LINE__;
							ret = UPNP_E_OUTOF_MEMORY;
						}
						break;
					}
					if (node) {
						((ThreadPoolJob *)(node->item))->jobId = STALE_JOBID;
					}
				}
				finger = GetNextSubscription(service, finger);
			}
		} else {
			line = __LINE__;
			ret = GENA_E_BAD_SERVICE;
		}
	}

ExitFunction:
	/* The only case where we want to free memory here is if the
	   struct was never queued. Else, let the normal cleanup take place.
	   reference_count is allocated first so it's ok to do nothing if it's 0
	*/
	if (reference_count && *reference_count == 0) {
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END NOTIFY ALL COMMON, ret = %d",
		ret);

	return ret;
}
Exemple #15
0
/* We take ownership of propertySet and will free it */
static int genaInitNotifyCommon(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	DOMString propertySet,
	const Upnp_SID sid)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *sub = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;
	ThreadPoolJob *job = NULL;

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN INITIAL NOTIFY COMMON");

	job = (ThreadPoolJob *)malloc(sizeof(ThreadPoolJob));
	if (job == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	memset(job, 0, sizeof(ThreadPoolJob));

	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if (servId_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
		goto ExitFunction;
	}

	service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
	if (service == NULL) {
		line = __LINE__;
		ret = GENA_E_BAD_SERVICE;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SERVICE IN INIT NOTFY: UDN %s, ServID: %s",
		UDN, servId);

	sub = GetSubscriptionSID(sid, service);
	if (sub == NULL || sub->active) {
		line = __LINE__;
		ret = GENA_E_BAD_SID;
		goto ExitFunction;
	}
	UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SUBSCRIPTION IN INIT NOTIFY: SID %s", sid);
	sub->active = 1;

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	/* schedule thread for initial notification */

	thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
	if (thread_struct == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
	} else {
		*reference_count = 1;
		thread_struct->servId = servId_copy;
		thread_struct->UDN = UDN_copy;
		thread_struct->headers = headers;
		thread_struct->propertySet = propertySet;
		memset(thread_struct->sid, 0, sizeof(thread_struct->sid));
		strncpy(thread_struct->sid, sid,
			sizeof(thread_struct->sid) - 1);
		thread_struct->ctime = time(0);
		thread_struct->reference_count = reference_count;
		thread_struct->device_handle = device_handle;

		TPJobInit(job, (start_routine)genaNotifyThread, thread_struct);
		TPJobSetFreeFunction(job, (free_routine)free_notify_struct);
		TPJobSetPriority(job, MED_PRIORITY);

		ret = ThreadPoolAdd(&gSendThreadPool, job, NULL);
		if (ret != 0) {
			if (ret == EOUTOFMEM) {
				line = __LINE__;
				ret = UPNP_E_OUTOF_MEMORY;
			}
		} else {
			ListNode *node = ListAddTail(&sub->outgoing, job);
			if (node != NULL) {
				((ThreadPoolJob *)node->item)->jobId = STALE_JOBID;
				line = __LINE__;
				ret = GENA_SUCCESS;
			} else {
				line = __LINE__;
				ret = UPNP_E_OUTOF_MEMORY;
			}
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS) {
		free(job);
		free(thread_struct);
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END INITIAL NOTIFY COMMON, ret = %d",
		ret);

	return ret;
}
Exemple #16
0
int genaNotifyAll(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	char **VarNames,
	char **VarValues,
	int var_count)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	DOMString propertySet = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *finger = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN NOTIFY ALL");

	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if( servId_copy == NULL ) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	ret = GeneratePropertySet(VarNames, VarValues, var_count, &propertySet);
	if (ret != XML_SUCCESS) {
		line = __LINE__;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENERATED PROPERTY SET IN EXT NOTIFY: %s",
		propertySet);

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
	} else {
		service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
		if (service != NULL) {
			finger = GetFirstSubscription(service);
			while (finger) {
				thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
				if (thread_struct == NULL) {
					line = __LINE__;
					ret = UPNP_E_OUTOF_MEMORY;
					break;
				}

				(*reference_count)++;
				thread_struct->reference_count = reference_count;
				thread_struct->UDN = UDN_copy;
				thread_struct->servId = servId_copy;
				thread_struct->headers = headers;
				thread_struct->propertySet = propertySet;
				memset(thread_struct->sid, 0,
					sizeof(thread_struct->sid));
				strncpy(thread_struct->sid, finger->sid,
					sizeof(thread_struct->sid) - 1);
				thread_struct->eventKey = finger->eventKey++;
				thread_struct->device_handle = device_handle;
				/* if overflow, wrap to 1 */
				if (finger->eventKey < 0) {
					finger->eventKey = 1;
				}


				TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct);
				TPJobSetFreeFunction(&job, (free_routine)free_notify_struct);
				TPJobSetPriority(&job, MED_PRIORITY);
				ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL);
				if (ret != 0) {
					line = __LINE__;
					if (ret == EOUTOFMEM) {
						line = __LINE__;
						ret = UPNP_E_OUTOF_MEMORY;
					}
					break;
				}

				finger = GetNextSubscription(service, finger);
			}
		} else {
			line = __LINE__;
			ret = GENA_E_BAD_SERVICE;
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS || *reference_count == 0) {
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END NOTIFY ALL, ret = %d",
		ret);

	return ret;
}
Exemple #17
0
/*!
 * \brief Thread job to Notify a control point.
 *
 * It validates the subscription and copies the subscription. Also make sure
 * that events are sent in order.
 *
 * \note calls the genaNotify to do the actual work.
 */
static void genaNotifyThread(
	/*! [in] notify thread structure containing all the headers and property set info. */
	void *input)
{
	subscription *sub;
	service_info *service;
	subscription sub_copy;
	notify_thread_struct *in = (notify_thread_struct *) input;
	int return_code;
	struct Handle_Info *handle_info;

	/* This should be a HandleLock and not a HandleReadLock otherwise if there
	 * is a lot of notifications, then multiple threads will acquire a read
	 * lock and the thread which sends the notification will be blocked forever
	 * on the HandleLock at the end of this function. */
	/*HandleReadLock(); */
	HandleLock();
	/* validate context */

	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}

	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service)) ||
	    copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}

	HandleUnlock();

	/* send the notify */
	return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
	freeSubscription(&sub_copy);
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	/* validate context */
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service))) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	sub->ToSendEventKey++;
	if (sub->ToSendEventKey < 0)
		/* wrap to 1 for overflow */
		sub->ToSendEventKey = 1;

	/* Remove head of event queue. Possibly activate next */
	{
		ListNode *node = ListHead(&sub->outgoing);
		if (node)
			ListDelNode(&sub->outgoing, node, 1);
		if (ListSize(&sub->outgoing) > 0) {
			ThreadPoolJob *job;
			ListNode *node = ListHead(&sub->outgoing);
			job = (ThreadPoolJob*)node->item;
			/* The new head of queue should not have already been
			   added to the pool, else something is very wrong */
			assert(job->jobId != STALE_JOBID);

			ThreadPoolAdd(&gSendThreadPool, job, NULL);
			job->jobId = STALE_JOBID;
		}
	}

	if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
		RemoveSubscriptionSID(in->sid, service);
	free_notify_struct(in);

	HandleUnlock();
}
Exemple #18
0
/*!
 * \brief Thread job to Notify a control point.
 *
 * It validates the subscription and copies the subscription. Also make sure
 * that events are sent in order.
 *
 * \note calls the genaNotify to do the actual work.
 */
static void genaNotifyThread(
	/*! [in] notify thread structure containing all the headers and property set info. */
	void *input)
{
	subscription *sub;
	service_info *service;
	subscription sub_copy;
	notify_thread_struct *in = (notify_thread_struct *) input;
	int return_code;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	/* This should be a HandleLock and not a HandleReadLock otherwise if there
	 * is a lot of notifications, then multiple threads will acquire a read
	 * lock and the thread which sends the notification will be blocked forever
	 * on the HandleLock at the end of this function. */
	/*HandleReadLock(); */
	HandleLock();
	/* validate context */

	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}

	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service)) ||
	    copy_subscription(sub, &sub_copy) != HTTP_SUCCESS) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
#ifdef UPNP_ENABLE_NOTIFICATION_REORDERING
	/*If the event is out of order push it back to the job queue */
	if (in->eventKey != sub->ToSendEventKey) {
		TPJobInit(&job, (start_routine) genaNotifyThread, input);
		TPJobSetFreeFunction(&job, (free_function) free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);
		/* Sleep a little before creating another thread otherwise if there is
		 * a lot of notifications to send, the device will take 100% of the CPU
		 * to create threads and push them back to the job queue. */
		imillisleep(1);
		ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		freeSubscription(&sub_copy);
		HandleUnlock();
		return;
	}
#endif

	HandleUnlock();

	/* send the notify */
	return_code = genaNotify(in->headers, in->propertySet, &sub_copy);
	freeSubscription(&sub_copy);
	HandleLock();
	if (GetHandleInfo(in->device_handle, &handle_info) != HND_DEVICE) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	/* validate context */
	if (!(service = FindServiceId(&handle_info->ServiceTable, in->servId, in->UDN)) ||
	    !service->active ||
	    !(sub = GetSubscriptionSID(in->sid, service))) {
		free_notify_struct(in);
		HandleUnlock();
		return;
	}
	sub->ToSendEventKey++;
	if (sub->ToSendEventKey < 0)
		/* wrap to 1 for overflow */
		sub->ToSendEventKey = 1;
	if (return_code == GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB)
		RemoveSubscriptionSID(in->sid, service);
	free_notify_struct(in);

	HandleUnlock();
}
Exemple #19
0
int genaInitNotifyExt(
	UpnpDevice_Handle device_handle,
	char *UDN,
	char *servId,
	IXML_Document *PropSet,
	const Upnp_SID sid)
{
	int ret = GENA_SUCCESS;
	int line = 0;

	int *reference_count = NULL;
	char *UDN_copy = NULL;
	char *servId_copy = NULL;
	DOMString propertySet = NULL;
	char *headers = NULL;
	notify_thread_struct *thread_struct = NULL;

	subscription *sub = NULL;
	service_info *service = NULL;
	struct Handle_Info *handle_info;
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENA BEGIN INITIAL NOTIFY EXT");
	
	reference_count = (int *)malloc(sizeof (int));
	if (reference_count == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}
	*reference_count = 0;
	
	UDN_copy = strdup(UDN);
	if (UDN_copy == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	servId_copy = strdup(servId);
	if( servId_copy == NULL ) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	HandleLock();

	if (GetHandleInfo(device_handle, &handle_info) != HND_DEVICE) {
		line = __LINE__;
		ret = GENA_E_BAD_HANDLE;
		goto ExitFunction;
	}

	service = FindServiceId(&handle_info->ServiceTable, servId, UDN);
	if (service == NULL) {
		line = __LINE__;
		ret = GENA_E_BAD_SERVICE;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SERVICE IN INIT NOTFY EXT: UDN %s, ServID: %s",
		UDN, servId);

	sub = GetSubscriptionSID(sid, service);
	if (sub == NULL || sub->active) {
		line = __LINE__;
		ret = GENA_E_BAD_SID;
		goto ExitFunction;
	}
	UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
		"FOUND SUBSCRIPTION IN INIT NOTIFY EXT: SID %s", sid);
	sub->active = 1;

	if (PropSet == 0) {
		line = __LINE__;
		ret = GENA_SUCCESS;
		goto ExitFunction;
	}

	propertySet = ixmlPrintNode((IXML_Node *)PropSet);
	if (propertySet == NULL) {
		line = __LINE__;
		ret = UPNP_E_INVALID_PARAM;
		goto ExitFunction;
	}
	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__,
		"GENERATED PROPERTY SET IN INIT EXT NOTIFY: %s",
		propertySet);

	headers = AllocGenaHeaders(propertySet);
	if (headers == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
		goto ExitFunction;
	}

	/* schedule thread for initial notification */

	thread_struct = (notify_thread_struct *)malloc(sizeof (notify_thread_struct));
	if (thread_struct == NULL) {
		line = __LINE__;
		ret = UPNP_E_OUTOF_MEMORY;
	} else {
		*reference_count = 1;
		thread_struct->servId = servId_copy;
		thread_struct->UDN = UDN_copy;
		thread_struct->headers = headers;
		thread_struct->propertySet = propertySet;
		memset(thread_struct->sid, 0, sizeof(thread_struct->sid));
		strncpy(thread_struct->sid, sid,
			sizeof(thread_struct->sid) - 1);
		thread_struct->eventKey = sub->eventKey++;
		thread_struct->reference_count = reference_count;
		thread_struct->device_handle = device_handle;

		TPJobInit(&job, (start_routine)genaNotifyThread, thread_struct);
		TPJobSetFreeFunction(&job, (free_routine)free_notify_struct);
		TPJobSetPriority(&job, MED_PRIORITY);

		ret = ThreadPoolAdd(&gSendThreadPool, &job, NULL);
		if (ret != 0) {
			if (ret == EOUTOFMEM) {
				line = __LINE__;
				ret = UPNP_E_OUTOF_MEMORY;
			}
		} else {
			line = __LINE__;
			ret = GENA_SUCCESS;
		}
	}

ExitFunction:
	if (ret != GENA_SUCCESS || PropSet == 0) {
		free(thread_struct);
		free(headers);
		ixmlFreeDOMString(propertySet);
		free(servId_copy);
		free(UDN_copy);
		free(reference_count);
	}

	HandleUnlock();

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, line,
		"GENA END INITIAL NOTIFY EXT, ret = %d",
		ret);

	return ret;
}
Exemple #20
0
/************************************************************************
* Function : genaRenewSubscription
*																	
* Parameters:														
*	IN UpnpClient_Handle client_handle: Client handle
*	IN const Upnp_SID in_sid: subscription ID
*	INOUT int * TimeOut: requested Duration, if -1, then "infinite".
*						in the OUT case: actual Duration granted 
*						by Service, -1 for infinite
*
* Description:														
*	This function renews a SID. It first validates the SID and 
*	client_handle and copies the subscription. It sends RENEW 
*	(modified SUBSCRIBE) http request to service and processes
*	the response.
*
* Returns: int
*	return UPNP_E_SUCCESS if service response is OK else 
*	returns appropriate error
***************************************************************************/
int
genaRenewSubscription( IN UpnpClient_Handle client_handle,
                       IN const Upnp_SID in_sid,
                       INOUT int *TimeOut )
{
    int return_code = GENA_SUCCESS;
    client_subscription *sub;
    client_subscription sub_copy;
    struct Handle_Info *handle_info;

    char *ActualSID;
    ThreadPoolJob tempJob;

    HandleLock(  );

    // validate handle and sid
    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        return GENA_E_BAD_HANDLE;
    }

    if( ( sub = GetClientSubClientSID( handle_info->ClientSubList,
                                       in_sid ) ) == NULL ) {
        HandleUnlock(  );
        return GENA_E_BAD_SID;
    }
    // remove old events
    if( TimerThreadRemove( &gTimerThread, sub->RenewEventId, &tempJob ) ==
        0 ) {

        free_upnp_timeout( ( upnp_timeout * ) tempJob.arg );
    }

    DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                         "REMOVED AUTO RENEW  EVENT" ) );

    sub->RenewEventId = -1;
    return_code = copy_client_subscription( sub, &sub_copy );

    HandleUnlock(  );

    if( return_code != HTTP_SUCCESS ) {
        return return_code;
    }

    return_code = gena_subscribe( sub_copy.EventURL, TimeOut,
                                  sub_copy.ActualSID, &ActualSID );
    HandleLock(  );

    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        if( return_code == UPNP_E_SUCCESS ) {
            free( ActualSID );
        }
        return GENA_E_BAD_HANDLE;
    }
    // we just called GetHandleInfo, so we don't check for return value
    //GetHandleInfo(client_handle, &handle_info);

    if( return_code != UPNP_E_SUCCESS ) {
        // network failure (remove client sub)
        RemoveClientSubClientSID( &handle_info->ClientSubList, in_sid );
        free_client_subscription( &sub_copy );
        HandleUnlock(  );
        return return_code;
    }
    // get subscription
    if( ( sub = GetClientSubClientSID( handle_info->ClientSubList,
                                       in_sid ) ) == NULL ) {
        free( ActualSID );
        free_client_subscription( &sub_copy );
        HandleUnlock(  );
        return GENA_E_BAD_SID;
    }
    // store actual sid
    free( sub->ActualSID );
    sub->ActualSID = ActualSID;

    // start renew subscription timer
    return_code = ScheduleGenaAutoRenew( client_handle, *TimeOut, sub );
    if( return_code != GENA_SUCCESS ) {
        RemoveClientSubClientSID( &handle_info->ClientSubList, sub->sid );
    }
    free_client_subscription( &sub_copy );
    HandleUnlock(  );
    return return_code;
}
int genaSubscribe(
	UpnpClient_Handle client_handle,
	const UpnpString *PublisherURL,
	int *TimeOut,
	UpnpString *out_sid)
{
	int return_code = GENA_SUCCESS;
	ClientSubscription *newSubscription = UpnpClientSubscription_new();
	uuid_upnp uid;
	Upnp_SID temp_sid;
	Upnp_SID temp_sid2;
	UpnpString *ActualSID = UpnpString_new();
	UpnpString *EventURL = UpnpString_new();
	struct Handle_Info *handle_info;
	int rc = 0;

	memset(temp_sid, 0, sizeof(temp_sid));
	memset(temp_sid2, 0, sizeof(temp_sid2));

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "GENA SUBSCRIBE BEGIN");

	UpnpString_clear(out_sid);

	HandleReadLock();
	/* validate handle */
	if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		return_code = GENA_E_BAD_HANDLE;
		SubscribeLock();
		goto error_handler;
	}
	HandleUnlock();

	/* subscribe */
	SubscribeLock();
	return_code = gena_subscribe(PublisherURL, TimeOut, NULL, ActualSID);
	HandleLock();
	if (return_code != UPNP_E_SUCCESS) {
		UpnpPrintf( UPNP_CRITICAL, GENA, __FILE__, __LINE__,
			"SUBSCRIBE FAILED in transfer error code: %d returned\n",
			return_code );
		goto error_handler;
	}

	if(GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		return_code = GENA_E_BAD_HANDLE;
		goto error_handler;
	}

	/* generate client SID */
	uuid_create(&uid );
	uuid_unpack(&uid, temp_sid);
	rc = snprintf(temp_sid2, sizeof(temp_sid2), "uuid:%s", temp_sid);
	if (rc < 0 || (unsigned int) rc >= sizeof(temp_sid2)) {
		return_code = UPNP_E_OUTOF_MEMORY;
		goto error_handler;
	}
	UpnpString_set_String(out_sid, temp_sid2);

	/* create event url */
	UpnpString_assign(EventURL, PublisherURL);

	/* fill subscription */
	if (newSubscription == NULL) {
		return_code = UPNP_E_OUTOF_MEMORY;
		goto error_handler;
	}
	UpnpClientSubscription_set_RenewEventId(newSubscription, -1);
	UpnpClientSubscription_set_SID(newSubscription, out_sid);
	UpnpClientSubscription_set_ActualSID(newSubscription, ActualSID);
	UpnpClientSubscription_set_EventURL(newSubscription, EventURL);
	UpnpClientSubscription_set_Next(newSubscription, handle_info->ClientSubList);
	handle_info->ClientSubList = newSubscription;

	/* schedule expiration event */
	return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, newSubscription);

error_handler:
		UpnpString_delete(ActualSID);
		UpnpString_delete(EventURL);
	if (return_code != UPNP_E_SUCCESS)
		UpnpClientSubscription_delete(newSubscription);
	HandleUnlock();
	SubscribeUnlock();

	return return_code;
}
Exemple #22
0
/************************************************************************
* Function : genaSubscribe
*																	
* Parameters:														
*	IN UpnpClient_Handle client_handle: 
*	IN char * PublisherURL: NULL Terminated, of the form : 
*						"http://134.134.156.80:4000/RedBulb/Event"
*	INOUT int * TimeOut: requested Duration, if -1, then "infinite".
*						in the OUT case: actual Duration granted 
*						by Service, -1 for infinite
*	OUT Upnp_SID out_sid:sid of subscription, memory passed in by caller
*
* Description:														
*	This function subscribes to a PublisherURL ( also mentioned as EventURL
*	some places). It sends SUBSCRIBE http request to service processes 
*	request. Finally adds a Subscription to 
*	the clients subscription list, if service responds with OK
*
* Returns: int
*	return UPNP_E_SUCCESS if service response is OK else 
*	returns appropriate error
***************************************************************************/
int
genaSubscribe( IN UpnpClient_Handle client_handle,
               IN char *PublisherURL,
               INOUT int *TimeOut,
               OUT Upnp_SID out_sid )
{
    int return_code = GENA_SUCCESS;
    client_subscription *newSubscription = NULL;
    uuid_upnp uid;
    Upnp_SID temp_sid;
    char *ActualSID = NULL;
    struct Handle_Info *handle_info;
    char *EventURL = NULL;

    DBGONLY( UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__,
                         "GENA SUBSCRIBE BEGIN" ) );
    HandleLock(  );

    memset( out_sid, 0, sizeof( Upnp_SID ) );

    // validate handle
    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        HandleUnlock(  );
        return GENA_E_BAD_HANDLE;
    }
    HandleUnlock(  );

    // subscribe
    SubscribeLock(  );
    return_code =
        gena_subscribe( PublisherURL, TimeOut, NULL, &ActualSID );
    HandleLock(  );
    if( return_code != UPNP_E_SUCCESS ) {
        DBGONLY( UpnpPrintf( UPNP_CRITICAL, GENA, __FILE__, __LINE__,
                             "SUBSCRIBE FAILED in transfer error code: %d returned\n",
                             return_code ) );
        goto error_handler;
    }

    if( GetHandleInfo( client_handle, &handle_info ) != HND_CLIENT ) {
        return_code = GENA_E_BAD_HANDLE;
        goto error_handler;
    }
    // generate client SID
    uuid_create( &uid );
    uuid_unpack( &uid, temp_sid );
    sprintf( out_sid, "uuid:%s", temp_sid );

    // create event url
    EventURL = ( char * )malloc( strlen( PublisherURL ) + 1 );
    if( EventURL == NULL ) {
        return_code = UPNP_E_OUTOF_MEMORY;
        goto error_handler;
    }

    strcpy( EventURL, PublisherURL );

    // fill subscription
    newSubscription =
        ( client_subscription * ) malloc( sizeof( client_subscription ) );
    if( newSubscription == NULL ) {
        return_code = UPNP_E_OUTOF_MEMORY;
        goto error_handler;
    }
    newSubscription->EventURL = EventURL;
    newSubscription->ActualSID = ActualSID;
    strcpy( newSubscription->sid, out_sid );
    newSubscription->RenewEventId = -1;
    newSubscription->next = handle_info->ClientSubList;
    handle_info->ClientSubList = newSubscription;

    // schedule expiration event
    return_code = ScheduleGenaAutoRenew( client_handle, *TimeOut,
                                         newSubscription );

  error_handler:
    if( return_code != UPNP_E_SUCCESS ) {
        free( ActualSID );
        free( EventURL );
        free( newSubscription );
    }
    HandleUnlock(  );
    SubscribeUnlock(  );
    return return_code;
}
int genaRenewSubscription(
	UpnpClient_Handle client_handle,
	const UpnpString *in_sid,
	int *TimeOut)
{
	int return_code = GENA_SUCCESS;
	ClientSubscription *sub = NULL;
	ClientSubscription *sub_copy = UpnpClientSubscription_new();
	struct Handle_Info *handle_info;
	UpnpString *ActualSID = UpnpString_new();
	ThreadPoolJob tempJob;

	HandleLock();

	/* validate handle and sid */
	if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		HandleUnlock();

		return_code = GENA_E_BAD_HANDLE;
		goto exit_function;
	}

	sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid);
	if (sub == NULL) {
		HandleUnlock();

		return_code = GENA_E_BAD_SID;
		goto exit_function;
	}

	/* remove old events */
	if (TimerThreadRemove(
		&gTimerThread,
		UpnpClientSubscription_get_RenewEventId(sub),
		&tempJob) == 0 ) {
		free_upnp_timeout((upnp_timeout *)tempJob.arg);
	}

	UpnpPrintf(UPNP_INFO, GENA, __FILE__, __LINE__, "REMOVED AUTO RENEW  EVENT");

	UpnpClientSubscription_set_RenewEventId(sub, -1);
	UpnpClientSubscription_assign(sub_copy, sub);

	HandleUnlock();

	return_code = gena_subscribe(
		UpnpClientSubscription_get_EventURL(sub_copy),
		TimeOut,
		UpnpClientSubscription_get_ActualSID(sub_copy),
		ActualSID);

	HandleLock();

	if (GetHandleInfo(client_handle, &handle_info) != HND_CLIENT) {
		HandleUnlock();
		return_code = GENA_E_BAD_HANDLE;
		goto exit_function;
	}

	/* we just called GetHandleInfo, so we don't check for return value */
	/*GetHandleInfo(client_handle, &handle_info); */
	if (return_code != UPNP_E_SUCCESS) {
		/* network failure (remove client sub) */
		RemoveClientSubClientSID(&handle_info->ClientSubList, in_sid);
		free_client_subscription(sub_copy);
		HandleUnlock();
		goto exit_function;
	}

	/* get subscription */
	sub = GetClientSubClientSID(handle_info->ClientSubList, in_sid);
	if (sub == NULL) {
		free_client_subscription(sub_copy);
		HandleUnlock();
		return_code = GENA_E_BAD_SID;
		goto exit_function;
	}

	/* store actual sid */
	UpnpClientSubscription_set_ActualSID(sub, ActualSID);

	/* start renew subscription timer */
	return_code = ScheduleGenaAutoRenew(client_handle, *TimeOut, sub);
	if (return_code != GENA_SUCCESS) {
		RemoveClientSubClientSID(
			&handle_info->ClientSubList,
			UpnpClientSubscription_get_SID(sub));
	}
	free_client_subscription(sub_copy);
	HandleUnlock();

exit_function:
	UpnpString_delete(ActualSID);
	UpnpClientSubscription_delete(sub_copy);
	return return_code;
}
Exemple #24
0
int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd,
		      enum SsdpSearchType SearchType,
		      struct sockaddr *DestAddr, char *DeviceType,
		      char *DeviceUDN, char *ServiceType, int Exp)
{
	int retVal = UPNP_E_SUCCESS;
	long unsigned int i;
	long unsigned int j;
	int defaultExp = DEFAULT_MAXAGE;
	struct Handle_Info *SInfo = NULL;
	char UDNstr[100];
	char devType[100];
	char servType[100];
	IXML_NodeList *nodeList = NULL;
	IXML_NodeList *tmpNodeList = NULL;
	IXML_Node *tmpNode = NULL;
	IXML_Node *tmpNode2 = NULL;
	IXML_Node *textNode = NULL;
	const DOMString tmpStr;
	const DOMString dbgStr;
	int NumCopy = 0;

	memset(UDNstr, 0, sizeof(UDNstr));
	memset(devType, 0, sizeof(devType));
	memset(servType, 0, sizeof(servType));

	UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
		   "Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag);

	/* Use a read lock */
	HandleReadLock();
	if (GetHandleInfo(Hnd, &SInfo) != HND_DEVICE) {
		retVal = UPNP_E_INVALID_HANDLE;
		goto end_function;
	}
	defaultExp = SInfo->MaxAge;
	/* parse the device list and send advertisements/replies */
	while (NumCopy == 0 || (AdFlag && NumCopy < NUM_SSDP_COPY)) {
		if (NumCopy != 0)
			imillisleep(SSDP_PAUSE);
		NumCopy++;
		for (i = 0lu;; i++) {
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Entering new device list with i = %lu\n\n",
				   i);
			tmpNode = ixmlNodeList_item(SInfo->DeviceList, i);
			if (!tmpNode) {
				UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
					   "Exiting new device list with i = %lu\n\n",
					   i);
				break;
			}
			dbgStr = ixmlNode_getNodeName(tmpNode);
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Extracting device type once for %s\n",
				   dbgStr);
			ixmlNodeList_free(nodeList);
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "deviceType");
			if (!nodeList)
				continue;
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting UDN for %s\n", dbgStr);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type\n");
			tmpNode2 = ixmlNodeList_item(nodeList, 0lu);
			if (!tmpNode2)
				continue;
			textNode = ixmlNode_getFirstChild(tmpNode2);
			if (!textNode)
				continue;
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type \n");
			tmpStr = ixmlNode_getNodeValue(textNode);
			if (!tmpStr)
				continue;
			strncpy(devType, tmpStr, sizeof(devType) - 1);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting device type = %s\n", devType);
			if (!tmpNode) {
				UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
					   "TempNode is NULL\n");
			}
			dbgStr = ixmlNode_getNodeName(tmpNode);
			UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
				   "Extracting UDN for %s\n", dbgStr);
			ixmlNodeList_free(nodeList);
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "UDN");
			if (!nodeList) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			tmpNode2 = ixmlNodeList_item(nodeList, 0lu);
			if (!tmpNode2) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			textNode = ixmlNode_getFirstChild(tmpNode2);
			if (!textNode) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			tmpStr = ixmlNode_getNodeValue(textNode);
			if (!tmpStr) {
				UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
					   __LINE__, "UDN not found!\n");
				continue;
			}
			strncpy(UDNstr, tmpStr, sizeof(UDNstr) - 1);
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Sending UDNStr = %s \n", UDNstr);
			if (AdFlag) {
				/* send the device advertisement */
				if (AdFlag == 1) {
                    DeviceAdvertisement(devType, i == 0lu, NumCopy - 1,
							    UDNstr,
							    SInfo->DescURL, Exp,
							    SInfo->DeviceAf,
							    SInfo->PowerState,
	                                                    SInfo->SleepPeriod,
	                                                    SInfo->RegistrationState);
				} else {
					/* AdFlag == -1 */
                    DeviceShutdown(devType, i == 0lu, NumCopy - 1, UDNstr,
						       SInfo->DescURL,
						       Exp, SInfo->DeviceAf,
						       SInfo->PowerState,
						       SInfo->SleepPeriod,
						       SInfo->RegistrationState);
				}
			} else {
				switch (SearchType) {
				case SSDP_ALL:
                    DeviceReply(DestAddr, devType, i == 0lu, NumCopy - 1,
						    UDNstr, SInfo->DescURL,
						    defaultExp, SInfo->PowerState,
						    SInfo->SleepPeriod,
						    SInfo->RegistrationState);
					break;
				case SSDP_ROOTDEVICE:
					if (i == 0lu) {
                        SendReply(DestAddr, devType, 1, NumCopy - 1,
							  UDNstr,
							  SInfo->DescURL,
							  defaultExp, 0,
							  SInfo->PowerState,
							  SInfo->SleepPeriod,
							  SInfo->RegistrationState);
					}
					break;
				case SSDP_DEVICEUDN: {
					if (DeviceUDN && strlen(DeviceUDN) != (size_t)0) {
						if (strcasecmp(DeviceUDN, UDNstr)) {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								"DeviceUDN=%s and search UDN=%s DID NOT match\n",
								UDNstr, DeviceUDN);
							break;
						} else {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								"DeviceUDN=%s and search UDN=%s MATCH\n",
								UDNstr, DeviceUDN);
                            SendReply(DestAddr, devType, 0, NumCopy - 1, UDNstr, SInfo->DescURL, defaultExp, 0,
								SInfo->PowerState,
								SInfo->SleepPeriod,
								SInfo->RegistrationState);
							break;
						}
					}
				}
				case SSDP_DEVICETYPE: {
					if (!strncasecmp(DeviceType, devType, strlen(DeviceType) - (size_t)2)) {
						if (atoi(strrchr(DeviceType, ':') + 1)
						    < atoi(&devType[strlen(devType) - (size_t)1])) {
							/* the requested version is lower than the device version
							 * must reply with the lower version number and the lower
							 * description URL */
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s MATCH\n",
								   devType, DeviceType);
                            SendReply(DestAddr, DeviceType, 0, NumCopy - 1, UDNstr, SInfo->LowerDescURL,
								  defaultExp, 1,
								  SInfo->PowerState,
								  SInfo->SleepPeriod,
								  SInfo->RegistrationState);
						} else if (atoi(strrchr(DeviceType, ':') + 1)
							   == atoi(&devType[strlen(devType) - (size_t)1])) {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s MATCH\n",
								   devType, DeviceType);
                            SendReply(DestAddr, DeviceType, 0, NumCopy - 1, UDNstr, SInfo->DescURL,
								  defaultExp, 1,
								  SInfo->PowerState,
								  SInfo->SleepPeriod,
								  SInfo->RegistrationState);
						} else {
							UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
								   "DeviceType=%s and search devType=%s DID NOT MATCH\n",
								   devType, DeviceType);
						}
					} else {
						UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
							   "DeviceType=%s and search devType=%s DID NOT MATCH\n",
							   devType, DeviceType);
					}
					break;
				}
				default:
					break;
				}
			}
			/* send service advertisements for services corresponding
			 * to the same device */
			UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
				   "Sending service Advertisement\n");
			/* Correct service traversal such that each device's serviceList
			 * is directly traversed as a child of its parent device. This
			 * ensures that the service's alive message uses the UDN of
			 * the parent device. */
			tmpNode = ixmlNode_getFirstChild(tmpNode);
			while (tmpNode) {
				dbgStr = ixmlNode_getNodeName(tmpNode);
				if (!strncmp
				    (dbgStr, SERVICELIST_STR,
				     sizeof SERVICELIST_STR)) {
					break;
				}
				tmpNode = ixmlNode_getNextSibling(tmpNode);
			}
			ixmlNodeList_free(nodeList);
			if (!tmpNode) {
				nodeList = NULL;
				continue;
			}
			nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "service");
			if (!nodeList) {
				UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
					   "Service not found 3\n");
				continue;
			}
			for (j = 0lu;; j++) {
				tmpNode = ixmlNodeList_item(nodeList, j);
				if (!tmpNode) {
					break;
				}
				ixmlNodeList_free(tmpNodeList);
				tmpNodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "serviceType");
				if (!tmpNodeList) {
					UpnpPrintf(UPNP_CRITICAL, API, __FILE__,
						   __LINE__,
						   "ServiceType not found \n");
					continue;
				}
				tmpNode2 = ixmlNodeList_item(tmpNodeList, 0lu);
				if (!tmpNode2)
					continue;
				textNode = ixmlNode_getFirstChild(tmpNode2);
				if (!textNode)
					continue;
				/* servType is of format Servicetype:ServiceVersion */
				tmpStr = ixmlNode_getNodeValue(textNode);
				if (!tmpStr)
					continue;
				strncpy(servType, tmpStr, sizeof(servType) - 1);
				UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
					   "ServiceType = %s\n", servType);
				if (AdFlag) {
					if (AdFlag == 1) {
                        ServiceAdvertisement(NumCopy - 1, UDNstr,
							servType, SInfo->DescURL,
							Exp, SInfo->DeviceAf,
							SInfo->PowerState,
							SInfo->SleepPeriod,
							SInfo->RegistrationState);
					} else {
						/* AdFlag == -1 */
                        ServiceShutdown(NumCopy - 1, UDNstr,
							servType, SInfo->DescURL,
							Exp, SInfo->DeviceAf,
							SInfo->PowerState,
							SInfo->SleepPeriod,
							SInfo->RegistrationState);
					}
				} else {
					switch (SearchType) {
					case SSDP_ALL:
                        ServiceReply(DestAddr,
                                 servType,
                                 NumCopy - 1,
							     UDNstr,
							     SInfo->DescURL,
							     defaultExp,
							     SInfo->PowerState,
							     SInfo->SleepPeriod,
							     SInfo->RegistrationState);
						break;
					case SSDP_SERVICE:
						if (ServiceType) {
							if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - (size_t)2)) {
								if (atoi(strrchr(ServiceType, ':') + 1) <
								    atoi(&servType[strlen(servType) - (size_t)1])) {
									/* the requested version is lower than the service version
									 * must reply with the lower version number and the lower
									 * description URL */
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
										   "ServiceType=%s and search servType=%s MATCH\n",
										   ServiceType, servType);
                                    SendReply(DestAddr, ServiceType, 0, NumCopy - 1, UDNstr, SInfo->LowerDescURL,
										  defaultExp, 1,
										  SInfo->PowerState,
										  SInfo->SleepPeriod,
										  SInfo->RegistrationState);
								} else if (atoi(strrchr (ServiceType, ':') + 1) ==
									   atoi(&servType[strlen(servType) - (size_t)1])) {
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
										   "ServiceType=%s and search servType=%s MATCH\n",
										   ServiceType, servType);
                                    SendReply(DestAddr, ServiceType, 0, NumCopy - 1, UDNstr, SInfo->DescURL,
										  defaultExp, 1,
										  SInfo->PowerState,
										  SInfo->SleepPeriod,
										  SInfo->RegistrationState);
								} else {
									UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
									   "ServiceType=%s and search servType=%s DID NOT MATCH\n",
									   ServiceType, servType);
								}
							} else {
								UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
									   "ServiceType=%s and search servType=%s DID NOT MATCH\n",
									   ServiceType, servType);
							}
						}
						break;
					default:
						break;
					}
				}
			}
			ixmlNodeList_free(tmpNodeList);
			tmpNodeList = NULL;
			ixmlNodeList_free(nodeList);
			nodeList = NULL;
		}
	}

end_function:
	ixmlNodeList_free(tmpNodeList);
	ixmlNodeList_free(nodeList);
	UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
		   "Exiting AdvertiseAndReply.\n");
	HandleUnlock();

	return retVal;
}