void Process_upnphttp(struct upnphttp * h) { char * h_tmp; char buf[2048]; int n; if(!h) return; switch(h->state) { case EWaitingForHttpRequest: #ifdef ENABLE_HTTPS if(h->ssl) { n = SSL_read(h->ssl, buf, sizeof(buf)); } else { n = recv(h->socket, buf, sizeof(buf), 0); } #else n = recv(h->socket, buf, sizeof(buf), 0); #endif if(n<0) { #ifdef ENABLE_HTTPS if(h->ssl) { int err; err = SSL_get_error(h->ssl, n); if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { syslog(LOG_ERR, "SSL_read() failed"); syslogsslerr(); h->state = EToDelete; } } else { #endif if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { syslog(LOG_ERR, "recv (state0): %m"); h->state = EToDelete; } /* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */ #ifdef ENABLE_HTTPS } #endif } else if(n==0) { syslog(LOG_WARNING, "HTTP Connection closed unexpectedly"); h->state = EToDelete; } else { const char * endheaders; /* if 1st arg of realloc() is null, * realloc behaves the same as malloc() */ h_tmp = (char *)realloc(h->req_buf, n + h->req_buflen + 1); if (h_tmp == NULL) { syslog(LOG_WARNING, "Unable to allocate new memory for h->req_buf)"); h->state = EToDelete; } else { h->req_buf = h_tmp; 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) { /* at this point, the request buffer (h->req_buf) * is guaranteed to contain the \r\n\r\n character sequence */ h->req_contentoff = endheaders - h->req_buf + 4; ProcessHttpQuery_upnphttp(h); } } break; case EWaitingForHttpContent: #ifdef ENABLE_HTTPS if(h->ssl) { n = SSL_read(h->ssl, buf, sizeof(buf)); } else { n = recv(h->socket, buf, sizeof(buf), 0); } #else n = recv(h->socket, buf, sizeof(buf), 0); #endif if(n<0) { #ifdef ENABLE_HTTPS if(h->ssl) { int err; err = SSL_get_error(h->ssl, n); if(err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) { syslog(LOG_ERR, "SSL_read() failed"); syslogsslerr(); h->state = EToDelete; } } else { #endif if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { syslog(LOG_ERR, "recv (state1): %m"); h->state = EToDelete; } /* if errno is EAGAIN, EWOULDBLOCK or EINTR, try again later */ #ifdef ENABLE_HTTPS } #endif } else if(n==0) { syslog(LOG_WARNING, "HTTP Connection closed inexpectedly"); h->state = EToDelete; } else { void * tmp = realloc(h->req_buf, n + h->req_buflen); if(!tmp) { syslog(LOG_ERR, "memory allocation error %m"); h->state = EToDelete; } else { h->req_buf = tmp; 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; case ESendingContinue: if(SendResp_upnphttp(h)) h->state = EWaitingForHttpContent; break; case ESendingAndClosing: SendRespAndClose_upnphttp(h); break; default: syslog(LOG_WARNING, "Unexpected state: %d", h->state); } }
void Process_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); } }
/* Parse and process Http Query * called once all the HTTP headers have been received, * so it is guaranteed that h->req_buf contains the \r\n\r\n * character sequence */ static void ProcessHttpQuery_upnphttp(struct upnphttp * h) { static const struct { const char * path; char * (* f)(int *); } path_desc[] = { { ROOTDESC_PATH, genRootDesc}, { WANIPC_PATH, genWANIPCn}, { WANCFG_PATH, genWANCfg}, #ifdef HAS_DUMMY_SERVICE { DUMMY_PATH, NULL}, #endif #ifdef ENABLE_L3F_SERVICE { L3F_PATH, genL3F}, #endif #ifdef ENABLE_6FC_SERVICE { WANIP6FC_PATH, gen6FC}, #endif #ifdef ENABLE_DP_SERVICE { DP_PATH, genDP}, #endif { NULL, NULL} }; char HttpCommand[16]; char HttpUrl[128]; char * HttpVer; char * p; int i; p = h->req_buf; if(!p) return; /* note : checking (*p != '\r') is enough to avoid runing off the * end of the buffer, because h->req_buf is guaranteed to contain * the \r\n\r\n character sequence */ 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; for(i=0; path_desc[i].path; i++) { if(strcasecmp(path_desc[i].path, HttpUrl) == 0) { if(path_desc[i].f) sendXMLdesc(h, path_desc[i].f); else #ifdef HAS_DUMMY_SERVICE sendDummyDesc(h); #else continue; #endif return; } } if(0 == memcmp(HttpUrl, "/ctl/", 5)) { /* 405 Method Not Allowed * Allow: POST */ h->respflags = FLAG_ALLOW_POST; Send405(h); return; } #ifdef ENABLE_EVENTS if(0 == memcmp(HttpUrl, "/evt/", 5)) { /* 405 Method Not Allowed * Allow: SUBSCRIBE, UNSUBSCRIBE */ h->respflags = FLAG_ALLOW_SUB_UNSUB; Send405(h); return; } #endif 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); } }
/* Parse and process Http Query * called once all the HTTP headers have been received. */ static void ProcessHttpQuery_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); } }