httpparser.H 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. * */
  13. /*
  14. * httpparser.H
  15. *
  16. * Created on: Apr 28, 2013
  17. * Author: xaxaxa
  18. */
  19. #ifndef HTTPPARSER_H_
  20. #define HTTPPARSER_H_
  21. #include <cpoll/cpoll.H>
  22. #include "headercontainer.H"
  23. #define CPPSP_MAXHEADERS 32
  24. namespace cppsp
  25. {
  26. using namespace CP;
  27. struct HTTPParser: public virtual RGC::Object
  28. {
  29. static inline char tolower(char c) {
  30. if (c <= 'Z' && c >= 'A') c = c - 'A' + 'a';
  31. return c;
  32. }
  33. //s2 must be all lowercase!!!!!
  34. static bool ci_equals(String s1, String s2) {
  35. if (s1.length() != s2.length()) return false;
  36. if (s1.length() == 0) return true;
  37. for (int i = 0; i < s1.length(); i++) {
  38. if (tolower(s1.data()[i]) != s2.data()[i]) return false;
  39. }
  40. return true;
  41. }
  42. headerContainer* hc;
  43. MemoryStream ms;
  44. String content;
  45. String reqLine;
  46. Delegate<bool()> state;
  47. int pos;
  48. int rpos;
  49. int _ctLen;
  50. int reqLine_i;
  51. int headerpos[CPPSP_MAXHEADERS];
  52. int headercount = 0;
  53. bool firstLine = true;
  54. HTTPParser(headerContainer* hc) :
  55. hc(hc), ms(8192), pos(0), rpos(0), _ctLen(0) {
  56. state= {&HTTPParser::_process_readingHeaders,this};
  57. }
  58. String beginPutData(int len) {
  59. if (ms.bufferSize - ms.bufferPos < len) ms.flushBuffer(len);
  60. return {(char*)ms.buffer + ms.bufferPos,ms.bufferSize-ms.bufferPos};
  61. }
  62. void endPutData(int len) {
  63. ms.bufferPos += len;
  64. ms.flush();
  65. }
  66. static inline char* findCRLF(const void* s, int len) {
  67. char* tmp = (char*) memchr(s, '\r', len);
  68. if (unlikely(tmp == NULL || tmp >= ((char*) s + len))) return NULL;
  69. if (tmp[1] == '\n') return tmp;
  70. else return (char*) memmem(tmp + 1, (char*) s + len - tmp - 1, "\r\n", 2);
  71. }
  72. bool _process_readingHeaders() {
  73. uint8_t* buf = ms.data();
  74. aaaaa: void* tmp = findCRLF(buf + rpos, ms.length() - rpos);
  75. if (tmp == NULL) {
  76. //minus one to catch any delimiters that might be cut off
  77. //in the middle
  78. if (rpos < ms.length() - 1) rpos = ms.length() - 1;
  79. return false;
  80. }
  81. int newpos = ((uint8_t*) tmp) - buf;
  82. //line: (buf+pos, newpos-pos)
  83. uint8_t* lineBuf = buf + pos;
  84. int lineBufLen = newpos - pos;
  85. if (firstLine) {
  86. reqLine.len = newpos - pos;
  87. reqLine_i = pos;
  88. firstLine = false;
  89. } else {
  90. if (lineBufLen == 0) {
  91. auto* items=hc->beginReplace(headercount);
  92. for(int i=0;i<headercount;i++) {
  93. int pos1=headerpos[i];
  94. int end=(i+1<headercount?headerpos[i+1]:this->pos)-2;
  95. lineBuf=buf+pos1;
  96. lineBufLen=end-pos1;
  97. tmp = memchr(lineBuf, ':', lineBufLen);
  98. if (tmp == NULL) {
  99. *(items++)= {(char*)lineBuf,(char*)NULL,lineBufLen,0};
  100. } else {
  101. headerContainer::item it;
  102. uint8_t* tmp1 = (uint8_t*) tmp - 1;
  103. while (tmp1 >= lineBuf && *tmp1 == ' ') tmp1--;
  104. it.name = (char*)lineBuf;
  105. it.nameLength = (int) (tmp1 - lineBuf + 1);
  106. tmp1 = (uint8_t*) tmp + 1;
  107. while (tmp1 < (buf + newpos) && *tmp1 == ' ') tmp1++;
  108. it.value = (char*)tmp1;
  109. it.valueLength = (int) (lineBuf + lineBufLen - tmp1);
  110. if (_ctLen == 0
  111. && ci_equals( {(char*) lineBuf, it.nameLength}, "content-length")) {
  112. _ctLen = atoi( {(char*) tmp1, it.valueLength});
  113. }
  114. *(items++)=it;
  115. }
  116. }
  117. hc->endReplace();
  118. rpos = pos = newpos + 2;
  119. state = {&HTTPParser::_process_readingContent,this};
  120. return _process_readingContent();
  121. }
  122. if(headercount>=CPPSP_MAXHEADERS) goto skipheader;
  123. headerpos[headercount++]=pos;
  124. skipheader:;
  125. }
  126. rpos = pos = newpos + 2;
  127. goto aaaaa;
  128. }
  129. bool _process_readingContent() {
  130. uint8_t* buf = ms.data();
  131. if (ms.length() - pos < _ctLen) return false;
  132. content= {(char*)buf+pos,_ctLen};
  133. pos += _ctLen;
  134. rpos = pos;
  135. _ctLen = 0;
  136. state = {&HTTPParser::_process_readingHeaders,this};
  137. firstLine = true;
  138. headercount=0;
  139. reqLine.d = (char*) buf + reqLine_i;
  140. return true;
  141. }
  142. //returns whether or not a complete http request was found
  143. //headers will be added to *hc, and content will be set to point
  144. //to any content received
  145. //note: *hc may be modified even when it returns false
  146. inline bool process() {
  147. if (pos >= ms.length()) return false;
  148. return state();
  149. }
  150. inline String getBufferData() {
  151. return {(char*)ms.buffer + pos, ms.length() - pos};
  152. }
  153. inline String getHistory(bool includeUnprocessed = true) {
  154. return {(char*)ms.buffer, includeUnprocessed ? ms.length() : pos};
  155. }
  156. void skip(int length) {
  157. pos+=length;
  158. if(rpos<pos)rpos=pos;
  159. }
  160. //free up buffer space
  161. void reset() {
  162. if (pos > 0) {
  163. int shift=firstLine?pos:reqLine_i;
  164. if (ms.length() - shift > 0) memmove(ms.buffer, ms.buffer + shift, ms.length() - shift);
  165. ms.len -= shift;
  166. rpos -= shift;
  167. pos -= shift;
  168. ms.bufferPos = ms.len;
  169. }
  170. }
  171. };
  172. class HTTPStream: public CP::Stream
  173. {
  174. public:
  175. HTTPParser* parser;
  176. Stream* stream;
  177. int32_t tryFixRead(void* buf, int32_t len) {
  178. int& bufPos = parser->pos;
  179. int bufLen = parser->ms.length();
  180. if (bufPos >= bufLen) return -1;
  181. int32_t l = len > (bufLen - bufPos) ? (bufLen - bufPos) : len;
  182. if (l <= 0) return 0;
  183. memcpy(buf, parser->ms.buffer + bufPos, l);
  184. bufPos += l;
  185. if (parser->rpos < bufPos) parser->rpos = bufPos;
  186. return l;
  187. }
  188. int32_t read(void* buf, int32_t len) {
  189. int32_t r;
  190. if ((r = tryFixRead(buf, len)) == -1) return stream->read(buf, len);
  191. else return r;
  192. }
  193. int32_t write(const void* buf, int32_t len) {
  194. return stream->write(buf, len);
  195. }
  196. void read(void* buf, int32_t len, const Callback& cb, bool repeat = false) {
  197. int32_t r;
  198. if ((r = tryFixRead(buf, len)) == -1) stream->read(buf, len, cb, repeat);
  199. else {
  200. cb(r);
  201. if (repeat && r > 0) stream->read(buf, len, cb, true);
  202. }
  203. }
  204. void write(const void* buf, int32_t len, const Callback& cb, bool repeat = false) override {
  205. stream->write(buf, len, cb, repeat);
  206. }
  207. //sync
  208. void close() override {
  209. }
  210. void flush() override {
  211. stream->flush();
  212. }
  213. //async
  214. void close(const Callback& cb) override {
  215. }
  216. void flush(const Callback& cb) override {
  217. stream->flush(cb);
  218. }
  219. void cancelRead() override {
  220. stream->cancelRead();
  221. }
  222. void cancelWrite() override {
  223. stream->cancelWrite();
  224. }
  225. int32_t readBuffer(void*& buf, int32_t maxlen) override {
  226. int& bufPos = parser->pos;
  227. int bufLen = parser->ms.length();
  228. if (bufPos >= bufLen) return 0;
  229. if (bufLen - bufPos < maxlen) maxlen = bufLen - bufPos;
  230. buf = parser->ms.buffer + bufPos;
  231. return maxlen;
  232. }
  233. void freeBuffer(void* buf, int32_t len) override {
  234. int& bufPos = parser->pos;
  235. bufPos += len;
  236. if (parser->rpos < bufPos) parser->rpos = bufPos;
  237. }
  238. };
  239. }
  240. #endif /* HTTPPARSER_H_ */