Esempio n. 1
0
/********************************************************************************
 * SampleUtil_Print
 *
 * Description: 
 *      Provides platform-specific print functionality.  This function should be
 *      called when you want to print content suitable for console output (i.e.,
 *      in a large text box or on a screen).  If your device/operating system is 
 *      not supported here, you should add a port.
 *
 * Parameters:
 *		Same as printf()
 *
 ********************************************************************************/
int
SampleUtil_Print( char *fmt,
                  ... )
{
    va_list ap;
    char buf[200];
    int rc;

    va_start( ap, fmt );
    rc = vsnprintf( buf, 200, fmt, ap );
    va_end( ap );

    ithread_mutex_lock( &display_mutex );
    if( gPrintFun )
        gPrintFun( buf );
    ithread_mutex_unlock( &display_mutex );

    return rc;
}
Esempio n. 2
0
/********************************************************************************
 * TvCtrlPointRemoveAll
 *
 * Description: 
 *       Remove all devices from the global device list.
 *
 * Parameters:
 *   None
 *
 ********************************************************************************/
int TvCtrlPointRemoveAll(void)
{
	struct TvDeviceNode *curdevnode, *next;

	ithread_mutex_lock(&DeviceListMutex);

	curdevnode = GlobalDeviceList;
	GlobalDeviceList = NULL;

	while (curdevnode) {
		next = curdevnode->next;
		TvCtrlPointDeleteNode(curdevnode);
		curdevnode = next;
	}

	ithread_mutex_unlock(&DeviceListMutex);

	return TV_SUCCESS;
}
Esempio n. 3
0
/******************************************************************************
 * DestroyResult
 *****************************************************************************/
static int 
DestroyResult (BrowseResult* const br)
{
	if (br) {
		if (br->cds && br->cds->cache)
			ithread_mutex_lock (&br->cds->cache_mutex);
		
		// Cached data will be really freed by talloc 
		// when its reference count drops to zero.
		if (talloc_free (br->children) == 0)
			Log_Printf (LOG_DEBUG, "ContentDir CACHE_FREE");
		
		if (br->cds && br->cds->cache)
			ithread_mutex_unlock (&br->cds->cache_mutex);
		
		*br = (BrowseResult) { };
	}
	
	return 0;
}
Esempio n. 4
0
int SampleUtil_Print(const char *fmt, ...)
{
#define MAX_BUF (8 * 1024)
	va_list ap;
	static char buf[MAX_BUF];
	int rc;

	/* Protect both the display and the static buffer with the mutex */
	ithread_mutex_lock(&display_mutex);

	va_start(ap, fmt);
	rc = vsnprintf(buf, MAX_BUF, fmt, ap);
	va_end(ap);
	if (gPrintFun)
		gPrintFun("%s", buf);

	ithread_mutex_unlock(&display_mutex);

	return rc;
}
Esempio n. 5
0
/*----------------------------------------------------------------------------*/
void FlushMRDevices(void)
{
	int i;

	for (i = 0; i < MAX_RENDERERS; i++) {
		if (glMRDevices[i].InUse) DelMRDevice(&glMRDevices[i]);
	}
}

/*----------------------------------------------------------------------------*/
void DelMRDevice(struct sMR *p)
{
	int i = 0;

	ithread_mutex_lock(&p->Mutex);
	p->Running = false;
	ithread_join(p->Thread, NULL);
	p->InUse = false;

	FlushActionList(p);
Esempio n. 6
0
/*
	Fuction:Print;
	INPUT:
		fmt -- strings to print;
	RETURN:The total length of strings;
*/
int
SA_Print( char *fmt,
                  ... )
{
    va_list ap;
    char buf[8000];
    int rc = 0;

    va_start( ap, fmt );
    #ifdef DEBUG
    rc = vsnprintf( buf, 8000, fmt, ap );
    #endif
    va_end( ap );
    ithread_mutex_lock( &display_mutex );
    if( gPrintFun )
        gPrintFun( buf );
    ithread_mutex_unlock( &display_mutex );

    return rc;
}
Esempio n. 7
0
/****************************************************************************
 * Function: ThreadPoolGetAttr
 *
 *  Description:
 *      Gets the current set of attributes
 *      associated with the thread pool.
 *  Parameters:
 *      tp - valid thread pool pointer
 *      out - non null pointer to store attributes
 *  Returns:
 *      0 on success, nonzero on failure
 *      Always returns 0.
 *****************************************************************************/
int ThreadPoolGetAttr( ThreadPool *tp, ThreadPoolAttr *out )
{
	assert( tp != NULL );
	assert( out != NULL );
	if( tp == NULL || out == NULL ) {
		return EINVAL;
	}

	if( !tp->shutdown ) {
		ithread_mutex_lock( &tp->mutex );
	}

	*out = tp->attr;

	if( !tp->shutdown ) {
		ithread_mutex_unlock( &tp->mutex );
	}

	return 0;
}
Esempio n. 8
0
/********************************************************************************
 * upnp_igd_handle_event
 *
 * Description:
 *       Handle a uPnP event that was received.  Process the event and update
 *       the appropriate service state table.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *   sid      -- The subscription id for the event
 *   eventkey -- The eventkey number for the event
 *   changes  -- The DOM document representing the changes
 *
 ********************************************************************************/
void upnp_igd_handle_event(upnp_igd_context* igd_ctxt, const char *sid, int eventkey, IXML_Document *changes) {
	upnp_igd_device_node *tmpdevnode;
	int service;

	ithread_mutex_lock(&igd_ctxt->devices_mutex);

	tmpdevnode = igd_ctxt->devices;
	while (tmpdevnode) {
		for (service = 0; service < IGD_SERVICE_SERVCOUNT; ++service) {
			if (strcmp(tmpdevnode->device.services[service].sid, sid) ==  0) {
				upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Received IGD %s Event: %d for SID %s", IGDServiceName[service], eventkey, sid);
				upnp_igd_state_update(igd_ctxt, tmpdevnode, service, changes, (char **)&tmpdevnode->device.services[service].variables);
				break;
			}
		}
		tmpdevnode = tmpdevnode->next;
	}

	ithread_mutex_unlock(&igd_ctxt->devices_mutex);
}
Esempio n. 9
0
File: log.c Progetto: Boxee/djmount
/*****************************************************************************
 * Log_Printf
 *****************************************************************************/
int
Log_Printf (Log_Level level, const char* fmt, ... )
{
	if (Log_IsActivated (level) && fmt) { 
		va_list ap;
		char buf[4096] = "";
		
		va_start (ap, fmt);
		int rc = vsnprintf (buf, sizeof(buf), fmt, ap);
		va_end (ap);
		
		if (rc >= 0) {
			ithread_mutex_lock (&g_log_mutex);
			gPrintFun (level, buf);
			ithread_mutex_unlock (&g_log_mutex);
		}
		return rc;
	}
	return -1;
}
Esempio n. 10
0
void upnp_context_add_callback(upnp_igd_context *igd_ctxt, upnp_igd_event event, void *arg) {
	upnp_igd_callback_event_node *node, *list;
	if(igd_ctxt->callback_fct != NULL) {
		// Create the node
		node = (upnp_igd_callback_event_node *) malloc(sizeof(upnp_igd_callback_event_node));
		node->event.event = event;
		node->event.arg = arg;
		node->next = NULL;

		ithread_mutex_lock(&igd_ctxt->callback_mutex);
		// Append to the list
		if(igd_ctxt->callback_events == NULL) {
			igd_ctxt->callback_events = node;
		} else {
			list = igd_ctxt->callback_events;
			while(list->next != NULL) list = list->next;
			list->next = node;
		}
		ithread_mutex_unlock(&igd_ctxt->callback_mutex);
	}
}
int upnp_append_variable(struct action_event *event,
			 int varnum, const char *paramname)
{
	const char *value;
	struct service *service = event->service;
	int retval = -1;

	//ENTER();

	assert(event != NULL);
	assert(paramname != NULL);

	if (varnum >= service->variable_count) {
#ifdef HAVE_LIBUPNP
		upnp_set_error(event, UPNP_E_INTERNAL_ERROR,
			       "Internal Error - illegal variable number %d",
			       varnum);
#endif
		goto out;
	}

#ifdef HAVE_LIBUPNP
	ithread_mutex_lock(service->service_mutex);
#endif

#if 0
	fprintf(stderr, "\tHZ: %s = '%s'\n", service->variable_names[varnum],
		service->variable_values[varnum]);
#endif
	value = service->variable_values[varnum];
	assert(value != NULL);
	retval = upnp_add_response(event, paramname, value);

#ifdef HAVE_LIBUPNP
	ithread_mutex_unlock(service->service_mutex);
#endif
out:
	//LEAVE();
	return retval;
}
Esempio n. 12
0
	if (!Device->Actions) Device->Actions = Action;
	else {
		p = Device->Actions;
		while (p->Next) p = p->Next;
		p->Next = Action;
	}
	ithread_mutex_unlock(&Device->ActionsMutex);
}

/*----------------------------------------------------------------------------*/
struct sAction *UnQueueAction(struct sMR *Device, bool Keep)
{
	struct sAction  *p = NULL;

	if (Keep) return Device->Actions;

	ithread_mutex_lock(&Device->ActionsMutex);
	if (Device->Actions) {
		p = Device->Actions;
		Device->Actions = Device->Actions->Next;
	}
	ithread_mutex_unlock(&Device->ActionsMutex);
Esempio n. 13
0
void UpnpPrintf(
	IN Upnp_LogLevel DLevel,
	IN Dbg_Module Module,
	IN const char *DbgFileName,
	IN int DbgLineNo,
	IN const char *FmtStr,
	... )
{
	va_list ArgList;
	
	if (!DebugAtThisLevel(DLevel, Module)) {
		return;
	}
	
	ithread_mutex_lock(&GlobalDebugMutex);
	va_start(ArgList, FmtStr);
	if (!DEBUG_TARGET) {
		if( DbgFileName ) {
			UpnpDisplayFileAndLine(stdout, DbgFileName, DbgLineNo);
		}
		vfprintf(stdout, FmtStr, ArgList);
		fflush(stdout);
	} else if (DLevel == 0) {
		if (DbgFileName) {
			UpnpDisplayFileAndLine(ErrFileHnd, DbgFileName, DbgLineNo);
		}
		vfprintf(ErrFileHnd, FmtStr, ArgList);
		fflush(ErrFileHnd);
	} else {
		if (DbgFileName) {
			UpnpDisplayFileAndLine(InfoFileHnd, DbgFileName, DbgLineNo);
		}
		vfprintf(InfoFileHnd, FmtStr, ArgList);
		fflush(InfoFileHnd);
	}
	va_end(ArgList);
	ithread_mutex_unlock(&GlobalDebugMutex);
}
Esempio n. 14
0
/********************************************************************************
 * upnp_igd_handle_subscribe_update
 *
 * Description:
 *       Handle a uPnP subscription update that was received.  Find the
 *       service the update belongs to, and update its subscription
 *       timeout.
 *
 * Parameters:
 *   igd_ctxt  -- The upnp igd context
 *   event_url -- The event URL for the subscription
 *   sid       -- The subscription id for the subscription
 *   timeout   -- The new timeout for the subscription
 *
 ********************************************************************************/
void upnp_igd_handle_subscribe_update(upnp_igd_context* igd_ctxt, const char *event_url, const Upnp_SID sid, int timeout) {
	upnp_igd_device_node *tmpdevnode;
	int service;

	ithread_mutex_lock(&igd_ctxt->devices_mutex);

	tmpdevnode = igd_ctxt->devices;
	while (tmpdevnode) {
		for (service = 0; service < IGD_SERVICE_SERVCOUNT; service++) {
			if (strcmp(tmpdevnode->device.services[service].event_url, event_url) == 0) {
				upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Received IGD %s Event Renewal for event_url %s", IGDServiceName[service], event_url);
				upnp_igd_strncpy(tmpdevnode->device.services[service].sid, sid, sizeof(tmpdevnode->device.services[service].sid));
				break;
			}
		}

		tmpdevnode = tmpdevnode->next;
	}

	ithread_mutex_unlock(&igd_ctxt->devices_mutex);

	return;
}
Esempio n. 15
0
/********************************************************************************
 * TvCtrlPointRemoveDevice
 *
 * Description: 
 *       Remove a device from the global device list.
 *
 * Parameters:
 *   UDN -- The Unique Device Name for the device to remove
 *
 ********************************************************************************/
int
TvCtrlPointRemoveDevice( char *UDN )
{
    struct TvDeviceNode *curdevnode,
     *prevdevnode;

    ithread_mutex_lock( &DeviceListMutex );

    curdevnode = GlobalDeviceList;
    if( !curdevnode ) {
        SampleUtil_Print
            ( "WARNING: TvCtrlPointRemoveDevice: Device list empty" );
    } else {
        if( 0 == strcmp( curdevnode->device.UDN, UDN ) ) {
            GlobalDeviceList = curdevnode->next;
            TvCtrlPointDeleteNode( curdevnode );
        } else {
            prevdevnode = curdevnode;
            curdevnode = curdevnode->next;

            while( curdevnode ) {
                if( strcmp( curdevnode->device.UDN, UDN ) == 0 ) {
                    prevdevnode->next = curdevnode->next;
                    TvCtrlPointDeleteNode( curdevnode );
                    break;
                }

                prevdevnode = curdevnode;
                curdevnode = curdevnode->next;
            }
        }
    }

    ithread_mutex_unlock( &DeviceListMutex );

    return TV_SUCCESS;
}
Esempio n. 16
0
/************************************************************************
 * Function: TimerThreadRemove
 * 
 *  Description:
 *     Removes an event from the timer Q.
 *     Events can only be removed 
 *     before they have been placed in the
 *     thread pool.
 *
 *  Parameters:
 *             timer - valid timer thread pointer.
 *             id - id of event to remove.
 *             out - space for returned job (Can be NULL)
 *  Return:
 *            0 on success.
 *            INVALID_EVENT_ID on error.
 *
 ************************************************************************/
int
TimerThreadRemove( TimerThread * timer,
                   int id,
                   ThreadPoolJob * out )
{
    int rc = INVALID_EVENT_ID;
    ListNode *tempNode = NULL;
    TimerEvent *temp = NULL;

    assert( timer != NULL );

    if( timer == NULL ) {
        return EINVAL;
    }

    ithread_mutex_lock( &timer->mutex );

    tempNode = ListHead( &timer->eventQ );

    while( tempNode != NULL ) {
        temp = ( TimerEvent * ) tempNode->item;
        if( temp->id == id )
        {

            ListDelNode( &timer->eventQ, tempNode, 0 );
            if( out != NULL )
                ( *out ) = temp->job;
            FreeTimerEvent( timer, temp );
            rc = 0;
            break;
        }
        tempNode = ListNext( &timer->eventQ, tempNode );
    }

    ithread_mutex_unlock( &timer->mutex );
    return rc;
}
Esempio n. 17
0
int RemoveMiniServerInterface(int iface)
{
    char addr[INET_ADDRSTRLEN] = { "\0" };
    uint16_t port = 0;
    if (iface < 0 || iface > MAX_NETWORK_INTERFACES)
        return UPNP_E_INVALID_PARAM;

    ithread_mutex_lock(&gMiniServerMutex);
    get_address(gMiniSocket->miniServerSock4[iface], addr);
    port = gMiniSocket->miniServerPort4[iface];
    sock_close(gMiniSocket->miniServerSock4[iface]);
    gMiniSocket->miniServerSock4[iface] = INVALID_SOCKET;
    sock_close(gMiniSocket->ssdpSock4[iface]);
    gMiniSocket->ssdpSock4[iface] = INVALID_SOCKET;
    sock_close(gMiniSocket->ssdpReqSock4[iface]);
    gMiniSocket->ssdpReqSock4[iface] = INVALID_SOCKET;
    ithread_mutex_unlock(&gMiniServerMutex);
    wake_miniserver();

    UpnpPrintf(UPNP_INFO, MSERV, __FILE__, __LINE__,
        "RemoveMiniServerInterface: %s:%d removed successfully from slot %d", addr, port, iface);

    return UPNP_E_SUCCESS;
}
Esempio n. 18
0
DBG_STATIC int xplaymode(struct action_event *event)
{
	char *newmode;
	int rc = 0;

	if (upnp_obtain_instanceid(event, NULL))
	{
		upnp_set_error(event, UPNP_TRANSPORT_E_INVALID_IID, "ID non-zero invalid");
		return -1;
	}

	newmode = upnp_get_string(event, "NewPlayMode");
	DBG_PRINT(DBG_LVL4, "Set NewPlayMode: %s\n", newmode);

	// Check MPD connection
	if (check_mpd_connection(TRUE) == STATUS_FAIL)
		return -1;

	ithread_mutex_lock(&transport_mutex);

	rc = output_playmode(newmode);
	if (rc != 0)
	{
		free(newmode);
		upnp_set_error(event, UPNP_TRANSPORT_E_PLAYMODE_NS, "Set playmode failed");
		goto out;
	}

	transport_change_var(event, TRANSPORT_VAR_CUR_PLAY_MODE, newmode);
	free(newmode);

out:
	ithread_mutex_unlock(&transport_mutex);

	return rc;
}
Esempio n. 19
0
static int handle_action_request(struct upnp_device *priv,
                                 struct Upnp_Action_Request *ar_event)
{
	struct service *event_service;
	struct action *event_action;

