httpClient.c 4.9 KB
#include "httpClient.h"

/*
------------
PUT /path/file.html HTTP/1.1
Host: www.host1.com:80
Content-Type: application/json; charset=UTF-8

[json file]
-----------
*/

int httpRequest(struct httpHeaders head, char* content, int content_size)
{
	struct netconn *neocon = NULL;
	struct ip_addr remote_ip;
	struct netbuf *netBufs;

	char* request;
	char* response;
	
	err_t connection_ok = -1;

	ip4_addr_set_u32(&remote_ip,ipaddr_addr(SERVER_IP));

	// Check or default params
	DBG_HTTP("Checking params\r\n");
	if (head.uri == NULL || head.host == NULL)
	{
		return 1;	
	}

	// Calculate header size
	DBG_HTTP("Calculating header size\r\n");
	int head_size = strlen(reqMethod2text(head.method));
	head_size += strlen(" ") + head.uri_size + strlen(" HTTP/1.1") + strlen(ENDL);
	head_size += strlen("Host: ") + head.host_size + strlen(ENDL);
	//if (remote_port != '0') head_size += sizeof ":" + 2*sizeof(char);
	if(content_size > 0)
	{
		head_size += strlen(CONTENT_TYPE_HEADER) + strlen(ENDL);
		head_size += strlen("Content-Length: ") + numberofdigits(content_size) + 2*(strlen(ENDL));
	}
	// Build request head
	DBG_HTTP("Building request head\r\n");
	int request_size = head_size + content_size + 2*(strlen(ENDL));
	request = (char *) chHeapAlloc(NULL,request_size);
	printf("%c[1;31m[ALLOC] Allocated %d bytes to %08x%c[1;00m\r\n",0x1B,request_size,request,0x1B);
	strcpy(request, reqMethod2text(head.method));
	strcat(request, " ");
	strcat(request, head.uri);
	strcat(request, " HTTP/1.1\r\n");
	strcat(request, "Host: ");
	strcat(request, head.host);
	//if (remote_port != '0'){ strcat(request, ":"); strcat(request, remote_port); }
	strcat(request, ENDL);
	if(content_size > 0)
	{
		strcat(request, CONTENT_TYPE_HEADER);
		strcat(request, ENDL); 
	}
	strcat(request, "Content-Length: ");
	char *str_content_size = int2string(content_size);
	strcat(request, str_content_size);
	chHeapFree(str_content_size);
	printf("%c[1;32m[FREE] Freed bytes from  %08x%c[1;00m\r\n",0x1B,str_content_size,0x1B);
	
	// Interlude
	strcat(request, ENDL);
	strcat(request, ENDL);
	
	// Build request with content
	if(content_size > 0)
	{
		DBG_HTTP("Adding content to request string\r\n");
		strcat(request, content);
	}
	else
	{
		DBG_HTTP("Skipping void content\r\n");
	}
	DBG_HTTP("Packet:\r\n\r\n%c[1;32m%s%c[1;00m \r\n\r\n",0x1B,request,0x1B);
	// Set connection
	DBG_HTTP("Setting connection\r\n");
	neocon = netconn_new(NETCONN_TCP);
	if(neocon == NULL)
	{	
		DBG_HTTP("%c[1;31m[ERROR] Socket creation FAILED. Have you called libwismart_EnableBsdSocketAPI()?%c[1;00m\r\n",0x1B,0x1B);
	}
	/*local_ip.addr = 0;//getip
	netconn_bind(neocon, IP_ADDR_ANY, LOCAL_PORT); //88 is provisional local port.*/
	DBG_HTTP("Establishing connection\r\n");
	netconn_connect(neocon, &remote_ip, DEFAULT_REMOTE_PORT);

	// Send Request
	DBG_HTTP("Sending request\r\n");
	err_t err=netconn_write(neocon, request, request_size, NETCONN_NOCOPY);
	DBG_HTTP("Write returned: %d\r\n",err);
	chHeapFree(request);
	printf("%c[1;32m[FREE] Freed bytes from  %08x%c[1;00m\r\n",0x1B,request,0x1B);
	
	// Wait for Response
	DBG_HTTP("Waiting for response\r\n");
	//neocon->recv_timeout = 5000; // for 5s
	connection_ok = netconn_recv(neocon, &netBufs);
	DBG_HTTP("Receive returned: %d\r\n",connection_ok);
	if(connection_ok !=0)
	{
		netbuf_delete(netBufs);
		netconn_close(neocon);
		netconn_delete(neocon);
		return 0;
	}
	// Manage Response
	DBG_HTTP("Response received. Let's parse the information\r\n");
	response = (char*)chHeapAlloc(NULL,4*sizeof(char));
	printf("%c[1;31m[ALLOC] Allocated %d bytes to %08x%c[1;00m\r\n",0x1B,4 * sizeof(char),response,0x1B);
	netbuf_copy_partial(netBufs,response,3,9); // read 3B starting from 9th -> read response code. "HTTP/1.1 301 Moved Permanently"
	DBG_HTTP("Response code: %s\r\n",response);
	int http_response = response2int(response);

	netbuf_delete(netBufs);
	netconn_close(neocon);
	netconn_delete(neocon);	
	chHeapFree(response);
	printf("%c[1;32m[FREE] Freed bytes from  %08x%c[1;00m\r\n",0x1B,response,0x1B);
	return http_response;
}

const char* reqMethod2text(enum reqMethod method)
{
	switch(method)
	{
	 case post:
		return "POST";
	 case put:
		return "PUT";
	 case get:
		return "GET";
	 case del:
		return "DELETE";
	 default:
		return NULL;
	}
}

char* int2string(int num)
{
	char* manders;
	manders = (char*)chHeapAlloc(NULL,numberofdigits(num)+1);
	printf("%c[1;31m[ALLOC] Allocated %d bytes to %08x%c[1;00m\r\n",0x1B,numberofdigits(num)+1,manders,0x1B);
	sprintf(manders, "%d", num);
	return manders;
}

int numberofdigits(int number) // 0 has one digit.
{
	int digits = 0;
    while (number)
	{
        number /= 10;
        digits++;
    }
    return (digits == 0 ? 1 : digits);
}

int response2int(char* chars) //int atoi (char[]) fa el mateix xD
{
	return ( (chars[0]-'0')*100 + (chars[1]-'0')*10 + (chars[2]-'0')*1 );
}