Axeda Ready Demo for Freescale FRDM-KL46Z as accident alert system

Dependencies:   FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem

Fork of AxedaGo-Freescal_FRDM-KL46Z by Axeda Corp

Revision:
0:65004368569c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AMMPC/axHTTP.c	Tue Jul 01 21:31:54 2014 +0000
@@ -0,0 +1,460 @@
+#include "axHTTP.h"
+#include "axStatusCodes.h"
+#include "axConstants.h"
+#include "ctype.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "axSettings.h"
+#include "axTransport.h"
+
+#define AX_HTTP_OK                  200
+#define AX_HTTP_SYNTAX_INVALID      400     //The Request syntax is incorrect
+#define AX_HTTP_UNAUTHORIZED        401     //You need permission to access that resource. Agent Authentication failure
+#define AX_HTTP_FORBIDDEN           403     //You need permission to access that resource.
+#define AX_HTTP_NOT_FOUND           404     //The resource was not found
+#define AX_HTTP_REQ_INVALID         405     //Content type is invalid, should be application/json most of the time
+#define AX_HTTP_CONTENT_INVALID     422     //The Request is valid syntactically but the content is invalid e.g. wrong instruction
+#define AX_HTTP_SERVER_ERROR        500     //The server attempted to handle your request but a failure occurred; check the server logs.
+
+#define HTTPKEY_GET         0
+#define HTTPKEY_POST        1
+#define HTTPKEY_PUT         2
+#define HTTPKEY_PROTOCOL    3
+#define HTTPKEY_CRLF        4
+
+
+#define HTTPH_HOST          0
+#define HTTPH_TYPE          1
+#define HTTPH_LENGTH        2
+#define HTTPH_CONNECTION    3
+#define HTTPH_XCOUNT        4
+#define HTTPH_CONTENTDIS    5
+#define HTTPH_MULTIPART     6
+#define HTTPH_FORMDATA      7
+#define HTTPH_ACCEPT        8
+
+#define HTTPR_TYPE          0
+#define HTTPR_LENGTH        1
+#define HTTPR_BODY_SEP      2
+#define HTTPR_DELIMS        3
+
+int http_debug=AX_FALSE;
+int x_count=0;
+
+int http_getResponse(HTTP_Transmission *response, ax_socket *source);
+
+char *HTTP_KEY[]= {"GET", "POST", "PUT", "HTTP/1.1", "\r\n"};
+char *HTTP_HEADER[] = { "Host: ", "Content-Type: ", "Content-Length: ", "Connection: close", "x-count: ", "Content-Disposition: ","multipart/form-data; boundary=", "form-data;", "Accept: */*"};
+char *HTTP_RESP[] = { "Content-Type:", "Content-Length:", "\r\n\r\n", " \r\n"}; 
+
+int http_send(HTTP_Transmission *request, char *host, int port, int secure, HTTP_Transmission *response){
+  int retVal=AX_UNKNOWN;
+
+  switch(request->operation) {
+      case AX_HTTP_GET:
+        retVal=http_send_get(request->resource, host, port, secure, response);
+      break;
+      case AX_HTTP_POST:
+        retVal=http_send_post(request->resource, host, port, secure, &request->headers, request->body, request->body_length, response);
+      break;
+      case AX_HTTP_PUT:
+              retVal=http_send_put(request->resource, host, port, secure, &request->headers, request->body, request->body_length, response);
+      break;
+      case AX_HTTP_MPOST:
+        retVal=http_send_mpost(request->resource, host, port, secure, &request->headers, request->body, request->body_length, request->mpData, 1, response);
+      break;
+      }
+
+  return retVal;
+  }
+
+int http_send_get(char *resource, char *host, int port, int secure, HTTP_Transmission *response) {
+  int retVal=AX_UNKNOWN;
+
+  if(!resource||!host||!response) { return AX_ARGNULL; }
+  if((port < 0)||(port>65536)) { return AX_NET_PORT_INVALID; }
+  int sz=strlen(HTTP_KEY[HTTPKEY_GET])+strlen(resource)+strlen(HTTP_KEY[HTTPKEY_PROTOCOL])+strlen(HTTP_HEADER[HTTPH_HOST])+strlen(host)+13+6+strlen(HTTP_HEADER[HTTPH_CONNECTION])+strlen(HTTP_HEADER[HTTPH_ACCEPT]); //+6 adds space for extra CRLFs, spaces, and null terminator
+
+  ax_socket sock;
+
+  retVal=net_socketInit(&sock);
+  retVal=net_socketOpen(&sock, host, port, secure);
+  if(retVal!=AX_OK){
+      return retVal;
+      }
+
+  char *buff=(char *)malloc(sizeof(char)*sz);
+  int wrtSz=snprintf(buff, sz, "%s %s %s%s%s%s:%d%s%s%s%s", HTTP_KEY[HTTPKEY_GET], resource, HTTP_KEY[HTTPKEY_PROTOCOL], HTTP_KEY[HTTPKEY_CRLF], HTTP_HEADER[HTTPH_HOST], host, port, HTTP_KEY[HTTPKEY_CRLF], HTTP_HEADER[HTTPH_CONNECTION], HTTP_KEY[HTTPKEY_CRLF], HTTP_KEY[HTTPKEY_CRLF]);
+
+  if(wrtSz>sz) { printDebug("http_send_get(): Buffer allocated for header was too small, truncated"); } 
+  retVal=net_socketWrite(&sock, buff, sz);
+  retVal=net_socketFlush(&sock);
+
+  retVal=http_getResponse(response, &sock);
+  if(retVal==AX_HTTP_OK) { retVal=AX_OK; }
+
+  net_socketClose(&sock);
+  free(buff);
+  return retVal;
+  }
+
+int http_send_put(char *resource, char *host, int port, int secure, HTTP_Headers *headers, char *data, int data_sz, HTTP_Transmission *response) {
+  int retVal=AX_UNKNOWN;
+
+  if(!resource||!host||!response) { return AX_ARGNULL; }
+  if((port < 0)||(port>65536)) { return AX_NET_PORT_INVALID; }
+  if((!data)&&(data_sz!=0)) { return AX_CONFLICTING_ARG; }
+
+  ax_socket sock;
+
+  retVal=net_socketInit(&sock);
+  retVal=net_socketOpen(&sock, host, port, secure);
+  if(retVal!=AX_OK){ //if a failure occurred bail out. failures here would be that a port is not free
+    return retVal;
+    }
+  printDebug("Attempting to create headers");
+   char *header=NULL;
+   header=createHeaders(header, HTTPKEY_PUT, resource, HTTPKEY_PROTOCOL, host, headers->contentType, data_sz, x_count); //returns a malloc'd string with the headers
+
+  retVal=net_socketWrite(&sock, header, strlen(header));
+  if(retVal!=AX_OK){ //if a failure occurred bail out. failures here would be that a port is not free
+      goto cleanup;
+      }
+  retVal=net_socketWrite(&sock, data, data_sz);
+  net_socketFlush(&sock);
+  if(retVal!=AX_OK) {
+     retVal=AX_NET_ERR_DATA_WRITE;
+     goto cleanup;
+     }
+
+  retVal=http_getResponse(response, &sock);
+  if(retVal==AX_HTTP_OK) { retVal=AX_OK; }
+
+  x_count++;
+   goto cleanup;
+
+
+cleanup:
+  net_socketClose(&sock);
+  free(header);
+  return retVal;
+}
+
+
+
+int http_send_post(char *resource, char *host, int port, int secure, HTTP_Headers *headers, char *data, int data_sz, HTTP_Transmission *response){
+  int retVal=AX_UNKNOWN;
+
+  if(!resource||!host||!response) { return AX_ARGNULL; }
+  if((port < 0)||(port>65536)) { return AX_NET_PORT_INVALID; }
+  if((!data)&&(data_sz!=0)) { return AX_CONFLICTING_ARG; }
+
+  ax_socket sock;
+
+  retVal=net_socketInit(&sock);
+  retVal=net_socketOpen(&sock, host, port, secure);
+  if(retVal!=AX_OK){ //if a failure occurred bail out. failures here would be that a port is not free
+    return retVal;
+    }
+  printDebug("Attempting to create headers");
+   char *header=NULL;
+   header=createHeaders(header, HTTPKEY_POST, resource, HTTPKEY_PROTOCOL, host, headers->contentType, data_sz, x_count); //returns a malloc'd string with the headers
+
+  retVal=net_socketWrite(&sock, header, strlen(header));
+  if(retVal!=AX_OK){ //if a failure occurred bail out. failures here would be that a port is not free
+      goto cleanup;
+      }
+  retVal=net_socketWrite(&sock, data, data_sz);
+  net_socketFlush(&sock);
+  x_count++;
+  printDebug("Transmission sent, Waiting for response\n");
+
+
+  retVal=http_getResponse(response, &sock);
+  if(retVal==AX_HTTP_OK) { retVal=AX_OK; }
+
+   goto cleanup;
+
+cleanup:
+  net_socketClose(&sock);
+  free(header);
+  return retVal;
+  }
+
+int http_send_mpost(char *resource, char *host, int port, int secure, HTTP_Headers *headers, char *data, int data_sz, HTTP_Part *files, int part_ct, HTTP_Transmission *response) {
+    int retVal=AX_UNKNOWN;
+ //   char xcount_tmp[10];
+//    char clength_tmp[10];
+    int boundary_sz=10;
+    int body_sz=0;
+    int hint_sz=0;
+    char *hint=NULL;
+	char *header=NULL;
+    ax_socket sock;
+
+      if(!resource||!host||!response) { return AX_ARGNULL; }
+    if((port < 0)||(port>65536)) { return AX_NET_PORT_INVALID; }
+    if((!data)&&(data_sz!=0)) { return AX_CONFLICTING_ARG; }
+ //Assemble body Parts
+    char *fileargs=NULL;
+    int file_arg_len=strlen(files->file_name)+51;
+    fileargs=(char *)malloc(sizeof(char)*file_arg_len);
+    int wrtfarg=snprintf(fileargs, file_arg_len, "name=\"file\"; filename=\"%s\"\r\nContent-Type: text/plain", files->file_name);
+    if(wrtfarg>file_arg_len) { printDebug("http_send_mpost(): Buffer allocated for file arguments was too small, truncated"); }
+    if(files->hint!=NULL)
+        {
+        hint_sz=strlen(files->hint)+18;//+1 for terminating char
+        hint=(char *)malloc(sizeof(char)*hint_sz);
+        int wrthint=snprintf(hint, hint_sz, "name=\"hint\"\r\n\r\n%s\r\n", files->hint);
+        if(wrthint>hint_sz) { printDebug("http_send_mpost(): Buffer allocated for hint was too small, truncated"); }
+        }
+//body size calculation here
+  //Boundary: --<boundary>
+    body_sz=body_sz+2+boundary_sz;   
+  //adding body ---for mparts
+    if(data_sz>0){
+      body_sz=body_sz+36+data_sz+boundary_sz;  
+      }
+  //Add Hint     Content-Disposition: form-data;name="<hint>"\r\n--<boundary>\r\n
+    if(files->hint!=NULL){
+      body_sz=body_sz+38+strlen(hint)+boundary_sz;  
+      }
+    if(files->data_sz>0) {
+      body_sz=body_sz+38+strlen(fileargs)+files->data_sz;
+      }
+    body_sz=body_sz+8+boundary_sz;
+
+//get a boundary for the multipart
+    char *boundary=(char *)malloc(sizeof(char)*boundary_sz);
+    http_getBoundary(boundary, boundary_sz);
+//convert the data size integer into a string
+ //  int wrtCLen=snprintf(clength_tmp, 10, "%d", body_sz);
+ //   if(wrtCLen>10) { printDebug("http_send_mpost(): Buffer allocated for clength_tmp was too small, truncated"); }
+    //Add operation line
+
+    printDebug("Attempting to create headers");
+
+//Create Content Type 
+	 int cTypeSz=0;
+	 cTypeSz=strlen(HTTP_HEADER[HTTPH_MULTIPART])+strlen(boundary)+1;
+	 char *contentType=(char *)calloc(cTypeSz, sizeof(char));       
+	 int wrt_ctype=snprintf(contentType, cTypeSz, "%s%s", HTTP_HEADER[HTTPH_MULTIPART], boundary);
+	 if(wrt_ctype>cTypeSz) { printDebug("http_send_mpost(): Buffer allocated for contentType was too small, truncated");}
+//Get the headers
+     header=createHeaders(header, HTTPKEY_POST, resource, HTTPKEY_PROTOCOL, host, contentType, body_sz, x_count); //returns a malloc'd string with the headers
+	 free(contentType); //we're done with the string we used to cat the values
+//Start to send the data
+	retVal=net_socketInit(&sock);
+    retVal=net_socketOpen(&sock, host, port, secure);
+    if(retVal!=AX_OK){ //if a failure occurred, bail out. A failure here would indicate that a port is closed, or the network is not available.
+      return retVal;
+      }
+//Write the headers
+    retVal=net_socketWrite(&sock, header, strlen(header));
+      if(retVal!=AX_OK){ goto cleanup; }
+
+   //write the body...
+   //start boundary
+      retVal=net_socketWrite(&sock, "--", 2);
+      retVal=net_socketWrite(&sock, boundary, boundary_sz);
+      retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+   //1st section -uses the data in body if specified
+    if(data_sz>0){
+      retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_CONTENTDIS], 21);
+      retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_FORMDATA], 11);
+      retVal=net_socketWrite(&sock, data, data_sz); //Write body data, the fields and values
+      retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+      retVal=net_socketWrite(&sock, "--", 2);
+      retVal=net_socketWrite(&sock, boundary, boundary_sz);
+      }
+    if(files->hint!=NULL){
+       retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_CONTENTDIS], 21);
+       retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_FORMDATA], 11);
+       retVal=net_socketWrite(&sock, hint, hint_sz); //Write body data, the fields and values
+       retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+       retVal=net_socketWrite(&sock, "--", 2);
+       retVal=net_socketWrite(&sock, boundary, boundary_sz);
+       retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+       }
+    if(files->data_sz>0) {
+        retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_CONTENTDIS], 21);
+        retVal=net_socketWrite(&sock, HTTP_HEADER[HTTPH_FORMDATA], 11);
+        retVal=net_socketWrite(&sock, fileargs, file_arg_len);
+        retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+        retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+        retVal=net_socketWrite(&sock, (char *)files->data, files->data_sz);
+        retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+        }
+      retVal=net_socketWrite(&sock, "--", 2);
+      retVal=net_socketWrite(&sock, boundary, boundary_sz);
+      retVal=net_socketWrite(&sock, "--", 2);
+      retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+      retVal=net_socketWrite(&sock, HTTP_KEY[HTTPKEY_CRLF], 2);
+
+
+    net_socketFlush(&sock);
+    x_count++;
+    retVal=http_getResponse(response, &sock);
+    if(retVal==AX_HTTP_OK) { retVal=AX_OK; }
+
+  cleanup:
+   net_socketClose(&sock);
+   free(header);
+   free(hint);
+   free(fileargs);
+   free(boundary);
+   return retVal;
+  }
+
+void http_add_mpart(HTTP_Transmission *request, char *file_name, unsigned char *data, int file_sz) {
+ //For future expansion.
+}
+
+//Return Handling
+HTTP_Transmission *http_parse(HTTP_Transmission *response, char *data){
+printDebug("Starting parse of ");
+printDebug(data);
+
+    char clength[7];
+    int reqSize=0;
+    char *temp=NULL;
+    char *bodyStart=NULL;
+    response->body_length=0;
+    response->response_code=-1; //indicate that no response code has been recieved(yet)
+
+    reqSize=strlen(data);
+    if(reqSize<=12) { printDebug("No Body included"); }
+    else { printDebug("body present" );
+    bodyStart=strstr(data, HTTP_RESP[HTTPR_BODY_SEP]);
+    if(bodyStart==NULL) { printDebug("D'oh! Couldn't parse for body\n"); }
+    else {
+	 int body_length=strlen(bodyStart)-4; //don't count the extra \r\n\r\n
+         response->body_length=body_length;
+         response->body=(char *)calloc(body_length+1, sizeof(char));
+         snprintf(response->body, body_length+1, "%s", bodyStart+4); //the +4 gets rid of the preceeding \r\n\r\n
+         }
+    }
+
+    temp = strtok(data, HTTP_RESP[HTTPR_DELIMS]);
+    while (temp!=NULL) {
+
+    if((strlen(temp)==3)&&(isdigit((int)temp[0]))&&(isdigit((int)temp[1]))&&(isdigit((int)temp[2]))) {
+        response->response_code=atoi(temp); //convert the text response code to an int.
+        }
+
+    if(strcmp(temp, HTTP_RESP[HTTPR_TYPE])==0) {
+        response->headers.contentType=strtok(NULL, HTTP_RESP[HTTPR_DELIMS]);
+        }
+    if(strcmp(temp, HTTP_RESP[HTTPR_LENGTH])==0){
+        temp=strtok(NULL, HTTP_RESP[HTTPR_DELIMS]);
+        strcpy(clength, temp);
+    response->body_length=atoi(clength);
+    if(response->body_length<=0) {
+         response->body_length=strlen(bodyStart+4);
+          }
+        }
+
+    temp=strtok(NULL, HTTP_RESP[HTTPR_DELIMS]);
+    }
+
+    return response;
+    }
+
+int http_getResponse(HTTP_Transmission *response, ax_socket *source){
+    int retVal=AX_UNKNOWN;
+    char *responseTxt=NULL;
+     responseTxt=(char *)calloc(AX_NET_BUFF_S, sizeof(char));
+     int length=0;
+     response->response_code=0;
+     retVal=net_socketRead(source, 300, (unsigned char *)responseTxt, AX_NET_BUFF_S, &length);
+     if(retVal==AX_OK) { printDebug("response received"); }
+     else { printDebug("Response Timeout"); return AX_NET_ERR_TIMEOUT;}
+     http_parse(response, (char *)responseTxt); 
+
+     free(responseTxt);
+    return response->response_code;
+    }
+
+
+//Supporting Methods
+/***************************************************************************************************/
+/*http_getBoundary()                                                                               */
+/*                                                                                                 */
+/*This method creates a unique string token that is used when creating mulitpart form transmissions*/
+/*in HTTP. It will return a random sequence of letters and numbers.                                */
+/***************************************************************************************************/
+char *http_getBoundary(char *buff, int length){
+    int ctr=0;
+    if(buff==NULL) { return NULL; } //if no pointer was given to us give a nothing back.
+    if(length<=0) {return NULL;} 
+       int randNum=0;
+       for(ctr=0; ctr<length; ctr++) {
+       randNum=abs(randInt()%62);
+           if(randNum<=10) {
+		if(randNum==0) { randNum++; } //avoid using slashes in boundary, char 47
+               buff[ctr]=randNum+47;
+               }
+           else if((randNum>10)&&(randNum<=36)) {
+               buff[ctr]=(randNum-10)+64;
+               }
+           else {
+               buff[ctr]=(randNum-37)+97;
+               }
+           if(buff[ctr]==32) {buff[ctr]=97; }
+       }
+
+    return buff;
+    }
+
+void zeroOutHTTPXmission(HTTP_Transmission *tgt){
+
+	    tgt->operation=-1;
+	    tgt->resource=NULL;
+	    tgt->headers.contentType=NULL;
+	    tgt->body=NULL;
+	    tgt->body_length=0;
+	    tgt->mpData=NULL;
+	    tgt->response_code=-1;
+	    tgt->secure=-1;
+}
+
+char *createHeaders(char *tgtBuff, int http_operation, char *resource, int httpver, char *hostname, char *contentType, int contentLength, int xCount) {
+  int headerSz=4;  //we account for the closing CRLF CRLF here
+  char clength_tmp[10];
+  char xCount_tmp[10];
+  int wrthdr=0;  
+//convert the ints to strings so we can get an strlen on them
+  snprintf(clength_tmp, 10, "%d", contentLength);
+  snprintf(xCount_tmp, 10, "%d", xCount);
+
+//String Size Calculations
+  headerSz=headerSz+strlen(resource)+strlen(HTTP_KEY[http_operation])+strlen(HTTP_KEY[httpver])+5; //"POST  HTTP/1.1" there are 2 spaces and a CRLF in there as well., 1 for the null
+  headerSz=headerSz+strlen(HTTP_HEADER[HTTPH_HOST])+strlen(hostname)+2;  //Host: <hostname>
+  headerSz=headerSz+strlen(HTTP_HEADER[HTTPH_TYPE])+strlen(contentType)+2;  //Content-Type: <contentType>
+  headerSz=headerSz+strlen(HTTP_HEADER[HTTPH_LENGTH])+strlen(clength_tmp)+2;  //Content-Length: <contentLength>
+  headerSz=headerSz+strlen(HTTP_HEADER[HTTPH_CONNECTION])+2; 		      //Connection: Close
+  if(xCount>0) {
+    headerSz=headerSz+strlen(HTTP_HEADER[HTTPH_XCOUNT])+strlen(xCount_tmp)+2;	
+   }
+
+//String buffer creation  
+  tgtBuff=(char *)calloc(headerSz, sizeof(char));
+//Stuffin the buffer
+  if((xCount>0)&&(http_debug==AX_TRUE)) {
+     wrthdr=snprintf(tgtBuff, headerSz, "%s %s %s\r\n%s%s\r\n%s%s\r\n%s%s\r\n%s\r\n%s%s\r\n\r\n", HTTP_KEY[http_operation], resource, HTTP_KEY[httpver], HTTP_HEADER[HTTPH_HOST], hostname, HTTP_HEADER[HTTPH_TYPE], contentType, HTTP_HEADER[HTTPH_LENGTH], clength_tmp, HTTP_HEADER[HTTPH_CONNECTION], HTTP_HEADER[HTTPH_XCOUNT], xCount_tmp);
+	}
+  else {
+     wrthdr=snprintf(tgtBuff, headerSz, "%s %s %s\r\n%s%s\r\n%s%s\r\n%s%s\r\n%s\r\n\r\n", HTTP_KEY[http_operation], resource, HTTP_KEY[httpver], HTTP_HEADER[HTTPH_HOST], hostname, HTTP_HEADER[HTTPH_TYPE], contentType, HTTP_HEADER[HTTPH_LENGTH], clength_tmp, HTTP_HEADER[HTTPH_CONNECTION]);   
+
+     }
+  if(wrthdr>headerSz) { printDebug("http_send_post(): Buffer allocated for header was too small, truncated"); }
+
+return tgtBuff;
+}
+
+
+
+
+
+