1 /* $Id: upnpdescgen.c,v 1.16 2010/11/11 23:48:13 jmaggard Exp $ */
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
5 * Copyright (c) 2006-2008, Thomas Bernard
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
35 #include "getifaddr.h"
36 #include "upnpdescgen.h"
37 #include "minidlnapath.h"
38 #include "upnpglobalvars.h"
39 #include "upnpdescstrings.h"
43 static const char * const upnptypes
[] =
55 static const char * const upnpdefaultvalues
[] =
61 static const char * const upnpallowedvalues
[] =
77 "Unconfigured", /* 14 */
81 "Unconfigured", /* 18 */
88 "ERROR_NONE", /* 25 */
91 "ContentFormatMismatch",
92 "InsufficientBandwidth",
99 "BrowseMetadata", /* 36 */
100 "BrowseDirectChildren",
102 "COMPLETED", /* 39 */
107 RESOURCE_PROTOCOL_INFO_VALUES
, /* 44 */
115 static const char xmlver
[] =
116 "<?xml version=\"1.0\"?>\r\n";
117 static const char root_service
[] =
118 "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
119 static const char root_device
[] =
120 "root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
122 /* root Description of the UPnP Device
123 * fixed to match UPnP_IGD_InternetGatewayDevice 1.0.pdf
124 * presentationURL is only "recommended" but the router doesn't appears
125 * in "Network connections" in Windows XP if it is not present. */
126 static const struct XMLElt rootDesc
[] =
128 {root_device
, INITHELPER(1,2)},
129 {"specVersion", INITHELPER(3,2)},
130 {"device", INITHELPER(5,14)},
133 {"/deviceType", "urn:schemas-upnp-org:device:MediaServer:1"},
134 {"/friendlyName", friendly_name
}, /* required */
135 {"/manufacturer", ROOTDEV_MANUFACTURER
}, /* required */
136 {"/manufacturerURL", ROOTDEV_MANUFACTURERURL
}, /* optional */
137 {"/modelDescription", ROOTDEV_MODELDESCRIPTION
}, /* recommended */
138 {"/modelName", ROOTDEV_MODELNAME
}, /* required */
139 {"/modelNumber", modelnumber
},
140 {"/modelURL", ROOTDEV_MODELURL
},
141 {"/serialNumber", serialnumber
},
142 {"/UDN", uuidvalue
}, /* required */
143 {"/dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\"", "DMS-1.50"},
144 {"/presentationURL", presentationurl
}, /* recommended */
145 {"iconList", INITHELPER(19,4)},
146 {"serviceList", INITHELPER(43,3)},
147 {"icon", INITHELPER(23,5)},
148 {"icon", INITHELPER(28,5)},
149 {"icon", INITHELPER(33,5)},
150 {"icon", INITHELPER(38,5)},
151 {"/mimetype", "image/png"},
155 {"/url", "/icons/sm.png"},
156 {"/mimetype", "image/png"},
160 {"/url", "/icons/lrg.png"},
161 {"/mimetype", "image/jpeg"},
165 {"/url", "/icons/sm.jpg"},
166 {"/mimetype", "image/jpeg"},
170 {"/url", "/icons/lrg.jpg"},
171 {"service", INITHELPER(46,5)},
172 {"service", INITHELPER(51,5)},
173 {"service", INITHELPER(56,5)},
174 {"/serviceType", "urn:schemas-upnp-org:service:ContentDirectory:1"},
175 {"/serviceId", "urn:upnp-org:serviceId:ContentDirectory"},
176 {"/controlURL", CONTENTDIRECTORY_CONTROLURL
},
177 {"/eventSubURL", CONTENTDIRECTORY_EVENTURL
},
178 {"/SCPDURL", CONTENTDIRECTORY_PATH
},
179 {"/serviceType", "urn:schemas-upnp-org:service:ConnectionManager:1"},
180 {"/serviceId", "urn:upnp-org:serviceId:ConnectionManager"},
181 {"/controlURL", CONNECTIONMGR_CONTROLURL
},
182 {"/eventSubURL", CONNECTIONMGR_EVENTURL
},
183 {"/SCPDURL", CONNECTIONMGR_PATH
},
184 {"/serviceType", "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"},
185 {"/serviceId", "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar"},
186 {"/controlURL", X_MS_MEDIARECEIVERREGISTRAR_CONTROLURL
},
187 {"/eventSubURL", X_MS_MEDIARECEIVERREGISTRAR_EVENTURL
},
188 {"/SCPDURL", X_MS_MEDIARECEIVERREGISTRAR_PATH
},
192 static const struct argument AddPortMappingArgs
[] =
205 static const struct argument DeletePortMappingArgs
[] =
213 static const struct argument SetConnectionTypeArgs
[] =
219 static const struct argument GetConnectionTypeInfoArgs
[] =
226 static const struct argument GetNATRSIPStatusArgs
[] =
233 static const struct argument GetGenericPortMappingEntryArgs
[] =
247 static const struct argument GetSpecificPortMappingEntryArgs
[] =
260 /* For ConnectionManager */
261 static const struct argument GetProtocolInfoArgs
[] =
268 static const struct argument PrepareForConnectionArgs
[] =
270 {"RemoteProtocolInfo", 1, 6},
271 {"PeerConnectionManager", 1, 4},
272 {"PeerConnectionID", 1, 7},
274 {"ConnectionID", 2, 7},
275 {"AVTransportID", 2, 8},
280 static const struct argument ConnectionCompleteArgs
[] =
282 {"ConnectionID", 1, 7},
286 static const struct argument GetCurrentConnectionIDsArgs
[] =
288 {"ConnectionIDs", 2, 2},
292 static const struct argument GetCurrentConnectionInfoArgs
[] =
294 {"ConnectionID", 1, 7},
296 {"AVTransportID", 2, 8},
297 {"ProtocolInfo", 2, 6},
298 {"PeerConnectionManager", 2, 4},
299 {"PeerConnectionID", 2, 7},
305 static const struct action ConnectionManagerActions
[] =
307 {"GetProtocolInfo", GetProtocolInfoArgs
}, /* R */
308 //OPTIONAL {"PrepareForConnection", PrepareForConnectionArgs}, /* R */
309 //OPTIONAL {"ConnectionComplete", ConnectionCompleteArgs}, /* R */
310 {"GetCurrentConnectionIDs", GetCurrentConnectionIDsArgs
}, /* R */
311 {"GetCurrentConnectionInfo", GetCurrentConnectionInfoArgs
}, /* R */
315 static const struct stateVar ConnectionManagerVars
[] =
317 {"SourceProtocolInfo", 1<<7, 0, 0, 44}, /* required */
318 {"SinkProtocolInfo", 1<<7, 0, 0, 48}, /* required */
319 {"CurrentConnectionIDs", 1<<7, 0, 0, 46}, /* required */
320 {"A_ARG_TYPE_ConnectionStatus", 0, 0, 27}, /* required */
321 {"A_ARG_TYPE_ConnectionManager", 0, 0}, /* required */
322 {"A_ARG_TYPE_Direction", 0, 0, 33}, /* required */
323 {"A_ARG_TYPE_ProtocolInfo", 0, 0}, /* required */
324 {"A_ARG_TYPE_ConnectionID", 4, 0}, /* required */
325 {"A_ARG_TYPE_AVTransportID", 4, 0}, /* required */
326 {"A_ARG_TYPE_RcsID", 4, 0}, /* required */
330 static const struct argument GetSearchCapabilitiesArgs
[] =
332 {"SearchCaps", 2, 10},
336 static const struct argument GetSortCapabilitiesArgs
[] =
342 static const struct argument GetSystemUpdateIDArgs
[] =
348 static const struct argument BrowseArgs
[] =
351 {"BrowseFlag", 1, 4},
353 {"StartingIndex", 1, 7},
354 {"RequestedCount", 1, 8},
355 {"SortCriteria", 1, 6},
357 {"NumberReturned", 2, 8},
358 {"TotalMatches", 2, 8},
363 static const struct argument SearchArgs
[] =
365 {"ContainerID", 1, 1},
366 {"SearchCriteria", 1, 3},
368 {"StartingIndex", 1, 7},
369 {"RequestedCount", 1, 8},
370 {"SortCriteria", 1, 6},
372 {"NumberReturned", 2, 8},
373 {"TotalMatches", 2, 8},
378 static const struct action ContentDirectoryActions
[] =
380 {"GetSearchCapabilities", GetSearchCapabilitiesArgs
}, /* R */
381 {"GetSortCapabilities", GetSortCapabilitiesArgs
}, /* R */
382 {"GetSystemUpdateID", GetSystemUpdateIDArgs
}, /* R */
383 {"Browse", BrowseArgs
}, /* R */
384 {"Search", SearchArgs
}, /* O */
385 #if 0 // Not implementing optional features yet...
386 {"CreateObject", CreateObjectArgs
}, /* O */
387 {"DestroyObject", DestroyObjectArgs
}, /* O */
388 {"UpdateObject", UpdateObjectArgs
}, /* O */
389 {"ImportResource", ImportResourceArgs
}, /* O */
390 {"ExportResource", ExportResourceArgs
}, /* O */
391 {"StopTransferResource", StopTransferResourceArgs
}, /* O */
392 {"GetTransferProgress", GetTransferProgressArgs
}, /* O */
393 {"DeleteResource", DeleteResourceArgs
}, /* O */
394 {"CreateReference", CreateReferenceArgs
}, /* O */
399 static const struct stateVar ContentDirectoryVars
[] =
401 {"TransferIDs", 1<<7, 0, 0, 48}, /* 0 */
402 {"A_ARG_TYPE_ObjectID", 0, 0},
403 {"A_ARG_TYPE_Result", 0, 0},
404 {"A_ARG_TYPE_SearchCriteria", 0, 0},
405 {"A_ARG_TYPE_BrowseFlag", 0, 0, 36},
406 /* Allowed Values : BrowseMetadata / BrowseDirectChildren */
407 {"A_ARG_TYPE_Filter", 0, 0}, /* 5 */
408 {"A_ARG_TYPE_SortCriteria", 0, 0},
409 {"A_ARG_TYPE_Index", 3, 0},
410 {"A_ARG_TYPE_Count", 3, 0},
411 {"A_ARG_TYPE_UpdateID", 3, 0},
412 //JM{"A_ARG_TYPE_TransferID", 3, 0}, /* 10 */
413 //JM{"A_ARG_TYPE_TransferStatus", 0, 0, 39},
414 /* Allowed Values : COMPLETED / ERROR / IN_PROGRESS / STOPPED */
415 //JM{"A_ARG_TYPE_TransferLength", 0, 0},
416 //JM{"A_ARG_TYPE_TransferTotal", 0, 0},
417 //JM{"A_ARG_TYPE_TagValueList", 0, 0},
418 //JM{"A_ARG_TYPE_URI", 5, 0}, /* 15 */
419 {"SearchCapabilities", 0, 0},
420 {"SortCapabilities", 0, 0},
421 {"SystemUpdateID", 3|0x80, 0, 0, 255},
422 //{"ContainerUpdateIDs", 0, 0},
426 static const struct argument GetIsAuthorizedArgs
[] =
433 static const struct argument GetIsValidatedArgs
[] =
440 static const struct argument GetRegisterDeviceArgs
[] =
442 {"RegistrationReqMsg", 1, 1},
443 {"RegistrationRespMsg", 2, 2},
447 static const struct action X_MS_MediaReceiverRegistrarActions
[] =
449 {"IsAuthorized", GetIsAuthorizedArgs
}, /* R */
450 {"IsValidated", GetIsValidatedArgs
}, /* R */
451 #if 0 // Not needed? WMP12 still works. Need to check with 360 and WMP11.
452 {"RegisterDevice", GetRegisterDeviceArgs
}, /* R */
457 static const struct stateVar X_MS_MediaReceiverRegistrarVars
[] =
459 {"A_ARG_TYPE_DeviceID", 0, 0},
460 {"A_ARG_TYPE_RegistrationReqMsg", 7, 0},
461 {"A_ARG_TYPE_RegistrationRespMsg", 7, 0},
462 {"A_ARG_TYPE_Result", 6, 0},
463 {"AuthorizationDeniedUpdateID", 3, 0},
464 {"AuthorizationGrantedUpdateID", 3, 0},
465 {"ValidationRevokedUpdateID", 3, 0},
466 {"ValidationSucceededUpdateID", 3, 0},
471 /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
473 static const struct argument GetCommonLinkPropertiesArgs
[] =
482 static const struct argument GetTotalBytesSentArgs
[] =
488 static const struct argument GetTotalBytesReceivedArgs
[] =
494 static const struct argument GetTotalPacketsSentArgs
[] =
500 static const struct argument GetTotalPacketsReceivedArgs
[] =
506 static const struct serviceDesc scpdContentDirectory
=
507 { ContentDirectoryActions
, ContentDirectoryVars
};
509 static const struct serviceDesc scpdConnectionManager
=
510 { ConnectionManagerActions
, ConnectionManagerVars
};
512 static const struct serviceDesc scpdX_MS_MediaReceiverRegistrar
=
513 { X_MS_MediaReceiverRegistrarActions
, X_MS_MediaReceiverRegistrarVars
};
516 * concatenate the string and use realloc to increase the
517 * memory buffer if needed. */
519 strcat_str(char * str
, int * len
, int * tmplen
, const char * s2
)
522 s2len
= (int)strlen(s2
);
523 if(*tmplen
<= (*len
+ s2len
))
528 *tmplen
+= s2len
+ 1;
529 str
= (char *)realloc(str
, *tmplen
);
531 /*strcpy(str + *len, s2); */
532 memcpy(str
+ *len
, s2
, s2len
+ 1);
538 * concatenate a character and use realloc to increase the
539 * size of the memory buffer if needed */
541 strcat_char(char * str
, int * len
, int * tmplen
, char c
)
543 if(*tmplen
<= (*len
+ 1))
546 str
= (char *)realloc(str
, *tmplen
);
553 /* iterative subroutine using a small stack
554 * This way, the progam stack usage is kept low */
556 genXML(char * str
, int * len
, int * tmplen
,
557 const struct XMLElt
* p
)
561 const char * eltname
, *s
;
567 const char * eltname
;
568 } pile
[16]; /* stack */
570 i
= 0; /* current node */
571 j
= 1; /* i + number of nodes*/
574 eltname
= p
[i
].eltname
;
577 if(eltname
[0] == '/')
580 printf("DBG: <%s>%s<%s>\n", eltname
+1, p
[i
].data
, eltname
);
582 str
= strcat_char(str
, len
, tmplen
, '<');
583 str
= strcat_str(str
, len
, tmplen
, eltname
+1);
584 str
= strcat_char(str
, len
, tmplen
, '>');
585 str
= strcat_str(str
, len
, tmplen
, p
[i
].data
);
586 str
= strcat_char(str
, len
, tmplen
, '<');
587 sscanf(eltname
, "%s", element
);
588 str
= strcat_str(str
, len
, tmplen
, element
);
589 str
= strcat_char(str
, len
, tmplen
, '>');
597 printf("DBG: pile[%d]\t%d %d\n", top
, i
, j
);
602 printf("DBG: i==j, </%s>\n", pile
[top
].eltname
);
604 str
= strcat_char(str
, len
, tmplen
, '<');
605 str
= strcat_char(str
, len
, tmplen
, '/');
606 s
= pile
[top
].eltname
;
607 for(c
= *s
; c
> ' '; c
= *(++s
))
608 str
= strcat_char(str
, len
, tmplen
, c
);
609 str
= strcat_char(str
, len
, tmplen
, '>');
619 printf("DBG: [%d] <%s>\n", i
, eltname
);
621 str
= strcat_char(str
, len
, tmplen
, '<');
622 str
= strcat_str(str
, len
, tmplen
, eltname
);
623 str
= strcat_char(str
, len
, tmplen
, '>');
626 /*j = i + p[k].nchild; */
627 i
= (unsigned long)p
[k
].data
& 0xffff;
628 j
= i
+ ((unsigned long)p
[k
].data
>> 16);
631 printf("DBG: +pile[%d]\t%d %d\n", top
, i
, j
);
635 pile
[top
].eltname
= eltname
;
641 * - Generate the root description of the UPnP device.
642 * - the len argument is used to return the length of
643 * the returned string.
644 * - tmp_uuid argument is used to build the uuid string */
646 genRootDesc(int * len
)
651 str
= (char *)malloc(tmplen
);
654 * len
= strlen(xmlver
);
655 /*strcpy(str, xmlver); */
656 memcpy(str
, xmlver
, *len
+ 1);
657 str
= genXML(str
, len
, &tmplen
, rootDesc
);
662 /* genServiceDesc() :
663 * Generate service description with allowed methods and
664 * related variables. */
666 genServiceDesc(int * len
, const struct serviceDesc
* s
)
669 const struct action
* acts
;
670 const struct stateVar
* vars
;
671 const struct argument
* args
;
676 str
= (char *)malloc(tmplen
);
679 /*strcpy(str, xmlver); */
680 *len
= strlen(xmlver
);
681 memcpy(str
, xmlver
, *len
+ 1);
683 acts
= s
->actionList
;
684 vars
= s
->serviceStateTable
;
686 str
= strcat_char(str
, len
, &tmplen
, '<');
687 str
= strcat_str(str
, len
, &tmplen
, root_service
);
688 str
= strcat_char(str
, len
, &tmplen
, '>');
690 str
= strcat_str(str
, len
, &tmplen
,
691 "<specVersion><major>1</major><minor>0</minor></specVersion>");
694 str
= strcat_str(str
, len
, &tmplen
, "<actionList>");
697 str
= strcat_str(str
, len
, &tmplen
, "<action><name>");
698 str
= strcat_str(str
, len
, &tmplen
, acts
[i
].name
);
699 str
= strcat_str(str
, len
, &tmplen
, "</name>");
704 str
= strcat_str(str
, len
, &tmplen
, "<argumentList>");
708 str
= strcat_str(str
, len
, &tmplen
, "<argument><name>");
709 p
= vars
[args
[j
].relatedVar
].name
;
710 str
= strcat_str(str
, len
, &tmplen
, (args
[j
].name
? args
[j
].name
: p
));
711 str
= strcat_str(str
, len
, &tmplen
, "</name><direction>");
712 str
= strcat_str(str
, len
, &tmplen
, args
[j
].dir
==1?"in":"out");
713 str
= strcat_str(str
, len
, &tmplen
,
714 "</direction><relatedStateVariable>");
715 str
= strcat_str(str
, len
, &tmplen
, p
);
716 str
= strcat_str(str
, len
, &tmplen
,
717 "</relatedStateVariable></argument>");
720 str
= strcat_str(str
, len
, &tmplen
,"</argumentList>");
722 str
= strcat_str(str
, len
, &tmplen
, "</action>");
723 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
726 str
= strcat_str(str
, len
, &tmplen
, "</actionList><serviceStateTable>");
730 str
= strcat_str(str
, len
, &tmplen
,
731 "<stateVariable sendEvents=\"");
732 str
= strcat_str(str
, len
, &tmplen
, (vars
[i
].itype
& 0x80)?"yes":"no");
733 str
= strcat_str(str
, len
, &tmplen
, "\"><name>");
734 str
= strcat_str(str
, len
, &tmplen
, vars
[i
].name
);
735 str
= strcat_str(str
, len
, &tmplen
, "</name><dataType>");
736 str
= strcat_str(str
, len
, &tmplen
, upnptypes
[vars
[i
].itype
& 0x0f]);
737 str
= strcat_str(str
, len
, &tmplen
, "</dataType>");
738 if(vars
[i
].iallowedlist
)
740 str
= strcat_str(str
, len
, &tmplen
, "<allowedValueList>");
741 for(j
=vars
[i
].iallowedlist
; upnpallowedvalues
[j
]; j
++)
743 str
= strcat_str(str
, len
, &tmplen
, "<allowedValue>");
744 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[j
]);
745 str
= strcat_str(str
, len
, &tmplen
, "</allowedValue>");
747 str
= strcat_str(str
, len
, &tmplen
, "</allowedValueList>");
749 /*if(vars[i].defaultValue) */
752 str
= strcat_str(str
, len
, &tmplen
, "<defaultValue>");
753 /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
754 str
= strcat_str(str
, len
, &tmplen
, upnpdefaultvalues
[vars
[i
].idefault
]);
755 str
= strcat_str(str
, len
, &tmplen
, "</defaultValue>");
757 str
= strcat_str(str
, len
, &tmplen
, "</stateVariable>");
758 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
761 str
= strcat_str(str
, len
, &tmplen
, "</serviceStateTable></scpd>");
766 /* genContentDirectory() :
767 * Generate the ContentDirectory xml description */
769 genContentDirectory(int * len
)
771 return genServiceDesc(len
, &scpdContentDirectory
);
774 /* genConnectionManager() :
775 * Generate the ConnectionManager xml description */
777 genConnectionManager(int * len
)
779 return genServiceDesc(len
, &scpdConnectionManager
);
782 /* genX_MS_MediaReceiverRegistrar() :
783 * Generate the X_MS_MediaReceiverRegistrar xml description */
785 genX_MS_MediaReceiverRegistrar(int * len
)
787 return genServiceDesc(len
, &scpdX_MS_MediaReceiverRegistrar
);
791 genEventVars(int * len
, const struct serviceDesc
* s
, const char * servns
)
793 const struct stateVar
* v
;
798 str
= (char *)malloc(tmplen
);
802 v
= s
->serviceStateTable
;
803 snprintf(buf
, sizeof(buf
), "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"%s\">", servns
);
804 str
= strcat_str(str
, len
, &tmplen
, buf
);
806 if(v
->itype
& 0x80) {
807 snprintf(buf
, sizeof(buf
), "<e:property><%s>", v
->name
);
808 str
= strcat_str(str
, len
, &tmplen
, buf
);
809 //printf("<e:property><s:%s>", v->name);
810 switch(v
->ieventvalue
) {
813 case 255: /* Magical values should go around here */
814 if( strcmp(v
->name
, "SystemUpdateID") == 0 )
816 snprintf(buf
, sizeof(buf
), "%d", updateID
);
817 str
= strcat_str(str
, len
, &tmplen
, buf
);
821 str
= strcat_str(str
, len
, &tmplen
, upnpallowedvalues
[v
->ieventvalue
]);
822 //printf("%s", upnpallowedvalues[v->ieventvalue]);
824 snprintf(buf
, sizeof(buf
), "</%s></e:property>", v
->name
);
825 str
= strcat_str(str
, len
, &tmplen
, buf
);
826 //printf("</s:%s></e:property>\n", v->name);
830 str
= strcat_str(str
, len
, &tmplen
, "</e:propertyset>");
831 //printf("</e:propertyset>\n");
833 //printf("%d\n", tmplen);
839 getVarsContentDirectory(int * l
)
841 return genEventVars(l
,
842 &scpdContentDirectory
,
843 "urn:schemas-upnp-org:service:ContentDirectory:1");
847 getVarsConnectionManager(int * l
)
849 return genEventVars(l
,
850 &scpdConnectionManager
,
851 "urn:schemas-upnp-org:service:ConnectionManager:1");
855 getVarsX_MS_MediaReceiverRegistrar(int * l
)
857 return genEventVars(l
,
858 &scpdX_MS_MediaReceiverRegistrar
,
859 "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1");