	event_service = find_service(priv->upnp_device_descriptor,
				     ar_event->ServiceID);
	event_action = find_action(event_service, ar_event->ActionName);

	if (event_action == NULL) {
		Log_error("upnp", "Unknown action '%s' for service '%s'",
			  ar_event->ActionName, ar_event->ServiceID);
		ar_event->ActionResult = NULL;
		ar_event->ErrCode = 401;
		return -1;
	}

	// We want to send the LastChange event only after the action is
	// finished - just to be conservative, we don't know how clients
	// react to get LastChange notifictions while in the middle of
	// issuing an action.
	//
	// So we nest the change collector level here, so that we only send the
	// LastChange after the action is finished ().
	//
	// Note, this is, in fact, only a preparation and not yet working as
	// described above: we are still in the middle
	// of executing the event-callback while sending the last change
	// event implicitly when calling UPnPLastChangeCollector_finish() below.
	// It would be good to enqueue the upnp_device_notify() after
	// the action event is finished.
	if (event_service->last_change) {
		ithread_mutex_lock(event_service->service_mutex);
		UPnPLastChangeCollector_start(event_service->last_change);
		ithread_mutex_unlock(event_service->service_mutex);
	}

#ifdef ENABLE_ACTION_LOGGING
	{
		char *action_request_xml = NULL;
		if (ar_event->ActionRequest) {
			action_request_xml = ixmlDocumenttoString(
					   ar_event->ActionRequest);
		}
		Log_info("upnp", "Action '%s'; Request: %s",
			 ar_event->ActionName, action_request_xml);
		free(action_request_xml);
	}
#endif

	if (event_action->callback) {
		struct action_event event;
		int rc;
		event.request = ar_event;
		event.status = 0;
		event.service = event_service;
                event.device = priv;

		rc = (event_action->callback) (&event);
		if (rc == 0) {
			ar_event->ErrCode = UPNP_E_SUCCESS;
#ifdef ENABLE_ACTION_LOGGING
			if (ar_event->ActionResult) {
				char *action_result_xml = NULL;
				action_result_xml = ixmlDocumenttoString(
						ar_event->ActionResult);
				Log_info("upnp", "Action '%s' OK; Response %s",
					 ar_event->ActionName,
					 action_result_xml);
				free(action_result_xml);
			} else {
				Log_info("upnp", "Action '%s' OK",
					 ar_event->ActionName);
			}
#endif
		}
		if (ar_event->ActionResult == NULL) {
			ar_event->ActionResult =
			    UpnpMakeActionResponse(ar_event->ActionName,
						   event_service->service_type,
						   0, NULL);
		}
	} else {
		Log_error("upnp",
			  "Got a valid action, but no handler defined (!)\n"
			  "  ErrCode:    %d\n"
			  "  Socket:     %d\n"
			  "  ErrStr:     '%s'\n"
			  "  ActionName: '%s'\n"
			  "  DevUDN:     '%s'\n"
			  "  ServiceID:  '%s'\n",
			  ar_event->ErrCode, ar_event->Socket, ar_event->ErrStr,
			  ar_event->ActionName, ar_event->DevUDN,
			  ar_event->ServiceID);
		ar_event->ErrCode = UPNP_E_SUCCESS;
	}

