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.
Dependents: Simple_HTTP_JSON HTTPWebServer-WIZwiki-W7500 HTTPWebServer-WIZwiki-W750023 WIZ750SR_test
Fork of httpServer by
HTTPConnection.cpp
- Committer:
- hjjeon
- Date:
- 2016-02-12
- Revision:
- 4:2903435e3811
- Parent:
- 2:dd293a10a772
File content as of revision 4:2903435e3811:
/* HTTPConnection.cpp */
#include "mbed.h"
#include "HTTPConnection.h"
//#define DEBUG
#include "hl_debug.h"
#include <vector>
using std::vector;
using std::string;
const struct HTTPRequestConfig {
const char* request_string;
HTTPRequestType request_type;
} g_requestConfig[] = {
{ "GET", HTTP_RT_GET },
{ "POST", HTTP_RT_POST},
{ "PUT", HTTP_RT_PUT},
{ "OPTIONS",HTTP_RT_OPTIONS},
{ "HEAD", HTTP_RT_HEAD},
{ "DELETE", HTTP_RT_DELETE},
{ "TRACE", HTTP_RT_TRACE},
{ "CONNECT",HTTP_RT_CONNECT}
};
HTTPConnection::HTTPConnection(TCPSocketConnection& clnt) : m_Tcp(clnt)
{
}
HTTPConnection::~HTTPConnection()
{
close();
}
void HTTPConnection::close()
{
m_Msg.headers.clear();
}
int HTTPConnection::poll()
{
static char buffer[256] = {};
int rcvd= 0;
int ret = 0;
int attri_len = 0;
INFO("Waiting for new data in connection");
// Try receiving request line
rcvd = receiveLine(buffer, 255, 3000);
if (rcvd == -1) {
// there was an error, probably the connection was closed, so close this connection as well
INFO("No more data available. Will close this connection now.");
close();
return -1;
}
// The Request has not yet been received so try it
rcvd = parse(buffer);
if (rcvd == -1) {
// Invalid content received, so close the connection
INFO("Invalid message received, so sending negative response and closing connection !");
//sprintf(buffer,"HTTP/1.1 400 BadRequest\n\rContent-Length: %d\n\rContent-Type: text\n\r\n\r\n\r",0);
m_Tcp.set_blocking(true, 1500);
//m_Tcp.send(buffer,strlen(buffer));
close();
rcvd = -1;
return -1;
}
// The request has been received, try receive the body
while(rcvd > 0) {
rcvd = receiveLine((char*)buffer, 255, 3000);
// First check if we received an empty line. This would indicate the end of the message or message body.
if (rcvd < 0) {
// there was an empty line, so we can start with performing the request
INFO("Request Header was received completely. Performing request.");
rcvd = 0;
break;
}
else {
// add message body
ret = parseHeader(buffer);
if (ret == 0) {
}
else {
attri_len = ret;
}
}
}
//Receive attribute data
if( attri_len != 0 )
{
m_Tcp.receive( m_Msg.attri, attri_len );
}
INFO("Leaving poll function!");
return rcvd;
}
int HTTPConnection::receiveLine(char* szLine, int nMaxLen, int nTimeout, char cLineTerm)
{
if ((szLine == NULL) || (nMaxLen == 0))
return -1;
szLine[0] = 0;
m_Tcp.set_blocking(false, 1500);
if (!m_Tcp.is_connected()) {
error("NOT COnnected anymore");
return -1;
}
Timer tm;
int i;
// Try to receive up to the max number of characters
for (i = 0 ; i < nMaxLen-1 ; i++) {
int c;
c = m_Tcp.receive( szLine + i, 1 );
// Check that - if no character was currently received - the timeout period is reached.
if ((c == 0) || (c==-1)) {
// no character was read, so check if operation timed out
//if (tm.read_ms() > nTimeout) {
// Operation timed out
//INFO("Timeout occured in function 'receiveLine'.");
return -1;
//}
}
// Check if line terminating character was received
if (szLine[i] == cLineTerm)
{
break;
}
}
// Terminate with \0
szLine[i] = 0;
// Trim for '\r' linefeed at the end
if( (i >0) && (szLine[i-1] == '\r')) {
i--;
szLine[i] = 0;
}
// return number of characters received in the line or return -2 if an empty line was received
if ((i == 0) || ((i==1) &&(szLine[0] == '\r')))
{
// empty line received, so return -2
return -2;
}
return i;
}
int HTTPConnection::parse(char* buffer)
{
// Check if buffer is invalid or its content not long enough.
if ((buffer == NULL) || (strlen(buffer) < 4)) {
ERR("Buffer content is invalid or too short.");
return -1;
}
std::vector<std::string> args;
args.clear();
int argno = 0;
// decompose string into a list of arguments
char s = 0; // current starting char
int nLen = strlen(buffer)+1;
//for(int i = 0; i < nLen; i++)
//printf("%d : %c\r\n", i, buffer[i]);
for (int i = 0 ; i < nLen ; i++) {
if ((buffer[i] == ' ') || (buffer[i] == '\n') || (buffer[i] == 0)) {
// new arg found
buffer[i] = 0;
if (argno++ == 1) {
// its the uri
// parse the uri args
parseUriArgs(&buffer[s], m_Msg.args);
}
INFO("Found argument \"%s\"", &buffer[s]);
args.push_back(&buffer[s]);
s = i+1;
}
}
// store the uri and the HTTP version
m_Msg.uri = args[1];
m_Msg.version = args[2];
// Find matching request type
for (int i = 0 ; i < sizeof(g_requestConfig)/sizeof(struct HTTPRequestConfig) ; i++) {
if (args.at(0) == g_requestConfig[i].request_string) {
m_Msg.request = g_requestConfig[i].request_type;
}
}
args.clear();
return 1;
}
int HTTPConnection::parseHeader(char *buffer)
{
// Check if the buffer is invalid or if the content is too short to be meaningful
if ((strlen(buffer) <3) || (buffer == NULL))
return -1;
//Find Content length
if(strncmp(buffer, "Content-Length", 14) == 0)
{
m_Msg.attri_len = atoi(&buffer[16]);
return m_Msg.attri_len;
}
/*
for (int i = 0 ; i < buflen ; i++) {
if (buffer[i] == ':') {
// touple found
buffer[i] = 0;
value_start = i+1;
m_Msg.headers[buffer] = &buffer[value_start];
INFO("Header name=\"%s\" : value=\"%s\".", buffer, &buffer[value_start]);
return 0;
}
}
*/
return 0;
//ERR("Did not recieve a valid header : \"%s\".", buffer);
//return -1;
}
int HTTPConnection::parseUriArgs(char *buffer, map<string,string>&args)
{
// Check if the buffer is invalid or if the content is too short to be meaningful
if ((strlen(buffer) <3) || (buffer == NULL))
return -1;
int args_start = -1;
int value_start = -1;
int buflen = strlen(buffer) +1;
const char* argname = NULL;
const char* valuename = NULL;
for (int i = 0; i < buflen ; i++) {
if (args_start == -1) { // args section not yet found
if (buffer[i] == '?') { // starts with a question mark, so got it
buffer[i] = 0;
args_start = i; // set the start of the args section
INFO("Argument section found !");
}
}
else { // search arg-value touples
if (argname == NULL) { // arg-name found ?
if (buffer[i] == '=') {
// yes, separate the arg-name
buffer[i] = 0;
argname = &buffer[args_start];
value_start = i+1;
INFO("Argument name %s", argname);
}
}
else { // search for end of value
if ((buffer[i] == '&') || (buffer[i] == 0) || (buffer[i] == '\r') || (buffer[i] == '\n')) {
buffer[i] = 0;
valuename = &buffer[value_start];
INFO("Argument value %s", valuename);
args[argname] = valuename;
// reset all indicators
argname = NULL;
valuename = NULL;
}
}
}
}
return 0;
}
