ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/package/kernel/realtek-wl/src/Users/mini_upnp/upnphttp.c b/package/kernel/realtek-wl/src/Users/mini_upnp/upnphttp.c
new file mode 100644
index 0000000..900eff8
--- /dev/null
+++ b/package/kernel/realtek-wl/src/Users/mini_upnp/upnphttp.c
@@ -0,0 +1,1814 @@
+

+#include <stdlib.h>

+#include <unistd.h>

+#include <stdio.h>

+#include <string.h>

+#include <sys/types.h>

+#include <sys/socket.h>

+#include <syslog.h>

+#include <arpa/inet.h>

+#include <limits.h>

+#include <sys/ioctl.h>

+#include <net/if.h>

+

+#include "upnphttp.h"

+#include "upnpsoap.h"

+

+static int get_sockfd(void)

+{

+	static int sockfd = -1;

+

+	if (sockfd == -1) {

+		if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1) {

+			perror("user: socket creation failed");

+			return(-1);

+		}

+	}

+	return sockfd;

+}

+

+IPCon IPCon_New(char * ifname)

+{

+	IPCon ipcon=NULL;

+

+	ipcon = (IPCon)malloc(sizeof(_IPCon));

+	if (!ipcon) { 

+		printf("Error in IPCon_New:Cannot allocate memory\n");

+		return NULL;

+	}

+

+	ipcon->ifname = ifname;

+	return (ipcon);

+}

+

+

+IPCon IPCon_Destroy(IPCon this)

+{

+	if (!this) 

+		return (NULL);

+

+	free(this);

+	return (NULL);

+}

+

+BOOLEAN  IPCon_GetIpAddr(IPCon this, struct in_addr *adr)

+{

+    	struct ifreq ifr;

+    	int fd;

+

+    	fd = get_sockfd();

+

+    	if (fd >= 0) {

+	    	strcpy(ifr.ifr_name, this->ifname);

+		ifr.ifr_addr.sa_family = AF_INET;

+

+		if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {

+			memcpy(adr,&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr,sizeof(struct in_addr));

+			close(fd);

+			return TRUE;

+		} else {

+		        close(fd);

+			return FALSE;

+	        }

+	}

+

+	return FALSE;

+}

+

+

+char *IPCon_GetIpAddrByStr(IPCon this)

+{

+	struct in_addr adr;

+	BOOLEAN result=FALSE;

+

+	result = IPCon_GetIpAddr(this,&adr);

+

+	if (result == FALSE) {

+		return NULL;

+	} else {

+		return inet_ntoa(adr);

+	}

+

+}

+

+int OpenAndConfHTTPSocket(const char * addr, unsigned short port)

+{

+	int s;

+	int i = 1;

+	struct sockaddr_in listenname;

+

+	if( (s = socket(PF_INET, SOCK_STREAM, 0)) < 0)

+	{

+		syslog(LOG_ERR, "socket(http): %m");

+		return -1;

+	}

+

+	if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)

+	{

+		syslog(LOG_WARNING, "setsockopt(http, SO_REUSEADDR): %m");

+	}

+

+	memset(&listenname, 0, sizeof(struct sockaddr_in));

+	listenname.sin_family = AF_INET;

+	listenname.sin_port = htons(port);

+	listenname.sin_addr.s_addr = htonl(INADDR_ANY);

+

+	if(bind(s, (struct sockaddr *)&listenname, sizeof(struct sockaddr_in)) < 0)

+	{

+		syslog(LOG_ERR, "bind(http): %m");

+		return -1;

+	}

+

+	if(listen(s, 6) < 0)

+	{

+		syslog(LOG_ERR, "listen(http): %m");

+		return -1;

+	}

+

+	return s;

+}

+

+int ReliableSend(int socket, const char *data, const int len)

+{

+	int n;

+	unsigned int byte_left = len;

+	int bytes_sent = 0;

+

+	if (socket < 0 || data == NULL || len <= 0)

+		return -1;

+

+	while (byte_left > 0) {

+		// write data

+		n = send(socket, data + bytes_sent, byte_left,

+			MSG_DONTROUTE | MSG_NOSIGNAL );

+		if( n == -1 ) {

+			syslog(LOG_ERR, "ReliableSend: sending failed!");

+			return -1;

+		}

+

+		byte_left = byte_left - n;

+		bytes_sent += n;

+	}

+

+	n = bytes_sent;

+	return n;

+}

+

+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;

+}

+

+void CloseSocket_upnphttp(struct upnphttp * h)

+{

+	close(h->socket);

+	h->socket = -1;

+	h->state = 100;

+}

+

+void Delete_upnphttp(struct upnphttp * h)

+{

+	if(h)

+	{

+		if(h->socket >= 0)

+		{

+

+			close(h->socket);

+			h->socket=-1; 

+		}

+

+

+		if(h->req_buf)

+		{

+			free(h->req_buf);

+			h->req_buf=NULL;

+		}

+

+

+		if(h->res_buf)

+		{

+

+			free(h->res_buf);

+			h->res_buf=NULL;

+		}

+

+		free(h);

+	}

+}

+

+/* parse HttpHeaders of the REQUEST */

+static void ParseHttpHeaders(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;

+			}

+		}

+		while(!(line[0] == '\r' && line[1] == '\n'))

+			line++;

+		line += 2;

+	}

+}

+

+/* very minimalistic 404 error message */

+static void Send404(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 = ReliableSend(h->socket, error404, sizeof(error404) - 1);

+	if (n != (sizeof(error404) - 1))

+	{

+		syslog(LOG_ERR, "Send404: %d bytes sent (out of %d)",

+						n, (sizeof(error404) - 1));

+	}

+	CloseSocket_upnphttp(h);

+}

+

+// support HNAP1

+void SendError(struct upnphttp * h, const int code, const char *title, const char *realm, const char *body)

+{

+	char *error_title=NULL;

+	char *error_realm=NULL;

+	char *error_body=NULL;

+	int len;

+	int n;

+	

+	if (code <=0 || title == NULL) {

+		Send404(h);

+		return;

+	}

+	

+	error_title = (char *)malloc(2048);

+	sprintf(error_title, "HTTP/1.1 %d %s\r\n"

+					"Connection: close\r\n"

+					"Content-type: text/html\r\n", code, title);

+	if (realm) {

+		error_realm = (char *)malloc(256);

+		sprintf(error_realm, "WWW-Authenticate: Basic realm=\"%s\"\r\n", realm);

+		strcat(error_title, error_realm);

+	}

+	

+	strcat(error_title, "\r\n");

+	

+	if (body) {

+		error_body = (char *)malloc(1024);

+		sprintf(error_body, "<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>"

+						"<BODY><H1>%s</H1>%s</BODY></HTML>\r\n", code, title, title, body);

+		strcat(error_title, error_body);

+	}

+

+	len = strlen(error_title);

+

+	n = ReliableSend(h->socket, error_title, len);

+	if (n != len)

+	{

+		syslog(LOG_ERR, "Send%d: %d bytes sent (out of %d)", code,

+						n, len);

+	}

+	CloseSocket_upnphttp(h);

+	if (error_title)

+	{

+		free(error_title);

+		error_title=NULL;

+	}

+	

+	if (error_realm)

+	{

+		free(error_realm);

+		error_realm=NULL;

+	}

+	

+	if(error_body)

+	{

+		free(error_body);

+		error_body=NULL;

+	}

+	

+}

+

+/* Precondition Failed */

+static void Send412PreconditionFailed(struct upnphttp * h)

+{

+	static const char error412[] = "HTTP/1.1 412 Precondition Failed\r\n"

+		"Content-Length: 0\r\n"

+		"Connection: close\r\n\r\n";

+	int n;

+	

+	n = ReliableSend(h->socket, error412, sizeof(error412) - 1);

+	if (n != (sizeof(error412) - 1))

+	{

+		syslog(LOG_ERR, "Send412PreconditionFailed: %d bytes sent (out of %d)",

+						n, (sizeof(error412) - 1));

+	}

+	CloseSocket_upnphttp(h);

+}

+

+/* Too Many Subscribers */

+static void Send412TooManySubscribers(struct upnphttp * h)

+{

+	static const char error412[] = "HTTP/1.1 412 Too Many Subscribers\r\n"

+		"Content-Length: 0\r\n"

+		"Connection: close\r\n\r\n";

+	int n;

+	

+	n = ReliableSend(h->socket, error412, sizeof(error412) - 1);

+	if (n != (sizeof(error412) - 1))

+	{

+		syslog(LOG_ERR, "Send412TooManySubscribers: %d bytes sent (out of %d)",

+						n, (sizeof(error412) - 1));

+	}

+	CloseSocket_upnphttp(h);

+}

+

+/* very minimalistic 501 error message */

+static void Send501(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 = ReliableSend(h->socket, error501, sizeof(error501) - 1);

+	if (n != (sizeof(error501) - 1))

+	{

+		syslog(LOG_ERR, "Send501: %d bytes sent (out of %d)",

+						n, (sizeof(error501) - 1));

+	}

+	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;

+}

+

+/* Sends the description generated by the parameter */

+static void sendXMLdesc(struct upnphttp * h, char * (f)(int *))

+{

+	char * desc;

+	int len;

+	desc = f(&len);

+	if(!desc)

+	{

+		syslog(LOG_ERR, "XML description generation failed");

+		return;

+	}

+	BuildResp_upnphttp(h, desc, len);

+	SendResp_upnphttp(h);

+	CloseSocket_upnphttp(h);

+	free(desc);

+}

+

+/* ProcessHTTPPOST_upnphttp()

+ * executes the SOAP query if it is possible */

+static void ProcessHTTPPOST_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");

+			BuildResp2_upnphttp(h, 400, "Bad Request",

+			                    err400str, sizeof(err400str) - 1);

+			SendResp_upnphttp(h);

+			CloseSocket_upnphttp(h);

+		}

+	}

+	else

+	{

+		/* waiting for remaining data */

+		h->state = 1;

+	}

+}

+

+Upnp_Document CreatePropertySet(void)

+{

+	Upnp_Document PropSet=NULL;

+

+	PropSet = (Upnp_Document) malloc(sizeof(Upnp_Document_CTX));

+	if (PropSet == NULL) {

+		syslog(LOG_ERR, "CreatePropertySet: out of memory!");

+		return NULL;

+	}

+	memset(PropSet, 0, sizeof(Upnp_Document_CTX));

+	LIST_INIT(&PropSet->doc_head);

+	return PropSet;

+}

+

+int UpnpAddToPropertySet(Upnp_Document PropSet,

+								const char *VarName, const char *message)

+{

+	struct Upnp_Document_element *tmp=NULL;

+	char *name=NULL;

+	char *content=NULL;

+	

+	if (PropSet == NULL || VarName == NULL || message == NULL)

+		return UPNP_E_INVALID_PARAM;

+

+	tmp = (struct Upnp_Document_element *) malloc(sizeof(struct Upnp_Document_element));

+	if (tmp == NULL) {

+		syslog(LOG_ERR, "UpnpAddToPropertySet: out of memory!");

+		return UPNP_E_OUTOF_MEMORY;

+	}

+	memset(tmp, 0, sizeof(struct Upnp_Document_element));

+

+	name = (char *) malloc(strlen(VarName) + 1);

+	if (name == NULL) {

+		syslog(LOG_ERR, "UpnpAddToPropertySet: out of memory!");

+		free(tmp);

+		return UPNP_E_OUTOF_MEMORY;

+	}

+	memset(name, 0, strlen(VarName) + 1);

+	memcpy(name, VarName, strlen(VarName));

+

+	content = (char *) malloc(strlen(message) + 1);

+	if (content == NULL) {

+		syslog(LOG_ERR, "UpnpAddToPropertySet: out of memory!");

+		free(tmp);

+		free(name);

+		return UPNP_E_OUTOF_MEMORY;

+	}

+	memset(content, 0, strlen(message) + 1);

+	memcpy(content, message, strlen(message));

+

+	PropSet->NumOfVarName += 1;

+	PropSet->TotalMessageLen = strlen(message) + (strlen(VarName) * 2);

+	tmp->VarName = name;

+	tmp->message = content;

+	LIST_INSERT_HEAD(&PropSet->doc_head, tmp, entries);

+	

+	return UPNP_E_SUCCESS;

+}

+

+static char *MakeEventBody(Upnp_Document PropSet, unsigned int *total_len)

+{

+	unsigned int len=0;

+	char *buf=NULL;

+	unsigned int buf_len=0;

+	struct Upnp_Document_element *e;

+	

+	if (PropSet == NULL || PropSet->NumOfVarName == 0)

+		return NULL;

+

+	buf_len = (strlen("<e:property><></></e:property>") * PropSet->NumOfVarName)

+				+ PropSet->TotalMessageLen + 100;

+	buf = (char *) malloc(buf_len);

+	if (buf == NULL) {

+		syslog(LOG_ERR, "MakeEventBody: out of memory!");

+		return NULL;

+	}

+	memset(buf, 0, buf_len);

+	

+	for(e = PropSet->doc_head.lh_first; e != NULL; e = e->entries.le_next)

+	{

+		if (e->VarName) {

+			char *tmpbuf=NULL;

+			unsigned int tmpbuf_len=0;

+			unsigned int propertyLen=0;

+

+			tmpbuf_len = strlen("<e:property><></></e:property>")

+						+ (strlen(e->VarName) * 2)

+						+ strlen(e->message) + 1;

+			tmpbuf = (char *) malloc(tmpbuf_len);

+			if (tmpbuf == NULL) {

+				syslog(LOG_ERR, "MakeEventBody: out of memory!");

+				free(buf);

+				return NULL;

+			}

+			memset(tmpbuf, 0, tmpbuf_len);

+			propertyLen = sprintf(tmpbuf, 

+				"<e:property><%s>%s</%s></e:property>",

+				e->VarName, e->message, e->VarName);

+			len += propertyLen;

+			strcat(buf, tmpbuf);

+			free(tmpbuf);

+		}

+	}

+

+	*total_len = len;

+	return buf;

+}