	if (event_service->last_change) {   // See comment above.
		ithread_mutex_lock(event_service->service_mutex);
		UPnPLastChangeCollector_finish(event_service->last_change);
		ithread_mutex_unlock(event_service->service_mutex);
	}
	return 0;
}
Esempio n. 20
0
/********************************************************************************
 * upnp_igd_add_device
 *
 * Description:
 *       If the device is not already included in the global device list,
 *       add it.  Otherwise, update its advertisement expiration timeout.
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *   desc_doc -- The description document for the device
 *   d_event  -- event associated with the new device
 *
 ********************************************************************************/
void upnp_igd_add_device(upnp_igd_context *igd_ctxt, IXML_Document *desc_doc, struct Upnp_Discovery *d_event) {
	upnp_igd_device_node *deviceNode, *tmpdevnode;
	int found = 0;
	int ret;
	int service, var;
	char presURL[200];

	char *serviceId;
	char *event_url;
	char *controlURL;
	Upnp_SID eventSID;

	char *deviceType = NULL;
	char *friendlyName = NULL;
	char *modelName = NULL;
	char *modelNumber = NULL;
	char *baseURL = NULL;
	char *relURL = NULL;
	char *UDN = NULL;

	UDN = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "UDN");
	deviceType = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "deviceType");
	friendlyName = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "friendlyName");
	modelName = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "modelName");
	modelNumber = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "modelNumber");
	baseURL = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "URLBase");
	relURL = upnp_igd_get_first_document_item(igd_ctxt, desc_doc, "presentationURL");

	ret = UpnpResolveURL((baseURL ? baseURL : d_event->Location), relURL, presURL);

	if (UPNP_E_SUCCESS != ret) {
		upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Error generating presURL from %s + %s", baseURL, relURL);
	}

	ithread_mutex_lock(&igd_ctxt->devices_mutex);

	if (strcmp(deviceType, IGDDeviceType) == 0) {
			/* Check if this device is already in the list */
			tmpdevnode = igd_ctxt->devices;
			while (tmpdevnode) {
				if (strcmp(tmpdevnode->device.udn, UDN) == 0) {
					found = 1;
					break;
				}
				tmpdevnode = tmpdevnode->next;
			}
			if (found) {
				/* The device is already there, so just update  */
				/* the advertisement timeout field */
				tmpdevnode->device.advr_time_out = d_event->Expires;
				upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "IGD device: %s[%s] | Update expires(%d)", friendlyName, UDN, tmpdevnode->device.advr_time_out);
			} else {
				upnp_igd_print(igd_ctxt, UPNP_IGD_MESSAGE, "Add IGD device: %s[%s]", friendlyName, UDN);

				/* Create a new device node */
				deviceNode = (upnp_igd_device_node *)  malloc(sizeof(upnp_igd_device_node));
				memset(deviceNode->device.services, '\0', sizeof(upnp_igd_service) * IGD_SERVICE_SERVCOUNT);
				strncpy(deviceNode->device.udn, UDN, sizeof(deviceNode->device.udn));
				strncpy(deviceNode->device.desc_doc_url, d_event->Location, sizeof(deviceNode->device.desc_doc_url));
				strncpy(deviceNode->device.friendly_name, friendlyName, sizeof(deviceNode->device.friendly_name));
				strncpy(deviceNode->device.model_name, modelName, sizeof(deviceNode->device.model_name));
				strncpy(deviceNode->device.model_number, modelNumber, sizeof(deviceNode->device.model_number));
				strncpy(deviceNode->device.pres_url, presURL, sizeof(deviceNode->device.pres_url));
				deviceNode->device.advr_time_out = d_event->Expires;

				// Reset values
				serviceId = NULL;
				event_url = NULL;
				controlURL = NULL;
				eventSID[0] = '\0';

				for (service = 0; service < IGD_SERVICE_SERVCOUNT;
				     service++) {
					if (upnp_igd_get_find_and_parse_service(igd_ctxt, desc_doc, d_event->Location,
							IGDServiceType[service], &serviceId, &event_url, &controlURL)) {
						upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Subscribing to EventURL %s...",event_url);
						ret =
						    UpnpSubscribe(igd_ctxt->upnp_handle, event_url, &IGDTimeOut[service], eventSID);
						if (ret == UPNP_E_SUCCESS) {
							upnp_igd_print(igd_ctxt, UPNP_IGD_DEBUG, "Subscribed to EventURL with SID=%s", eventSID);
						} else {
							upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Error Subscribing to EventURL -- %d", ret);
							strcpy(eventSID, "");
						}
					} else {
						upnp_igd_print(igd_ctxt, UPNP_IGD_ERROR, "Could not find Service: %s", IGDServiceType[service]);
					}
					if(serviceId != NULL) {
						upnp_igd_strncpy(deviceNode->device.services[service].service_id, serviceId, sizeof(deviceNode->device.services[service].service_id));
					}
					upnp_igd_strncpy(deviceNode->device.services[service].service_type, IGDServiceName[service], sizeof(deviceNode->device.services[service].service_type));
					if(controlURL != NULL) {
						upnp_igd_strncpy(deviceNode->device.services[service].control_url, controlURL, sizeof(deviceNode->device.services[service].control_url));
					}
					if(event_url != NULL) {
						upnp_igd_strncpy(deviceNode->device.services[service].event_url, event_url, sizeof(deviceNode->device.services[service].event_url));
					}
					if(eventSID != NULL) {
						upnp_igd_strncpy(deviceNode->device.services[service].sid, eventSID, sizeof(deviceNode->device.services[service].sid));
					}
					for (var = 0; var < IGDVarCount[service]; var++) {
						deviceNode->device.services[service].variables[var] = (char *)malloc(IGD_MAX_VAL_LEN);
						strcpy(deviceNode->device.services[service].variables[var], "");
					}
				}

				deviceNode->next = NULL;
				/* Insert the new device node in the list */
				if ((tmpdevnode = igd_ctxt->devices)) {
					while (tmpdevnode) {
						if (tmpdevnode->next) {
							tmpdevnode = tmpdevnode->next;
						} else {
							tmpdevnode->next = deviceNode;
							break;
						}
					}
				} else {
					igd_ctxt->devices = deviceNode;
				}

				// Ask some details
				upnp_igd_send_action(igd_ctxt, deviceNode, IGD_SERVICE_WANIPCONNECTION, "GetNATRSIPStatus", NULL, NULL, 0, upnp_igd_callback, igd_ctxt);

				// Usefull on some router
				upnp_igd_send_action(igd_ctxt, deviceNode, IGD_SERVICE_WANIPCONNECTION, "GetStatusInfo", NULL, NULL, 0, upnp_igd_callback, igd_ctxt);
				upnp_igd_send_action(igd_ctxt, deviceNode, IGD_SERVICE_WANIPCONNECTION, "GetExternalIPAddress", NULL, NULL, 0, upnp_igd_callback, igd_ctxt);
				
				upnp_context_add_callback(igd_ctxt, UPNP_IGD_DEVICE_ADDED, NULL);

				if (serviceId)
					free(serviceId);
				if (controlURL)
					free(controlURL);
				if (event_url)
					free(event_url);
			}
	}

	ithread_mutex_unlock(&igd_ctxt->devices_mutex);

	if (deviceType)
		free(deviceType);
	if (friendlyName)
		free(friendlyName);
	if (modelName)
		free(modelName);
	if (modelNumber)
		free(modelNumber);
	if (UDN)
		free(UDN);
	if (baseURL)
		free(baseURL);
	if (relURL)
		free(relURL);
}
Esempio n. 21
0
/********************************************************************************
 * upnp_igd_set_device_timeout
 *
 * Description:
 *       Set devices lease time 
 *
 * Parameters:
 *   igd_ctxt -- The upnp igd context
 *   seconds  -- The number of seconds
 *
 ********************************************************************************/
void upnp_igd_set_devices_timeout(upnp_igd_context *igd_ctxt, int seconds) {
	ithread_mutex_lock(&igd_ctxt->mutex);
	igd_ctxt->max_adv_timeout = seconds;
	igd_ctxt->timer_timeout = igd_ctxt->max_adv_timeout/2;
	ithread_mutex_unlock(&igd_ctxt->mutex);
}
Esempio n. 22
0
/************************************************************************
 * Function: TimerThreadSchedule
 * 
 *  Description:
 *     Schedules an event to run at a specified time.
 *
 *  Parameters:
 *             timer - valid timer thread pointer.
 *             time_t - time of event.
 *                      either in absolute seconds,
 *                      or relative seconds in the future.
 *             timeoutType - either ABS_SEC, or REL_SEC.
 *                           if REL_SEC, then the event
 *                           will be scheduled at the
 *                           current time + REL_SEC.
 *             
 *             func - function to schedule
 *             arg - argument to function
 *             priority - priority of job.
 *             id - id of timer event. (out)
 *  Return:
 *            0 on success, nonzero on failure
 *			  EOUTOFMEM if not enough memory to schedule job
 ************************************************************************/
