1 Star 3 Fork 4

jiftle / minidlna

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
upnpdescgen.c 20.59 KB
一键复制 编辑 原始数据 按行查看 历史
jiftle 提交于 2018-11-05 15:03 . 导入minidlna 1.2.1代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
*
* Copyright (c) 2006-2008, Thomas Bernard
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "event.h"
#include "getifaddr.h"
#include "upnpdescgen.h"
#include "minidlnapath.h"
#include "upnpglobalvars.h"
#undef DESC_DEBUG
static const char * const upnptypes[] =
{
"string",
"boolean",
"ui2",
"ui4",
"i4",
"uri",
"int",
"bin.base64"
};
static const char * const upnpdefaultvalues[] =
{
0,
"Unconfigured"
};
static const char * const upnpallowedvalues[] =
{
0, /* 0 */
"DSL", /* 1 */
"POTS",
"Cable",
"Ethernet",
0,
"Up", /* 6 */
"Down",
"Initializing",
"Unavailable",
0,
"TCP", /* 11 */
"UDP",
0,
"Unconfigured", /* 14 */
"IP_Routed",
"IP_Bridged",
0,
"Unconfigured", /* 18 */
"Connecting",
"Connected",
"PendingDisconnect",
"Disconnecting",
"Disconnected",
0,
"ERROR_NONE", /* 25 */
0,
"OK", /* 27 */
"ContentFormatMismatch",
"InsufficientBandwidth",
"UnreliableChannel",
"Unknown",
0,
"Input", /* 33 */
"Output",
0,
"BrowseMetadata", /* 36 */
"BrowseDirectChildren",
0,
"COMPLETED", /* 39 */
"ERROR",
"IN_PROGRESS",
"STOPPED",
0,
RESOURCE_PROTOCOL_INFO_VALUES, /* 44 */
0,
"0", /* 46 */
0,
"", /* 48 */
0
};
static const char xmlver[] =
"<?xml version=\"1.0\"?>\r\n";
static const char root_service[] =
"scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
static const char root_device[] =
"root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
/* root Description of the UPnP Device */
static const struct XMLElt rootDesc[] =
{
{root_device, INITHELPER(1,2)},
{"specVersion", INITHELPER(3,2)},
{"device", INITHELPER(5,(14))},
{"/major", "1"},
{"/minor", "0"},
{"/deviceType", "urn:schemas-upnp-org:device:MediaServer:1"},
{"/friendlyName", friendly_name}, /* required */
{"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
{"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */
{"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
{"/modelName", modelname}, /* required */
{"/modelNumber", modelnumber},
{"/modelURL", ROOTDEV_MODELURL},
{"/serialNumber", serialnumber},
{"/UDN", uuidvalue}, /* required */
{"/dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\"", "DMS-1.50"},
{"/presentationURL", presentationurl}, /* recommended */
{"iconList", INITHELPER((19),4)},
{"serviceList", INITHELPER((43),3)},
{"icon", INITHELPER((23),5)},
{"icon", INITHELPER((28),5)},
{"icon", INITHELPER((33),5)},
{"icon", INITHELPER((38),5)},
{"/mimetype", "image/png"},
{"/width", "48"},
{"/height", "48"},
{"/depth", "24"},
{"/url", "/icons/sm.png"},
{"/mimetype", "image/png"},
{"/width", "120"},
{"/height", "120"},
{"/depth", "24"},
{"/url", "/icons/lrg.png"},
{"/mimetype", "image/jpeg"},
{"/width", "48"},
{"/height", "48"},
{"/depth", "24"},
{"/url", "/icons/sm.jpg"},
{"/mimetype", "image/jpeg"},
{"/width", "120"},
{"/height", "120"},
{"/depth", "24"},
{"/url", "/icons/lrg.jpg"},
{"service", INITHELPER((46),5)},
{"service", INITHELPER((51),5)},
{"service", INITHELPER((56),5)},
{"/serviceType", "urn:schemas-upnp-org:service:ContentDirectory:1"},
{"/serviceId", "urn:upnp-org:serviceId:ContentDirectory"},
{"/controlURL", CONTENTDIRECTORY_CONTROLURL},
{"/eventSubURL", CONTENTDIRECTORY_EVENTURL},
{"/SCPDURL", CONTENTDIRECTORY_PATH},
{"/serviceType", "urn:schemas-upnp-org:service:ConnectionManager:1"},
{"/serviceId", "urn:upnp-org:serviceId:ConnectionManager"},
{"/controlURL", CONNECTIONMGR_CONTROLURL},
{"/eventSubURL", CONNECTIONMGR_EVENTURL},
{"/SCPDURL", CONNECTIONMGR_PATH},
{"/serviceType", "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1"},
{"/serviceId", "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar"},
{"/controlURL", X_MS_MEDIARECEIVERREGISTRAR_CONTROLURL},
{"/eventSubURL", X_MS_MEDIARECEIVERREGISTRAR_EVENTURL},
{"/SCPDURL", X_MS_MEDIARECEIVERREGISTRAR_PATH},
{0, 0}
};
/* For ConnectionManager */
static const struct argument GetProtocolInfoArgs[] =
{
{"Source", 2, 0},
{"Sink", 2, 1},
{NULL, 0, 0}
};
static const struct argument GetCurrentConnectionIDsArgs[] =
{
{"ConnectionIDs", 2, 2},
{NULL, 0, 0}
};
static const struct argument GetCurrentConnectionInfoArgs[] =
{
{"ConnectionID", 1, 7},
{"RcsID", 2, 9},
{"AVTransportID", 2, 8},
{"ProtocolInfo", 2, 6},
{"PeerConnectionManager", 2, 4},
{"PeerConnectionID", 2, 7},
{"Direction", 2, 5},
{"Status", 2, 3},
{NULL, 0, 0}
};
static const struct action ConnectionManagerActions[] =
{
{"GetProtocolInfo", GetProtocolInfoArgs}, /* R */
{"GetCurrentConnectionIDs", GetCurrentConnectionIDsArgs}, /* R */
{"GetCurrentConnectionInfo", GetCurrentConnectionInfoArgs}, /* R */
{0, 0}
};
static const struct stateVar ConnectionManagerVars[] =
{
{"SourceProtocolInfo", 0|EVENTED, 0, 0, 44}, /* required */
{"SinkProtocolInfo", 0|EVENTED, 0, 0, 48}, /* required */
{"CurrentConnectionIDs", 0|EVENTED, 0, 0, 46}, /* required */
{"A_ARG_TYPE_ConnectionStatus", 0, 0, 27}, /* required */
{"A_ARG_TYPE_ConnectionManager", 0, 0}, /* required */
{"A_ARG_TYPE_Direction", 0, 0, 33}, /* required */
{"A_ARG_TYPE_ProtocolInfo", 0, 0}, /* required */
{"A_ARG_TYPE_ConnectionID", 4, 0}, /* required */
{"A_ARG_TYPE_AVTransportID", 4, 0}, /* required */
{"A_ARG_TYPE_RcsID", 4, 0}, /* required */
{0, 0}
};
static const struct argument GetSearchCapabilitiesArgs[] =
{
{"SearchCaps", 2, 11},
{0, 0}
};
static const struct argument GetSortCapabilitiesArgs[] =
{
{"SortCaps", 2, 12},
{0, 0}
};
static const struct argument GetSystemUpdateIDArgs[] =
{
{"Id", 2, 13},
{0, 0}
};
static const struct argument UpdateObjectArgs[] =
{
{"ObjectID", 1, 1},
{"CurrentTagValue", 1, 10},
{"NewTagValue", 1, 10},
{0, 0}
};
static const struct argument BrowseArgs[] =
{
{"ObjectID", 1, 1},
{"BrowseFlag", 1, 4},
{"Filter", 1, 5},
{"StartingIndex", 1, 7},
{"RequestedCount", 1, 8},
{"SortCriteria", 1, 6},
{"Result", 2, 2},
{"NumberReturned", 2, 8},
{"TotalMatches", 2, 8},
{"UpdateID", 2, 9},
{0, 0}
};
static const struct argument SearchArgs[] =
{
{"ContainerID", 1, 1},
{"SearchCriteria", 1, 3},
{"Filter", 1, 5},
{"StartingIndex", 1, 7},
{"RequestedCount", 1, 8},
{"SortCriteria", 1, 6},
{"Result", 2, 2},
{"NumberReturned", 2, 8},
{"TotalMatches", 2, 8},
{"UpdateID", 2, 9},
{0, 0}
};
static const struct action ContentDirectoryActions[] =
{
{"GetSearchCapabilities", GetSearchCapabilitiesArgs}, /* R */
{"GetSortCapabilities", GetSortCapabilitiesArgs}, /* R */
{"GetSystemUpdateID", GetSystemUpdateIDArgs}, /* R */
{"Browse", BrowseArgs}, /* R */
{"Search", SearchArgs}, /* O */
{"UpdateObject", UpdateObjectArgs}, /* O */
#if 0 // Not implementing optional features yet...
{"CreateObject", CreateObjectArgs}, /* O */
{"DestroyObject", DestroyObjectArgs}, /* O */
{"ImportResource", ImportResourceArgs}, /* O */
{"ExportResource", ExportResourceArgs}, /* O */
{"StopTransferResource", StopTransferResourceArgs}, /* O */
{"GetTransferProgress", GetTransferProgressArgs}, /* O */
{"DeleteResource", DeleteResourceArgs}, /* O */
{"CreateReference", CreateReferenceArgs}, /* O */
#endif
{0, 0}
};
static const struct stateVar ContentDirectoryVars[] =
{
{"TransferIDs", 0|EVENTED, 0, 0, 48}, /* 0 */
{"A_ARG_TYPE_ObjectID", 0, 0},
{"A_ARG_TYPE_Result", 0, 0},
{"A_ARG_TYPE_SearchCriteria", 0, 0},
{"A_ARG_TYPE_BrowseFlag", 0, 0, 36},
/* Allowed Values : BrowseMetadata / BrowseDirectChildren */
{"A_ARG_TYPE_Filter", 0, 0}, /* 5 */
{"A_ARG_TYPE_SortCriteria", 0, 0},
{"A_ARG_TYPE_Index", 3, 0},
{"A_ARG_TYPE_Count", 3, 0},
{"A_ARG_TYPE_UpdateID", 3, 0},
{"A_ARG_TYPE_TagValueList", 0, 0},
{"SearchCapabilities", 0, 0},
{"SortCapabilities", 0, 0},
{"SystemUpdateID", 3|EVENTED, 0, 0, 255},
{0, 0}
};
static const struct argument GetIsAuthorizedArgs[] =
{
{"DeviceID", 1, 0},
{"Result", 2, 3},
{NULL, 0, 0}
};
static const struct argument GetIsValidatedArgs[] =
{
{"DeviceID", 1, 0},
{"Result", 2, 3},
{NULL, 0, 0}
};
static const struct argument GetRegisterDeviceArgs[] =
{
{"RegistrationReqMsg", 1, 1},
{"RegistrationRespMsg", 2, 2},
{NULL, 0, 0}
};
static const struct action X_MS_MediaReceiverRegistrarActions[] =
{
{"IsAuthorized", GetIsAuthorizedArgs}, /* R */
{"IsValidated", GetIsValidatedArgs}, /* R */
{"RegisterDevice", GetRegisterDeviceArgs},
{0, 0}
};
static const struct stateVar X_MS_MediaReceiverRegistrarVars[] =
{
{"A_ARG_TYPE_DeviceID", 0, 0},
{"A_ARG_TYPE_RegistrationReqMsg", 7, 0},
{"A_ARG_TYPE_RegistrationRespMsg", 7, 0},
{"A_ARG_TYPE_Result", 6, 0},
{"AuthorizationDeniedUpdateID", 3|EVENTED, 0},
{"AuthorizationGrantedUpdateID", 3|EVENTED, 0},
{"ValidationRevokedUpdateID", 3|EVENTED, 0},
{"ValidationSucceededUpdateID", 3|EVENTED, 0},
{0, 0}
};
static const struct serviceDesc scpdContentDirectory =
{ ContentDirectoryActions, ContentDirectoryVars };
static const struct serviceDesc scpdConnectionManager =
{ ConnectionManagerActions, ConnectionManagerVars };
static const struct serviceDesc scpdX_MS_MediaReceiverRegistrar =
{ X_MS_MediaReceiverRegistrarActions, X_MS_MediaReceiverRegistrarVars };
/* strcat_str()
* concatenate the string and use realloc to increase the
* memory buffer if needed. */
static char *
strcat_str(char * str, int * len, int * tmplen, const char * s2)
{
char *p;
int s2len;
s2len = (int)strlen(s2);
if(*tmplen <= (*len + s2len))
{
if(s2len < 256)
*tmplen += 256;
else
*tmplen += s2len + 1;
p = realloc(str, *tmplen);
if (!p)
{
if(s2len < 256)
*tmplen -= 256;
else
*tmplen -= s2len + 1;
return str;
}
else
str = p;
}
/*strcpy(str + *len, s2); */
memcpy(str + *len, s2, s2len + 1);
*len += s2len;
return str;
}
/* strcat_char() :
* concatenate a character and use realloc to increase the
* size of the memory buffer if needed */
static char *
strcat_char(char * str, int * len, int * tmplen, char c)
{
char *p;
if(*tmplen <= (*len + 1))
{
*tmplen += 256;
p = (char *)realloc(str, *tmplen);
if (!p)
{
*tmplen -= 256;
return str;
}
else
str = p;
}
str[*len] = c;
(*len)++;
return str;
}
/* iterative subroutine using a small stack
* This way, the progam stack usage is kept low */
static char *
genXML(char * str, int * len, int * tmplen,
const struct XMLElt * p)
{
uint16_t i, j, k;
int top;
const char * eltname, *s;
char c;
char element[64];
struct {
unsigned short i;
unsigned short j;
const char * eltname;
} pile[16]; /* stack */
top = -1;
i = 0; /* current node */
j = 1; /* i + number of nodes*/
for(;;)
{
eltname = p[i].eltname;
if(!eltname)
return str;
if(eltname[0] == '/')
{
#ifdef DESC_DEBUG
printf("DBG: <%s>%s<%s>\n", eltname+1, p[i].data, eltname);
#endif
str = strcat_char(str, len, tmplen, '<');
str = strcat_str(str, len, tmplen, eltname+1);
str = strcat_char(str, len, tmplen, '>');
str = strcat_str(str, len, tmplen, p[i].data);
str = strcat_char(str, len, tmplen, '<');
sscanf(eltname, "%s", element);
str = strcat_str(str, len, tmplen, element);
str = strcat_char(str, len, tmplen, '>');
for(;;)
{
if(top < 0)
return str;
i = ++(pile[top].i);
j = pile[top].j;
#ifdef DESC_DEBUG
printf("DBG: pile[%d]\t%d %d\n", top, i, j);
#endif
if(i==j)
{
#ifdef DESC_DEBUG
printf("DBG: i==j, </%s>\n", pile[top].eltname);
#endif
str = strcat_char(str, len, tmplen, '<');
str = strcat_char(str, len, tmplen, '/');
s = pile[top].eltname;
for(c = *s; c > ' '; c = *(++s))
str = strcat_char(str, len, tmplen, c);
str = strcat_char(str, len, tmplen, '>');
top--;
}
else
break;
}
}
else
{
#ifdef DESC_DEBUG
printf("DBG: [%d] <%s>\n", i, eltname);
#endif
str = strcat_char(str, len, tmplen, '<');
str = strcat_str(str, len, tmplen, eltname);
str = strcat_char(str, len, tmplen, '>');
k = i;
/*i = p[k].index; */
/*j = i + p[k].nchild; */
i = (unsigned long)p[k].data & 0xffff;
j = i + ((unsigned long)p[k].data >> 16);
top++;
#ifdef DESC_DEBUG
printf("DBG: +pile[%d]\t%d %d\n", top, i, j);
#endif
pile[top].i = i;
pile[top].j = j;
pile[top].eltname = eltname;
}
}
}
/* genRootDesc() :
* - Generate the root description of the UPnP device.
* - the len argument is used to return the length of
* the returned string.
* - tmp_uuid argument is used to build the uuid string */
char *
genRootDesc(int * len)
{
char * str;
int tmplen;
tmplen = 2560;
str = (char *)malloc(tmplen);
if(str == NULL)
return NULL;
* len = strlen(xmlver);
memcpy(str, xmlver, *len + 1);
str = genXML(str, len, &tmplen, rootDesc);
str[*len] = '\0';
return str;
}
char *
genRootDescSamsung(int * len)
{
char * str;
int tmplen;
struct XMLElt samsungRootDesc[sizeof(rootDesc)/sizeof(struct XMLElt)];
tmplen = 2560;
str = (char *)malloc(tmplen);
if(str == NULL)
return NULL;
* len = strlen(xmlver);
memcpy(str, xmlver, *len + 1);
/* Replace the optional modelURL and manufacturerURL fields with Samsung foo */
memcpy(&samsungRootDesc, &rootDesc, sizeof(rootDesc));
samsungRootDesc[8].eltname = "/sec:ProductCap";
samsungRootDesc[8].data = "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
samsungRootDesc[12].eltname = "/sec:X_ProductCap";
samsungRootDesc[12].data = "smi,DCM10,getMediaInfo.sec,getCaptionInfo.sec";
str = genXML(str, len, &tmplen, samsungRootDesc);
str[*len] = '\0';
return str;
}
/* genServiceDesc() :
* Generate service description with allowed methods and
* related variables. */
static char *
genServiceDesc(int * len, const struct serviceDesc * s)
{
int i, j;
const struct action * acts;
const struct stateVar * vars;
const struct argument * args;
const char * p;
char * str;
int tmplen;
tmplen = 2048;
str = (char *)malloc(tmplen);
if(str == NULL)
return NULL;
/*strcpy(str, xmlver); */
*len = strlen(xmlver);
memcpy(str, xmlver, *len + 1);
acts = s->actionList;
vars = s->serviceStateTable;
str = strcat_char(str, len, &tmplen, '<');
str = strcat_str(str, len, &tmplen, root_service);
str = strcat_char(str, len, &tmplen, '>');
str = strcat_str(str, len, &tmplen,
"<specVersion><major>1</major><minor>0</minor></specVersion>");
i = 0;
str = strcat_str(str, len, &tmplen, "<actionList>");
while(acts[i].name)
{
str = strcat_str(str, len, &tmplen, "<action><name>");
str = strcat_str(str, len, &tmplen, acts[i].name);
str = strcat_str(str, len, &tmplen, "</name>");
/* argument List */
args = acts[i].args;
if(args)
{
str = strcat_str(str, len, &tmplen, "<argumentList>");
j = 0;
while(args[j].dir)
{
str = strcat_str(str, len, &tmplen, "<argument><name>");
p = vars[args[j].relatedVar].name;
str = strcat_str(str, len, &tmplen, (args[j].name ? args[j].name : p));
str = strcat_str(str, len, &tmplen, "</name><direction>");
str = strcat_str(str, len, &tmplen, args[j].dir==1?"in":"out");
str = strcat_str(str, len, &tmplen,
"</direction><relatedStateVariable>");
str = strcat_str(str, len, &tmplen, p);
str = strcat_str(str, len, &tmplen,
"</relatedStateVariable></argument>");
j++;
}
str = strcat_str(str, len, &tmplen,"</argumentList>");
}
str = strcat_str(str, len, &tmplen, "</action>");
/*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
i++;
}
str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
i = 0;
while(vars[i].name)
{
str = strcat_str(str, len, &tmplen,
"<stateVariable sendEvents=\"");
str = strcat_str(str, len, &tmplen, (vars[i].itype & EVENTED)?"yes":"no");
str = strcat_str(str, len, &tmplen, "\"><name>");
str = strcat_str(str, len, &tmplen, vars[i].name);
str = strcat_str(str, len, &tmplen, "</name><dataType>");
str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
str = strcat_str(str, len, &tmplen, "</dataType>");
if(vars[i].iallowedlist)
{
str = strcat_str(str, len, &tmplen, "<allowedValueList>");
for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
{
str = strcat_str(str, len, &tmplen, "<allowedValue>");
str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
str = strcat_str(str, len, &tmplen, "</allowedValue>");
}
str = strcat_str(str, len, &tmplen, "</allowedValueList>");
}
/*if(vars[i].defaultValue) */
if(vars[i].idefault)
{
str = strcat_str(str, len, &tmplen, "<defaultValue>");
/*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
str = strcat_str(str, len, &tmplen, "</defaultValue>");
}
str = strcat_str(str, len, &tmplen, "</stateVariable>");
/*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
i++;
}
str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
str[*len] = '\0';
return str;
}
/* genContentDirectory() :
* Generate the ContentDirectory xml description */
char *
genContentDirectory(int * len)
{
return genServiceDesc(len, &scpdContentDirectory);
}
/* genConnectionManager() :
* Generate the ConnectionManager xml description */
char *
genConnectionManager(int * len)
{
return genServiceDesc(len, &scpdConnectionManager);
}
/* genX_MS_MediaReceiverRegistrar() :
* Generate the X_MS_MediaReceiverRegistrar xml description */
char *
genX_MS_MediaReceiverRegistrar(int * len)
{
return genServiceDesc(len, &scpdX_MS_MediaReceiverRegistrar);
}
static char *
genEventVars(int * len, const struct serviceDesc * s, const char * servns)
{
const struct stateVar * v;
char * str;
int tmplen;
char buf[512];
tmplen = 512;
str = (char *)malloc(tmplen);
if(str == NULL)
return NULL;
*len = 0;
v = s->serviceStateTable;
snprintf(buf, sizeof(buf), "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"%s\">", servns);
str = strcat_str(str, len, &tmplen, buf);
while(v->name) {
if(v->itype & EVENTED) {
snprintf(buf, sizeof(buf), "<e:property><%s>", v->name);
str = strcat_str(str, len, &tmplen, buf);
//printf("<e:property><s:%s>", v->name);
switch(v->ieventvalue) {
case 0:
break;
case 255: /* Magical values should go around here */
if( strcmp(v->name, "SystemUpdateID") == 0 )
{
snprintf(buf, sizeof(buf), "%d", updateID);
str = strcat_str(str, len, &tmplen, buf);
}
break;
default:
str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
//printf("%s", upnpallowedvalues[v->ieventvalue]);
}
snprintf(buf, sizeof(buf), "</%s></e:property>", v->name);
str = strcat_str(str, len, &tmplen, buf);
//printf("</s:%s></e:property>\n", v->name);
}
v++;
}
str = strcat_str(str, len, &tmplen, "</e:propertyset>");
//printf("</e:propertyset>\n");
//printf("\n");
//printf("%d\n", tmplen);
str[*len] = '\0';
return str;
}
char *
getVarsContentDirectory(int * l)
{
return genEventVars(l,
&scpdContentDirectory,
"urn:schemas-upnp-org:service:ContentDirectory:1");
}
char *
getVarsConnectionManager(int * l)
{
return genEventVars(l,
&scpdConnectionManager,
"urn:schemas-upnp-org:service:ConnectionManager:1");
}
char *
getVarsX_MS_MediaReceiverRegistrar(int * l)
{
return genEventVars(l,
&scpdX_MS_MediaReceiverRegistrar,
"urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1");
}
C
1
https://gitee.com/yctxkj/minidlna.git
git@gitee.com:yctxkj/minidlna.git
yctxkj
minidlna
minidlna
master

搜索帮助