Search code examples
c++cxmllinuxupnp

How to make upnp action?


I want to implement port-forwarding using intel-upnp. I got XML data like:

Device found at location: http://192.168.10.1:49152/gatedesc.xml  
service urn:schemas-upnp-org:service:WANIPConnection:1  
controlurl /upnp/control/WANIPConn1  
eventsuburl : /upnp/control/WANIPConn1  
scpdurl : /gateconnSCPD.xml  

And now, I want to make upnp-action. But, I don't know how to make it. If you know some code snippet or helpful URL in C, please tell me.

char actionxml[250];  
IXML_Document *action = NULL;  
strcpy(actionxml, "<u:GetConnectionTypeInfo xmlns:u=\"urn:schemas-upnp- org:service:WANCommonInterfaceConfig:1\">");  
action = ixmlParseBuffer(actionxml);  
int ret = UpnpSendActionAsync( g_handle,
                    "http:192.168.10.1:49152/upnp/control/WANCommonIFC1",
                    "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
                    NULL,
                    action,
                    upnp_callback,
                    NULL);

Solution

  • I know this is an old question, but it can be kept for reference. You can take a look at the sample code in the libupnp library here: https://github.com/mrjimenez/pupnp/blob/master/upnp/sample/common/tv_ctrlpt.c

    The relevant code is in the function TvCtrlPointSendAction():

    int TvCtrlPointSendAction(
        int service,
        int devnum,
        const char *actionname,
        const char **param_name,
        char **param_val,
        int param_count)
    {
        struct TvDeviceNode *devnode;
        IXML_Document *actionNode = NULL;
        int rc = TV_SUCCESS;
        int param;
    
        ithread_mutex_lock(&DeviceListMutex);
    
        rc = TvCtrlPointGetDevice(devnum, &devnode);
        if (TV_SUCCESS == rc) {
            if (0 == param_count) {
                actionNode =
                    UpnpMakeAction(actionname, TvServiceType[service],
                           0, NULL);
            } else {
                for (param = 0; param < param_count; param++) {
                    if (UpnpAddToAction
                        (&actionNode, actionname,
                         TvServiceType[service], param_name[param],
                         param_val[param]) != UPNP_E_SUCCESS) {
                        SampleUtil_Print
                            ("ERROR: TvCtrlPointSendAction: Trying to add action param\n");
                        /*return -1; // TBD - BAD! leaves mutex locked */
                    }
                }
            }
    
            rc = UpnpSendActionAsync(ctrlpt_handle,
                         devnode->device.
                         TvService[service].ControlURL,
                         TvServiceType[service], NULL,
                         actionNode,
                         TvCtrlPointCallbackEventHandler, NULL);
    
            if (rc != UPNP_E_SUCCESS) {
                SampleUtil_Print("Error in UpnpSendActionAsync -- %d\n",
                         rc);
                rc = TV_ERROR;
            }
        }
    
        ithread_mutex_unlock(&DeviceListMutex);
    
        if (actionNode)
            ixmlDocument_free(actionNode);
    
        return rc;
    }
    

    The explanation is that you should create the action with UpnpMakeAction() if you have no parameters or UpnpAddToAction() if you have parameters to create your action, and then send it either synchronously or asynchronously.