int
TimerThreadSchedule( TimerThread * timer,
                     time_t timeout,
                     TimeoutType type,
                     ThreadPoolJob * job,
                     Duration duration,
                     int *id )
{

    int rc = EOUTOFMEM;
    int found = 0;
    int tempId = 0;

    ListNode *tempNode = NULL;
    TimerEvent *temp = NULL;
    TimerEvent *newEvent = NULL;

    assert( timer != NULL );
    assert( job != NULL );

    if( ( timer == NULL ) || ( job == NULL ) ) {
        return EINVAL;
    }

    CalculateEventTime( &timeout, type );
    ithread_mutex_lock( &timer->mutex );

    if( id == NULL )
        id = &tempId;

    ( *id ) = INVALID_EVENT_ID;

    newEvent = CreateTimerEvent( timer, job, duration, timeout,
                                 timer->lastEventId );

    if( newEvent == NULL ) {
        ithread_mutex_unlock( &timer->mutex );
        return rc;
    }

    tempNode = ListHead( &timer->eventQ );
    //add job to Q
    //Q is ordered by eventTime
    //with the head of the Q being the next event

    while( tempNode != NULL ) {
        temp = ( TimerEvent * ) tempNode->item;
        if( temp->eventTime >= timeout )
        {

            if( ListAddBefore( &timer->eventQ, newEvent, tempNode ) !=
                NULL )
                rc = 0;
            found = 1;
            break;

        }
        tempNode = ListNext( &timer->eventQ, tempNode );
    }

    //add to the end of Q
    if( !found ) {

        if( ListAddTail( &timer->eventQ, newEvent ) != NULL )
            rc = 0;

    }
    //signal change in Q
    if( rc == 0 ) {

        ithread_cond_signal( &timer->condition );
    } else {
        FreeTimerEvent( timer, newEvent );
    }
    ( *id ) = timer->lastEventId++;
    ithread_mutex_unlock( &timer->mutex );

    return rc;
}
Esempio n. 23
0
/********************************************************************************
 * SampleUtil_PrintEvent
 *
 * Description: 
 *       Prints callback event structure details.
 *
 * Parameters:
 *   EventType -- The type of callback event
 *   Event -- The callback event structure
 *
 ********************************************************************************/
