📄 upnphttp.c
字号:
CloseSocket_upnphttp(h); } else { /* - add to the subscriber list * - respond HTTP/x.x 200 OK * - Send the initial event message *//* Server:, SID:; Timeout: Second-(xx|infinite) */ if(h->req_Callback) { sid = upnpevents_addSubscriber(path, h->req_Callback, h->req_CallbackLen, h->req_Timeout); h->respflags = FLAG_TIMEOUT; if(sid) { syslog(LOG_DEBUG, "generated sid=%s", sid); h->respflags |= FLAG_SID; h->req_SID = sid; h->req_SIDLen = strlen(sid); } BuildResp_upnphttp(h, 0, 0); } else { /* subscription renew */ /* Invalid SID412 Precondition Failed. If a SID does not correspond to a known,un-expired subscription, the publisher must respondwith HTTP error 412 Precondition Failed. */ if(renewSubscription(h->req_SID, h->req_SIDLen, h->req_Timeout) < 0) { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else { BuildResp_upnphttp(h, 0, 0); } } SendResp_upnphttp(h); CloseSocket_upnphttp(h); }}static voidProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path){ syslog(LOG_DEBUG, "ProcessHTTPUnSubscribe %s", path); syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID); /* Remove from the list */ if(upnpevents_removeSubscriber(h->req_SID, h->req_SIDLen) < 0) { BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); } else { BuildResp_upnphttp(h, 0, 0); } SendResp_upnphttp(h); CloseSocket_upnphttp(h);}#endif/* Parse and process Http Query * called once all the HTTP headers have been received. */static voidProcessHttpQuery_upnphttp(struct upnphttp * h){ char HttpCommand[16]; char HttpUrl[128]; char * HttpVer; char * p; int i; p = h->req_buf; if(!p) return; for(i = 0; i<15 && *p != ' ' && *p != '\r'; i++) HttpCommand[i] = *(p++); HttpCommand[i] = '\0'; while(*p==' ') p++; for(i = 0; i<127 && *p != ' ' && *p != '\r'; i++) HttpUrl[i] = *(p++); HttpUrl[i] = '\0'; while(*p==' ') p++; HttpVer = h->HttpVer; for(i = 0; i<15 && *p != '\r'; i++) HttpVer[i] = *(p++); HttpVer[i] = '\0'; syslog(LOG_INFO, "HTTP REQUEST : %s %s (%s)", HttpCommand, HttpUrl, HttpVer); ParseHttpHeaders(h); if(strcmp("POST", HttpCommand) == 0) { h->req_command = EPost; ProcessHTTPPOST_upnphttp(h); } else if(strcmp("GET", HttpCommand) == 0) { h->req_command = EGet; if(strcmp(ROOTDESC_PATH, HttpUrl) == 0) { sendXMLdesc(h, genRootDesc); } else if(strcmp(WANIPC_PATH, HttpUrl) == 0) { sendXMLdesc(h, genWANIPCn); } else if(strcmp(WANCFG_PATH, HttpUrl) == 0) { sendXMLdesc(h, genWANCfg); }#ifdef HAS_DUMMY_SERVICE else if(strcmp(DUMMY_PATH, HttpUrl) == 0) { sendDummyDesc(h); }#endif#ifdef ENABLE_L3F_SERVICE else if(strcmp(L3F_PATH, HttpUrl) == 0) { sendXMLdesc(h, genL3F); }#endif else { syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); Send404(h); } }#ifdef ENABLE_EVENTS else if(strcmp("SUBSCRIBE", HttpCommand) == 0) { h->req_command = ESubscribe; ProcessHTTPSubscribe_upnphttp(h, HttpUrl); } else if(strcmp("UNSUBSCRIBE", HttpCommand) == 0) { h->req_command = EUnSubscribe; ProcessHTTPUnSubscribe_upnphttp(h, HttpUrl); }#else else if(strcmp("SUBSCRIBE", HttpCommand) == 0) { syslog(LOG_NOTICE, "SUBSCRIBE not implemented. ENABLE_EVENTS compile option disabled"); Send501(h); }#endif else { syslog(LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand); Send501(h); }}voidProcess_upnphttp(struct upnphttp * h){ char buf[2048]; int n; if(!h) return; switch(h->state) { case 0: n = recv(h->socket, buf, 2048, 0); if(n<0) { syslog(LOG_ERR, "recv (state0): %m"); h->state = 100; } else if(n==0) { syslog(LOG_WARNING, "HTTP Connection closed inexpectedly"); h->state = 100; } else { const char * endheaders; /* if 1st arg of realloc() is null, * realloc behaves the same as malloc() */ h->req_buf = (char *)realloc(h->req_buf, n + h->req_buflen + 1); memcpy(h->req_buf + h->req_buflen, buf, n); h->req_buflen += n; h->req_buf[h->req_buflen] = '\0'; /* search for the string "\r\n\r\n" */ endheaders = findendheaders(h->req_buf, h->req_buflen); if(endheaders) { h->req_contentoff = endheaders - h->req_buf + 4; ProcessHttpQuery_upnphttp(h); } } break; case 1: n = recv(h->socket, buf, 2048, 0); if(n<0) { syslog(LOG_ERR, "recv (state1): %m"); h->state = 100; } else if(n==0) { syslog(LOG_WARNING, "HTTP Connection closed inexpectedly"); h->state = 100; } else { /*fwrite(buf, 1, n, stdout);*/ /* debug */ h->req_buf = (char *)realloc(h->req_buf, n + h->req_buflen); memcpy(h->req_buf + h->req_buflen, buf, n); h->req_buflen += n; if((h->req_buflen - h->req_contentoff) >= h->req_contentlen) { ProcessHTTPPOST_upnphttp(h); } } break; default: syslog(LOG_WARNING, "Unexpected state: %d", h->state); }}static const char httpresphead[] = "%s %d %s\r\n" /*"Content-Type: text/xml; charset=\"utf-8\"\r\n"*/ "Content-Type: %s\r\n" "Connection: close\r\n" "Content-Length: %d\r\n" /*"Server: miniupnpd/1.0 UPnP/1.0\r\n"*/ "Server: " MINIUPNPD_SERVER_STRING "\r\n" ; /*"\r\n";*//* "<?xml version=\"1.0\"?>\n" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" "<s:Body>" "</s:Body>" "</s:Envelope>";*//* with response code and response message * also allocate enough memory */voidBuildHeader_upnphttp(struct upnphttp * h, int respcode, const char * respmsg, int bodylen){ int templen; if(!h->res_buf) { templen = sizeof(httpresphead) + 128 + bodylen; h->res_buf = (char *)malloc(templen); h->res_buf_alloclen = templen; } h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen, httpresphead, h->HttpVer, respcode, respmsg, (h->respflags&FLAG_HTML)?"text/html":"text/xml", bodylen); /* Additional headers */#ifdef ENABLE_EVENTS if(h->respflags & FLAG_TIMEOUT) { h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, "Timeout: Second-"); if(h->req_Timeout) { h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, "%d\r\n", h->req_Timeout); } else { h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, "infinite\r\n"); } } if(h->respflags & FLAG_SID) { h->res_buflen += snprintf(h->res_buf + h->res_buflen, h->res_buf_alloclen - h->res_buflen, "SID: %s\r\n", h->req_SID); }#endif h->res_buf[h->res_buflen++] = '\r'; h->res_buf[h->res_buflen++] = '\n'; if(h->res_buf_alloclen < (h->res_buflen + bodylen)) { h->res_buf = (char *)realloc(h->res_buf, (h->res_buflen + bodylen)); h->res_buf_alloclen = h->res_buflen + bodylen; }}voidBuildResp2_upnphttp(struct upnphttp * h, int respcode, const char * respmsg, const char * body, int bodylen){ BuildHeader_upnphttp(h, respcode, respmsg, bodylen); if(body) memcpy(h->res_buf + h->res_buflen, body, bodylen); h->res_buflen += bodylen;}/* responding 200 OK ! */voidBuildResp_upnphttp(struct upnphttp * h, const char * body, int bodylen){ BuildResp2_upnphttp(h, 200, "OK", body, bodylen);}voidSendResp_upnphttp(struct upnphttp * h){ int n; n = send(h->socket, h->res_buf, h->res_buflen, 0); if(n<0) { syslog(LOG_ERR, "send(res_buf): %m"); } else if(n < h->res_buflen) { /* TODO : handle correctly this case */ syslog(LOG_ERR, "send(res_buf): %d bytes sent (out of %d)", n, h->res_buflen); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -