WebSocket client library

Files at this revision

API Documentation at this revision

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;
 
 };