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
AMMPC/axHTTP.c
- Committer:
- AxedaCorp
- Date:
- 2014-07-01
- Revision:
- 0:65004368569c
File content as of revision 0:65004368569c:
#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;
}
