REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
aWOT.cpp
Go to the documentation of this file.
1/*
2 aWOT, Express.js inspired microcontreller web framework for the Web of Things
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21*/
22
23#include "web/aWOT.h"
24
25FLASHMEM Response::Response(net::EthernetClient *client, uint8_t *writeBuffer, int writeBufferLength)
26 : m_stream(client), m_headers(), m_contentLenghtSet(false), m_contentTypeSet(false), m_keepAlive(false),
27 m_statusSent(0), m_headersSent(false), m_sendingStatus(false), m_sendingHeaders(false),
28 m_headersCount(0), m_bytesSent(0), m_ended(false), m_buffer(writeBuffer),
29 m_bufferLength(writeBufferLength), m_bufFill(0) {}
30
31FLASHMEM int Response::availableForWrite() { return SERVER_OUTPUT_BUFFER_SIZE - m_bufFill - 1; }
32
33FLASHMEM void Response::beginHeaders() {
34 if (!m_statusSent) {
35 status(200);
36 }
37
38 m_sendingHeaders = true;
39
40 P(headerSeprator) = ": ";
41 for (int i = 0; i < m_headersCount; i++) {
42 print(m_headers[i].name);
43 printP(headerSeprator);
44 print(m_headers[i].value);
45 m_printCRLF();
46 }
47}
48
49FLASHMEM int Response::bytesSent() { return m_bytesSent; }
50
51FLASHMEM void Response::end() { m_ended = true; }
52
53FLASHMEM void Response::endHeaders() {
54 m_printCRLF();
55 m_flushBuf();
56 m_sendingHeaders = false;
57 m_headersSent = true;
58}
59
60FLASHMEM bool Response::ended() { return m_ended; }
61
62FLASHMEM void Response::flush() {
63 m_flushBuf();
64
65 m_stream->flush();
66}
67
68FLASHMEM const char *Response::get(const char *name) {
69 for (int i = 0; i < m_headersCount; i++) {
70 if (Application::strcmpi(name, m_headers[i].name) == 0) {
71 return m_headers[m_headersCount].value;
72 }
73 }
74
75 return NULL;
76}
77
78FLASHMEM bool Response::headersSent() { return m_headersSent; }
79
80FLASHMEM void Response::printP(const unsigned char *string) {
81 if (m_shouldPrintHeaders()) {
82 m_printHeaders();
83 }
84
85 while (uint8_t value = pgm_read_byte(string++)) {
86 write(value);
87 }
88}
89
90FLASHMEM void Response::printP(const char *string) { printP((unsigned char *)string); }
91
92FLASHMEM void Response::sendStatus(int code) {
93 status(code);
94
95 m_printHeaders();
96
97 if (code != 204 && code != 304) {
98 m_printStatus(code);
99 }
100}
101
102FLASHMEM void Response::set(const char *name, const char *value) {
103 if (m_headersCount >= SERVER_MAX_HEADERS) {
104 return;
105 }
106
107 m_headers[m_headersCount].name = name;
108 m_headers[m_headersCount].value = value;
109 m_headersCount++;
110
111 P(contentType) = "Content-Type";
112 if (Application::strcmpiP(name, contentType) == 0) {
113 m_contentTypeSet = true;
114 }
115
116 P(contentLength) = "Content-Length";
117 if (Application::strcmpiP(name, contentLength) == 0) {
118 m_contentLenghtSet = true;
119 }
120
121 P(connection) = "Connection";
122 if (Application::strcmpiP(name, connection) == 0) {
123 P(keepAlive) = "keep-alive";
124 m_keepAlive = Application::strcmpiP(value, keepAlive) == 0;
125 }
126}
127
128FLASHMEM void Response::setDefaults() {
129 if (!m_contentTypeSet) {
130 set("Content-Type", "text/plain");
131 }
132
133 if (m_keepAlive && !m_contentLenghtSet) {
134 set("Transfer-Encoding", "chunked");
135 }
136
137 if (!m_keepAlive) {
138 m_contentLenghtSet = true;
139 set("Connection", "close");
140 }
141}
142
143FLASHMEM void Response::status(int code) {
144 if (m_statusSent) {
145 return;
146 }
147
148 m_statusSent = code;
149
150 m_sendingStatus = true;
151 P(httpVersion) = "HTTP/1.1 ";
152 printP(httpVersion);
153 print(code);
154 P(space) = " ";
155 printP(space);
156 m_printStatus(code);
157
158 m_printCRLF();
159
160 if (code < 200) {
161 beginHeaders();
162 endHeaders();
163 m_statusSent = 0;
164 } else if (code == 204 || code == 304) {
165 m_contentLenghtSet = true;
166 m_contentTypeSet = true;
167 }
168
169 m_sendingStatus = false;
170}
171
172FLASHMEM int Response::statusSent() { return m_statusSent; }
173
174FLASHMEM size_t Response::write(uint8_t data) {
175 if (m_shouldPrintHeaders()) {
176 m_printHeaders();
177 }
178
179 m_buffer[m_bufFill++] = data;
180
181 if (m_bufFill == SERVER_OUTPUT_BUFFER_SIZE) {
182 if (m_headersSent && !m_contentLenghtSet) {
183 // m_stream->print(m_bufFill, HEX); // never mess in output around like that.
184 // m_stream->print(CRLF);
185 }
186
187 m_stream->writeFully(m_buffer, SERVER_OUTPUT_BUFFER_SIZE);
188
189 if (m_headersSent && !m_contentLenghtSet) {
190 m_stream->print(CRLF);
191 }
192
193 m_bufFill = 0;
194 }
195
196 size_t bytesSent = sizeof(data);
197 m_bytesSent += bytesSent;
198 return bytesSent;
199}
200
201FLASHMEM size_t Response::write(uint8_t *buffer, size_t bufferLength) {
202 if (m_shouldPrintHeaders()) {
203 m_printHeaders();
204 }
205
206 m_flushBuf();
207
208 if (m_headersSent && !m_contentLenghtSet) {
209 // m_stream->print(bufferLength, HEX); // don't mess in output like that
210 // m_stream->print(CRLF);
211 }
212
213 m_stream->writeFully(buffer, bufferLength);
214
215 if (m_headersSent && !m_contentLenghtSet) {
216 m_stream->print(CRLF);
217 }
218
219 m_bytesSent += bufferLength;
220 return bufferLength;
221}
222
223FLASHMEM void Response::writeP(const unsigned char *data, size_t length) {
224 if (m_shouldPrintHeaders()) {
225 m_printHeaders();
226 }
227
228 while (length--) {
229 write(pgm_read_byte(data++));
230 }
231}
232
233FLASHMEM void Response::m_printStatus(int code) {
234 switch (code) {
235#ifndef LOW_MEMORY_MCU
236 case 100: {
237 P(Continue) = "Continue";
238 printP(Continue);
239 break;
240 }
241 case 101: {
242 P(SwitchingProtocols) = "Switching Protocols";
243 printP(SwitchingProtocols);
244 break;
245 }
246 case 102: {
247 P(Processing) = "Processing";
248 printP(Processing);
249 break;
250 }
251 case 103: {
252 P(EarlyHints) = "Early Hints";
253 printP(EarlyHints);
254 break;
255 }
256 case 200: {
257 P(OK) = "OK";
258 printP(OK);
259 break;
260 }
261 case 201: {
262 P(Created) = "Created";
263 printP(Created);
264 break;
265 }
266 case 202: {
267 P(Accepted) = "Accepted";
268 printP(Accepted);
269 break;
270 }
271 case 203: {
272 P(NonAuthoritativeInformation) = "Non-Authoritative Information";
273 printP(NonAuthoritativeInformation);
274 break;
275 }
276 case 204: {
277 P(NoContent) = "No Content";
278 printP(NoContent);
279 break;
280 }
281 case 205: {
282 P(ResetContent) = "Reset Content";
283 printP(ResetContent);
284 break;
285 }
286 case 206: {
287 P(PartialContent) = "Partial Content";
288 printP(PartialContent);
289 break;
290 }
291 case 207: {
292 P(MultiStatus) = "Multi-Status";
293 printP(MultiStatus);
294 break;
295 }
296 case 208: {
297 P(AlreadyReported) = "Already Reported";
298 printP(AlreadyReported);
299 break;
300 }
301 case 226: {
302 P(IMUsed) = "IM Used";
303 printP(IMUsed);
304 break;
305 }
306 case 300: {
307 P(MultipleChoices) = "Multiple Choices";
308 printP(MultipleChoices);
309 break;
310 }
311 case 301: {
312 P(MovedPermanently) = "Moved Permanently";
313 printP(MovedPermanently);
314 break;
315 }
316 case 302: {
317 P(Found) = "Found";
318 printP(Found);
319 break;
320 }
321 case 303: {
322 P(SeeOther) = "See Other";
323 printP(SeeOther);
324 break;
325 }
326 case 304: {
327 P(NotModified) = "Not Modified";
328 printP(NotModified);
329 break;
330 }
331 case 305: {
332 P(UseProxy) = "Use Proxy";
333 printP(UseProxy);
334 break;
335 }
336 case 306: {
337 P(Unused) = "(Unused)";
338 printP(Unused);
339 break;
340 }
341 case 307: {
342 P(TemporaryRedirect) = "Temporary Redirect";
343 printP(TemporaryRedirect);
344 break;
345 }
346 case 308: {
347 P(PermanentRedirect) = "Permanent Redirect";
348 printP(PermanentRedirect);
349 break;
350 }
351 case 400: {
352 P(BadRequest) = "Bad Request";
353 printP(BadRequest);
354 break;
355 }
356 case 401: {
357 P(Unauthorized) = "Unauthorized";
358 printP(Unauthorized);
359 break;
360 }
361 case 402: {
362 P(PaymentRequired) = "Payment Required";
363 printP(PaymentRequired);
364 break;
365 }
366 case 403: {
367 P(Forbidden) = "Forbidden";
368 printP(Forbidden);
369 break;
370 }
371 case 404: {
372 P(NotFound) = "Not Found";
373 printP(NotFound);
374 break;
375 }
376 case 405: {
377 P(MethodNotAllowed) = "Method Not Allowed";
378 printP(MethodNotAllowed);
379 break;
380 }
381 case 406: {
382 P(NotAcceptable) = "Not Acceptable";
383 printP(NotAcceptable);
384 break;
385 }
386 case 407: {
387 P(ProxyAuthenticationRequired) = "Proxy Authentication Required";
388 printP(ProxyAuthenticationRequired);
389 break;
390 }
391 case 408: {
392 P(RequestTimeout) = "Request Timeout";
393 printP(RequestTimeout);
394 break;
395 }
396 case 409: {
397 P(Conflict) = "Conflict";
398 printP(Conflict);
399 break;
400 }
401 case 410: {
402 P(Gone) = "Gone";
403 printP(Gone);
404 break;
405 }
406 case 411: {
407 P(LengthRequired) = "Length Required";
408 printP(LengthRequired);
409 break;
410 }
411 case 412: {
412 P(PreconditionFailed) = "Precondition Failed";
413 printP(PreconditionFailed);
414 break;
415 }
416 case 413: {
417 P(PayloadTooLarge) = "Payload Too Large";
418 printP(PayloadTooLarge);
419 break;
420 }
421 case 414: {
422 P(URITooLong) = "URI Too Long";
423 printP(URITooLong);
424 break;
425 }
426 case 415: {
427 P(UnsupportedMediaType) = "Unsupported Media Type";
428 printP(UnsupportedMediaType);
429 break;
430 }
431 case 416: {
432 P(RangeNotSatisfiable) = "Range Not Satisfiable";
433 printP(RangeNotSatisfiable);
434 break;
435 }
436 case 417: {
437 P(ExpectationFailed) = "Expectation Failed";
438 printP(ExpectationFailed);
439 break;
440 }
441 case 421: {
442 P(MisdirectedRequest) = "Misdirected Request";
443 printP(MisdirectedRequest);
444 break;
445 }
446 case 422: {
447 P(UnprocessableEntity) = "Unprocessable Entity";
448 printP(UnprocessableEntity);
449 break;
450 }
451 case 423: {
452 P(Locked) = "Locked";
453 printP(Locked);
454 break;
455 }
456 case 424: {
457 P(FailedDependency) = "Failed Dependency";
458 printP(FailedDependency);
459 break;
460 }
461 case 425: {
462 P(TooEarly) = "Too Early";
463 printP(TooEarly);
464 break;
465 }
466 case 426: {
467 P(UpgradeRequired) = "Upgrade Required";
468 printP(UpgradeRequired);
469 break;
470 }
471 case 428: {
472 P(PreconditionRequired) = "Precondition Required";
473 printP(PreconditionRequired);
474 break;
475 }
476 case 429: {
477 P(TooManyRequests) = "Too Many Requests";
478 printP(TooManyRequests);
479 break;
480 }
481 case 431: {
482 P(RequestHeaderFieldsTooLarge) = "Request Header Fields Too Large";
483 printP(RequestHeaderFieldsTooLarge);
484 break;
485 }
486 case 451: {
487 P(UnavailableForLegalReasons) = "Unavailable For Legal Reasons";
488 printP(UnavailableForLegalReasons);
489 break;
490 }
491 case 500: {
492 P(InternalServerError) = "Internal Server Error";
493 printP(InternalServerError);
494 break;
495 }
496 case 501: {
497 P(NotImplemented) = "Not Implemented";
498 printP(NotImplemented);
499 break;
500 }
501 case 502: {
502 P(BadGateway) = "Bad Gateway";
503 printP(BadGateway);
504 break;
505 }
506 case 503: {
507 P(ServiceUnavailable) = "Service Unavailable";
508 printP(ServiceUnavailable);
509 break;
510 }
511 case 504: {
512 P(GatewayTimeout) = "Gateway Timeout";
513 printP(GatewayTimeout);
514 break;
515 }
516 case 505: {
517 P(HTTPVersionNotSupported) = "HTTP Version Not Supported";
518 printP(HTTPVersionNotSupported);
519 break;
520 }
521 case 506: {
522 P(VariantAlsoNegotiates) = "Variant Also Negotiates";
523 printP(VariantAlsoNegotiates);
524 break;
525 }
526 case 507: {
527 P(InsufficientStorage) = "Insufficient Storage";
528 printP(InsufficientStorage);
529 break;
530 }
531 case 508: {
532 P(LoopDetected) = "Loop Detected";
533 printP(LoopDetected);
534 break;
535 }
536 case 510: {
537 P(NotExtended) = "Not Extended";
538 printP(NotExtended);
539 break;
540 }
541 case 511: {
542 P(NetworkAuthenticationRequired) = "Network Authentication Required";
543 printP(NetworkAuthenticationRequired);
544 break;
545 }
546#else
547 case 200: {
548 P(OK) = "OK";
549 printP(OK);
550 break;
551 }
552 case 201: {
553 P(Created) = "Created";
554 printP(Created);
555 break;
556 }
557 case 202: {
558 P(Accepted) = "Accepted";
559 printP(Accepted);
560 break;
561 }
562 case 204: {
563 P(NoContent) = "No Content";
564 printP(NoContent);
565 break;
566 }
567 case 303: {
568 P(SeeOther) = "See Other";
569 printP(SeeOther);
570 break;
571 }
572 case 304: {
573 P(NotModified) = "Not Modified";
574 printP(NotModified);
575 break;
576 }
577 case 400: {
578 P(BadRequest) = "Bad Request";
579 printP(BadRequest);
580 break;
581 }
582 case 401: {
583 P(Unauthorized) = "Unauthorized";
584 printP(Unauthorized);
585 break;
586 }
587 case 402: {
588 P(PaymentRequired) = "Payment Required";
589 printP(PaymentRequired);
590 break;
591 }
592 case 403: {
593 P(Forbidden) = "Forbidden";
594 printP(Forbidden);
595 break;
596 }
597 case 404: {
598 P(NotFound) = "Not Found";
599 printP(NotFound);
600 break;
601 }
602 case 405: {
603 P(MethodNotAllowed) = "Method Not Allowed";
604 printP(MethodNotAllowed);
605 break;
606 }
607 case 406: {
608 P(NotAcceptable) = "Not Acceptable";
609 printP(NotAcceptable);
610 break;
611 }
612 case 407: {
613 P(ProxyAuthenticationRequired) = "Proxy Authentication Required";
614 printP(ProxyAuthenticationRequired);
615 break;
616 }
617 case 408: {
618 P(RequestTimeout) = "Request Timeout";
619 printP(RequestTimeout);
620 break;
621 }
622
623 case 431: {
624 P(RequestHeaderFieldsTooLarge) = "Request Header Fields Too Large";
625 printP(RequestHeaderFieldsTooLarge);
626 break;
627 }
628 case 500: {
629 P(InternalServerError) = "Internal Server Error";
630 printP(InternalServerError);
631 break;
632 }
633 case 505: {
634 P(HTTPVersionNotSupported) = "HTTP Version Not Supported";
635 printP(HTTPVersionNotSupported);
636 break;
637 }
638#endif
639 default: {
640 print(code);
641 break;
642 }
643 }
644}
645
646FLASHMEM bool Response::m_shouldPrintHeaders() {
647 return (!m_headersSent && !m_sendingHeaders && !m_sendingStatus);
648}
649
650FLASHMEM void Response::m_printHeaders() {
651 setDefaults();
652 beginHeaders();
653 endHeaders();
654}
655
656FLASHMEM void Response::m_printCRLF() { print(CRLF); }
657
658FLASHMEM void Response::m_flushBuf() {
659 if (m_bufFill > 0) {
660 if (m_headersSent && !m_contentLenghtSet) {
661 // m_stream->print(m_bufFill, HEX); // do the fucking not mess in my lovely output, aWOT.
662 // m_stream->print(CRLF);
663 }
664
665 m_stream->writeFully(m_buffer, m_bufFill);
666
667 if (m_headersSent && !m_contentLenghtSet) {
668 m_stream->print(CRLF);
669 }
670
671 m_bufFill = 0;
672 };
673}
674
675FLASHMEM void Response::m_finalize() {
676 m_flushBuf();
677
678 if (m_headersSent && !m_contentLenghtSet) {
679 // m_stream->print(0, HEX); // leave me alone! please!
680 // m_stream->print(CRLF);
681 // m_stream->print(CRLF);
682 }
683}
684
685FLASHMEM Request::Request(net::EthernetClient *client, Response *m_response, HeaderNode *headerTail,
686 char *urlBuffer, int urlBufferLength, unsigned long timeout, void *context)
687 : context(context), m_stream(client), m_response(m_response), m_method(UNKNOWN), m_minorVersion(-1),
688 m_pushback(), m_pushbackDepth(0), m_readingContent(false), m_left(0), m_bytesRead(0),
689 m_headerTail(headerTail), m_query(NULL), m_queryLength(0), m_readTimedout(false), m_path(urlBuffer),
690 m_pathLength(urlBufferLength - 1), m_pattern(NULL), m_route(NULL) {
691 _timeout = timeout;
692}
693
694FLASHMEM int Request::availableForWrite() { return m_response->availableForWrite(); }
695
696FLASHMEM int Request::available() { return std::min(m_stream->available(), m_left + m_pushbackDepth); }
697
698FLASHMEM int Request::bytesRead() { return m_bytesRead; }
699
700FLASHMEM Stream *Request::stream() { return m_stream; }
701
702FLASHMEM char *Request::get(const char *name) {
703 HeaderNode *headerNode = m_headerTail;
704
705 while (headerNode != NULL) {
706 if (Application::strcmpi(headerNode->name, name) == 0) {
707 return headerNode->buffer;
708 }
709
710 headerNode = headerNode->next;
711 }
712
713 return NULL;
714}
715
716FLASHMEM void Request::flush() { return m_response->flush(); }
717
718FLASHMEM bool Request::form(char *name, int nameLength, char *value, int valueLength) {
719 int ch;
720 bool foundSomething = false;
721 bool readingName = true;
722
723 memset(name, 0, nameLength);
724 memset(value, 0, valueLength);
725
726 while ((ch = m_timedRead()) != -1) {
727 foundSomething = true;
728 if (ch == '+') {
729 ch = ' ';
730 } else if (ch == '=') {
731 readingName = false;
732 continue;
733 } else if (ch == '&') {
734 return nameLength > 0 && valueLength > 0;
735 } else if (ch == '%') {
736 int high = m_timedRead();
737 if (high == -1) {
738 return false;
739 }
740
741 int low = m_timedRead();
742 if (low == -1) {
743 return false;
744 }
745
746 if (high > 0x39) {
747 high -= 7;
748 }
749
750 high &= 0x0f;
751
752 if (low > 0x39) {
753 low -= 7;
754 }
755
756 low &= 0x0f;
757
758 ch = (high << 4) | low;
759 }
760
761 if (readingName && --nameLength) {
762 *name++ = ch;
763 } else if (!readingName && --valueLength) {
764 *value++ = ch;
765 }
766 }
767
768 return foundSomething && nameLength > 0 && valueLength > 0;
769}
770
771FLASHMEM int Request::left() { return m_left + m_pushbackDepth; }
772
773FLASHMEM Request::MethodType Request::method() { return m_method; }
774
775FLASHMEM char *Request::path() { return m_path; }
776
777FLASHMEM int Request::peek() {
778 int ch = read();
779
780 if (ch != -1) {
781 push(ch);
782 }
783
784 return ch;
785}
786
787FLASHMEM void Request::push(uint8_t ch) {
788 m_pushback[m_pushbackDepth++] = ch;
789
790 // can't raise error here, so just replace last char over and over
791 if (m_pushbackDepth == SERVER_PUSHBACK_BUFFER_SIZE) {
792 m_pushbackDepth = SERVER_PUSHBACK_BUFFER_SIZE - 1;
793 }
794}
795
796FLASHMEM char *Request::query() { return m_query; }
797
798FLASHMEM bool Request::query(const char *name, char *buffer, int bufferLength) {
799 memset(buffer, 0, bufferLength);
800
801 char *position = m_query;
802 int nameLength = strlen(name);
803
804 while ((position = strstr(position, name))) {
805 char previous = *(position - 1);
806
807 if ((previous == '\0' || previous == '&') && *(position + nameLength) == '=') {
808 position = position + nameLength + 1;
809 while (*position && *position != '&' && --bufferLength) {
810 *buffer++ = *position++;
811 }
812
813 return bufferLength > 0;
814 }
815
816 position++;
817 }
818
819 return false;
820}
821
822int Request::read() {
823 if (m_pushbackDepth > 0) {
824 return m_pushback[--m_pushbackDepth];
825 }
826
827 if (m_readingContent && !m_left) {
828 _timeout = 0;
829 return -1;
830 }
831
832 int ch = m_stream->read();
833 if (ch == -1) {
834 return -1;
835 }
836
837 if (m_readingContent) {
838 m_left--;
839 }
840
841 m_bytesRead++;
842 return ch;
843}
844
845int Request::read(uint8_t *buf, size_t size) {
846 int ret = 0;
847
848 while (m_pushbackDepth > 0) {
849 *buf++ = m_pushback[--m_pushbackDepth];
850 size--;
851 ret++;
852 }
853
854 int read = m_stream->read(buf, (size < (unsigned)m_left ? size : m_left));
855 if (read == -1) {
856 if (ret > 0) {
857 return ret;
858 }
859
860 return -1;
861 }
862
863 ret += read;
864 m_bytesRead += read;
865 m_left -= read;
866
867 return ret;
868}
869
870FLASHMEM bool Request::route(const char *name, char *buffer, int bufferLength) {
871 int part = 0;
872 int i = 1;
873
874 while (m_pattern[i]) {
875 if (m_pattern[i] == '/') {
876 part++;
877 }
878
879 if (m_pattern[i++] == ':') {
880 int j = 0;
881
882 while ((m_pattern[i] && name[j]) && m_pattern[i] == name[j]) {
883 i++;
884 j++;
885 }
886
887 if (!name[j] && (m_pattern[i] == '/' || !m_pattern[i])) {
888 return route(part, buffer, bufferLength);
889 }
890 }
891 }
892
893 return false;
894}
895
896FLASHMEM bool Request::route(int number, char *buffer, int bufferLength) {
897 memset(buffer, 0, bufferLength);
898 int part = -1;
899 const char *routeStart = m_route;
900
901 while (*routeStart) {
902 if (*routeStart++ == '/') {
903 part++;
904
905 if (part == number) {
906 while (*routeStart && *routeStart != '/' && --bufferLength) {
907 *buffer++ = *routeStart++;
908 }
909
910 return bufferLength > 0;
911 }
912 }
913 }
914
915 return false;
916}
917
918FLASHMEM int Request::minorVersion() { return m_minorVersion; }
919
920FLASHMEM size_t Request::write(uint8_t data) { return m_response->write(data); }
921
922FLASHMEM size_t Request::write(uint8_t *buffer, size_t bufferLength) {
923 return m_response->write(buffer, bufferLength);
924}
925
926FLASHMEM bool Request::m_processMethod() {
927 P(GET_VERB) = "GET ";
928 P(HEAD_VERB) = "HEAD ";
929 P(POST_VERB) = "POST ";
930 P(PUT_VERB) = "PUT ";
931 P(DELETE_VERB) = "DELETE ";
932 P(PATCH_VERB) = "PATCH ";
933 P(OPTIONS_VERB) = "OPTIONS ";
934
935 if (m_expectP(GET_VERB)) {
936 m_method = GET;
937 } else if (m_expectP(HEAD_VERB)) {
938 m_method = HEAD;
939 } else if (m_expectP(POST_VERB)) {
940 m_method = POST;
941 } else if (m_expectP(PUT_VERB)) {
942 m_method = PUT;
943 } else if (m_expectP(DELETE_VERB)) {
944 m_method = DELETE;
945 } else if (m_expectP(PATCH_VERB)) {
946 m_method = PATCH;
947 } else if (m_expectP(OPTIONS_VERB)) {
948 m_method = OPTIONS;
949 } else {
950 return false;
951 }
952
953 return true;
954}
955
956FLASHMEM bool Request::m_readURL() {
957 char *request = m_path;
958 int bufferLeft = m_pathLength;
959 int ch;
960
961 while ((ch = m_timedRead()) != -1 && ch != ' ' && ch != '\n' && ch != '\r' && --bufferLeft) {
962 if (ch == '%') {
963 int high = m_timedRead();
964 if (high == -1) {
965 return false;
966 }
967
968 int low = m_timedRead();
969 if (low == -1) {
970 return false;
971 }
972
973 if (high > 0x39) {
974 high -= 7;
975 }
976
977 high &= 0x0f;
978
979 if (low > 0x39) {
980 low -= 7;
981 }
982
983 low &= 0x0f;
984
985 ch = (high << 4) | low;
986 }
987
988 *request++ = ch;
989 }
990
991 *request = 0;
992
993 return bufferLeft > 0;
994}
995
996FLASHMEM bool Request::m_readVersion() {
997 while (!m_expect(CRLF)) {
998 P(HTTP_10) = "1.0";
999 P(HTTP_11) = "1.1";
1000
1001 if (m_expectP(HTTP_10)) {
1002 m_minorVersion = 0;
1003 } else if (m_expectP(HTTP_11)) {
1004 m_minorVersion = 1;
1005 } else if (m_timedRead() == -1) {
1006 return false;
1007 }
1008 }
1009
1010 return true;
1011}
1012
1013FLASHMEM void Request::m_processURL() {
1014 char *qmLocation = strchr(m_path, '?');
1015 int qmOffset = (qmLocation == NULL) ? 0 : 1;
1016
1017 m_pathLength = (qmLocation == NULL) ? strlen(m_path) : (qmLocation - m_path);
1018 m_query = m_path + m_pathLength + qmOffset;
1019 m_queryLength = strlen(m_query);
1020
1021 if (qmOffset) {
1022 *qmLocation = 0;
1023 }
1024}
1025
1026FLASHMEM bool Request::m_processHeaders() {
1027 bool canEnd = true;
1028
1029 while (!(canEnd && m_expect(CRLF))) {
1030 canEnd = false;
1031 P(ContentLength) = "Content-Length:";
1032 if (m_expectP(ContentLength)) {
1033 if (!m_readInt(m_left) || !m_expect(CRLF)) {
1034 return false;
1035 }
1036
1037 canEnd = true;
1038 } else {
1039 HeaderNode *headerNode = m_headerTail;
1040
1041 while (headerNode != NULL) {
1042 P(headerSeparator) = ":";
1043 if (m_expect(headerNode->name) && m_expectP(headerSeparator)) {
1044 if (!m_headerValue(headerNode->buffer, headerNode->bufferLength)) {
1045 return false;
1046 }
1047
1048 canEnd = true;
1049 break;
1050 }
1051
1052 headerNode = headerNode->next;
1053 }
1054 }
1055
1056 if (!canEnd) {
1057 while (!m_expect(CRLF)) {
1058 if (m_timedRead() == -1) {
1059 return false;
1060 }
1061 }
1062
1063 canEnd = true;
1064 }
1065 }
1066
1067 m_readingContent = true;
1068
1069 return true;
1070}
1071
1072FLASHMEM bool Request::m_headerValue(char *buffer, int bufferLength) {
1073 int ch;
1074
1075 if (buffer[0] != '\0') {
1076 int length = strlen(buffer);
1077 buffer[length] = ',';
1078 buffer = buffer + length + 1;
1079 bufferLength = bufferLength - (length + 1);
1080 }
1081
1082 if (!m_skipSpace()) {
1083 return false;
1084 }
1085
1086 while ((ch = m_timedRead()) != -1) {
1087 if (--bufferLength > 0) {
1088 *buffer++ = ch;
1089 }
1090
1091 if (m_expect(CRLF)) {
1092 *buffer = '\0';
1093 return bufferLength > 0;
1094 }
1095 }
1096
1097 return false;
1098}
1099
1100FLASHMEM bool Request::m_readInt(int &number) {
1101 bool negate = false;
1102 bool gotNumber = false;
1103
1104 if (!m_skipSpace()) {
1105 return false;
1106 }
1107
1108 int ch = m_timedRead();
1109 if (ch == -1) {
1110 return false;
1111 }
1112
1113 if (ch == '-') {
1114 negate = true;
1115 ch = m_timedRead();
1116 if (ch == -1) {
1117 return false;
1118 }
1119 }
1120
1121 number = 0;
1122
1123 while (ch >= '0' && ch <= '9') {
1124 gotNumber = true;
1125 number = number * 10 + ch - '0';
1126 ch = m_timedRead();
1127 if (ch == -1) {
1128 return false;
1129 }
1130 }
1131
1132 push(ch);
1133
1134 if (negate) {
1135 number = -number;
1136 }
1137
1138 return gotNumber;
1139}
1140
1141FLASHMEM void Request::m_setRoute(const char *route, const char *pattern) {
1142 m_route = route;
1143 m_pattern = pattern;
1144}
1145
1146FLASHMEM int Request::m_getUrlPathLength() { return m_pathLength; }
1147
1148FLASHMEM bool Request::m_expect(const char *expected) {
1149 const char *candidate = expected;
1150
1151 while (*candidate != 0) {
1152 int ch = m_timedRead();
1153 if (ch == -1) {
1154 return false;
1155 }
1156
1157 if (tolower(ch) != tolower(*candidate++)) {
1158 push(ch);
1159
1160 while (--candidate != expected) {
1161 push(candidate[-1]);
1162 }
1163
1164 return false;
1165 }
1166 }
1167
1168 return true;
1169}
1170
1171FLASHMEM bool Request::m_expectP(const unsigned char *expected) {
1172 const unsigned char *candidate = expected;
1173
1174 while (pgm_read_byte(candidate) != 0) {
1175 int ch = m_timedRead();
1176 if (ch == -1) {
1177 return false;
1178 }
1179
1180 if (tolower(ch) != tolower(pgm_read_byte(candidate++))) {
1181 push(ch);
1182
1183 while (--candidate != expected) {
1184 push(pgm_read_byte(candidate - 1));
1185 }
1186
1187 return false;
1188 }
1189 }
1190
1191 return true;
1192}
1193
1194FLASHMEM bool Request::m_skipSpace() {
1195 int ch;
1196
1197 while ((ch = m_timedRead()) != -1 && (ch == ' ' || ch == '\t'))
1198 ;
1199
1200 if (ch == -1) {
1201 return false;
1202 }
1203
1204 push(ch);
1205
1206 return true;
1207}
1208
1209FLASHMEM void Request::m_reset() {
1210 HeaderNode *headerNode = m_headerTail;
1211 while (headerNode != NULL) {
1212 headerNode->buffer[0] = '\0';
1213 headerNode = headerNode->next;
1214 }
1215}
1216
1217FLASHMEM bool Request::m_timedout() { return m_readTimedout; }
1218
1219FLASHMEM int Request::m_timedRead() {
1220 // int ch = timedRead(); //TODO: not woriking native yet
1221 int ch = read();
1222 if (ch == -1) {
1223 m_readTimedout = true;
1224 }
1225
1226 return ch;
1227}
1228
1229FLASHMEM Router::Router() : m_head(NULL) {}
1230
1231FLASHMEM Router::~Router() {
1232 MiddlewareNode *current = m_head;
1233 MiddlewareNode *next;
1234
1235 while (current != NULL) {
1236 next = current->next;
1237 delete current;
1238
1239 current = next;
1240 }
1241
1242 m_head = NULL;
1243}
1244
1245FLASHMEM void Router::del(const char *path, MIDDLEWARE_PARAM middleware) {
1246 m_addMiddleware(Request::DELETE, path, middleware);
1247}
1248
1249FLASHMEM void Router::del(MIDDLEWARE_PARAM middleware) { del(NULL, middleware); }
1250
1251FLASHMEM void Router::get(const char *path, MIDDLEWARE_PARAM middleware) {
1252 m_addMiddleware(Request::GET, path, middleware);
1253}
1254
1255FLASHMEM void Router::get(MIDDLEWARE_PARAM middleware) { get(NULL, middleware); }
1256
1257FLASHMEM void Router::head(const char *path, MIDDLEWARE_PARAM middleware) {
1258 m_addMiddleware(Request::HEAD, path, middleware);
1259}
1260
1261FLASHMEM void Router::head(MIDDLEWARE_PARAM middleware) { head(NULL, middleware); }
1262
1263FLASHMEM void Router::options(const char *path, MIDDLEWARE_PARAM middleware) {
1264 m_addMiddleware(Request::OPTIONS, path, middleware);
1265}
1266
1267FLASHMEM void Router::options(MIDDLEWARE_PARAM middleware) { options(NULL, middleware); }
1268
1269FLASHMEM void Router::post(const char *path, MIDDLEWARE_PARAM middleware) {
1270 m_addMiddleware(Request::POST, path, middleware);
1271}
1272
1273FLASHMEM void Router::post(MIDDLEWARE_PARAM middleware) { post(NULL, middleware); }
1274
1275FLASHMEM void Router::put(const char *path, MIDDLEWARE_PARAM middleware) {
1276 m_addMiddleware(Request::PUT, path, middleware);
1277}
1278
1279FLASHMEM void Router::put(MIDDLEWARE_PARAM middleware) { put(NULL, middleware); }
1280
1281FLASHMEM void Router::patch(const char *path, MIDDLEWARE_PARAM middleware) {
1282 m_addMiddleware(Request::PATCH, path, middleware);
1283}
1284
1285FLASHMEM void Router::patch(MIDDLEWARE_PARAM middleware) { patch(NULL, middleware); }
1286
1287FLASHMEM void Router::use(const char *path, MIDDLEWARE_PARAM middleware) {
1288 m_addMiddleware(Request::ALL, path, middleware);
1289}
1290
1291FLASHMEM void Router::use(MIDDLEWARE_PARAM middleware) { use(NULL, middleware); }
1292
1293FLASHMEM void Router::use(const char *path, Router *router) {
1294 MiddlewareNode *tail = new MiddlewareNode();
1295 tail->path = path;
1296 tail->middleware = NULL;
1297 tail->router = router;
1298 tail->next = NULL;
1299 m_mountMiddleware(tail);
1300}
1301
1302FLASHMEM void Router::use(Router *router) { use(NULL, router); }
1303
1304FLASHMEM void Router::m_addMiddleware(Request::MethodType type, const char *path,
1305 MIDDLEWARE_PARAM middleware) {
1306 MiddlewareNode *tail = new MiddlewareNode();
1307 tail->path = path;
1308 tail->middleware = middleware;
1309 tail->router = NULL;
1310 tail->type = type;
1311 tail->next = NULL;
1312
1313 m_mountMiddleware(tail);
1314}
1315
1316FLASHMEM void Router::m_mountMiddleware(MiddlewareNode *tail) {
1317 if (m_head == NULL) {
1318 m_head = tail;
1319 } else {
1320 MiddlewareNode *current = m_head;
1321
1322 while (current->next != NULL) {
1323 current = current->next;
1324 }
1325
1326 current->next = tail;
1327 }
1328}
1329
1330FLASHMEM void Router::m_dispatchMiddleware(Request &request, Response &response, int urlShift) {
1331 MiddlewareNode *middleware = m_head;
1332
1333 while (middleware != NULL && !response.ended()) {
1334 if (middleware->router != NULL) {
1335 int prefixLength = middleware->path ? strlen(middleware->path) : 0;
1336 int shift = urlShift + prefixLength;
1337
1338 if (middleware->path == NULL ||
1339 strncmp(middleware->path, request.path() + urlShift, prefixLength) == 0) {
1340 middleware->router->m_dispatchMiddleware(request, response, shift);
1341 }
1342 } else if (middleware->type == request.method() || middleware->type == Request::ALL) {
1343 if (middleware->path == NULL || m_routeMatch(request.path() + urlShift, middleware->path)) {
1344 request.m_setRoute(request.path() + urlShift, middleware->path);
1345 middleware->middleware(request, response);
1346 }
1347 }
1348
1349 middleware = middleware->next;
1350 }
1351}
1352
1353FLASHMEM bool Router::m_routeMatch(const char *route, const char *pattern) {
1354 if (pattern[0] == '\0' && route[0] == '\0') {
1355 return true;
1356 }
1357
1358 bool match = false;
1359 int i = 0;
1360 int j = 0;
1361
1362 while (pattern[i] && route[j]) {
1363 if (pattern[i] == ':') {
1364 while (pattern[i] && pattern[i] != '/') {
1365 i++;
1366 }
1367
1368 while (route[j] && route[j] != '/') {
1369 j++;
1370 }
1371
1372 match = true;
1373 } else if (pattern[i] == route[j]) {
1374 j++;
1375 i++;
1376 match = true;
1377 } else {
1378 match = false;
1379 break;
1380 }
1381 }
1382
1383 if (match && !pattern[i] && route[j] == '/' && !route[i]) {
1384 match = true;
1385 } else if (pattern[i] || route[j]) {
1386 match = false;
1387 }
1388
1389 return match;
1390}
1391
1392FLASHMEM Application::Application() : m_final(NULL), m_notFound(NULL), m_headerTail(NULL), m_timeout(1000) {}
1393
1394FLASHMEM int Application::strcmpi(const char *s1, const char *s2) {
1395 int i;
1396
1397 for (i = 0; s1[i] && s2[i]; ++i) {
1398 if (s1[i] == s2[i] || (s1[i] ^ 32) == s2[i]) {
1399 continue;
1400 } else {
1401 break;
1402 }
1403 }
1404
1405 if (s1[i] == s2[i]) {
1406 return 0;
1407 }
1408
1409 if ((s1[i] | 32) < (s2[i] | 32)) {
1410 return -1;
1411 }
1412
1413 return 1;
1414}
1415
1416FLASHMEM int Application::strcmpiP(const char *s1, const unsigned char *s2) {
1417 int i = 0;
1418
1419 for (i = 0; s1[i] && pgm_read_byte(s2 + i); ++i) {
1420 if (s1[i] == pgm_read_byte(s2 + i) || (s1[i] ^ 32) == pgm_read_byte(s2 + i)) {
1421 continue;
1422 } else {
1423 break;
1424 }
1425 }
1426
1427 if (s1[i] == pgm_read_byte(s2 + i)) {
1428 return 0;
1429 }
1430
1431 if ((s1[i] | 32) < (pgm_read_byte(s2 + i) | 32)) {
1432 return -1;
1433 }
1434
1435 return 1;
1436}
1437
1438FLASHMEM Application::~Application() {
1439 Request::HeaderNode *current = m_headerTail;
1440 Request::HeaderNode *next;
1441
1442 while (current != NULL) {
1443 next = current->next;
1444 delete current;
1445 current = next;
1446 }
1447
1448 m_headerTail = NULL;
1449}
1450
1451FLASHMEM void Application::del(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1452 m_defaultRouter.m_addMiddleware(Request::DELETE, path, middleware);
1453}
1454
1455FLASHMEM void Application::del(Router::MIDDLEWARE_PARAM middleware) { del(NULL, middleware); }
1456
1457FLASHMEM void Application::finally(Router::MIDDLEWARE_PARAM final) { m_final = final; }
1458
1459FLASHMEM void Application::get(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1460 m_defaultRouter.m_addMiddleware(Request::GET, path, middleware);
1461}
1462
1463FLASHMEM void Application::get(Router::MIDDLEWARE_PARAM middleware) { get(NULL, middleware); }
1464
1465FLASHMEM void Application::head(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1466 m_defaultRouter.m_addMiddleware(Request::HEAD, path, middleware);
1467}
1468
1469FLASHMEM void Application::head(Router::MIDDLEWARE_PARAM middleware) { head(NULL, middleware); }
1470
1471FLASHMEM void Application::notFound(Router::MIDDLEWARE_PARAM notFound) { m_notFound = notFound; }
1472
1473FLASHMEM void Application::options(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1474 m_defaultRouter.m_addMiddleware(Request::OPTIONS, path, middleware);
1475}
1476
1477FLASHMEM void Application::options(Router::MIDDLEWARE_PARAM middleware) { options(NULL, middleware); }
1478
1479FLASHMEM void Application::patch(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1480 m_defaultRouter.m_addMiddleware(Request::PATCH, path, middleware);
1481}
1482
1483FLASHMEM void Application::patch(Router::MIDDLEWARE_PARAM middleware) { patch(NULL, middleware); }
1484
1485FLASHMEM void Application::post(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1486 m_defaultRouter.m_addMiddleware(Request::POST, path, middleware);
1487}
1488
1489FLASHMEM void Application::post(Router::MIDDLEWARE_PARAM middleware) { post(NULL, middleware); }
1490
1491FLASHMEM void Application::put(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1492 m_defaultRouter.m_addMiddleware(Request::PUT, path, middleware);
1493}
1494
1495FLASHMEM void Application::put(Router::MIDDLEWARE_PARAM middleware) { put(NULL, middleware); }
1496
1497FLASHMEM void Application::process(net::EthernetClient *client, void *context) {
1498 if (!client) {
1499 return;
1500 }
1501
1502 char urlBuffer[SERVER_URL_BUFFER_SIZE];
1503 process(client, urlBuffer, SERVER_URL_BUFFER_SIZE, context);
1504}
1505
1506FLASHMEM void Application::process(net::EthernetClient *client, char *urlBuffer, int urlBufferLength,
1507 void *context) {
1508 if (!client) {
1509 return;
1510 }
1511
1512 uint8_t writeBuffer[SERVER_OUTPUT_BUFFER_SIZE];
1513 process(client, urlBuffer, urlBufferLength, writeBuffer, SERVER_OUTPUT_BUFFER_SIZE, context);
1514}
1515
1516FLASHMEM void Application::process(net::EthernetClient *client, char *urlBuffer, int urlBufferLength,
1517 uint8_t *writeBuffer, int writeBufferLength, void *context) {
1518 if (!client) {
1519 return;
1520 }
1521
1522 Response response(client, writeBuffer, writeBufferLength);
1523 Request request(client, &response, m_headerTail, urlBuffer, urlBufferLength, m_timeout, context);
1524
1525 m_process(request, response);
1526
1527 if (m_final != NULL) {
1528 m_final(request, response);
1529 }
1530
1531 response.m_finalize();
1532
1533 Request::HeaderNode *headerNode = m_headerTail;
1534 while (headerNode != NULL) {
1535 headerNode->buffer[0] = '\0';
1536 headerNode = headerNode->next;
1537 }
1538}
1539
1540FLASHMEM void Application::process(Stream *stream, void *context) {
1541 if (!stream) {
1542 return;
1543 }
1544
1545 StreamClient client(stream);
1546 process(&client, context);
1547}
1548
1549FLASHMEM void Application::process(Stream *stream, char *buffer, int bufferLength, void *context) {
1550 if (!stream) {
1551 return;
1552 }
1553
1554 StreamClient client(stream);
1555 process(&client, buffer, bufferLength, context);
1556}
1557
1558FLASHMEM void Application::process(Stream *stream, char *urlBuffer, int urlBufferLength, uint8_t *writeBuffer,
1559 int writeBufferLength, void *context) {
1560 if (!stream) {
1561 return;
1562 }
1563
1564 StreamClient client(stream);
1565 process(&client, urlBuffer, urlBufferLength, writeBuffer, writeBufferLength, context);
1566}
1567
1568FLASHMEM void Application::use(const char *path, Router::MIDDLEWARE_PARAM middleware) {
1569 m_defaultRouter.m_addMiddleware(Request::ALL, path, middleware);
1570}
1571
1572FLASHMEM void Application::use(Router::MIDDLEWARE_PARAM middleware) { use(NULL, middleware); }
1573
1574FLASHMEM void Application::setTimeout(unsigned long timeoutMillis) { m_timeout = timeoutMillis; }
1575
1576FLASHMEM void Application::use(const char *path, Router *router) { m_defaultRouter.use(path, router); }
1577
1578FLASHMEM void Application::use(Router *router) { use(NULL, router); }
1579
1580FLASHMEM void Application::m_process(Request &request, Response &response) {
1581 if (!request.m_processMethod()) {
1582 if (request.m_timedout()) {
1583 return response.sendStatus(408);
1584 }
1585
1586 return response.sendStatus(400);
1587 }
1588
1589 if (!request.m_readURL()) {
1590 if (request.m_timedout()) {
1591 return response.sendStatus(408);
1592 }
1593
1594 return response.sendStatus(414);
1595 }
1596
1597 request.m_processURL();
1598
1599 if (!request.m_readVersion()) {
1600 if (request.m_timedout()) {
1601 return response.sendStatus(408);
1602 }
1603
1604 return response.sendStatus(505);
1605 }
1606
1607 if (!request.m_processHeaders()) {
1608 if (request.m_timedout()) {
1609 return response.sendStatus(408);
1610 }
1611
1612 return response.sendStatus(431);
1613 }
1614
1615 m_defaultRouter.m_dispatchMiddleware(request, response);
1616
1617 if (!response.statusSent() && !response.ended()) {
1618 if (m_notFound != NULL) {
1619 response.status(404);
1620 return m_notFound(request, response);
1621 }
1622
1623 return response.sendStatus(404);
1624 }
1625
1626 if (!response.headersSent()) {
1627 response.m_printHeaders();
1628 }
1629}
1630
1631FLASHMEM void Application::header(const char *name, char *buffer, int bufferLength) {
1632 Request::HeaderNode *newNode = new Request::HeaderNode();
1633
1634 buffer[0] = '\0';
1635
1636 newNode->name = name;
1637 newNode->buffer = buffer;
1638 newNode->bufferLength = bufferLength;
1639 newNode->next = NULL;
1640
1641 if (m_headerTail == NULL) {
1642 m_headerTail = newNode;
1643 } else {
1644 Request::HeaderNode *headerNode = m_headerTail;
1645
1646 while (headerNode->next != NULL) {
1647 headerNode = headerNode->next;
1648 }
1649
1650 headerNode->next = newNode;
1651 }
1652}
utils::status status
Definition daq.h:21
uint32_t uint32_t size
Definition flasher.cpp:63
uint32_t ch(uint32_t x, uint32_t y, uint32_t z)
Definition dcp.cpp:25