+

+static void UpnpSendEvent(char *packet,

+								const char *EventBody, const unsigned int bodylength,

+								struct upnp_subscription_record *subscribe_list,

+								struct upnp_subscription_element *sub)

+{

+	unsigned int packetLength;

+	struct sockaddr_in dest;

+	int n, sockfd=-1;

+	struct EvtRespElement *EvtResp=NULL;

+	

+	if (packet == NULL || EventBody == NULL || bodylength == 0 ||

+		subscribe_list == NULL || sub == NULL)

+		return;

+

+	packetLength = sprintf(packet,

+		"NOTIFY %s HTTP/1.1\r\n"

+		"SERVER: " MINIUPNPD_SERVER_STRING "\r\n"

+		"HOST: %s:%d\r\n"

+		"Content-Type: text/xml; charset=\"utf-8\"\r\n"

+		"NT: upnp:event\r\n"

+		"NTS: upnp:propchange\r\n"

+		"SID: %s\r\n"

+		"SEQ: %d\r\n"

+		"Content-Length: %d\r\n\r\n"

+		"<?xml version=\"1.0\" encoding=\"utf-8\"?>"

+		"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">"

+		"%s"

+		"</e:propertyset>",

+		sub->callback_url,

+		sub->IP,

+		sub->port,

+		sub->sid,

+		(int)sub->seq,

+		bodylength+110,

+		EventBody);

+	

+	sub->seq++;

+	if (sub->seq >= UINT_MAX)

+		sub->seq = 1;

+	//printf("Packet------------>\n%s\n<-----------------Packet\n\n", packet);

+

+	memset(&dest,0,sizeof(struct sockaddr_in));

+	dest.sin_addr.s_addr = sub->IP_inet_addr;

+	dest.sin_port = htons(sub->port);

+	dest.sin_family = AF_INET;

+

+	// create a socket

+	if ((sockfd = socket( AF_INET, SOCK_STREAM, 0 )) == -1) {

+		syslog(LOG_ERR, "UpnpSendEvent: creating a socket falied!");

+		return;

+	}

+	if (connect( sockfd, ( struct sockaddr * )&dest,

+                 sizeof( struct sockaddr_in ) ) == -1) {

+		syslog(LOG_ERR, "UpnpSendEvent: connecting a socket falied!");

+		close(sockfd);

+		return;

+    	}

+

+	n = ReliableSend(sockfd, packet, packetLength);

+	if (n != packetLength)

+	{

+		syslog(LOG_ERR, "UpnpSendEvent: %d bytes sent (out of %d)",

+						n, packetLength);

+		close(sockfd);

+		return;

+	}

+

+	EvtResp = (struct EvtRespElement *) malloc(sizeof(struct EvtRespElement));

+	if (EvtResp == NULL) {

+		syslog(LOG_ERR, "UpnpSendEvent: out of memory!");

+		close(sockfd);

+		return;

+	}

+	memset(EvtResp, 0, sizeof(struct EvtRespElement));

+	EvtResp->socket = sockfd;

+	memcpy(EvtResp->sid, sub->sid, strlen(sub->sid));

+	EvtResp->TimeOut = 30;

+	LIST_INSERT_HEAD(&subscribe_list->EvtResp_head, EvtResp, entries);

+}

+

+void UpnpSendEventSingle(Upnp_Document PropSet,

+								struct upnp_subscription_record *subscribe_list,

+								struct upnp_subscription_element *sub)

+{

+	char *packet=NULL;

+	unsigned int bodylength=0;

+	char *EventBody=NULL;

+

+	if (PropSet == NULL || sub == NULL || subscribe_list == NULL ||

+		subscribe_list->subscription_head.lh_first == NULL)

+		return;

+

+	EventBody = MakeEventBody(PropSet, &bodylength);

+	if (EventBody == NULL) {

+		syslog(LOG_ERR, "UpnpSendEventSingle: MakeEventBody failed!");

+		return;

+	}

+

+	packet = (char *) malloc(bodylength + 483);

+	if (packet == NULL) {

+		syslog(LOG_ERR, "UpnpSendEventSingle: out of memory!");

+		free(EventBody);

+		return;

+	}

+	memset(packet, 0, bodylength + 483);

+

+	UpnpSendEvent(packet, EventBody, bodylength, subscribe_list, sub);

+	free(EventBody);

+	free(packet);

+}

+

+void ProcessEventingResp(struct EvtRespElement *EvtResp)

+{

+	char *buf=NULL;

+	int n;

+

+	if (EvtResp == NULL)

+		return;

+

+	buf = (char *) malloc(512);

+	if (buf == NULL) {

+		close(EvtResp->socket);

+		return;

+	}

+	memset(buf, 0, 512);

+	

+	if ((n = recv(EvtResp->socket, buf, 512, 0)) == -1) {

+		syslog(LOG_ERR, "ProcessEventingResp: Receive failed!");

+	}

+	else if(n==0)

+	{

+		syslog(LOG_WARNING, "ProcessEventingResp: connection closed inexpectedly");

+	}

+	

+	//printf("------------>\nProcessEventingResp: sid[%s]\n%s\n<--------------\n", EvtResp->sid, buf);

+	close(EvtResp->socket);

+	free(buf);

+}

+

+void UpnpSendEventAll(Upnp_Document PropSet,

+							struct upnp_subscription_record *sub_list)

+{

+	struct upnp_subscription_element *sub;

+	unsigned int bodylength=0;

+	char *EventBody=NULL;

+	char *packet=NULL;

+

+	if (PropSet == NULL || sub_list == NULL || sub_list->subscription_head.lh_first == NULL)

+		return;

+

+	EventBody = MakeEventBody(PropSet, &bodylength);

+	if (EventBody == NULL) {

+		syslog(LOG_ERR, "UpnpSendEventAll: MakeEventBody failed!");

+		return;

+	}

+

+	packet = (char *) malloc(bodylength + 483);

+	if (packet == NULL) {

+		syslog(LOG_ERR, "UpnpSendEventAll: out of memory!");

+		free(EventBody);

+		return;

+	}

+	

+	for (sub = sub_list->subscription_head.lh_first; sub != NULL; sub = sub->entries.le_next)

+	{

+		memset(packet, 0, bodylength + 483);

+		UpnpSendEvent(packet, EventBody, bodylength, sub_list, sub);

+	}

+	free(EventBody);

+	free(packet);

+}

