Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem
Fork of AxedaGo-Freescal_FRDM-KL46Z revert by
Diff: AMMPC/axHTTP.c
- 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;
+}
+
+
+
+
+
+
