GainSpan Wi-Fi library see: http://mbed.org/users/gsfan/notebook/gainspan_wifi/

Dependents:   GSwifi_httpd GSwifi_websocket GSwifi_tcpclient GSwifi_tcpserver ... more

Fork of GSwifi by gs fan

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GSwifi_http.cpp Source File

GSwifi_http.cpp

Go to the documentation of this file.
00001 /* Copyright (C) 2013 gsfan, MIT License
00002  *
00003  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004  * and associated documentation files (the "Software"), to deal in the Software without restriction,
00005  * including without limitation the rights to use, copy, modify, merge, publish, distribute,
00006  * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00007  * furnished to do so, subject to the following conditions:
00008  *
00009  * The above copyright notice and this permission notice shall be included in all copies or
00010  * substantial portions of the Software.
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013  * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017  */
00018 /** @file
00019  * @brief Gainspan wi-fi module library for mbed
00020  * GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc.
00021  */
00022 
00023 #include "GSwifi_conf.h"
00024 #ifdef GS_ENABLE_HTTP
00025 
00026 #include "dbg.h"
00027 #include "mbed.h"
00028 #include "GSwifi.h"
00029 #include <string.h>
00030 
00031 
00032 int GSwifi::httpGet (Host &host, const char *uri, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) {
00033     char cmd[GS_CMD_SIZE];
00034 
00035     if (! _connect || _status != GSSTAT_READY) return -1;
00036 
00037     if (host.getIp().isNull()) {
00038         if (getHostByName(host)) {
00039             if (getHostByName(host)) return -1;
00040         }
00041     }
00042     if (host.getPort() == 0) {
00043         if (ssl) {
00044             host.setPort(443);
00045         } else {
00046             host.setPort(80);
00047         }
00048     }
00049 
00050     command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection:
00051     sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName());  // Host:
00052     command(cmd, GSRES_NORMAL);
00053     if (user && pwd) {
00054         char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE];
00055         snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
00056         base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2));
00057         sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2);  // Authorization:
00058         command(cmd, GSRES_NORMAL);
00059     } else {
00060         command("AT+HTTPCONFDEL=2", GSRES_NORMAL);
00061     }
00062     command("AT+HTTPCONFDEL=5", GSRES_NORMAL);
00063     command("AT+HTTPCONFDEL=7", GSRES_NORMAL);
00064 
00065     sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
00066     if (ssl) {
00067         strcat(cmd, ",1");
00068     }
00069     if (command(cmd, GSRES_HTTP)) return -1;
00070     newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPGET, ponGsReceive);
00071 
00072     sprintf(cmd, "AT+HTTPSEND=%d,1,%d,%s", _cid, GS_TIMEOUT / 1000, uri);  // GET
00073     command(cmd, GSRES_NORMAL);
00074 
00075     return _cid;
00076 }
00077 
00078 int GSwifi::httpPost (Host &host, const char *uri, const char *body, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) {
00079     char cmd[GS_CMD_SIZE];
00080     int i, len;
00081 
00082     if (! _connect || _status != GSSTAT_READY) return -1;
00083 
00084     if (host.getIp().isNull()) {
00085         if (getHostByName(host)) {
00086             if (getHostByName(host)) return -1;
00087         }
00088     }
00089     if (host.getPort() == 0) {
00090         if (ssl) {
00091             host.setPort(443);
00092         } else {
00093             host.setPort(80);
00094         }
00095     }
00096     len = strlen(body);
00097 
00098     command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection:
00099     sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName());  // Host:
00100     command(cmd, GSRES_NORMAL);
00101     sprintf(cmd, "AT+HTTPCONF=5,%d", len);  // Content-Length:
00102     command(cmd, GSRES_NORMAL);
00103     command("AT+HTTPCONF=7,application/x-www-form-urlencoded", GSRES_NORMAL); // Content-type:
00104     if (user && pwd) {
00105         char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE];
00106         snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
00107         base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2));
00108         sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2);  // Authorization:
00109         command(cmd, GSRES_NORMAL);
00110     } else {
00111         command("AT+HTTPCONFDEL=2", GSRES_NORMAL);
00112     }
00113 
00114     sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
00115     if (ssl) {
00116         strcat(cmd, ",1");
00117     }
00118     if (command(cmd, GSRES_HTTP)) return -1;
00119     newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPPOST, ponGsReceive);
00120 
00121     sprintf(cmd, "AT+HTTPSEND=%d,3,%d,%s,%d", _cid, GS_TIMEOUT / 1000, uri, len);  // POST
00122     command(cmd, GSRES_NORMAL);
00123 
00124     if (acquireUart()) return -1;
00125     sprintf(cmd, "\x1bH%X", _cid);
00126     _gs_puts(cmd);
00127     for (i = 0; i < len; i ++) {
00128         _gs_putc(body[i]);
00129         DBG("%c", body[i]);
00130     }
00131     releaseUart();
00132 
00133     return _cid;
00134 }
00135 
00136 int GSwifi::wsOpen (Host &host, const char *uri, const char *user, const char *pwd, onGsReceiveFunc ponGsReceive) {
00137     int cid;
00138     char cmd[GS_CMD_SIZE], tmp[GS_CMD_SIZE];
00139 
00140     if (! _connect || _status != GSSTAT_READY) return -1;
00141 
00142     if (host.getIp().isNull()) {
00143         if (getHostByName(host)) {
00144             if (getHostByName(host)) return -1;
00145         }
00146     }
00147     if (host.getPort() == 0) {
00148         host.setPort(80);
00149     }
00150 
00151     cid = open(host, GSPROT_TCP);
00152     if (cid < 0) return -1;
00153     DBG("cid %d\r\n", cid);
00154 
00155     // send request
00156     send(cid, "GET ", 4);
00157     send(cid, uri, strlen(uri));
00158     send(cid, " HTTP/1.1\r\n", 11);
00159     if (host.getName() && host.getName()[0] != 0) {
00160         send(cid, "Host: ", 5);
00161         send(cid, host.getName(), strlen(host.getName()));
00162         send(cid, "\r\n", 2);
00163     }
00164     if (user && pwd) {
00165         snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
00166         base64encode(tmp, strlen(tmp), cmd, sizeof(cmd));
00167         send(cid, "Authorization: Basic ", 21);
00168         send(cid, cmd, strlen(cmd));
00169         send(cid, "\r\n", 2);
00170     }
00171     send(cid, "Upgrade: websocket\r\n", 20);
00172     send(cid, "Connection: Upgrade\r\n", 21);
00173     send(cid, "Sec-WebSocket-Key: ", 19);
00174     getMacAddress(tmp);
00175     memcpy(&tmp[6], host.getName(), 10);
00176     base64encode(tmp, 16, cmd, sizeof(cmd));
00177     send(cid, cmd, strlen(cmd));
00178     send(cid, "\r\n", 2);
00179     send(cid, "Sec-WebSocket-Version: 13\r\n", 27);
00180     send(cid, "\r\n", 2);
00181 
00182     if (wait_ws(cid, 101)) {
00183         close(cid);
00184         return -1;
00185     }
00186     wait_ws(cid, 0);
00187 
00188     _gs_sock[cid].onGsReceive.attach(ponGsReceive);
00189     return cid;
00190 }
00191 
00192 int GSwifi::wait_ws (int cid, int code) {
00193     Timer timeout;
00194     int i, n, len;
00195     char buf[200], data[100];
00196 
00197     if (code == 0) {
00198       // dummy read
00199       timeout.start();
00200       while (timeout.read_ms() < GS_TIMEOUT) {
00201         wait_ms(10);
00202         if (_gs_sock[cid].data->isEmpty()) break;
00203         poll();
00204         n = recv(cid, buf, sizeof(buf));
00205         if (n <= 0) break;
00206       }
00207       timeout.stop();
00208       return 0;
00209     }
00210 
00211     // wait responce
00212     len = 0;
00213     timeout.start();
00214     while (timeout.read_ms() < GS_TIMEOUT) {
00215         wait_ms(10);
00216         poll();
00217         n = recv(cid, buf, sizeof(buf));
00218         for (i = 0; i < n; i ++) {
00219             if (buf[i] == '\r') continue;
00220             if (buf[i] == '\n') {
00221                 if (len == 0) continue;
00222                 goto next;
00223             } else
00224             if (len < sizeof(data) - 1) {
00225                 data[len] = buf[i];
00226                 len ++;
00227             }
00228         }
00229     }
00230 next:
00231     data[len] = 0;
00232     DBG("ws: %s\r\n", data);
00233     timeout.stop();
00234  
00235     // check return code
00236     if (strncmp(data, "HTTP/1.1 ", 9) != 0) return -1;
00237     i = atoi(&data[9]);
00238     DBG("ws status %d\r\n", i);
00239     if (i == code) return 0;
00240  
00241     return -1;
00242 }
00243 
00244 int GSwifi::wsSend (int cid, const char *buf, int len, const char *mask) {
00245     int r;
00246     char tmp[10];
00247 
00248     tmp[0] = 0x81; // single, text frame
00249     tmp[1] = (mask == NULL) ? 0 : 0x80;
00250 
00251     if (len < 126) {
00252         tmp[1] |= len;
00253         r = send(cid, tmp, 2);
00254     } else {
00255         tmp[1] |= 126;
00256         tmp[2] = (len >> 8) & 0xff;
00257         tmp[3] = len & 0xff;
00258         r = send(cid, tmp, 4);
00259     }
00260 
00261     if (r == 0) {
00262         if (mask) {
00263             int i;
00264             char tmp2[len];
00265             send(cid, mask, 4);
00266             for (i = 0; i < len; i ++) {
00267                 tmp2[i] = buf[i] ^ mask[i & 0x03];
00268             }
00269             r = send(cid, tmp2, len);
00270         } else {
00271             r = send(cid, buf, len);
00272         }
00273     }
00274     return r;
00275 }
00276 
00277 
00278 /* base64encode code from 
00279  * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00280  */
00281 int GSwifi::base64encode (char *input, int length, char *output, int len) {
00282     static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00283     unsigned int c, c1, c2, c3;
00284 
00285     if (len < ((((length-1)/3)+1)<<2)) return -1;
00286     for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
00287         c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
00288         c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
00289         c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
00290 
00291         c = ((c1 & 0xFC) >> 2);
00292         output[j+0] = base64[c];
00293         c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
00294         output[j+1] = base64[c];
00295         c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
00296         output[j+2] = (length>i+1)?base64[c]:'=';
00297         c = (c3 & 0x3F);
00298         output[j+3] = (length>i+2)?base64[c]:'=';
00299     }
00300     output[(((length-1)/3)+1)<<2] = '\0';
00301     return 0;
00302 }
00303 
00304 /* urlencode code from 
00305  * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00306  */
00307 int GSwifi::urlencode (char *str, char *buf, int len) {
00308 //  char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
00309     char *pstr = str, *pbuf = buf;
00310 
00311     if (len < (strlen(str) * 3 + 1)) return -1;
00312     while (*pstr) {
00313         if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
00314             *pbuf++ = *pstr;
00315         else if (*pstr == ' ') 
00316             *pbuf++ = '+';
00317         else 
00318             *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
00319         pstr++;
00320     }
00321     *pbuf = '\0';
00322     return 0;
00323 }
00324 
00325 /* urldecode code from 
00326  * Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
00327  */
00328 int GSwifi::urldecode (char *str, char *buf, int len) {
00329 //  char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
00330     char *pstr = str, *pbuf = buf;
00331 
00332     if (len < (strlen(str) / 3 - 1)) return -1;
00333     while (*pstr) {
00334         if (*pstr == '%') {
00335             if (pstr[1] && pstr[2]) {
00336                 *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
00337                 pstr += 2;
00338             }
00339         } else if (*pstr == '+') { 
00340             *pbuf++ = ' ';
00341         } else {
00342             *pbuf++ = *pstr;
00343         }
00344         pstr++;
00345     }
00346     *pbuf = '\0';
00347     return 0;
00348 }
00349 
00350 #endif