+

+void UpnpDocument_free(Upnp_Document PropSet)

+{

+	struct Upnp_Document_element *e;

+	struct Upnp_Document_element *next;

+	

+	if (PropSet == NULL)

+		return;

+

+	for(e = PropSet->doc_head.lh_first; e != NULL; )

+	{

+		next = e->entries.le_next;

+		if (e->VarName)

+			free(e->VarName);

+		if (e->message)

+			free(e->message);

+		LIST_REMOVE(e, entries);

+		free(e);

+		e = next;

+	}

+

+	free(PropSet);

+}

+

+static int BuildSubscribeResponse(struct upnphttp * h, struct process_upnp_subscription *sub)

+{

+	char *Subresp=NULL;

+	int n, packet_len, ret=UPNP_E_SUCCESS;

+

+	Subresp = (char *) malloc(300);

+	if (Subresp == NULL) {

+		syslog(LOG_ERR, "BuildSubscribeResponse: out of memory!");

+		return UPNP_E_OUTOF_MEMORY;

+	}

+	memset(Subresp, 0, 300);

+	

+	packet_len = sprintf(Subresp, 

+		"HTTP/1.1 200 OK \r\n"

+		"Server: " MINIUPNPD_SERVER_STRING "\r\n"

+		"SID: %s\r\n"

+		"TIMEOUT: Second-%d\r\n"

+		"Content-Length: 0\r\n"

+		"\r\n",

+		sub->sid, (int)h->subscribe_list->max_subscription_time);

+	

+	//printf("BuildSubscribeResponse------->\n%s<------------BuildSubscribeResponse\n", Subresp);

+

+	n = ReliableSend(h->socket, Subresp, packet_len);

+	if (n != packet_len)

+	{

+		syslog(LOG_ERR, "BuildSubscribeResponse: %d bytes sent (out of %d)",

+						n, packet_len);

+	}

+	

+	free(Subresp);

+	CloseSocket_upnphttp(h);

+	return ret;

+}

+

+static void BuildUnSubscribeResponse(struct upnphttp * h)

+{

+	static const char UnSubresp[] =

+		"HTTP/1.1 200 OK \r\n"

+		"Content-Length: 0\r\n"

+		"\r\n";

+

+	int n;

+	

+	n = ReliableSend(h->socket, UnSubresp, sizeof(UnSubresp) - 1);

+	if (n != (sizeof(UnSubresp) - 1))

+	{

+		syslog(LOG_ERR, "BuildUnSubscribeResponse: %d bytes sent (out of %d)",

+						n, (sizeof(UnSubresp) - 1));

+	}

+	CloseSocket_upnphttp(h);

+}

+

+static struct upnp_subscription_element *UPnPTryToSubscribe

+	(struct upnphttp * h, struct process_upnp_subscription *sub)

+{

+	int SIDNumber,rnumber;

+	char *SID=NULL;

+	struct upnp_subscription_element *new_sub=NULL;

+	

+	if (h == NULL || sub == NULL)

+		return NULL;

+	

+	if (h->subscribe_list->total_subscription >= h->subscribe_list->max_subscription_num)	

+		return NULL;

+

+	new_sub = (struct upnp_subscription_element *) malloc(sizeof(struct upnp_subscription_element));

+	if (new_sub == NULL)

+		return NULL;

+	memset(new_sub, 0, sizeof(struct upnp_subscription_element));

+	

+	//

+	// The SID must be globally unique, so lets generate it using

+	// a bunch of random hex characters

+	//

+	SID = (char*)malloc(SID_LEN);

+	if (SID == NULL) {

+		free(new_sub);

+		return NULL;

+	}

+	memset(SID,0,SID_LEN);

+	sprintf(SID,"uuid:");

+	for(SIDNumber=5;SIDNumber<=12;++SIDNumber)

+	{

+		rnumber = rand()%16;

+		sprintf(SID+SIDNumber,"%x",rnumber);

+	}

+	sprintf(SID+SIDNumber,"-");

+	for(SIDNumber=14;SIDNumber<=17;++SIDNumber)

+	{

+		rnumber = rand()%16;

+		sprintf(SID+SIDNumber,"%x",rnumber);

+	}

+	sprintf(SID+SIDNumber,"-");

+	for(SIDNumber=19;SIDNumber<=22;++SIDNumber)

+	{

+		rnumber = rand()%16;

+		sprintf(SID+SIDNumber,"%x",rnumber);

+	}

+	sprintf(SID+SIDNumber,"-");

+	for(SIDNumber=24;SIDNumber<=27;++SIDNumber)

+	{

+		rnumber = rand()%16;

+		sprintf(SID+SIDNumber,"%x",rnumber);

+	}

+	sprintf(SID+SIDNumber,"-");

+	for(SIDNumber=29;SIDNumber<=40;++SIDNumber)

+	{

+		rnumber = rand()%16;

+		sprintf(SID+SIDNumber,"%x",rnumber);

+	}

+

+	memcpy(sub->sid, SID, SID_LEN);

+	if (BuildSubscribeResponse(h, sub) != UPNP_E_SUCCESS) {

+		free(SID);

+		free(new_sub);

+		return NULL;

+	}

+

+	memcpy(new_sub->IP, sub->IP, IP_ADDRLEN);

+	new_sub->IP_inet_addr = sub->IP_inet_addr;

+	new_sub->port = sub->port;

+	memcpy(new_sub->sid, SID, SID_LEN);

+	memcpy(new_sub->callback_url, sub->callback_url, URL_MAX_LEN);

+	new_sub->TimeOut = sub->TimeOut;

+//WPS2DOTX

+//	new_sub->subscription_timeout = h->subscribe_list->subscription_timeout;

+	new_sub->subscription_timeout = sub->TimeOut;

+

+//	printf("\n\nsubscription_timeout=%d\n",new_sub->subscription_timeout);

+	

+	new_sub->eventID = UPNP_EVENT_SUBSCRIPTION_REQUEST;

+	LIST_INSERT_HEAD(&h->subscribe_list->subscription_head, new_sub, entries);

+	h->subscribe_list->total_subscription++;

+	syslog(LOG_INFO, "Subscribe: total_subscription [%d]",

+	       (int)h->subscribe_list->total_subscription);

+		

+	free(SID);

+	return new_sub;

+}

+

+static char *GetTokenValue(const unsigned long buf, const unsigned long len, unsigned int *Value_len)

