SocketIO is a compatibility library on top of the MBED Websockets API. Currently the broadcast paradigm is supported. There is much more to the SocketIO spec that could be built into this API. Have fun!

Dependents:   df-2013-thermostat-handson df-2013-minihack-thermostat-complete df-2013-minihack-thermostat df-2013-thermostat-remotes ... more

Committer:
ansond
Date:
Sun Nov 10 02:17:45 2013 +0000
Revision:
12:8fe60d9ca3bf
Parent:
11:b32005b69b5c
updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:5e68215d973a 1 #include "SocketIO.h"
ansond 0:5e68215d973a 2
ansond 0:5e68215d973a 3 // constructor
ansond 0:5e68215d973a 4 SocketIO::SocketIO(char * myurl) {
ansond 0:5e68215d973a 5 // prepare the sessionkey URL
ansond 0:5e68215d973a 6 this->prepareSessionKeyURL(myurl, DEFAULT_VERSION);
ansond 0:5e68215d973a 7 }
ansond 0:5e68215d973a 8
ansond 0:5e68215d973a 9 // constructor
ansond 0:5e68215d973a 10 SocketIO::SocketIO(char * myurl, int myversion) {
ansond 0:5e68215d973a 11 // prepare the sessionkey URL
ansond 0:5e68215d973a 12 this->prepareSessionKeyURL(myurl, myversion);
ansond 0:5e68215d973a 13 }
ansond 0:5e68215d973a 14
ansond 0:5e68215d973a 15 // connect to the SocketIO server
ansond 0:5e68215d973a 16 bool SocketIO::connect() {
ansond 0:5e68215d973a 17 bool connected = this->is_connected();
ansond 0:5e68215d973a 18
ansond 0:5e68215d973a 19 // make sure we are not already connected
ansond 0:5e68215d973a 20 if (connected == false) {
ansond 0:5e68215d973a 21 // first we must acquire the session key
ansond 0:5e68215d973a 22 bool connected = this->acquireSessionKey();
ansond 0:5e68215d973a 23
ansond 0:5e68215d973a 24 // next we must create a new URL to connect to with the session key
ansond 0:5e68215d973a 25 if (connected == true) {
ansond 0:5e68215d973a 26 // create our session URL
ansond 0:5e68215d973a 27 this->prepareSessionURL();
ansond 0:5e68215d973a 28
ansond 0:5e68215d973a 29 // allocate our websocket endpoint
ansond 0:5e68215d973a 30 this->ws = new Websocket(this->url_session);
ansond 0:5e68215d973a 31
ansond 0:5e68215d973a 32 // connect!
ansond 0:5e68215d973a 33 connected = this->attemptWebSocketConnect();
ansond 0:5e68215d973a 34 }
ansond 0:5e68215d973a 35 }
ansond 0:5e68215d973a 36
ansond 0:5e68215d973a 37 // return our connection status
ansond 0:5e68215d973a 38 return connected;
ansond 0:5e68215d973a 39 }
ansond 0:5e68215d973a 40
ansond 0:5e68215d973a 41 // gracefully disconnect from the SocketIO server
ansond 0:5e68215d973a 42 bool SocketIO::close() {
ansond 0:5e68215d973a 43 bool closed = false;
ansond 0:5e68215d973a 44
ansond 0:5e68215d973a 45 // if we are connected lets disconnect
ansond 0:5e68215d973a 46 if (this->ws != NULL) {
ansond 2:2979735cb379 47 this->ws->send("0::");
ansond 0:5e68215d973a 48 this->ws->close();
ansond 0:5e68215d973a 49 closed = this->ws->is_connected();
ansond 0:5e68215d973a 50 }
ansond 0:5e68215d973a 51
ansond 0:5e68215d973a 52 // now clean up memory
ansond 0:5e68215d973a 53 if (this->ws != NULL) delete this->ws;
ansond 0:5e68215d973a 54 if (this->url_session != NULL) delete this->url_session;
ansond 0:5e68215d973a 55 if (this->url_session_key != NULL) delete this->url_session_key;
ansond 0:5e68215d973a 56 if (this->session_key != NULL) delete this->session_key;
ansond 0:5e68215d973a 57 if (this->ws_channel != NULL) delete this->ws_channel;
ansond 0:5e68215d973a 58
ansond 0:5e68215d973a 59 // return our status
ansond 0:5e68215d973a 60 return closed;
ansond 0:5e68215d973a 61 }
ansond 0:5e68215d973a 62
ansond 0:5e68215d973a 63 // emit a message (broadcast) to the SocketIO server
ansond 0:5e68215d973a 64 int SocketIO::emit(char *name, char * args) {
ansond 0:5e68215d973a 65 int bytesSent = 0;
ansond 0:5e68215d973a 66
ansond 0:5e68215d973a 67 // only emit if we are connected
ansond 0:5e68215d973a 68 if (this->is_connected() == true) {
ansond 0:5e68215d973a 69 // prepare the JSON message for SocketIO
ansond 11:b32005b69b5c 70 char buffer[512];
ansond 0:5e68215d973a 71 char *json = this->prepareSocketIOJSONMessage(name,args,buffer);
ansond 0:5e68215d973a 72
ansond 3:529ce2bcfe77 73 // send a heartbeat
ansond 9:4f02450a402a 74 bytesSent = this->ws->send("2::");
ansond 3:529ce2bcfe77 75
ansond 0:5e68215d973a 76 // send the message
ansond 9:4f02450a402a 77 if (bytesSent > 0) bytesSent = this->ws->send(json);
ansond 0:5e68215d973a 78 }
ansond 0:5e68215d973a 79
ansond 0:5e68215d973a 80 return bytesSent;
ansond 0:5e68215d973a 81 }
ansond 0:5e68215d973a 82
ansond 0:5e68215d973a 83 // read a message from the SocketIO server
ansond 0:5e68215d973a 84 bool SocketIO::read(char * message) {
ansond 0:5e68215d973a 85 bool didRead = false;
ansond 0:5e68215d973a 86
ansond 0:5e68215d973a 87 // only read if we are connected
ansond 0:5e68215d973a 88 if (this->is_connected() == true && message != NULL) {
ansond 0:5e68215d973a 89 // attempt a read
ansond 0:5e68215d973a 90 didRead = this->ws->read(message);
ansond 0:5e68215d973a 91 }
ansond 0:5e68215d973a 92
ansond 0:5e68215d973a 93 // return our status
ansond 0:5e68215d973a 94 return didRead;
ansond 0:5e68215d973a 95 }
ansond 0:5e68215d973a 96
ansond 0:5e68215d973a 97 // Are we connected?
ansond 0:5e68215d973a 98 bool SocketIO::is_connected() {
ansond 0:5e68215d973a 99 bool isConnected = false;
ansond 0:5e68215d973a 100
ansond 0:5e68215d973a 101 // if we have an endpoint - get its connection status
ansond 0:5e68215d973a 102 if (this->ws != NULL) isConnected = this->ws->is_connected();
ansond 0:5e68215d973a 103
ansond 0:5e68215d973a 104 return isConnected;
ansond 0:5e68215d973a 105 }
ansond 0:5e68215d973a 106
ansond 0:5e68215d973a 107 // Private Methods
ansond 0:5e68215d973a 108
ansond 0:5e68215d973a 109 // prepare a SocketIO compatible JSON packet
ansond 0:5e68215d973a 110 char *SocketIO::prepareSocketIOJSONMessage(char *name, char *args, char *buffer) {
ansond 7:a9bafd7a45fc 111 sprintf(buffer,"5:::{\"name\": \"%s\", \"args\": %s}",name, args);
ansond 0:5e68215d973a 112 return buffer;
ansond 0:5e68215d973a 113 }
ansond 0:5e68215d973a 114
ansond 0:5e68215d973a 115 // prepare the session URL
ansond 0:5e68215d973a 116 void SocketIO::prepareSessionURL() {
ansond 0:5e68215d973a 117 // allocate the buffer
ansond 0:5e68215d973a 118 this->url_session = new char[256];
ansond 0:5e68215d973a 119
ansond 0:5e68215d973a 120 // fill the buffer
ansond 6:f71f8a61dc98 121 sprintf(this->url_session,"ws://%s/socket.io/%d/%s",this->url,this->version,this->session_key);
ansond 0:5e68215d973a 122 }
ansond 0:5e68215d973a 123
ansond 0:5e68215d973a 124 // attempt a connection via websockets
ansond 0:5e68215d973a 125 bool SocketIO::attemptWebSocketConnect() {
ansond 0:5e68215d973a 126 // attempt connect
ansond 0:5e68215d973a 127 int status = 0;
ansond 0:5e68215d973a 128 for(int i=0;i<10;++i) {
ansond 0:5e68215d973a 129 status = this->ws->connect();
ansond 0:5e68215d973a 130 if (status != 0) i = 10;
ansond 0:5e68215d973a 131 }
ansond 0:5e68215d973a 132
ansond 0:5e68215d973a 133 // set the socket.io connect command
ansond 0:5e68215d973a 134 if (this->ws->is_connected()) this->ws->send("1::");
ansond 0:5e68215d973a 135
ansond 0:5e68215d973a 136 // return connection status
ansond 0:5e68215d973a 137 return this->is_connected();
ansond 0:5e68215d973a 138 }
ansond 0:5e68215d973a 139
ansond 0:5e68215d973a 140 // prepare the session key URL
ansond 0:5e68215d973a 141 void SocketIO::prepareSessionKeyURL(char *myurl, int myversion) {
ansond 0:5e68215d973a 142 // save the base URL
ansond 0:5e68215d973a 143 this->url = myurl;
ansond 0:5e68215d973a 144
ansond 0:5e68215d973a 145 // set our version
ansond 0:5e68215d973a 146 this->version = myversion;
ansond 0:5e68215d973a 147
ansond 0:5e68215d973a 148 // build out the session key URL
ansond 0:5e68215d973a 149 this->url_session_key = new char[256];
ansond 0:5e68215d973a 150 time_t seconds = time(NULL);
ansond 0:5e68215d973a 151 sprintf(this->url_session_key,"http://%s/socket.io/%d/?t=%d",this->url,this->version,seconds);
ansond 0:5e68215d973a 152
ansond 0:5e68215d973a 153 // setup the session key and channel buffers
ansond 0:5e68215d973a 154 this->session_key = new char[128];
ansond 0:5e68215d973a 155 this->ws_channel = new char[128];
ansond 0:5e68215d973a 156 }
ansond 0:5e68215d973a 157
ansond 0:5e68215d973a 158 // parse the socket.io session key
ansond 0:5e68215d973a 159 void SocketIO::parseSessionKey(char *response, char *sessionkey, char *channel) {
ansond 0:5e68215d973a 160 int val1 = 0;
ansond 0:5e68215d973a 161 int val2 = 0;
ansond 0:5e68215d973a 162
ansond 0:5e68215d973a 163 // convert ":" to " "
ansond 0:5e68215d973a 164 for(int i=0;i<strlen(response);++i) if (response[i] == ':') response[i] = ' ';
ansond 0:5e68215d973a 165
ansond 0:5e68215d973a 166 // format: Session_ID YY ZZ CHANNEL
ansond 0:5e68215d973a 167 char t_sessionkey[128];
ansond 5:912301390ce1 168 sscanf(response,"%s %d %d %s",t_sessionkey,&val1,&val2,channel);
ansond 0:5e68215d973a 169
ansond 0:5e68215d973a 170 // create
ansond 5:912301390ce1 171 sprintf(sessionkey,"%s/%s",channel,t_sessionkey);
ansond 0:5e68215d973a 172 }
ansond 0:5e68215d973a 173
ansond 0:5e68215d973a 174 // acquire the session key for our session
ansond 0:5e68215d973a 175 bool SocketIO::acquireSessionKey() {
ansond 0:5e68215d973a 176 bool haveKey = false;
ansond 0:5e68215d973a 177 HTTPClient http;
ansond 0:5e68215d973a 178 char response[513];
ansond 12:8fe60d9ca3bf 179 memset(response,'\0',513);
ansond 0:5e68215d973a 180
ansond 0:5e68215d973a 181 // make sure we have buffers
ansond 0:5e68215d973a 182 if (this->session_key != NULL && this->ws_channel != NULL) {
ansond 0:5e68215d973a 183 // request our session key
ansond 0:5e68215d973a 184 int nread = http.get(this->url_session_key,response,512);
ansond 0:5e68215d973a 185
ansond 0:5e68215d973a 186 // parse the session key
ansond 0:5e68215d973a 187 if (!nread)
ansond 0:5e68215d973a 188 // parse into the session key
ansond 0:5e68215d973a 189 this->parseSessionKey(response,this->session_key,this->ws_channel);
ansond 0:5e68215d973a 190
ansond 0:5e68215d973a 191 // update our status
ansond 0:5e68215d973a 192 if (strlen(this->session_key) > 0) haveKey = true;
ansond 0:5e68215d973a 193 }
ansond 0:5e68215d973a 194
ansond 0:5e68215d973a 195 // return status
ansond 0:5e68215d973a 196 return haveKey;
ansond 0:5e68215d973a 197 }