Port of LwIP performed by Ralf in 2010. Not recommended for use with recent mbed libraries, but good demos of raw LwIP possible
Dependents: LwIP_raw_API_serverExample tiny-dtls
HTTPServer/HTTPRPC.h@0:0791c1fece8e, 2012-09-18 (annotated)
- Committer:
- RodColeman
- Date:
- Tue Sep 18 14:41:24 2012 +0000
- Revision:
- 0:0791c1fece8e
[mbed] converted /Eth_TCP_Wei_Server/lwip
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RodColeman | 0:0791c1fece8e | 1 | #ifndef HTTPRPC_H |
RodColeman | 0:0791c1fece8e | 2 | #define HTTPRPC_H |
RodColeman | 0:0791c1fece8e | 3 | |
RodColeman | 0:0791c1fece8e | 4 | #include "HTTPServer.h" |
RodColeman | 0:0791c1fece8e | 5 | #include "platform.h" |
RodColeman | 0:0791c1fece8e | 6 | #ifdef MBED_RPC |
RodColeman | 0:0791c1fece8e | 7 | #include "rpc.h" |
RodColeman | 0:0791c1fece8e | 8 | |
RodColeman | 0:0791c1fece8e | 9 | /** |
RodColeman | 0:0791c1fece8e | 10 | * A datastorage helper for the HTTPRPC class |
RodColeman | 0:0791c1fece8e | 11 | */ |
RodColeman | 0:0791c1fece8e | 12 | class HTTPRPCData : public HTTPData { |
RodColeman | 0:0791c1fece8e | 13 | public: char result[255]; |
RodColeman | 0:0791c1fece8e | 14 | }; |
RodColeman | 0:0791c1fece8e | 15 | |
RodColeman | 0:0791c1fece8e | 16 | /** |
RodColeman | 0:0791c1fece8e | 17 | * Thsi class enables you to make rpc calls to your mbed. |
RodColeman | 0:0791c1fece8e | 18 | * Furthermore it is a good example how to write a HTTPHandler for small data chunks. |
RodColeman | 0:0791c1fece8e | 19 | */ |
RodColeman | 0:0791c1fece8e | 20 | class HTTPRPC : public HTTPHandler { |
RodColeman | 0:0791c1fece8e | 21 | public: |
RodColeman | 0:0791c1fece8e | 22 | /** |
RodColeman | 0:0791c1fece8e | 23 | * We have to know the prefix for the RPCHandler. |
RodColeman | 0:0791c1fece8e | 24 | * A good default choice is /rpc so we made this default. |
RodColeman | 0:0791c1fece8e | 25 | */ |
RodColeman | 0:0791c1fece8e | 26 | HTTPRPC(const char *path = "/rpc") : HTTPHandler(path) {} |
RodColeman | 0:0791c1fece8e | 27 | HTTPRPC(HTTPServer *server, const char *path = "/rpc") : HTTPHandler(path) { server->addHandler(this); } |
RodColeman | 0:0791c1fece8e | 28 | |
RodColeman | 0:0791c1fece8e | 29 | private: |
RodColeman | 0:0791c1fece8e | 30 | /** |
RodColeman | 0:0791c1fece8e | 31 | * If you need some Headerfeelds you have tor register the feelds here. |
RodColeman | 0:0791c1fece8e | 32 | */ |
RodColeman | 0:0791c1fece8e | 33 | // virtual void reg(HTTPServer *svr) { |
RodColeman | 0:0791c1fece8e | 34 | // svr->registerField("Content-Length"); |
RodColeman | 0:0791c1fece8e | 35 | // } |
RodColeman | 0:0791c1fece8e | 36 | |
RodColeman | 0:0791c1fece8e | 37 | /** |
RodColeman | 0:0791c1fece8e | 38 | * If a new RPCRequest Header is complete received the server will call this function. |
RodColeman | 0:0791c1fece8e | 39 | * This is the right place for preparing our datastructures. |
RodColeman | 0:0791c1fece8e | 40 | * Furthermore we will execute the rpc call and store the anwere. |
RodColeman | 0:0791c1fece8e | 41 | * But we will not send a response. This will be hapen in the send method. |
RodColeman | 0:0791c1fece8e | 42 | */ |
RodColeman | 0:0791c1fece8e | 43 | virtual HTTPStatus init(HTTPConnection *con) const { |
RodColeman | 0:0791c1fece8e | 44 | HTTPRPCData *data = new HTTPRPCData(); |
RodColeman | 0:0791c1fece8e | 45 | con->data = data; |
RodColeman | 0:0791c1fece8e | 46 | char *query = con->getURL()+strlen(_prefix); |
RodColeman | 0:0791c1fece8e | 47 | clean(query); |
RodColeman | 0:0791c1fece8e | 48 | rpc(query, data->result); |
RodColeman | 0:0791c1fece8e | 49 | |
RodColeman | 0:0791c1fece8e | 50 | const char *nfields = "Cache-Control: no-cache, no-store, must-revalidate\r\nPragma: no-cache\r\nExpires: Thu, 01 Dec 1994 16:00:00 GM"; |
RodColeman | 0:0791c1fece8e | 51 | char *old = (char *)con->getHeaderFields(); |
RodColeman | 0:0791c1fece8e | 52 | int oldlen = strlen(old); |
RodColeman | 0:0791c1fece8e | 53 | int atrlen = strlen(nfields); |
RodColeman | 0:0791c1fece8e | 54 | char *fields = new char[atrlen+oldlen+3]; |
RodColeman | 0:0791c1fece8e | 55 | strcpy(fields,old); |
RodColeman | 0:0791c1fece8e | 56 | fields[oldlen+0] = '\r'; |
RodColeman | 0:0791c1fece8e | 57 | fields[oldlen+1] = '\n'; |
RodColeman | 0:0791c1fece8e | 58 | strcpy(&fields[oldlen+2], nfields); |
RodColeman | 0:0791c1fece8e | 59 | fields[atrlen+2+oldlen] = '\0'; |
RodColeman | 0:0791c1fece8e | 60 | con->setHeaderFields(fields); |
RodColeman | 0:0791c1fece8e | 61 | if(*old) { |
RodColeman | 0:0791c1fece8e | 62 | delete old; |
RodColeman | 0:0791c1fece8e | 63 | } |
RodColeman | 0:0791c1fece8e | 64 | |
RodColeman | 0:0791c1fece8e | 65 | con->setLength(strlen(data->result)); |
RodColeman | 0:0791c1fece8e | 66 | return HTTP_OK; |
RodColeman | 0:0791c1fece8e | 67 | } |
RodColeman | 0:0791c1fece8e | 68 | |
RodColeman | 0:0791c1fece8e | 69 | /** |
RodColeman | 0:0791c1fece8e | 70 | * If we got an POST request the send method will not be executed. |
RodColeman | 0:0791c1fece8e | 71 | * If we want to send data we have to trigger it the first time by ourself. |
RodColeman | 0:0791c1fece8e | 72 | * So we execute the send method. |
RodColeman | 0:0791c1fece8e | 73 | * |
RodColeman | 0:0791c1fece8e | 74 | * If the rpc call is the content of the POST body we would not be able to execute it. |
RodColeman | 0:0791c1fece8e | 75 | * Were parsing only the URL. |
RodColeman | 0:0791c1fece8e | 76 | */ |
RodColeman | 0:0791c1fece8e | 77 | virtual HTTPHandle data(HTTPConnection *con, void *, int) const { |
RodColeman | 0:0791c1fece8e | 78 | return send(con, con->sndbuf()); |
RodColeman | 0:0791c1fece8e | 79 | } |
RodColeman | 0:0791c1fece8e | 80 | |
RodColeman | 0:0791c1fece8e | 81 | /** |
RodColeman | 0:0791c1fece8e | 82 | * Send the result back to the client. |
RodColeman | 0:0791c1fece8e | 83 | * If we have not enought space wait for next time. |
RodColeman | 0:0791c1fece8e | 84 | */ |
RodColeman | 0:0791c1fece8e | 85 | virtual HTTPHandle send(HTTPConnection *con, int maximum) const { |
RodColeman | 0:0791c1fece8e | 86 | HTTPRPCData *data = static_cast<HTTPRPCData *>(con->data); |
RodColeman | 0:0791c1fece8e | 87 | if(maximum>64) { |
RodColeman | 0:0791c1fece8e | 88 | con->write(data->result, con->getLength()); |
RodColeman | 0:0791c1fece8e | 89 | return HTTP_SuccessEnded; |
RodColeman | 0:0791c1fece8e | 90 | } else { |
RodColeman | 0:0791c1fece8e | 91 | // To less memory. |
RodColeman | 0:0791c1fece8e | 92 | return HTTP_SenderMemory; |
RodColeman | 0:0791c1fece8e | 93 | } |
RodColeman | 0:0791c1fece8e | 94 | } |
RodColeman | 0:0791c1fece8e | 95 | |
RodColeman | 0:0791c1fece8e | 96 | /** |
RodColeman | 0:0791c1fece8e | 97 | * To reduce memory usage we sodify the URL directly |
RodColeman | 0:0791c1fece8e | 98 | * and replace '%20',',','+','=' with spaces. |
RodColeman | 0:0791c1fece8e | 99 | */ |
RodColeman | 0:0791c1fece8e | 100 | inline void clean(char *str) const { |
RodColeman | 0:0791c1fece8e | 101 | while(*str++) { |
RodColeman | 0:0791c1fece8e | 102 | if(*str=='%'&&*(str+1)=='2'&&*(str+2)=='0') { |
RodColeman | 0:0791c1fece8e | 103 | *str = ' '; |
RodColeman | 0:0791c1fece8e | 104 | *(str+1) = ' '; |
RodColeman | 0:0791c1fece8e | 105 | *(str+2) = ' '; |
RodColeman | 0:0791c1fece8e | 106 | } |
RodColeman | 0:0791c1fece8e | 107 | if(*str==','||*str=='+'||*str=='=') { |
RodColeman | 0:0791c1fece8e | 108 | *str = ' '; |
RodColeman | 0:0791c1fece8e | 109 | } |
RodColeman | 0:0791c1fece8e | 110 | } |
RodColeman | 0:0791c1fece8e | 111 | } |
RodColeman | 0:0791c1fece8e | 112 | }; |
RodColeman | 0:0791c1fece8e | 113 | #endif |
RodColeman | 0:0791c1fece8e | 114 | |
RodColeman | 0:0791c1fece8e | 115 | #endif |