int
SampleUtil_PrintEvent( IN Upnp_EventType EventType,
                       IN void *Event )
{

    ithread_mutex_lock( &display_mutex );

    SampleUtil_Print
        ( "\n\n\n======================================================================\n" );
    SampleUtil_Print
        ( "----------------------------------------------------------------------\n" );
    SampleUtil_PrintEventType( EventType );

    switch ( EventType ) {

            /*
               SSDP 
             */
        case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
        case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
        case UPNP_DISCOVERY_SEARCH_RESULT:
            {
                struct Upnp_Discovery *d_event =
                    ( struct Upnp_Discovery * )Event;

                SampleUtil_Print( "ErrCode     =  %d\n",
                                  d_event->ErrCode );
                SampleUtil_Print( "Expires     =  %d\n",
                                  d_event->Expires );
                SampleUtil_Print( "DeviceId    =  %s\n",
                                  d_event->DeviceId );
                SampleUtil_Print( "DeviceType  =  %s\n",
                                  d_event->DeviceType );
                SampleUtil_Print( "ServiceType =  %s\n",
                                  d_event->ServiceType );
                SampleUtil_Print( "ServiceVer  =  %s\n",
                                  d_event->ServiceVer );
                SampleUtil_Print( "Location    =  %s\n",
                                  d_event->Location );
                SampleUtil_Print( "OS          =  %s\n", d_event->Os );
                SampleUtil_Print( "Ext         =  %s\n", d_event->Ext );

            }
            break;

        case UPNP_DISCOVERY_SEARCH_TIMEOUT:
            // Nothing to print out here
            break;

            /*
               SOAP 
             */
        case UPNP_CONTROL_ACTION_REQUEST:
            {
                struct Upnp_Action_Request *a_event =
                    ( struct Upnp_Action_Request * )Event;
                char *xmlbuff = NULL;

                SampleUtil_Print( "ErrCode     =  %d\n",
                                  a_event->ErrCode );
                SampleUtil_Print( "ErrStr      =  %s\n", a_event->ErrStr );
                SampleUtil_Print( "ActionName  =  %s\n",
                                  a_event->ActionName );
                SampleUtil_Print( "UDN         =  %s\n", a_event->DevUDN );
                SampleUtil_Print( "ServiceID   =  %s\n",
                                  a_event->ServiceID );
                if( a_event->ActionRequest ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionRequest );
                    if( xmlbuff )
                        SampleUtil_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionResult );
                    if( xmlbuff )
                        SampleUtil_Print( "ActResult   =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActResult   =  (null)\n" );
                }
            }
            break;

        case UPNP_CONTROL_ACTION_COMPLETE:
            {
                struct Upnp_Action_Complete *a_event =
                    ( struct Upnp_Action_Complete * )Event;
                char *xmlbuff = NULL;

                SampleUtil_Print( "ErrCode     =  %d\n",
                                  a_event->ErrCode );
                SampleUtil_Print( "CtrlUrl     =  %s\n",
                                  a_event->CtrlUrl );
                if( a_event->ActionRequest ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionRequest );
                    if( xmlbuff )
                        SampleUtil_Print( "ActRequest  =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActRequest  =  (null)\n" );
                }

                if( a_event->ActionResult ) {
                    xmlbuff = ixmlPrintDocument( a_event->ActionResult );
                    if( xmlbuff )
                        SampleUtil_Print( "ActResult   =  %s\n", xmlbuff );
                    if( xmlbuff )
                        ixmlFreeDOMString( xmlbuff );
                    xmlbuff = NULL;
                } else {
                    SampleUtil_Print( "ActResult   =  (null)\n" );
                }
            }
            break;

        case UPNP_CONTROL_GET_VAR_REQUEST:
            {
                struct Upnp_State_Var_Request *sv_event =
                    ( struct Upnp_State_Var_Request * )Event;

                SampleUtil_Print( "ErrCode     =  %d\n",
                                  sv_event->ErrCode );
                SampleUtil_Print( "ErrStr      =  %s\n",
                                  sv_event->ErrStr );
                SampleUtil_Print( "UDN         =  %s\n",
                                  sv_event->DevUDN );
                SampleUtil_Print( "ServiceID   =  %s\n",
                                  sv_event->ServiceID );
                SampleUtil_Print( "StateVarName=  %s\n",
                                  sv_event->StateVarName );
                SampleUtil_Print( "CurrentVal  =  %s\n",
                                  sv_event->CurrentVal );
            }
            break;

        case UPNP_CONTROL_GET_VAR_COMPLETE:
            {
                struct Upnp_State_Var_Complete *sv_event =
                    ( struct Upnp_State_Var_Complete * )Event;

                SampleUtil_Print( "ErrCode     =  %d\n",
                                  sv_event->ErrCode );
                SampleUtil_Print( "CtrlUrl     =  %s\n",
                                  sv_event->CtrlUrl );
                SampleUtil_Print( "StateVarName=  %s\n",
                                  sv_event->StateVarName );
                SampleUtil_Print( "CurrentVal  =  %s\n",
                                  sv_event->CurrentVal );
            }
            break;

            /*
               GENA 
             */
        case UPNP_EVENT_SUBSCRIPTION_REQUEST:
            {
                struct Upnp_Subscription_Request *sr_event =
                    ( struct Upnp_Subscription_Request * )Event;

                SampleUtil_Print( "ServiceID   =  %s\n",
                                  sr_event->ServiceId );
                SampleUtil_Print( "UDN         =  %s\n", sr_event->UDN );
                SampleUtil_Print( "SID         =  %s\n", sr_event->Sid );
            }
            break;

        case UPNP_EVENT_RECEIVED:
            {
                struct Upnp_Event *e_event = ( struct Upnp_Event * )Event;
                char *xmlbuff = NULL;

                SampleUtil_Print( "SID         =  %s\n", e_event->Sid );
                SampleUtil_Print( "EventKey    =  %d\n",
                                  e_event->EventKey );
                xmlbuff = ixmlPrintDocument( e_event->ChangedVariables );
                SampleUtil_Print( "ChangedVars =  %s\n", xmlbuff );
                ixmlFreeDOMString( xmlbuff );
                xmlbuff = NULL;
            }
            break;

        case UPNP_EVENT_RENEWAL_COMPLETE:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SampleUtil_Print( "SID         =  %s\n", es_event->Sid );
                SampleUtil_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SampleUtil_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

        case UPNP_EVENT_SUBSCRIBE_COMPLETE:
        case UPNP_EVENT_UNSUBSCRIBE_COMPLETE:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SampleUtil_Print( "SID         =  %s\n", es_event->Sid );
                SampleUtil_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SampleUtil_Print( "PublisherURL=  %s\n",
                                  es_event->PublisherUrl );
                SampleUtil_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

        case UPNP_EVENT_AUTORENEWAL_FAILED:
        case UPNP_EVENT_SUBSCRIPTION_EXPIRED:
            {
                struct Upnp_Event_Subscribe *es_event =
                    ( struct Upnp_Event_Subscribe * )Event;

                SampleUtil_Print( "SID         =  %s\n", es_event->Sid );
                SampleUtil_Print( "ErrCode     =  %d\n",
                                  es_event->ErrCode );
                SampleUtil_Print( "PublisherURL=  %s\n",
                                  es_event->PublisherUrl );
                SampleUtil_Print( "TimeOut     =  %d\n",
                                  es_event->TimeOut );
            }
            break;

    }
    SampleUtil_Print
        ( "----------------------------------------------------------------------\n" );
    SampleUtil_Print
        ( "======================================================================\n\n\n\n" );

    ithread_mutex_unlock( &display_mutex );
    return ( 0 );
}
Esempio n. 24
0
int wphoto_upnp_handshake(void)
{
	int ret = -1, err;
	char descurl[256];
	const char *desc_xml = "MobileDevDesc.xml";
	struct timespec timer;
	int camera_responded_save;
	char *camera_url_save;
	int pinged_camera;

	ithread_mutex_init(&state_mutex, NULL);
	ithread_cond_init(&state_cond, NULL);
	camera_url = NULL;
	camera_responded = 0;
	err = UpnpInit(NULL, 0);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpInit", err);
		goto err_init;
	}
	server_ip = UpnpGetServerIpAddress();
	server_port = UpnpGetServerPort();
	if (init_xml_docs() < 0) {
		perror("init_xml_docs");
		goto err_init;
	}

	printf("address: %s:%d\n", server_ip, server_port);

	snprintf(descurl, sizeof(descurl), "http://%s:%d/%s",
			server_ip, server_port, desc_xml);
	err = web_add_callback("/MobileDevDesc.xml", web_MobileDevDesc, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	err = web_add_callback("/desc_iml/CameraConnectedMobile.xml",
			web_CameraConnectedMobile, NULL);
	if (err) {
		perror("web_add_callback");
		goto err_init;
	}
	if (web_start() < 0) {
		printf("web_init error\n");
		goto err_init;
	}
	err = UpnpRegisterRootDevice(descurl, upnp_device_event_handler,
			&device_handle, &device_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterRootDevice", err);
		goto err_init;
	}
	err = UpnpRegisterClient(upnp_client_event_handler,
			&client_handle, &client_handle);
	if (err != UPNP_E_SUCCESS) {
		upnp_perror("UpnpRegisterClient", err);
		goto err_register;
	}
	clock_gettime(CLOCK_REALTIME, &timer);
	discovery_timeout = 1;
	camera_responded_save = 0;
	camera_url_save = NULL;
	pinged_camera = 0;
	do {
		int wait_err;

		if (!camera_responded_save) {
			err = UpnpSendAdvertisement(device_handle, 0);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSendAdvertisement", err);
				goto err_register;
			}
			printf("NOTIFY sent\n");
		}
		if (camera_url_save && !pinged_camera)
			if (ping_camera(camera_url_save) == 0)
				pinged_camera = 1;
		timer.tv_sec += ADVERTISEMENT_INTERVAL;
wait:
		ithread_mutex_lock(&state_mutex);
		wait_err = 0;
		while (camera_responded == camera_responded_save &&
				strcmp_null(camera_url, camera_url_save) == 0 &&
				!discovery_timeout && wait_err == 0)
			wait_err = ithread_cond_timedwait(
					&state_cond, &state_mutex, &timer);
		camera_responded_save = camera_responded;
		if (strcmp_null(camera_url, camera_url_save) != 0) {
			free(camera_url_save);
			camera_url_save = strdup(camera_url);
		}
		/*
		 * Once we have the camera url, we stop sending M-SEARCH
		 * requests
		 */
		if (discovery_timeout && !camera_url_save) {
			err = UpnpSearchAsync(client_handle, MSEARCH_INTERVAL,
					CAMERA_SERVICE_NAME, (void*)42);
			if (err != UPNP_E_SUCCESS) {
				upnp_perror("UpnpSearchAsync", err);
				goto err_register;
			}
			printf("M-SEARCH sent\n");
		}
		discovery_timeout = 0;
		ithread_mutex_unlock(&state_mutex);
		if (wait_err != ETIMEDOUT &&
				(!pinged_camera || !camera_responded_save))
			goto wait;
	} while (!pinged_camera || !camera_responded_save);
	return 0;
err_register:
	UpnpUnRegisterRootDevice(device_handle);
err_init:
	UpnpFinish();
	return ret;
}
Esempio n. 25
0
/******************************************************************************
 * BrowseOrSearchWithCache
 *****************************************************************************/
static const ContentDir_BrowseResult*
BrowseOrSearchWithCache (ContentDir* cds, void* result_context, 
			 const char* objectId, const char* const criteria)
{
	if (cds == NULL || objectId == NULL || criteria == NULL)
		return NULL; // ---------->

	BrowseResult* br = talloc (result_context, BrowseResult);
	if (br == NULL)
		return NULL; // ---------->
	*br = (BrowseResult) { .cds = cds };

	if (cds->cache == NULL) {
		/*
		 * No cache
		 */
		br->children = BrowseOrSearchAll (cds, br, objectId, criteria);
	} else {
		/*
		 * Lookup and/or update cache 
		 */   
		ithread_mutex_lock (&cds->cache_mutex);

		char key_buffer [strlen(objectId) + strlen(criteria) + 2 ];
		const char* key;
		if (criteria == CRITERIA_BROWSE_CHILDREN) {
			key = objectId;
		} else {
			// criteria == "BrowseMetadata" or Search criteria
			sprintf (key_buffer, "%s\t%s", objectId, criteria);
			key = key_buffer;
		}

		Children** cp = (Children**) Cache_Get (cds->cache, key);
		if (cp) {
			if (*cp) {
				// cache hit
				br->children = *cp;
			} else {
				// cache new (or expired)

				// Note: use the cache as parent context for 
				// allocation of result.
				br->children = BrowseOrSearchAll
					(cds, cds->cache, objectId, criteria);
				// set cache
				*cp = br->children;
			}
		}
		// Add a reference to the cached result before returning it
		if (br->children) {
			talloc_increase_ref_count (br->children);    
			talloc_set_destructor (br, DestroyResult);
		}
		
		ithread_mutex_unlock (&cds->cache_mutex);
	}

	if (br->children == NULL) {
		talloc_free (br);
		br = NULL;
	}
	
	return br;
}
Esempio n. 26
0
/********************************************************************************
 * TvCtrlPointAddDevice
 *
 * Description: 
 *       If the device is not already included in the global device list,
 *       add it.  Otherwise, update its advertisement expiration timeout.
 *
 * Parameters:
 *   DescDoc -- The description document for the device
 *   location -- The location of the description document URL
 *   expires -- The expiration time for this advertisement
 *
 ********************************************************************************/
void TvCtrlPointAddDevice(
	IXML_Document *DescDoc,
	const char *location,
	int expires)
{
	char *deviceType = NULL;
	char *friendlyName = NULL;
	char presURL[200];
	char *baseURL = NULL;
	char *relURL = NULL;
	char *UDN = NULL;
	char *serviceId[TV_SERVICE_SERVCOUNT] = { NULL, NULL };
	char *eventURL[TV_SERVICE_SERVCOUNT] = { NULL, NULL };
	char *controlURL[TV_SERVICE_SERVCOUNT] = { NULL, NULL };
	Upnp_SID eventSID[TV_SERVICE_SERVCOUNT];
	int TimeOut[TV_SERVICE_SERVCOUNT] = {
		default_timeout,
		default_timeout
	};
	struct TvDeviceNode *deviceNode;
	struct TvDeviceNode *tmpdevnode;
	int ret = 1;
	int found = 0;
	int service;
	int var;

	ithread_mutex_lock(&DeviceListMutex);

	/* Read key elements from description document */
	UDN = SampleUtil_GetFirstDocumentItem(DescDoc, "UDN");
	deviceType = SampleUtil_GetFirstDocumentItem(DescDoc, "deviceType");
	friendlyName = SampleUtil_GetFirstDocumentItem(DescDoc, "friendlyName");
	baseURL = SampleUtil_GetFirstDocumentItem(DescDoc, "URLBase");
	relURL = SampleUtil_GetFirstDocumentItem(DescDoc, "presentationURL");

	ret = UpnpResolveURL((baseURL ? baseURL : location), relURL, presURL);

	if (UPNP_E_SUCCESS != ret)
		SampleUtil_Print("Error generating presURL from %s + %s\n",
				 baseURL, relURL);

	if (strcmp(deviceType, TvDeviceType) == 0) {
		SampleUtil_Print("Found Tv device\n");

		/* Check if this device is already in the list */
		tmpdevnode = GlobalDeviceList;
		while (tmpdevnode) {
			if (strcmp(tmpdevnode->device.UDN, UDN) == 0) {
				found = 1;
				break;
			}
			tmpdevnode = tmpdevnode->next;
		}

		if (found) {
			/* The device is already there, so just update  */
			/* the advertisement timeout field */
			tmpdevnode->device.AdvrTimeOut = expires;
		} else {
			for (service = 0; service < TV_SERVICE_SERVCOUNT;
			     service++) {
				if (SampleUtil_FindAndParseService
				    (DescDoc, location, TvServiceType[service],
				     &serviceId[service], &eventURL[service],
				     &controlURL[service])) {
					SampleUtil_Print
					    ("Subscribing to EventURL %s...\n",
					     eventURL[service]);
					ret =
					    UpnpSubscribe(ctrlpt_handle,
							  eventURL[service],
							  &TimeOut[service],
							  eventSID[service]);
					if (ret == UPNP_E_SUCCESS) {
						SampleUtil_Print
						    ("Subscribed to EventURL with SID=%s\n",
						     eventSID[service]);
					} else {
						SampleUtil_Print
						    ("Error Subscribing to EventURL -- %d\n",
						     ret);
						strcpy(eventSID[service], "");
					}
				} else {
					SampleUtil_Print
					    ("Error: Could not find Service: %s\n",
					     TvServiceType[service]);
				}
			}
			/* Create a new device node */
			deviceNode =
			    (struct TvDeviceNode *)
			    malloc(sizeof(struct TvDeviceNode));
			strcpy(deviceNode->device.UDN, UDN);
			strcpy(deviceNode->device.DescDocURL, location);
			strcpy(deviceNode->device.FriendlyName, friendlyName);
			strcpy(deviceNode->device.PresURL, presURL);
			deviceNode->device.AdvrTimeOut = expires;
			for (service = 0; service < TV_SERVICE_SERVCOUNT;
			     service++) {
				strcpy(deviceNode->device.TvService[service].
				       ServiceId, serviceId[service]);
				strcpy(deviceNode->device.TvService[service].
				       ServiceType, TvServiceType[service]);
				strcpy(deviceNode->device.TvService[service].
				       ControlURL, controlURL[service]);
				strcpy(deviceNode->device.TvService[service].
				       EventURL, eventURL[service]);
				strcpy(deviceNode->device.TvService[service].
				       SID, eventSID[service]);
				for (var = 0; var < TvVarCount[service]; var++) {
					deviceNode->device.
					    TvService[service].VariableStrVal
					    [var] =
					    (char *)malloc(TV_MAX_VAL_LEN);
					strcpy(deviceNode->device.
					       TvService[service].VariableStrVal
					       [var], "");
				}
			}
			deviceNode->next = NULL;
			/* Insert the new device node in the list */
			if ((tmpdevnode = GlobalDeviceList)) {
				while (tmpdevnode) {
					if (tmpdevnode->next) {
						tmpdevnode = tmpdevnode->next;
					} else {
						tmpdevnode->next = deviceNode;
						break;
					}
				}
			} else {
				GlobalDeviceList = deviceNode;
			}
			/*Notify New Device Added */
			SampleUtil_StateUpdate(NULL, NULL,
					       deviceNode->device.UDN,
					       DEVICE_ADDED);
		}
	}

	ithread_mutex_unlock(&DeviceListMutex);

	if (deviceType)
		free(deviceType);
	if (friendlyName)
		free(friendlyName);
	if (UDN)
		free(UDN);
	if (baseURL)
		free(baseURL);
	if (relURL)
		free(relURL);
	for (service = 0; service < TV_SERVICE_SERVCOUNT; service++) {
		if (serviceId[service])
			free(serviceId[service]);
		if (controlURL[service])
			free(controlURL[service]);
		if (eventURL[service])
			free(eventURL[service]);
	}
}
Esempio n. 27
0
/********************************************************************************
 * TvCtrlPointPrintDevice
 *
 * Description: 
 *       Print the identifiers and state table for a device from
 *       the global device list.
 *
 * Parameters:
 *   devnum -- The number of the device (order in the list,
 *             starting with 1)
 *
 ********************************************************************************/