+{

+	unsigned long start=0, end=0;

+	unsigned long buffer_end;

+	char *line;

+	

+	if (len == 0)

+		return NULL;

+	

+	line = (char *)buf;

+	buffer_end = (unsigned long)line + len;

+	

+	while ((unsigned long)line < buffer_end) {

+		if ((*line == ' ') || (*line == ':') || (*line == '-'))

+			line++;

+		else {

+			start = (unsigned long)line;

+			break;

+		}

+	}

+	if (start == 0) {

+		*Value_len = 0;

+		return NULL;

+	}

+	

+	while ((unsigned long)line < buffer_end) {

+		if ((*line == ' ') || (*line == '\r') || (*line == '\n')) {

+			end = (unsigned long)line;

+			break;

+		}

+		else

+			line++;

+	}

+	if (end == 0) {

+		*Value_len = 0;

+		return NULL;

+	}

+

+	*Value_len = (unsigned int)(end - start);

+	return (char *)start;

+}

+

+static __inline__ void GetLineLen(const unsigned long buf, unsigned int *line_len)

+{

+	unsigned long start=0;

+	const unsigned short MaxCharsPerLine = 1000;

+	unsigned short NumChars=0;

+	char *line;

+

+	line = (char *)buf;

+	start = (unsigned long)line;

+	while (*line != '\n') {

+		NumChars++;

+		if (NumChars >= MaxCharsPerLine) {

+			syslog(LOG_WARNING, "Too many characters in a line!");

+			*line_len = 0;

+			return;

+		}

+		line++;

+	}

+

+	*line_len = (unsigned long)line + 1 - start;

+	return;

+}

+

+

+// To do : support IPv6

+static __inline__ int GetIPandPortandCallBack(const unsigned long buf, const unsigned int buf_len,

+							struct process_upnp_subscription *sub)

+{

+	char *line=NULL;

+	unsigned long buffer_end=0;

+	unsigned char dot_count=0;

+	unsigned long start=0;

+	unsigned long end=0;

+	unsigned char GotIPandPort=0;

+

+	line = (char *)buf;

+	buffer_end = (unsigned long)line + buf_len;

+	while ((unsigned long)line < buffer_end) {

+		if (*line == ' ') {

+			line++;

+			continue;

+		}

+		if (strncasecmp("<http://", line, 8) != 0)

+			return UPNP_E_INVALID_PARAM;

+		else

+			break;

+	}

+	

+	line += 8;

+	start =(unsigned long) line;

+	while ((unsigned long)line < buffer_end) {

+		if (*line == '.')

+			dot_count++;

+		if ((*line == ':') || (*line == '/')) {

+			if (dot_count != IP_V4_DOT_COUNT)

+				return UPNP_E_INVALID_PARAM;

+			memcpy(sub->IP, (char *)start, (unsigned long)line-start);

+			if ((sub->IP_inet_addr = inet_addr(sub->IP)) == -1)

+				return UPNP_E_INVALID_PARAM;

+			break;

+		}

+		line++;

+	}

+

+	if (*line == '/') {

+		sub->port = 80;

+		GotIPandPort = 1;

+		start = (unsigned long)line;

+		end = 0;

+		goto get_callback;

+	}

+		

+	line += 1;

+	start = (unsigned long)line;

+	while ((unsigned long)line < buffer_end) {

+		if (*line == '/') {

+			end = (unsigned long)line;

+			if (end <= start)

+				return UPNP_E_INVALID_PARAM;

+			else {

+				char port[10];

+				memset(port, 0, 10);

+				memcpy(port, (char *)start, end-start);

+				sub->port = atoi(port);

+				GotIPandPort = 1;

+				start = (unsigned long)line;

+				end = 0;

+				break;

+			}

+		}

+		line++;

+	}

+

+get_callback:

+	if (!GotIPandPort)

+		return UPNP_E_INVALID_PARAM;

+	while ((unsigned long)line < buffer_end) {

+		if (*line == '>') {

+			end = (unsigned long)line;

+			if (end <= start)

+				return UPNP_E_INVALID_PARAM;

+			else {

+				memcpy(sub->callback_url, (char *)start, end-start);

+				return UPNP_E_SUCCESS;

+			}

+		}

+		line++;

+	}

+	

+	return UPNP_E_INVALID_PARAM;

+}

+

+static int ParseSUBSCRIBEPacket(struct upnphttp * h,

+							struct process_upnp_subscription *sub)

+{

+	char *line=NULL, *value=NULL, *tmp=NULL;

+	unsigned int line_len=0, value_len=0, tmp_len=0;

+	unsigned long buffer_end=0;

+	

+	if (h->req_buf == NULL || h->req_contentoff == 0)

+		return UPNP_E_INVALID_PARAM;

+

+	line = h->req_buf;

+	buffer_end = (unsigned long)h->req_buf + h->req_contentoff;

+	while ((unsigned long)line < buffer_end) {

+		if (*line == ' ') {

+			line++;

+			continue;

+		}

+		GetLineLen((const unsigned long)line, &line_len);

+		if (line_len == 0)

+			return UPNP_E_INVALID_PARAM;

+		else if (line_len > 2) {

+			if (strncasecmp("SUBSCRIBE", line, 9) == 0) {

+				value = GetTokenValue((const unsigned long)line+9, line_len-9, &value_len);

+				if (value == NULL || value_len == 0)

+					return UPNP_E_INVALID_PARAM;

+				

+				if (strncasecmp(h->subscribe_list->event_url, value, value_len) != 0) {

+					syslog(LOG_WARNING, "SUBSCRIBE event url mismatched!");

+					return UPNP_E_INVALID_PARAM;

+				}

+			}

+			else if (strncasecmp("UNSUBSCRIBE", line, 11) == 0) {

+				value = GetTokenValue((const unsigned long)line+11, line_len-11, &value_len);

+				if (value == NULL || value_len == 0)

+					return UPNP_E_INVALID_PARAM;

+				

+				if (strncasecmp(h->subscribe_list->event_url, value, value_len) != 0) {

+					syslog(LOG_WARNING, "UNSUBSCRIBE event url mismatched!");

+					return UPNP_E_INVALID_PARAM;

+				}

+			}

+			else if (strncasecmp("Host", line, 4) == 0) {

+				value = GetTokenValue((const unsigned long)line+4, line_len-4, &value_len);

+				if (value == NULL || value_len == 0)

+					return UPNP_E_INVALID_PARAM;

+				

+				char host_info[30];

+				memset(host_info, 0, 30);

+				sprintf(host_info, "%s:%d", h->subscribe_list->my_IP, h->subscribe_list->my_port);

+				if (strncmp(value, host_info, value_len) != 0) {

+					syslog(LOG_WARNING, "Wrong host [%s]", host_info);

+					return UPNP_E_INVALID_PARAM;

+				}

+			}

+			else if (strncasecmp("Callback", line, 8) == 0) {

+				value = GetTokenValue((const unsigned long)line+8, line_len-8, &value_len);

+				if (value == NULL || value_len == 0 || (value_len > (URL_MAX_LEN-1)))

+					return UPNP_E_INVALID_PARAM;

+

+				if (GetIPandPortandCallBack((const unsigned long) value, value_len, sub) != UPNP_E_SUCCESS)

+					return UPNP_E_INVALID_PARAM;

+			}

+			else if (strncasecmp("Timeout", line, 7) == 0) {

+				value = GetTokenValue((const unsigned long)line+7, line_len-7, &value_len);

+				if (value == NULL || value_len == 0 || value_len < 8)

+					return UPNP_E_INVALID_PARAM;

+				

+				if (strncasecmp("Second", value, 6) != 0)

+					return UPNP_E_INVALID_PARAM;

+				tmp = value + 6;

+				tmp_len = value_len - 6;

+				value = GetTokenValue((const unsigned long)tmp, tmp_len+1, &value_len);

+				if (value_len == 0)

+					return UPNP_E_INVALID_PARAM;

+				else if (value_len == 8 && (strncasecmp("infinite", line, 8) == 0))

+					sub->TimeOut = MAX_SUB_TIMEOUT;

+				else {

+					if (value_len > 4)

+						sub->TimeOut = MAX_SUB_TIMEOUT;

+					else {

+						char time_out[5];

+						memset(time_out, 0, 5);

+						memcpy(time_out, value, value_len);

+						sub->TimeOut = atoi(time_out);

+					}

+				}

+			}

+			else if (strncasecmp("SID", line, 3) == 0) {

+				value = GetTokenValue((const unsigned long)line+3, line_len-3, &value_len);

+				if (value == NULL || value_len == 0 || value_len < 4)

+					return UPNP_E_INVALID_PARAM;

+				

+				if (strncasecmp("uuid", value, 4) != 0)

+					return UPNP_E_INVALID_PARAM;

+				tmp = value + 4;

+				tmp_len = value_len - 4;

+				value = GetTokenValue((const unsigned long)tmp, tmp_len+1, &value_len);

+				if (value == NULL || value_len == 0 || value_len != 36)

+					return UPNP_E_INVALID_PARAM;

+

+				char sid[SID_LEN];

+				memset(sid, 0, SID_LEN);

+				memcpy(sub->sid, "uuid:", 5);

+				memcpy(sub->sid+5, value, value_len);

+			}

+		}

+		

+		line += line_len;

+	}

+

+	return UPNP_E_SUCCESS;

+}

+

+static void UPnPProcessSUBSCRIBE(struct upnphttp * h)

+{

+	struct process_upnp_subscription sub;

+	struct upnp_subscription_element *new_sub=NULL;

+	int ret;

+

+	memset(&sub, 0, sizeof(struct process_upnp_subscription));

+	ret = ParseSUBSCRIBEPacket(h, &sub);

+	if (ret != UPNP_E_SUCCESS) {

+		Send412PreconditionFailed(h);

+		return;

+	}

+	else {

+#ifdef DEBUG

+		printf("IP [%s]\n", sub.IP);

+		printf("Host [%d.%d.%d.%d:%d]\n", (sub.IP_inet_addr>>24)&0xFF,

+			(sub.IP_inet_addr>>16)&0xFF,

+			(sub.IP_inet_addr>>8)&0xFF,

+			(sub.IP_inet_addr)&0xFF, sub.port);

+		printf("SID [%s]\n", sub.sid);

+		printf("CallBack %s\n", sub.callback_url);

+		printf("Timeout [%d]\n", (int)sub.TimeOut);

+#endif

+

+		if (sub.TimeOut == 0)

+			sub.TimeOut = MAX_SUB_TIMEOUT;

+		

+		if (sub.sid[0] == 0) 

+		{ //Subscribe

+			if (sub.callback_url[0] == 0) {

+				Send412PreconditionFailed(h);

+				return;

+			}

+

+			new_sub = UPnPTryToSubscribe(h, &sub);

+			if (new_sub == NULL) {

+				Send412TooManySubscribers(h);

+				return;

+			}

+

+			if (h->subscribe_list->EventCallBack)

+				h->subscribe_list->EventCallBack(new_sub);

+		}

+		else 

+		{ // Renewal subscription

+			struct upnp_subscription_element *e;

+			struct upnp_subscription_element *next;

+			unsigned char count=0;

+

+			for(e = h->subscribe_list->subscription_head.lh_first; e != NULL; )

+			{

+				next = e->entries.le_next;

+				if(strcmp(e->sid, sub.sid) == 0)

+				{

+					count++;

+					if (BuildSubscribeResponse(h, &sub) != UPNP_E_SUCCESS) {

+						LIST_REMOVE(e, entries);

+						h->subscribe_list->total_subscription--;

+						free(e);

+						syslog(LOG_ERR, "UPnPProcessSUBSCRIBE : renew failed!");

+						return;

+					}

+					else {

+						//WPS2DOTX

+						//e->subscription_timeout = h->subscribe_list->subscription_timeout;

+						e->subscription_timeout = (int)sub.TimeOut;

+						

+						e->eventID = UPNP_EVENT_RENEWAL_COMPLETE;

+					}

+					syslog(LOG_INFO, "Renewal subscription: total_subscription [%d]",

+	       				(int)h->subscribe_list->total_subscription);

+					if (h->subscribe_list->EventCallBack){

+						h->subscribe_list->EventCallBack(e);

+						if(e->wscdReNewState == 1){

+							Send412PreconditionFailed(h);

+							e->wscdReNewState = 0;

+						}						

+					}

+				}

+				e = next;

+			}

+			if (count == 0) {

+				Send412PreconditionFailed(h);

+				syslog(LOG_ERR, "UPnPProcessSUBSCRIBE[renew] : Could not find the sid[%s]!", sub.sid);

+				if (new_sub == NULL) {

+					new_sub = (struct upnp_subscription_element *)malloc(sizeof(struct upnp_subscription_element));

+					if (new_sub == NULL)

+						return;

+					memset(new_sub, 0, sizeof(struct upnp_subscription_element));

+					new_sub->eventID = UPNP_EVENT_RENEWAL_COMPLETE;

+					memcpy(new_sub->sid, sub.sid, strlen(sub.sid));

+					if (h->subscribe_list->EventCallBack)

+						h->subscribe_list->EventCallBack(new_sub);

+					free(new_sub);

+				}

+				else

+					syslog(LOG_ERR, "UPnPProcessSUBSCRIBE[renew] : Could not allocate buffer for new_sub!");

+			}

+		}

+	}

+}

+

+static void UPnPProcessUNSUBSCRIBE(struct upnphttp * h)

+{

+	struct process_upnp_subscription sub;

+	struct upnp_subscription_element *e;

+	struct upnp_subscription_element *next;

+	int ret;

+	unsigned char count=0;

+

+	memset(&sub, 0, sizeof(struct process_upnp_subscription));

+	ret = ParseSUBSCRIBEPacket(h, &sub);

+	if (ret != UPNP_E_SUCCESS) {

+		Send412PreconditionFailed(h);

+		return;

+	}

+	else {

+#ifdef DEBUG

+		printf("IP [%s]\n", sub.IP);

+		printf("Host [%d.%d.%d.%d:%d]\n", (sub.IP_inet_addr>>24)&0xFF,

+			(sub.IP_inet_addr>>16)&0xFF,

+			(sub.IP_inet_addr>>8)&0xFF,

+			(sub.IP_inet_addr)&0xFF, sub.port);

+		printf("SID [%s]\n", sub.sid);

+		printf("CallBack %s\n", sub.callback_url);

+		printf("Timeout [%d]\n", (int)sub.TimeOut);

+#endif

+

+		if (sub.sid[0] == 0) {

+			Send412PreconditionFailed(h);

+			return;

+		}

+

+		for(e = h->subscribe_list->subscription_head.lh_first; e != NULL; )

+		{

+			next = e->entries.le_next;

+			if(strcmp(e->sid, sub.sid) == 0)

+			{

+				count++;

+				LIST_REMOVE(e, entries);

+				BuildUnSubscribeResponse(h);

+				h->subscribe_list->total_subscription--;

+				syslog(LOG_INFO, "UNSUBSCRIBE: total_subscription [%d]",

+	       			(int)h->subscribe_list->total_subscription);

+				

+				e->eventID = UPNP_EVENT_UNSUBSCRIBE_COMPLETE;

+				if (h->subscribe_list->EventCallBack)

+					h->subscribe_list->EventCallBack(e);

+				free(e);

+			}

+			e = next;

+		}

+

+		if (count == 0) {

+			BuildUnSubscribeResponse(h);

+			syslog(LOG_ERR, "UPnPProcessUNSUBSCRIBE : Could not find the sid!");

+		}

+	}

+}

+

+/* 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 (strncasecmp((char *)h->req_buf, "GET /HNAP", 9) == 0) {

+			i = 0;

+			int len;

+			while(h->soapMethods[i].methodName)

+			{

+				len = strlen(h->soapMethods[i].methodName);

+				if(strncmp("GetDeviceSettings", h->soapMethods[i].methodName, len) == 0)

+				{

+					h->soapMethods[i].methodImpl(h);

+					return;

+				}

+				i++;

+			}

+			syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl);

+			Send404(h);

+			return;

+		}

+		i = 0;

+		if (h->sendDesc) {

+		while(h->sendDesc[i].DescName)

+		{

+			if(strcmp(h->sendDesc[i].DescName, HttpUrl) == 0)

+			{

+				sendXMLdesc(h, h->sendDesc[i].sendDescImpl);

+				return;

+			}

+			i++;

+		}

+		}

+

+		syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl);

+		Send404(h);

+	}

+	else if(strcmp("SUBSCRIBE", HttpCommand) == 0)

+	{

+		//printf("<<--------------------\n%s\n------------------->>\n", h->req_buf);

+		UPnPProcessSUBSCRIBE(h);

+	}

+	else if(strcmp("UNSUBSCRIBE", HttpCommand) == 0) 

+	{

+		//printf("<<--------------------\n%s\n------------------->>\n", h->req_buf);

+		UPnPProcessUNSUBSCRIBE(h);

+	}

+	else

+	{

+		syslog(LOG_NOTICE, "Unsupported HTTP Command %s", HttpCommand);

+		Send501(h);

+	}

+}

+

+

+void Process_upnphttp(struct upnphttp * h)

+{

+	char *buf=NULL;

+	int n;

+	

+	if(!h)

+		return;

+

+	buf = (char *) malloc(2048);

+	if (buf == NULL) {

+		syslog(LOG_ERR, "Process_upnphttp: out of memory!");

+		return;

+	}

+	memset(buf, 0, 2048);

+	

+	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, "connection closed inexpectedly");

+			h->state = 100;

+		}

+		else

+		{

+			const char * endheaders;

+			/*printf("== PACKET RECEIVED (%d bytes) ==\n", n);

+			fwrite(buf, 1, n, stdout);	// debug

+			printf("== END OF PACKET RECEIVED ==\n");*/

+			/* 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);

+			h->req_buf = (char *)realloc(h->req_buf, 2048); //Brad modify for HNAP, bug fix

+			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, "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);

+	}

+

+	free(buf);

+}

+

+static const char httpresphead[] =

+	"%s %d %s\r\n"

+	"Content-Type: text/xml; charset=\"utf-8\"\r\n"

+	"Connection: close\r\n"

+	"Content-Length: %d\r\n"

+	"Server: " MINIUPNPD_SERVER_STRING "\r\n"

+	"Ext:\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 */

+void

+BuildHeader_upnphttp(struct upnphttp * h, int respcode,

+                     const char * respmsg,

+                     int bodylen)

+{

+	int templen;

+	if(!h->res_buf)

+	{

+		templen = sizeof(httpresphead) + 64 + bodylen;

+		h->res_buf = (char *)malloc(templen);

+		memset(h->res_buf, 0, templen);

+		h->res_buf_alloclen = templen;

+	}

+	h->res_buflen = snprintf(h->res_buf, h->res_buf_alloclen,

+	                         httpresphead, h->HttpVer,

+	                         respcode, respmsg, bodylen);

+	if(h->res_buf_alloclen < (h->res_buflen + bodylen))

+	{

+		h->res_buf = (char *)realloc(h->res_buf, (h->res_buflen + bodylen));

+		memset(h->res_buf, 0, (h->res_buflen + bodylen));

+		h->res_buf_alloclen = h->res_buflen + bodylen;

+	}

+}

+

+void

+BuildResp2_upnphttp(struct upnphttp * h, int respcode,

+                    const char * respmsg,

+                    const char * body, int bodylen)

+{

+	BuildHeader_upnphttp(h, respcode, respmsg, bodylen);

+	memcpy(h->res_buf + h->res_buflen, body, bodylen);

+	h->res_buflen += bodylen;

+}

+

+/* responding 200 OK ! */

+void BuildResp_upnphttp(struct upnphttp * h,

+                        const char * body, int bodylen)

+{

+	BuildResp2_upnphttp(h, 200, "OK", body, bodylen);

+}

+

+void SendResp_upnphttp(struct upnphttp * h)

+{

+	int n;

+	

+	n = ReliableSend(h->socket, h->res_buf, h->res_buflen);

+	if (n != h->res_buflen)

+	{

+		syslog(LOG_ERR, "SendResp_upnphttp: %d bytes sent (out of %d)",

+						n, h->res_buflen);

+	}

+}

+

+static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

+static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";

+

+/* encode 3 8-bit binary bytes as 4 '6-bit' characters */

+static void ILibencodeblock( unsigned char in[3], unsigned char out[4], int len )

