📄 upnphttp.c
字号:
/* $Id: upnphttp.c,v 1.56 2008/04/26 22:37:29 nanard Exp $ *//* Project : miniupnp * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard * Copyright (c) 2005-2008 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file included in this distribution. * */#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/param.h>#include <syslog.h>#include <ctype.h>#include "config.h"#include "upnphttp.h"#include "upnpdescgen.h"#include "miniupnpdpath.h"#include "upnpsoap.h"#include "upnpevents.h"struct upnphttp * New_upnphttp(int s){ struct upnphttp * ret; if(s<0) return NULL; ret = (struct upnphttp *)malloc(sizeof(struct upnphttp)); if(ret == NULL) return NULL; memset(ret, 0, sizeof(struct upnphttp)); ret->socket = s; return ret;}voidCloseSocket_upnphttp(struct upnphttp * h){ if(close(h->socket) < 0) { syslog(LOG_ERR, "CloseSocket_upnphttp: close(%d): %m", h->socket); } h->socket = -1; h->state = 100;}voidDelete_upnphttp(struct upnphttp * h){ if(h) { if(h->socket >= 0) CloseSocket_upnphttp(h); if(h->req_buf) free(h->req_buf); if(h->res_buf) free(h->res_buf); free(h); }}/* parse HttpHeaders of the REQUEST */static voidParseHttpHeaders(struct upnphttp * h){ char * line; char * colon; char * p; int n; line = h->req_buf; /* TODO : check if req_buf, contentoff are ok */ while(line < (h->req_buf + h->req_contentoff)) { colon = strchr(line, ':'); if(colon) { if(strncasecmp(line, "Content-Length", 14)==0) { p = colon; while(*p < '0' || *p > '9') p++; h->req_contentlen = atoi(p); /*printf("*** Content-Lenght = %d ***\n", h->req_contentlen); printf(" readbufflen=%d contentoff = %d\n", h->req_buflen, h->req_contentoff);*/ } else if(strncasecmp(line, "SOAPAction", 10)==0) { p = colon; n = 0; while(*p == ':' || *p == ' ' || *p == '\t') p++; while(p[n]>=' ') { n++; } if((p[0] == '"' && p[n-1] == '"') || (p[0] == '\'' && p[n-1] == '\'')) { p++; n -= 2; } h->req_soapAction = p; h->req_soapActionLen = n; }#ifdef ENABLE_EVENTS else if(strncasecmp(line, "Callback", 8)==0) { p = colon; while(*p != '<' && *p != '\r' ) p++; n = 0; while(p[n] != '>' && p[n] != '\r' ) n++; h->req_Callback = p + 1; h->req_CallbackLen = MAX(0, n - 1); } else if(strncasecmp(line, "SID", 3)==0) { p = colon + 1; while(isspace(*p)) p++; n = 0; while(!isspace(p[n])) n++; h->req_SID = p; h->req_SIDLen = n; } /* Timeout: Seconds-nnnn *//* TIMEOUTRecommended. Requested duration until subscription expires,either number of seconds or infinite. Recommendationby a UPnP Forum working committee. Defined by UPnP vendor. Consists of the keyword "Second-" followed (without anintervening space) by either an integer or the keyword "infinite". */ else if(strncasecmp(line, "Timeout", 7)==0) { p = colon + 1; while(isspace(*p)) p++; if(strncasecmp(p, "Second-", 7)==0) { h->req_Timeout = atoi(p+7); } }#endif } while(!(line[0] == '\r' && line[1] == '\n')) line++; line += 2; }}/* very minimalistic 404 error message */static voidSend404(struct upnphttp * h){/* static const char error404[] = "HTTP/1.1 404 Not found\r\n" "Connection: close\r\n" "Content-type: text/html\r\n" "\r\n" "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>" "<BODY><H1>Not Found</H1>The requested URL was not found" " on this server.</BODY></HTML>\r\n"; int n; n = send(h->socket, error404, sizeof(error404) - 1, 0); if(n < 0) { syslog(LOG_ERR, "Send404: send(http): %m"); }*/ static const char body404[] = "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>" "<BODY><H1>Not Found</H1>The requested URL was not found" " on this server.</BODY></HTML>\r\n"; h->respflags = FLAG_HTML; BuildResp2_upnphttp(h, 404, "Not Found", body404, sizeof(body404) - 1); SendResp_upnphttp(h); CloseSocket_upnphttp(h);}/* very minimalistic 501 error message */static voidSend501(struct upnphttp * h){/* static const char error501[] = "HTTP/1.1 501 Not Implemented\r\n" "Connection: close\r\n" "Content-type: text/html\r\n" "\r\n" "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>" "<BODY><H1>Not Implemented</H1>The HTTP Method " "is not implemented by this server.</BODY></HTML>\r\n"; int n; n = send(h->socket, error501, sizeof(error501) - 1, 0); if(n < 0) { syslog(LOG_ERR, "Send501: send(http): %m"); }*/ static const char body501[] = "<HTML><HEAD><TITLE>501 Not Implemented</TITLE></HEAD>" "<BODY><H1>Not Implemented</H1>The HTTP Method " "is not implemented by this server.</BODY></HTML>\r\n"; h->respflags = FLAG_HTML; BuildResp2_upnphttp(h, 501, "Not Implemented", body501, sizeof(body501) - 1); SendResp_upnphttp(h); CloseSocket_upnphttp(h);}static const char *findendheaders(const char * s, int len){ while(len-->0) { if(s[0]=='\r' && s[1]=='\n' && s[2]=='\r' && s[3]=='\n') return s; s++; } return NULL;}#ifdef HAS_DUMMY_SERVICEstatic voidsendDummyDesc(struct upnphttp * h){ static const char xml_desc[] = "<?xml version=\"1.0\"?>\r\n" "<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">" " <specVersion>" " <major>1</major>" " <minor>0</minor>" " </specVersion>" " <actionList />" " <serviceStateTable />" "</scpd>\r\n"; BuildResp_upnphttp(h, xml_desc, sizeof(xml_desc)-1); SendResp_upnphttp(h); CloseSocket_upnphttp(h);}#endif/* Sends the description generated by the parameter */static voidsendXMLdesc(struct upnphttp * h, char * (f)(int *)){ char * desc; int len; desc = f(&len); if(!desc) { static const char error500[] = "<HTML><HEAD><TITLE>Error 500</TITLE>" "</HEAD><BODY>Internal Server Error</BODY></HTML>\r\n"; syslog(LOG_ERR, "Failed to generate XML description"); h->respflags = FLAG_HTML; BuildResp2_upnphttp(h, 500, "Internal Server Error", error500, sizeof(error500)-1); } else { BuildResp_upnphttp(h, desc, len); } SendResp_upnphttp(h); CloseSocket_upnphttp(h); free(desc);}/* ProcessHTTPPOST_upnphttp() * executes the SOAP query if it is possible */static voidProcessHTTPPOST_upnphttp(struct upnphttp * h){ if((h->req_buflen - h->req_contentoff) >= h->req_contentlen) { if(h->req_soapAction) { /* we can process the request */ syslog(LOG_INFO, "SOAPAction: %.*s", h->req_soapActionLen, h->req_soapAction); ExecuteSoapAction(h, h->req_soapAction, h->req_soapActionLen); } else { static const char err400str[] = "<html><body>Bad request</body></html>"; syslog(LOG_INFO, "No SOAPAction in HTTP headers"); h->respflags = FLAG_HTML; BuildResp2_upnphttp(h, 400, "Bad Request", err400str, sizeof(err400str) - 1); SendResp_upnphttp(h); CloseSocket_upnphttp(h); } } else { /* waiting for remaining data */ h->state = 1; }}#ifdef ENABLE_EVENTSstatic voidProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path){ const char * sid; syslog(LOG_DEBUG, "ProcessHTTPSubscribe %s", path); syslog(LOG_DEBUG, "Callback '%.*s' Timeout=%d", h->req_CallbackLen, h->req_Callback, h->req_Timeout); syslog(LOG_DEBUG, "SID '%.*s'", h->req_SIDLen, h->req_SID); if(!h->req_Callback && !h->req_SID) { /* Missing or invalid CALLBACK : 412 Precondition Failed. * If CALLBACK header is missing or does not contain a valid HTTP URL, * the publisher must respond with HTTP error 412 Precondition Failed*/ BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); SendResp_upnphttp(h);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -