📄 upnpdescgen.c
字号:
#ifdef ENABLE_L3F_SERVICE/* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */static const struct argument SetDefaultConnectionServiceArgs[] ={ {1, 0}, /* in */ {0, 0}};static const struct argument GetDefaultConnectionServiceArgs[] ={ {2, 0}, /* out */ {0, 0}};static const struct action L3FActions[] ={ {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */ {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */ {0, 0}};static const struct stateVar L3FVars[] ={ {"DefaultConnectionService", 0|0x80, 0, 0, 255}, /* Required */ {0, 0}};static const struct serviceDesc scpdL3F ={ L3FActions, L3FVars };#endif/* 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){ int s2len; s2len = (int)strlen(s2); if(*tmplen <= (*len + s2len)) { if(s2len < 256) *tmplen += 256; else *tmplen += s2len + 1; str = (char *)realloc(str, *tmplen); } /*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){ if(*tmplen <= (*len + 1)) { *tmplen += 256; str = (char *)realloc(str, *tmplen); } 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){ unsigned short i, j, k; int top; const char * eltname, *s; char c; 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] == '/') { /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */ 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, '<'); str = strcat_str(str, len, tmplen, eltname); str = strcat_char(str, len, tmplen, '>'); for(;;) { if(top < 0) return str; i = ++(pile[top].i); j = pile[top].j; /*printf(" pile[%d]\t%d %d\n", top, i, j); */ if(i==j) { /*printf("</%s>\n", pile[top].eltname); */ 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 { /*printf("<%s>\n", eltname); */ 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)p[k].data & 0xffff; j = i + ((unsigned)p[k].data >> 16); top++; /*printf(" +pile[%d]\t%d %d\n", top, i, j); */ 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 = 2048; str = (char *)malloc(tmplen); if(str == NULL) return NULL; * len = strlen(xmlver); /*strcpy(str, xmlver); */ memcpy(str, xmlver, *len + 1); str = genXML(str, len, &tmplen, rootDesc); 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>New"); p = vars[args[j].relatedVar].name; if(0 == memcmp(p, "PortMapping", 11) && 0 != memcmp(p + 11, "Description", 11)) { if(0 == memcmp(p + 11, "NumberOfEntries", 15)) str = strcat_str(str, len, &tmplen, "PortMappingIndex"); else str = strcat_str(str, len, &tmplen, p + 11); } else { str = strcat_str(str, len, &tmplen, 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=\"");#ifdef ENABLE_EVENTS str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");#else /* for the moment allways send no. Wait for SUBSCRIBE implementation * before setting it to yes */ str = strcat_str(str, len, &tmplen, "no");#endif 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;}/* genWANIPCn() : * Generate the WANIPConnection xml description */char *genWANIPCn(int * len){ return genServiceDesc(len, &scpdWANIPCn);}/* genWANCfg() : * Generate the WANInterfaceConfig xml description. */char *genWANCfg(int * len){ return genServiceDesc(len, &scpdWANCfg);}#ifdef ENABLE_L3F_SERVICEchar *genL3F(int * len){ return genServiceDesc(len, &scpdL3F);}#endif#ifdef ENABLE_EVENTSstatic char *genEventVars(int * len, const struct serviceDesc * s, const char * servns){ char tmp[16]; const struct stateVar * v; char * str; int tmplen; tmplen = 512; str = (char *)malloc(tmplen); if(str == NULL) return NULL; *len = 0; v = s->serviceStateTable; str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\""); str = strcat_str(str, len, &tmplen, servns); str = strcat_str(str, len, &tmplen, "\">"); while(v->name) { if(v->itype & 0x80) { str = strcat_str(str, len, &tmplen, "<e:property><s:"); str = strcat_str(str, len, &tmplen, v->name); str = strcat_str(str, len, &tmplen, ">"); //printf("<e:property><s:%s>", v->name); switch(v->ieventvalue) { case 0: break; case 253: /* Port mapping number of entries magical value */ snprintf(tmp, sizeof(tmp), "%d", upnp_get_portmapping_number_of_entries()); str = strcat_str(str, len, &tmplen, tmp); break; case 254: /* External ip address magical value */ if(use_ext_ip_addr) str = strcat_str(str, len, &tmplen, use_ext_ip_addr); else { char ext_ip_addr[INET_ADDRSTRLEN]; if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) { str = strcat_str(str, len, &tmplen, "0.0.0.0"); } else { str = strcat_str(str, len, &tmplen, ext_ip_addr); } } /*str = strcat_str(str, len, &tmplen, "0.0.0.0");*/ break; case 255: /* DefaultConnectionService magical value */ str = strcat_str(str, len, &tmplen, uuidvalue); str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1"); //printf("%s:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1", uuidvalue); break; default: str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]); //printf("%s", upnpallowedvalues[v->ieventvalue]); } str = strcat_str(str, len, &tmplen, "</s:"); str = strcat_str(str, len, &tmplen, v->name); str = strcat_str(str, len, &tmplen, "></e:property>"); //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 *getVarsWANIPCn(int * l){ return genEventVars(l, &scpdWANIPCn, "urn:schemas-upnp-org:service:WANIPConnection:1");}char *getVarsWANCfg(int * l){ return genEventVars(l, &scpdWANCfg, "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");}#ifdef ENABLE_L3F_SERVICEchar *getVarsL3F(int * l){ return genEventVars(l, &scpdL3F, "urn:schemas-upnp-org:service:Layer3Forwarding:1");}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -