Simple websocket client

Dependents:   Websocket_Ethernet_HelloWorld Websocket_Wifly_HelloWorld RPC_Wifly_HelloWorld RPC_Ethernet_HelloWorld ... more

Files at this revision

API Documentation at this revision

Comitter:
donatien
Date:
Wed Aug 29 15:27:51 2012 +0000
Parent:
5:bb09d7a6c92f
Child:
7:4567996414a5
Commit message:
removed useof std::string

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	Wed Aug 29 13:49:48 2012 +0000
+++ b/Websocket.cpp	Wed Aug 29 15:27:51 2012 +0000
@@ -1,5 +1,4 @@
 #include "Websocket.h"
-#include <string>
 
 #define MAX_TRY_WRITE 50
 #define MAX_TRY_READ 30
@@ -23,56 +22,112 @@
 }
 
 void Websocket::fillFields(char * url) {
-    char *res = NULL;
-    char *res1 = NULL;
+  int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
+  if(ret)
+  {
+    ERR("URL parsing failed; please use: \"ws://ip-or-domain[:port]/path\"");
+    return;
+  }
 
-    char buf[50];
-    strcpy(buf, url);
+  if(port == 0) //TODO do handle WSS->443
+  {
+    port = 80;
+  }
+  
+  if(strcmp(scheme, "ws"))
+  {
+    ERR("Wrong scheme, please use \"ws\" instead");
+  }
+}
 
-    res = strtok(buf, ":");
-    if (strcmp(res, "ws")) {
-        DBG("\r\nFormat printfor: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n");
-    } else {
-        //ip_domain and port
-        res = strtok(NULL, "/");
+int Websocket::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
+{
+  char* schemePtr = (char*) url;
+  char* hostPtr = (char*) strstr(url, "://");
+  if(hostPtr == NULL)
+  {
+    WARN("Could not find host");
+    return -1; //URL is invalid
+  }
+
+  if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
+  {
+    WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
+    return -1;
+  }
+  memcpy(scheme, schemePtr, hostPtr - schemePtr);
+  scheme[hostPtr - schemePtr] = '\0';
+
+  hostPtr+=3;
+
+  size_t hostLen = 0;
 
-        //path
-        res1 = strtok(NULL, " ");
-        if (res1 != NULL) {
-            path = res1;
-        }
-
-        //ip_domain
-        res = strtok(res, ":");
+  char* portPtr = strchr(hostPtr, ':');
+  if( portPtr != NULL )
+  {
+    hostLen = portPtr - hostPtr;
+    portPtr++;
+    if( sscanf(portPtr, "%hu", port) != 1)
+    {
+      WARN("Could not find port");
+      return -1;
+    }
+  }
+  else
+  {
+    *port=0;
+  }
+  char* pathPtr = strchr(hostPtr, '/');
+  if( hostLen == 0 )
+  {
+    hostLen = pathPtr - hostPtr;
+  }
 
-        //port
-        res1 = strtok(NULL, " ");
-        if (res1 != NULL) {
-            port = res1;
-        } else {
-            port = "80";
-        }
+  if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
+  {
+    WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
+    return -1;
+  }
+  memcpy(host, hostPtr, hostLen);
+  host[hostLen] = '\0';
 
-        if (res != NULL) {
-            ip_domain = res;
-        }
-    }
+  size_t pathLen;
+  char* fragmentPtr = strchr(hostPtr, '#');
+  if(fragmentPtr != NULL)
+  {
+    pathLen = fragmentPtr - pathPtr;
+  }
+  else
+  {
+    pathLen = strlen(pathPtr);
+  }
+
+  if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
+  {
+    WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
+    return -1;
+  }
+  memcpy(path, pathPtr, pathLen);
+  path[pathLen] = '\0';
+
+  return 0;
 }
 
 
 bool Websocket::connect() {
     char cmd[200];
 
-    while (socket.connect(ip_domain.c_str(), atoi(port.c_str())) < 0) {
-        ERR("Unable to connect to (%s) on port (%d)\r\n", ip_domain.c_str(), atoi(port.c_str()));
+    while (socket.connect(host, port) < 0) {
+        ERR("Unable to connect to (%s) on port (%d)", host, port);
         wait(0.2);
+        return false;
     }
 
     // sent http header to upgrade to the ws protocol
-    sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str());
+    sprintf(cmd, "GET %s HTTP/1.1\r\n", path);
     write(cmd, strlen(cmd));
-
-    sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str());
+    
+    sprintf(cmd, "Host: %s:%d\r\n", host, port);
     write(cmd, strlen(cmd));
 
     sprintf(cmd, "Upgrade: WebSocket\r\n");
@@ -117,7 +172,7 @@
         return false;
     }
 
-    INFO("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n", ip_domain.c_str(), path.c_str(), port.c_str());
+    INFO("\r\nhost: %s\r\npath: %s\r\nport: %d\r\n\r\n", host, path, port);
     return true;
 }
 
@@ -260,7 +315,7 @@
     return socket.is_connected();
 }
 
-std::string Websocket::getPath() {
+char* Websocket::getPath() {
     return path;
 }
 
--- a/Websocket.h	Wed Aug 29 13:49:48 2012 +0000
+++ b/Websocket.h	Wed Aug 29 15:27:51 2012 +0000
@@ -32,7 +32,6 @@
 #define WEBSOCKET_H
 
 #include "mbed.h"
-#include <string>
 
 #include "TCPSocketConnection.h"
 
@@ -120,19 +119,21 @@
         *
         * @return path
         */
-        std::string getPath();
+        char* getPath();
 
     private:
 
         void fillFields(char * url);
+        int parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen); //Parse URL
         int sendOpcode(uint8_t opcode, char * msg);
         int sendLength(uint32_t len, char * msg);
         int sendMask(char * msg);
         int readChar(char * pC, bool block = true);
-
-        std::string ip_domain;
-        std::string path;
-        std::string port;
+        
+        char scheme[8];
+        uint16_t port;
+        char host[32];
+        char path[64];
         
         TCPSocketConnection socket;