int TvCtrlPointPrintDevice(int devnum)
{
	struct TvDeviceNode *tmpdevnode;
	int i = 0, service, var;
	char spacer[15];

	if (devnum <= 0) {
		SampleUtil_Print(
			"Error in TvCtrlPointPrintDevice: "
			"invalid devnum = %d\n",
			devnum);
		return TV_ERROR;
	}

	ithread_mutex_lock(&DeviceListMutex);

	SampleUtil_Print("TvCtrlPointPrintDevice:\n");
	tmpdevnode = GlobalDeviceList;
	while (tmpdevnode) {
		i++;
		if (i == devnum)
			break;
		tmpdevnode = tmpdevnode->next;
	}
	if (!tmpdevnode) {
		SampleUtil_Print(
			"Error in TvCtrlPointPrintDevice: "
			"invalid devnum = %d  --  actual device count = %d\n",
			devnum, i);
	} else {
		SampleUtil_Print(
			"  TvDevice -- %d\n"
			"    |                  \n"
			"    +- UDN        = %s\n"
			"    +- DescDocURL     = %s\n"
			"    +- FriendlyName   = %s\n"
			"    +- PresURL        = %s\n"
			"    +- Adver. TimeOut = %d\n",
			devnum,
			tmpdevnode->device.UDN,
			tmpdevnode->device.DescDocURL,
			tmpdevnode->device.FriendlyName,
			tmpdevnode->device.PresURL,
			tmpdevnode->device.AdvrTimeOut);
		for (service = 0; service < TV_SERVICE_SERVCOUNT; service++) {
			if (service < TV_SERVICE_SERVCOUNT - 1)
				sprintf(spacer, "    |    ");
			else
				sprintf(spacer, "         ");
			SampleUtil_Print(
				"    |                  \n"
				"    +- Tv %s Service\n"
				"%s+- ServiceId       = %s\n"
				"%s+- ServiceType     = %s\n"
				"%s+- EventURL        = %s\n"
				"%s+- ControlURL      = %s\n"
				"%s+- SID             = %s\n"
				"%s+- ServiceStateTable\n",
				TvServiceName[service],
				spacer,
				tmpdevnode->device.TvService[service].ServiceId,
				spacer,
				tmpdevnode->device.TvService[service].ServiceType,
				spacer,
				tmpdevnode->device.TvService[service].EventURL,
				spacer,
				tmpdevnode->device.TvService[service].ControlURL,
				spacer,
				tmpdevnode->device.TvService[service].SID,
				spacer);
			for (var = 0; var < TvVarCount[service]; var++) {
				SampleUtil_Print(
					"%s     +- %-10s = %s\n",
					spacer,
					TvVarName[service][var],
					tmpdevnode->device.TvService[service].VariableStrVal[var]);
			}
		}
	}
	SampleUtil_Print("\n");
	ithread_mutex_unlock(&DeviceListMutex);

	return TV_SUCCESS;
}
static void service_unlock(void)
{
#ifdef HAVE_LIBUPNP
	ithread_mutex_unlock(&transport_mutex);
#endif
}
Esempio n. 29
0
/****************************************************************************
 * Function: TimerThreadWorker
 *
 *  Description:
 *      Implements timer thread.
 *      Waits for next event to occur and schedules
 *      associated job into threadpool.
 *      Internal Only.
 *  Parameters:
 *      void * arg -> is cast to TimerThread *
 *****************************************************************************/
static void *
TimerThreadWorker( void *arg )
{
    TimerThread *timer = ( TimerThread * ) arg;
    ListNode *head = NULL;

    TimerEvent *nextEvent = NULL;

    time_t currentTime = 0;
    time_t nextEventTime = 0;
    struct timespec timeToWait;

    int tempId;

    assert( timer != NULL );

    ithread_mutex_lock( &timer->mutex );

    while( 1 )
    {

        //mutex should always be locked at top of loop

        //Check for shutdown

        if( timer->shutdown )
        {

            timer->shutdown = 0;
            ithread_cond_signal( &timer->condition );
            ithread_mutex_unlock( &timer->mutex );
            return NULL;

        }

        nextEvent = NULL;

        //Get the next event if possible
        if( timer->eventQ.size > 0 )
        {
            head = ListHead( &timer->eventQ );

            nextEvent = ( TimerEvent * ) head->item;
            nextEventTime = nextEvent->eventTime;
        }

        currentTime = time( NULL );

        //If time has elapsed, schedule job

        if( ( nextEvent != NULL ) && ( currentTime >= nextEventTime ) )
        {

            if( nextEvent->persistent ) {

                ThreadPoolAddPersistent( timer->tp, &nextEvent->job,
                                         &tempId );
            } else {

                ThreadPoolAdd( timer->tp, &nextEvent->job, &tempId );
            }

            ListDelNode( &timer->eventQ, head, 0 );
            FreeTimerEvent( timer, nextEvent );

            continue;

        }

        if( nextEvent != NULL ) {
            timeToWait.tv_nsec = 0;
            timeToWait.tv_sec = nextEvent->eventTime;

            ithread_cond_timedwait( &timer->condition, &timer->mutex,
                                    &timeToWait );

        } else {
            ithread_cond_wait( &timer->condition, &timer->mutex );
        }

    }
}
Esempio n. 30
0
static int handle_subscription_request(struct upnp_device *priv,
                                       struct Upnp_Subscription_Request
                                              *sr_event)
{
	struct service *srv;
	int rc;

	assert(priv != NULL);

	Log_info("upnp", "Subscription request for %s (%s)",
		 sr_event->ServiceId, sr_event->UDN);

	srv = find_service(priv->upnp_device_descriptor, sr_event->ServiceId);
	if (srv == NULL) {
		Log_error("upnp", "%s: Unknown service '%s'", __FUNCTION__,
			  sr_event->ServiceId);
		return -1;
	}

	int result = -1;
	ithread_mutex_lock(&(priv->device_mutex));

	// There is really only one variable evented: LastChange
	const char *eventvar_names[] = {
		"LastChange",
		NULL
	};
	const char *eventvar_values[] = {
		NULL, NULL
	};

	// Build the current state of the variables as one gigantic initial
	// LastChange update.
	ithread_mutex_lock(srv->service_mutex);
	const int var_count =
		VariableContainer_get_num_vars(srv->variable_container);
	// TODO(hzeller): maybe use srv->last_change directly ?
	upnp_last_change_builder_t *builder = UPnPLastChangeBuilder_new(srv->event_xml_ns);
	for (int i = 0; i < var_count; ++i) {
		const char *name;
		const char *value =
			VariableContainer_get(srv->variable_container, i, &name);
		// Send over all variables except "LastChange" itself. Also all
		// A_ARG_TYPE variables are not evented.
		if (value && strcmp("LastChange", name) != 0
		    && strncmp("A_ARG_TYPE_", name, strlen("A_ARG_TYPE_")) != 0) {
			UPnPLastChangeBuilder_add(builder, name, value);
		}
	}
	ithread_mutex_unlock(srv->service_mutex);
	char *xml_value = UPnPLastChangeBuilder_to_xml(builder);
	Log_info("upnp", "Initial variable sync: %s", xml_value);
	eventvar_values[0] = xmlescape(xml_value, 0);
	free(xml_value);
	UPnPLastChangeBuilder_delete(builder);

	rc = UpnpAcceptSubscription(priv->device_handle,
				    sr_event->UDN, sr_event->ServiceId,
				    eventvar_names, eventvar_values, 1,
				    sr_event->Sid);
	if (rc == UPNP_E_SUCCESS) {
		result = 0;
	} else {
		Log_error("upnp", "Accept Subscription Error: %s (%d)",
			  UpnpGetErrorMessage(rc), rc);
	}

	ithread_mutex_unlock(&(priv->device_mutex));

	free((char*)eventvar_values[0]);

	return result;
}