Websocket client. You can only use this class with a Wifly module. If you want to use websockets over ethernet, take a look at the Websocket class.

Websocket.cpp

Committer:
samux
Date:
2011-10-20
Revision:
2:06909bc328c0
Parent:
0:08afdb5fb5ca

File content as of revision 2:06909bc328c0:

#include "Websocket.h"
#include <string>

Websocket::Websocket(char * url, Wifly * wifi) {
    this->wifi = wifi;
    netif = WIF;
    fillFields(url);
}


void Websocket::fillFields(char * url) {
    char *res = NULL;
    char *res1 = NULL;

    char buf[50];
    strcpy(buf, url);

    res = strtok(buf, ":");
    if (strcmp(res, "ws")) {
#ifdef DEBUG
        printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n");
#endif
    } else {
        //ip_domain and port
        res = strtok(NULL, "/");

        //path
        res1 = strtok(NULL, " ");
        if (res1 != NULL)
            path = res1;

        //ip_domain
        res = strtok(res, ":");

        //port
        res1 = strtok(NULL, " ");
        //port
        port = (res1 != NULL) ? res1 : "80";

        if (res != NULL)
            ip_domain = res;
    }
}


bool Websocket::connect() {
    char cmd[50];
    if (netif == WIF) {
        wifi->send("exit\r", "NO");
        //enter in cmd mode
        while (!wifi->send("$$$", "CMD")) {
#ifdef DEBUG
            printf("cannot enter in CMD mode\r\n");
#endif
            wifi->exit();
        }


        //open the connection
        sprintf(cmd, "open %s %s\r\n", ip_domain.c_str(), port.c_str());
        if (!wifi->send(cmd, "OPEN*")) {
#ifdef DEBUG
            printf("Websocket::connect cannot open\r\n");
#endif
            return false;
        }


        //send websocket HTTP header
        sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str());
        wifi->send(cmd, "NO");

        sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str());
        wifi->send(cmd, "NO");

        wifi->send("Upgrade: WebSocket\r\n", "NO");

        sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain.c_str(), port.c_str());
        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;
#ifdef DEBUG
        printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain.c_str(), this->path.c_str(), this->port.c_str());
#endif
        return true;
    }
    //the program shouldn't be here
    return false;
}

void Websocket::send(char * str) {
    if (netif == WIF) {
        wifi->putc('\x00');
        wifi->send(str, "NO");
        wifi->putc('\xff');
    }
}

bool Websocket::read(char * message) {
    int i = 0;

    if (netif == WIF) {
        if (!wifi->read(message))
            return false;

        //we check if the first byte is 0x00
        if (message == NULL || message[0] != 0x00) {
            message = NULL;
            return false;
        }

        while (message[i + 1] != 0xff && i < strlen(message + 1))
            i++;

        if (message[i+1] == 0xff) {
            message[i+1] = 0;
            memcpy(message, message + 1, strlen(message + 1) + 1);
            return true;
        } else {
            message = NULL;
            return false;
        }
    }
    //the program shouldn't be here
    return false;
}

bool Websocket::close() {
    if (netif == WIF) {
        if (!wifi->cmdMode()) {
#ifdef DEBUG
            printf("Websocket::close: cannot enter in cmd mode\r\n");
#endif
            return false;
        }

        wifi->send("close\r", "NO");

        if (!wifi->exit())
            return false;
    }
    //the program shouldn't be here
    return false;
}



bool Websocket::connected() {
    if (netif == WIF) {
        char str[10];

        wait(0.25);
        if (!wifi->cmdMode()) {
#ifdef DEBUG
            printf("Websocket::connected: cannot enter in cmd mode\r\n");
#endif
            return false;
        }
        wait(0.25);

        wifi->send("show c\r\n", "NO", str);

        if (str[3] == '1') {
            if (!wifi->exit()) {
#ifdef DEBUG
                printf("Websocket::connected: cannot exit\r\n");
#endif
                return false;
            }
            return true;
        }
        if (!wifi->exit()) {
#ifdef DEBUG
            printf("Websocket::connected: cannot exit\r\n");
#endif
        }
        return false;
    }
    //the program shouldn't be here
    return false;
}

std::string Websocket::getPath()
{
    return path;
}