⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 upnphttp.c

📁 miniupnpd可以在嵌入式linux中实现upnp功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $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 + -