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