Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: GSwifi_httpd GSwifi_websocket GSwifi_tcpclient GSwifi_tcpserver ... more
Fork of GSwifi by
GSwifi_http.cpp
- Committer:
- gsfan
- Date:
- 2013-02-26
- Revision:
- 32:e19538c1f13d
- Parent:
- 30:f3e9053d9b46
- Child:
- 35:515ec79792d3
File content as of revision 32:e19538c1f13d:
/* Copyright (C) 2013 gsfan, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Gainspan wi-fi module library for mbed
* GS1011MIC, GS1011MIP, GainSpan WiFi Breakout, etc.
*/
#include "dbg.h"
#include "mbed.h"
#include "GSwifi.h"
#include <string.h>
int GSwifi::httpGet (Host &host, const char *uri, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) {
char cmd[GS_CMD_SIZE];
if (! _connect || _status != GSSTAT_READY) return -1;
if (host.getIp().isNull()) {
if (getHostByName(host)) {
if (getHostByName(host)) return -1;
}
}
if (host.getPort() == 0) {
if (ssl) {
host.setPort(443);
} else {
host.setPort(80);
}
}
command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection:
sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName()); // Host:
command(cmd, GSRES_NORMAL);
if (user && pwd) {
char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE];
snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2));
sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2); // Authorization:
command(cmd, GSRES_NORMAL);
} else {
command("AT+HTTPCONFDEL=2", GSRES_NORMAL);
}
command("AT+HTTPCONFDEL=5", GSRES_NORMAL);
command("AT+HTTPCONFDEL=7", GSRES_NORMAL);
sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
if (ssl) {
strcat(cmd, ",1");
}
if (command(cmd, GSRES_HTTP)) return -1;
newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPGET, ponGsReceive);
sprintf(cmd, "AT+HTTPSEND=%d,1,%d,%s", _cid, GS_TIMEOUT / 1000, uri); // GET
command(cmd, GSRES_NORMAL);
return _cid;
}
int GSwifi::httpPost (Host &host, const char *uri, const char *body, const char *user, const char *pwd, int ssl, onGsReceiveFunc ponGsReceive) {
char cmd[GS_CMD_SIZE];
int i, len;
if (! _connect || _status != GSSTAT_READY) return -1;
if (host.getIp().isNull()) {
if (getHostByName(host)) {
if (getHostByName(host)) return -1;
}
}
if (host.getPort() == 0) {
if (ssl) {
host.setPort(443);
} else {
host.setPort(80);
}
}
len = strlen(body);
command("AT+HTTPCONF=3,close", GSRES_NORMAL); // Connection:
sprintf(cmd, "AT+HTTPCONF=11,%s", host.getName()); // Host:
command(cmd, GSRES_NORMAL);
sprintf(cmd, "AT+HTTPCONF=5,%d", len); // Content-Length:
command(cmd, GSRES_NORMAL);
command("AT+HTTPCONF=7,application/x-www-form-urlencoded", GSRES_NORMAL); // Content-type:
if (user && pwd) {
char tmp[GS_CMD_SIZE], tmp2[GS_CMD_SIZE];
snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
base64encode(tmp, strlen(tmp), tmp2, sizeof(tmp2));
sprintf(cmd, "AT+HTTPCONF=2,Basic %s", tmp2); // Authorization:
command(cmd, GSRES_NORMAL);
} else {
command("AT+HTTPCONFDEL=2", GSRES_NORMAL);
}
sprintf(cmd, "AT+HTTPOPEN=%d.%d.%d.%d,%d", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
if (ssl) {
strcat(cmd, ",1");
}
if (command(cmd, GSRES_HTTP)) return -1;
newSock(_cid, GSTYPE_CLIENT, GSPROT_HTTPPOST, ponGsReceive);
sprintf(cmd, "AT+HTTPSEND=%d,3,%d,%s,%d", _cid, GS_TIMEOUT / 1000, uri, len); // POST
command(cmd, GSRES_NORMAL);
_gs.printf("\x1bH%X", _cid);
for (i = 0; i < len; i ++) {
_gs_putc(body[i]);
DBG("%c", body[i]);
}
return _cid;
}
int GSwifi::wsOpen (Host &host, const char *uri, const char *user, const char *pwd, onGsReceiveFunc ponGsReceive) {
int cid;
char cmd[GS_CMD_SIZE], tmp[GS_CMD_SIZE];
if (! _connect || _status != GSSTAT_READY) return -1;
if (host.getIp().isNull()) {
if (getHostByName(host)) {
if (getHostByName(host)) return -1;
}
}
if (host.getPort() == 0) {
host.setPort(80);
}
cid = open(host, GSPROT_TCP);
if (cid < 0) return -1;
DBG("cid %d\r\n", cid);
// send request
send(cid, "GET ", 4);
send(cid, uri, strlen(uri));
send(cid, " HTTP/1.1\r\n", 11);
if (host.getName() && host.getName()[0] != 0) {
send(cid, "Host: ", 5);
send(cid, host.getName(), strlen(host.getName()));
send(cid, "\r\n", 2);
}
if (user && pwd) {
snprintf(tmp, sizeof(tmp), "%s:%s", user, pwd);
base64encode(tmp, strlen(tmp), cmd, sizeof(cmd));
send(cid, "Authorization: Basic ", 21);
send(cid, cmd, strlen(cmd));
send(cid, "\r\n", 2);
}
send(cid, "Upgrade: websocket\r\n", 20);
send(cid, "Connection: Upgrade\r\n", 21);
send(cid, "Sec-WebSocket-Key: ", 19);
getMacAddress(tmp);
memcpy(&tmp[6], host.getName(), 10);
base64encode(tmp, 16, cmd, sizeof(cmd));
send(cid, cmd, strlen(cmd));
send(cid, "\r\n", 2);
send(cid, "Sec-WebSocket-Version: 13\r\n", 27);
send(cid, "\r\n", 2);
if (wait_ws(cid, 101)) {
close(cid);
return -1;
}
wait_ws(cid, 0);
_gs_sock[cid].onGsReceive.attach(ponGsReceive);
return cid;
}
int GSwifi::wait_ws (int cid, int code) {
Timer timeout;
int i, n, len;
char buf[200], data[100];
if (code == 0) {
// dummy read
timeout.start();
while (timeout.read_ms() < GS_TIMEOUT) {
wait_ms(10);
if (_gs_sock[cid].data->isEmpty()) break;
poll();
n = recv(cid, buf, sizeof(buf));
if (n <= 0) break;
}
timeout.stop();
return 0;
}
// wait responce
len = 0;
timeout.start();
while (timeout.read_ms() < GS_TIMEOUT) {
wait_ms(10);
poll();
n = recv(cid, buf, sizeof(buf));
for (i = 0; i < n; i ++) {
if (buf[i] == '\r') continue;
if (buf[i] == '\n') {
if (len == 0) continue;
goto next;
} else
if (len < sizeof(data) - 1) {
data[len] = buf[i];
len ++;
}
}
}
next:
data[len] = 0;
DBG("ws: %s\r\n", data);
timeout.stop();
// check return code
if (strncmp(data, "HTTP/1.1 ", 9) != 0) return -1;
i = atoi(&data[9]);
DBG("ws status %d\r\n", i);
if (i == code) return 0;
return -1;
}
int GSwifi::wsSend (int cid, const char *buf, int len, const char *mask) {
int r;
char tmp[10];
tmp[0] = 0x81; // single, text frame
tmp[1] = (mask == NULL) ? 0 : 0x80;
if (len < 126) {
tmp[1] |= len;
r = send(cid, tmp, 2);
} else {
tmp[1] |= 126;
tmp[2] = (len >> 8) & 0xff;
tmp[3] = len & 0xff;
r = send(cid, tmp, 4);
}
if (r == 0) {
if (mask) {
int i;
char tmp2[len];
send(cid, mask, 4);
for (i = 0; i < len; i ++) {
tmp2[i] = buf[i] ^ mask[i & 0x03];
}
r = send(cid, tmp2, len);
} else {
r = send(cid, buf, len);
}
}
return r;
}
/* base64encode code from
* Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
*/
int GSwifi::base64encode (char *input, int length, char *output, int len) {
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned int c, c1, c2, c3;
if (len < ((((length-1)/3)+1)<<2)) return -1;
for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
c = ((c1 & 0xFC) >> 2);
output[j+0] = base64[c];
c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
output[j+1] = base64[c];
c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
output[j+2] = (length>i+1)?base64[c]:'=';
c = (c3 & 0x3F);
output[j+3] = (length>i+2)?base64[c]:'=';
}
output[(((length-1)/3)+1)<<2] = '\0';
return 0;
}
/* urlencode code from
* Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
*/
int GSwifi::urlencode (char *str, char *buf, int len) {
// char *pstr = str, *buf = (char*)malloc(strlen(str) * 3 + 1), *pbuf = buf;
char *pstr = str, *pbuf = buf;
if (len < (strlen(str) * 3 + 1)) return -1;
while (*pstr) {
if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
*pbuf++ = *pstr;
else if (*pstr == ' ')
*pbuf++ = '+';
else
*pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
pstr++;
}
*pbuf = '\0';
return 0;
}
/* urldecode code from
* Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
*/
int GSwifi::urldecode (char *str, char *buf, int len) {
// char *pstr = str, *buf = (char*)malloc(strlen(str) + 1), *pbuf = buf;
char *pstr = str, *pbuf = buf;
if (len < (strlen(str) / 3 - 1)) return -1;
while (*pstr) {
if (*pstr == '%') {
if (pstr[1] && pstr[2]) {
*pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
pstr += 2;
}
} else if (*pstr == '+') {
*pbuf++ = ' ';
} else {
*pbuf++ = *pstr;
}
pstr++;
}
*pbuf = '\0';
return 0;
}

GainSpan Wi-Fi GS1011