Own fork of MbedSmartRest

Dependents:   MbedSmartRestMain MbedSmartRestMain

Fork of MbedSmartRest by Cumulocity Official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HTTPResponseFilter.cpp Source File

HTTPResponseFilter.cpp

00001 /*
00002  * HTTPResponseFilter.cpp
00003  *
00004  * Created on: Feb 1, 2013
00005  * * Authors: Vincent Wochnik <v.wochnik@gmail.com>
00006  *
00007  * Copyright (c) 2013 Cumulocity GmbH
00008  *
00009  * Permission is hereby granted, free of charge, to any person obtaining
00010  * a copy of this software and associated documentation files (the
00011  * "Software"), to deal in the Software without restriction, including
00012  * without limitation the rights to use, copy, modify, merge, publish,
00013  * distribute, sublicense, and/or sell copies of the Software, and to
00014  * permit persons to whom the Software is furnished to do so, subject to
00015  * the following conditions:
00016  *
00017  * The above copyright notice and this permission notice shall be
00018  * included in all copies or substantial portions of the Software.
00019  *
00020  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00021  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00022  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00023  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00024  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00025  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00026  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00027  */
00028 
00029 #include "HTTPResponseFilter.h"
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <ctype.h>
00033 #include <stdio.h>
00034 
00035 const char *cExpectedStatus = "HTTP/1.* ";
00036 const char *cContentLength = "Content-Length: ";
00037 
00038 HTTPResponseFilter::HTTPResponseFilter(AbstractDataSource& source) : _source(source), _state(RESPF_STATE_INIT)
00039 {
00040     _length = _read = 0;
00041 }
00042 
00043 HTTPResponseFilter::~HTTPResponseFilter()
00044 {
00045 }
00046 
00047 char HTTPResponseFilter::read()
00048 {
00049     if (_state != RESPF_STATE_READ_HEADERS)
00050         return 0;
00051     if ((_length > 0) && (_length == _read))
00052         return 0;
00053     _read++;
00054     return _source.read();
00055 }
00056 
00057 uint8_t HTTPResponseFilter::status()
00058 {
00059     if (_state != RESPF_STATE_READ_HEADERS)
00060         return DS_STATUS_ERROR;
00061     if ((_length > 0) && (_length == _read))
00062         return DS_STATUS_CLOSED;
00063     return _source.status();
00064 }
00065 
00066 uint16_t HTTPResponseFilter::readStatus()
00067 {
00068     uint16_t res = 0;
00069     uint8_t state = 0;
00070     char c;
00071     size_t offset = 0;
00072     uint8_t status = DS_STATUS_OK;
00073     
00074     if (_state != RESPF_STATE_INIT)
00075         return 0;
00076         
00077     while ((state < 3) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
00078         switch (state) {
00079         case 0: // read expected status line
00080             if ((cExpectedStatus[offset] != c) && (cExpectedStatus[offset] != '*'))
00081                 state = 3;
00082             offset++;
00083             if (offset == strlen(cExpectedStatus)) {
00084                 state = 1;
00085             }
00086             break;
00087         case 1:
00088             if (isspace(c))
00089                 state = 2;
00090             if (isdigit(c))
00091                 res = (res * 10) + (c - '0');
00092             break;
00093         case 2:
00094             if (c == '\n')
00095                 state = 3;
00096             break;
00097         }
00098     }
00099 
00100     if ((status != DS_STATUS_OK) || (state != 3))
00101         return 0;
00102 
00103     _state = RESPF_STATE_READ_STATUS;        
00104     return res;
00105 }
00106 
00107 bool HTTPResponseFilter::skipHeaders()
00108 {
00109     uint8_t state = 0;
00110     char c;
00111     size_t offset = 0;
00112     uint8_t status = DS_STATUS_OK;
00113 
00114     if (_state != RESPF_STATE_READ_STATUS)
00115         return false;
00116 
00117     while ((state < 5) && (((c = _source.read()) > 0) || ((status = _source.status()) == DS_STATUS_OK))) {
00118         switch (state) {
00119         case 0: // start of line
00120             if (offset == 0) {
00121                 if (cContentLength[0] == c)
00122                     state = 1;
00123                 if (c == '\r')
00124                     state = 4;
00125             } else {
00126                 if (c == '\r')
00127                     state = 3;
00128             }
00129             offset++;
00130             break;
00131         case 1:
00132             if (c == '\r')
00133                 state = 3;
00134             else if (cContentLength[offset] != c)
00135                 state = 0;
00136             else if (offset == strlen(cContentLength)-1)
00137                 state = 2;
00138             offset++;
00139             break;
00140         case 2:
00141             if (isdigit(c))
00142                 _length = (_length * 10) + (c - '0');
00143             else if (c == '\r')
00144                 state = 3;
00145             else
00146                 state = 0;
00147             offset++;
00148             break;
00149         case 3:
00150             if (c == '\n') {
00151                 state = 0;
00152                 offset = 0;
00153             }
00154             break;
00155         case 4:
00156             if (c == '\n')
00157                 state = 5;
00158             break;
00159         }
00160     }
00161 
00162     if ((status != DS_STATUS_OK) || (state != 5))
00163         return false;
00164         
00165     _state = RESPF_STATE_READ_HEADERS;
00166     return true;
00167 }
00168 
00169 void HTTPResponseFilter::reset()
00170 {
00171     _state = RESPF_STATE_INIT;
00172     _length = _read = 0;
00173 }