+{

+	out[0] = cb64[ in[0] >> 2 ];

+	out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];

+	out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');

+	out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');

+}

+

+/*! \fn ILibBase64Encode(unsigned char* input, const int inputlen, unsigned char** output)

+	\brief Base64 encode a stream adding padding and line breaks as per spec.

+	\par

+	\b Note: The encoded stream must be freed

+	\param input The stream to encode

+	\param inputlen The length of \a input

+	\param output The encoded stream

+	\returns The length of the encoded stream

+*/

+int ILibBase64Encode(unsigned char* input, const int inputlen, unsigned char** output)

+{

+	unsigned char* out=NULL;

+	unsigned char* in;

+	

+	*output = (unsigned char*)malloc(((inputlen * 4) / 3) + 5);

+	out = *output;

+	if (out == NULL)

+		return 0;

+	in  = input;

+	

+	if (input == NULL || inputlen == 0)

+	{

+		*output = NULL;

+		return 0;

+	}

+	

+	while ((in+3) <= (input+inputlen))

+	{

+		ILibencodeblock(in, out, 3);

+		in += 3;

+		out += 4;

+	}

+	if ((input+inputlen)-in == 1)

+	{

+		ILibencodeblock(in, out, 1);

+		out += 4;

+	}

+	else

+	if ((input+inputlen)-in == 2)

+	{

+		ILibencodeblock(in, out, 2);

+		out += 4;

+	}

+	*out = 0;

+	

+	return (int)(out-*output);

+}

+

+/* Decode 4 '6-bit' characters into 3 8-bit binary bytes */

+static void ILibdecodeblock( unsigned char in[4], unsigned char out[3] )

+{

+	out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);

+	out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);

+	out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);

+}

+

+/*! \fn ILibBase64Decode(unsigned char* input, const int inputlen, unsigned char** output)

+	\brief Decode a base64 encoded stream discarding padding, line breaks and noise

+	\par

+	\b Note: The decoded stream must be freed

+	\param input The stream to decode

+	\param inputlen The length of \a input

+	\param output The decoded stream

+	\returns The length of the decoded stream

+*/

+int ILibBase64Decode(unsigned char* input, const int inputlen, unsigned char** output)

+{

+	unsigned char* inptr;

+	unsigned char* out=NULL;

+	unsigned char v;

+	unsigned char in[4];

+	int i, len;

+	

+	if (input == NULL || inputlen == 0)

+	{

+		*output = NULL;

+		return 0;

+	}

+	

+	*output = (unsigned char*)malloc(((inputlen * 3) / 4) + 4);

+	out = *output;

+	if (out == NULL)

+		return 0;

+	inptr = input;

+	

+	while( inptr <= (input+inputlen) )

+	{

+		for( len = 0, i = 0; i < 4 && inptr <= (input+inputlen); i++ )

+		{

+			v = 0;

+			while( inptr <= (input+inputlen) && v == 0 ) {

+				v = (unsigned char) *inptr;

+				inptr++;

+				v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);

+				if( v ) {

+					v = (unsigned char) ((v == '$') ? 0 : v - 61);

+				}

+			}

+			if( inptr <= (input+inputlen) ) {

+				len++;

+				if( v ) {

+					in[ i ] = (unsigned char) (v - 1);

+				}

+			}

+			else {

+				in[i] = 0;

+			}

+		}

+		if( len )

+		{

+			ILibdecodeblock( in, out );

+			out += len-1;

+		}

+	}

+	*out = 0;

+	return (int)(out-*output);

+}

+

+int OpenAndConfUNIXSocket(const char *file_path)

+{

+	int s, len;

+	struct sockaddr_un local;

+

+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {

+            	perror("UNIXSocket");

+            	return -1;

+    	}

+	

+    	local.sun_family = AF_UNIX;

+     	strcpy(local.sun_path, file_path);

+     	unlink(local.sun_path);

+     	//len = strlen(local.sun_path) + sizeof(local.sun_family);

+     	len = sizeof(struct sockaddr_un);

+    	if (bind(s, (struct sockaddr *)&local, len) == -1) {

+            	perror("UNIXSocket bind");

+            	return -1;

+     	}

+

+     	if (listen(s, 5) == -1) {

+            	perror("UNIXSocket listen");

+            	return -1;

+     	}

+

+	return s;

+}

+

+int CreateUnixSocket(const char *function_name,

+								const char *file_path,

+								const int time_out)

+{

+	struct sockaddr_un remote;

+	struct timeval tv;

+	int len, s;

+

+	if (file_path == NULL)

+		return -1;

+

+	if (time_out < 0)

+		return -1;

+	

+	// Inter Process Communication

+	if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {

+            	return -1;

+      	}

+	

+	tv.tv_sec = time_out;

+	tv.tv_usec = 0;

+	if(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0)

+	{

+		if (function_name) {

+			syslog(LOG_WARNING, "%s : setsockopt(unix_socket, SO_RCVTIMEO): %m", function_name);

+		}

+		else {

+			syslog(LOG_WARNING, "setsockopt(unix_socket, SO_RCVTIMEO): %m");

+		}

+	}

+	

+	remote.sun_family = AF_UNIX;

+      	strcpy(remote.sun_path, file_path);

+     	//len = strlen(remote.sun_path) + sizeof(remote.sun_family);

+     	len = sizeof(struct sockaddr_un);

+     	if (connect(s, (struct sockaddr *)&remote, len) == -1) {

+		close(s);

+           	return -1;

+     	}

+	return s;

+}

+

+int UnixSocketSendAndReceive(const char *function_name,

+								const char *file_path,

+								const int time_out,

+								const char *in, char *out, const int out_len)

+{

+	int s=-1, t, in_len, ret=-1;

+

+	if (file_path == NULL || in == NULL || out == NULL || out_len < 1)

+		return -1;

+	

+	s = CreateUnixSocket(function_name, file_path, time_out);

+	if (s == -1) {

+		if (function_name)

+			syslog(LOG_ERR, "%s : CreateUnixSocket failed", function_name);

+		goto finish;

+	}

+

+	in_len = strlen(in);

+	if (ReliableSend(s, in, in_len) != in_len) {

+		if (function_name) {

+			syslog(LOG_ERR, "%s : Unix socket send: %m", function_name);

+		}

+            	goto finish;

+     	}

+	if ((t = recv(s, out, out_len, 0)) > 0) {

+           	out[t] = '\0';

+		ret = 0;

+	}

+	else {

+           	if (t < 0) {

+			if (function_name) {

+				syslog(LOG_ERR, "%s : Unix socket recv: %m", function_name);

+			}

+           	}

+          	else {

+			if (function_name) {

+				syslog(LOG_WARNING, "%s : Server closed connection: %m", function_name);

+			}

+          	}

+    	}

+

+finish:

+	if (s >= 0)

+		close(s);

+	return ret;

+}