WebSocket client library
Revision 6:01a1eb7c0145, committed 2011-08-24
- Comitter:
- samux
- Date:
- Wed Aug 24 10:49:36 2011 +0000
- Parent:
- 5:0f3422b6ca44
- Child:
- 7:b15978708360
- Commit message:
Changed in this revision
Websocket.cpp | Show annotated file Show diff for this revision Revisions of this file |
Websocket.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/Websocket.cpp Mon Aug 15 13:46:01 2011 +0000 +++ b/Websocket.cpp Wed Aug 24 10:49:36 2011 +0000 @@ -1,159 +1,362 @@ #include "Websocket.h" +#include <string> -Websocket::Websocket(char * url, int port, Wifly * wifi) -{ +Websocket::Websocket(char * url, Wifly * wifi) { + this->wifi = wifi; + wifi_use = true; + eth_use = false; + fillFields(wifi_use, url); +} + +void Websocket::fillFields(bool wifi, char * url) { char *res = NULL; + char *res1 = NULL; + char buf[30]; strcpy(buf, url); - + res = strtok(buf, ":"); - if (strcmp(res, "ws")) + if (strcmp(res, "ws")) { this->ip_domain = NULL; this->path = NULL; - printf("\r\nFormat error: please use: \"ws://ip-or-domain/path\"\r\n\r\n"); - } - else + printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); + } + else { - res = strtok(NULL, ":"); - res = strtok(res, "/"); - if(res != NULL) - { + //ip_domain and port + res = strtok(NULL, "/"); + + //path + res1 = strtok(NULL, " "); + if (res1 != NULL) { + path = (char *) malloc (sizeof(char) * strlen(res1)); + strcpy(this->path, res1); + } + + //ip_domain + res = strtok(res, ":"); + if (res != NULL) { ip_domain = (char *) malloc (sizeof(char) * strlen(res)); strcpy(this->ip_domain, res); + //if we use ethernet, we must decode ip address or use dnsresolver + if (!wifi) { + printf("ethernet use\r\n"); + strcpy(buf, res); + //we try to decode the ip address + if (buf[0] >= '0' && buf[0] <= '9') { + res = strtok(buf, "."); + int i = 0; + int ip[4]; + while (res != NULL) { + ip[i] = atoi(res); + res = strtok(NULL, "."); + i++; + } + server_ip = IpAddr(ip[0], ip[1], ip[2], ip[3]); + printf("server=%i.%i.%i.%i\n",server_ip[0],server_ip[1],server_ip[2],server_ip[3]); + } + //we must use dnsresolver to find the ip address + else { + DNSResolver dr; + server_ip = dr.resolveName(buf); + printf("server=%i.%i.%i.%i\n",server_ip[0],server_ip[1],server_ip[2],server_ip[3]); + } + } } - res = strtok(NULL, " "); - if(res != NULL) - { - path = (char *) malloc (sizeof(char) * strlen(res)); - strcpy(this->path, res); + + //port + res = strtok(NULL, ":"); + if (res != NULL) { + port = (char *) malloc (sizeof(char) * strlen(res)); + strcpy(this->port, res); + } else { + port = (char *) malloc (sizeof(char) * 3); + strcpy(this->port, "80"); } - - this->port = port; - this->wifi = wifi; - } } -bool Websocket::connect() -{ + +Websocket::Websocket(char * url) { + wifi_use = false; + eth_use = true; + eth_writeable = false; + eth_readable = false; + eth_connected = false; + fillFields(wifi_use, url); +} + + + + +bool Websocket::connect() { char cmd[50]; - wifi->Send("exit\r", "NO"); - //enter in cmd mode - while(!wifi->Send("$$$", "CMD")) - { - printf("cannot enter in CMD mode\r\n"); - wifi->exit(); - } - + if ( wifi_use ) { + wifi->Send("exit\r", "NO"); + //enter in cmd mode + while (!wifi->Send("$$$", "CMD")) { + printf("cannot enter in CMD mode\r\n"); + wifi->exit(); + } + + + //open the connection + sprintf(cmd, "open %s %s\r\n", ip_domain, port); + if (!wifi->Send(cmd, "OPEN")) { + printf("Websocket::connect cannot open\r\n"); + return false; + } + + + //send websocket HTTP header + sprintf(cmd, "GET /%s HTTP/1.1\r\n", path); + wifi->Send(cmd, "NO"); + + sprintf(cmd, "Host: %s:%s\r\n", ip_domain, port); + wifi->Send(cmd, "NO"); + + wifi->Send("Upgrade: WebSocket\r\n", "NO"); + + sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain, port); + wifi->Send(cmd, "NO"); + + + wifi->Send("Connection: Upgrade\r\n", "NO"); + wifi->Send("Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n", "NO"); + wifi->Send("Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n", "NO"); + if (!wifi->Send("^n:ds[4U", "8jKS'y:G*Co,Wxa-")) + return false; + + printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain, this->path, this->port); + return true; + } else if ( eth_use ) { + int i = 0; + + EthernetErr ethErr = eth.setup(); + if (ethErr) { + printf("Error %d in setup.\r\n", ethErr); + return false; + } + + printf("setup OK\r\n"); + + IpAddr ipt = eth.getIp(); + printf("mbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]); + + sock.setOnEvent(this, &Websocket::onTCPSocketEvent); + Host server (server_ip, atoi(port)); + TCPSocketErr bindErr = sock.connect(server); + if (bindErr) { + printf("binderr: %d", bindErr); + return false; + } + + + Timer tmr; + tmr.start(); + char msg[10]; - //open the connection - sprintf(cmd, "open %s %d\r\n", ip_domain, port); - if(!wifi->Send(cmd, "OPEN")) - { - printf("Websocket::connect cannot open\r\n"); - return false; + while (true) { + Net::poll(); + if (tmr.read() > 0.1) { + tmr.reset(); + if (eth_connected) { + switch (i) { + case 0: + sprintf(cmd, "GET /%s HTTP/1.1\r\n", path); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 1: + sprintf(cmd, "Host: %s:%s\r\n", ip_domain, port); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 2: + sprintf(cmd, "Upgrade: WebSocket\r\n"); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 3: + sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain, port); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 4: + sprintf(cmd, "Connection: Upgrade\r\n"); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 5: + sprintf(cmd, "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 6: + sprintf(cmd, "Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n"); + sock.send(cmd, strlen(cmd)); + i++; + break; + case 7: + sock.send("^n:ds[4U", 8); + i++; + break; + case 8: + if(eth_readable) + { + string checking; + size_t found = string::npos; + sock.recv(msg, 10); + Net::poll(); + checking = msg; + found = checking.find("HTTP"); + if(found != string::npos) + { + //printf("checking: %s\r\n", checking); + i++; + break; + } + else + return false; + } + break; + + default: + break; + } + } + if (i==9) + { + printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain, this->path, this->port); + return true; + } + } + } + } - - - //send websocket HTTP header - sprintf(cmd, "GET /%s HTTP/1.1\r\n", path); - wifi->Send(cmd, "NO"); - - sprintf(cmd, "Host: %s:%d\r\n", ip_domain, port); - wifi->Send(cmd, "NO"); - - wifi->Send("Upgrade: WebSocket\r\n", "NO"); - - sprintf(cmd, "Origin: http:%s:%d\r\n", ip_domain, port); - wifi->Send(cmd, "NO"); - - - wifi->Send("Connection: Upgrade\r\n", "NO"); - wifi->Send("Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n", "NO"); - wifi->Send("Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n", "NO"); - if(!wifi->Send("^n:ds[4U", "8jKS'y:G*Co,Wxa-")) - return false; - - printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %d\r\n\r\n",this->ip_domain, this->path, this->port); return true; } -void Websocket::Send(char * str) -{ +void Websocket::Send(char * str) { char cmd[100]; - wifi->putc('\x00'); - sprintf(cmd, "%s%c", str, '\xff'); - wifi->Send(cmd, "NO"); + if (wifi_use) { + wifi->putc('\x00'); + sprintf(cmd, "%s%c", str, '\xff'); + wifi->Send(cmd, "NO"); + } else if (eth_use) { + sprintf(cmd, "%c%s%c", 0x00, str, 0xff); + Net::poll(); + sock.send(cmd, strlen(cmd + 1) + 1); + } } -bool Websocket::read(char * message) -{ +bool Websocket::read(char * message) { int i = 0; char char_read; - - if (!wifi->readable()) - { + + if (!wifi->readable()) { message = NULL; return false; } - - if (wifi->getc() != 0x00) - { + + if (wifi->getc() != 0x00) { message = NULL; return false; } - + while ( (char_read = wifi->getc()) != 0xff) message[i++] = char_read; - + return true; } -bool Websocket::close() -{ - if(!wifi->CmdMode()) - { +bool Websocket::close() { + if (!wifi->CmdMode()) { printf("Websocket::close: cannot enter in cmd mode\r\n"); return false; } - + wifi->Send("close\r", "NO"); - - if(!wifi->exit()) + + if (!wifi->exit()) return false; - + return true; } -bool Websocket::connected() -{ - char str[10]; - - wait(0.25); - if(!wifi->CmdMode()) - { - printf("Websocket::connected: cannot enter in cmd mode\r\n"); - return false; - } - wait(0.25); - - wifi->Send("show c\r\n", "NO"); - wifi->read(str); - - if(str[3] == '1') - { - if(!wifi->exit()) - { - printf("Websocket::connected: cannot exit\r\n"); +bool Websocket::connected() { + if (wifi_use) { + char str[10]; + + wait(0.25); + if (!wifi->CmdMode()) { + printf("Websocket::connected: cannot enter in cmd mode\r\n"); return false; } - return true; + wait(0.25); + + wifi->Send("show c\r\n", "NO"); + wifi->read(str); + + if (str[3] == '1') { + if (!wifi->exit()) { + printf("Websocket::connected: cannot exit\r\n"); + return false; + } + return true; + } + if (!wifi->exit()) + printf("Websocket::connected: cannot exit\r\n"); + return false; + } + else if (eth_use) + return eth_connected; + + return true; +} + + + + + +void Websocket::onTCPSocketEvent(TCPSocketEvent e) { + switch (e) { + case TCPSOCKET_CONNECTED: + eth_connected = true; + printf("TCP Socket Connected\r\n"); + break; + case TCPSOCKET_WRITEABLE: + eth_writeable = true; + break; + case TCPSOCKET_READABLE: + printf("TCP Socket Readable\r\n"); + eth_readable = true; + break; + case TCPSOCKET_CONTIMEOUT: + printf("TCP Socket Timeout\r\n"); + eth_connected = false; + break; + case TCPSOCKET_CONRST: + printf("TCP Socket CONRST\r\n"); + eth_connected = false; + break; + case TCPSOCKET_CONABRT: + printf("TCP Socket CONABRT\r\n"); + eth_connected = false; + break; + case TCPSOCKET_ERROR: + printf("TCP Socket Error\r\n"); + eth_connected = false; + break; + case TCPSOCKET_DISCONNECTED: + eth_connected = false; + break; + default: + printf("DEFAULT\r\n"); } - if(!wifi->exit()) - printf("Websocket::connected: cannot exit\r\n"); - return false; - -} \ No newline at end of file +} + +
--- a/Websocket.h Mon Aug 15 13:46:01 2011 +0000 +++ b/Websocket.h Wed Aug 24 10:49:36 2011 +0000 @@ -33,6 +33,10 @@ #include "mbed.h" #include "Wifly.h" +#include "EthernetNetIf.h" +#include "TCPSocket.h" +#include "dnsresolve.h" + /** Websocket client Class. * * Warning: you must use a wifi module (Wifly RN131-C) to use this class @@ -76,13 +80,20 @@ { public: /** - * Constructor + * Constructor for a wifi module * - * @param url The Websocket url in the form "ws://ip_domain/path" - * @param port port + * @param url The Websocket url in the form "ws://ip_domain[:port]/path" (by default: port = 80) * @param wifi pointer to a wifi module (the communication will be establish by this module) */ - Websocket(char * url, int port, Wifly * wifi); + Websocket(char * url, Wifly * wifi); + + /** + * Constructor for an ethernet communication + * + * @param url The Websocket url in the form "ws://ip_domain[:port]/path" (by default: port = 80) + * @param port port + */ + Websocket(char * url); /** * Connect to the websocket @@ -120,12 +131,30 @@ * @return true if the connection has been closed, false otherwise */ bool close(); + + private: + + void fillFields(bool wifi, char * url); + void onTCPSocketEvent(TCPSocketEvent e); + char * ip_domain; char * path; - int port; + char * port; + Wifly * wifi; + + bool eth_connected; + bool eth_readable; + bool eth_writeable; + + bool wifi_use; + bool eth_use; + + EthernetNetIf eth; + TCPSocket sock; + IpAddr server_ip; };