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:
Mon Jul 08 02:43:43 2013 +0000
Revision:
2:2979735cb379
Parent:
0:5e68215d973a
Child:
3:529ce2bcfe77
header update

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 0:5e68215d973a 70 char buffer[256];
ansond 0:5e68215d973a 71 char *json = this->prepareSocketIOJSONMessage(name,args,buffer);
ansond 0:5e68215d973a 72
ansond 0:5e68215d973a 73 // send the message
ansond 0:5e68215d973a 74 bytesSent = this->ws->send(json);
ansond 0:5e68215d973a 75 }
ansond 0:5e68215d973a 76
ansond 0:5e68215d973a 77 return bytesSent;
ansond 0:5e68215d973a 78 }
ansond 0:5e68215d973a 79
ansond 0:5e68215d973a 80 // read a message from the SocketIO server
ansond 0:5e68215d973a 81 bool SocketIO::read(char * message) {
ansond 0:5e68215d973a 82 bool didRead = false;
ansond 0:5e68215d973a 83
ansond 0:5e68215d973a 84 // only read if we are connected
ansond 0:5e68215d973a 85 if (this->is_connected() == true && message != NULL) {
ansond 0:5e68215d973a 86 // attempt a read
ansond 0:5e68215d973a 87 didRead = this->ws->read(message);
ansond 0:5e68215d973a 88 }
ansond 0:5e68215d973a 89
ansond 0:5e68215d973a 90 // return our status
ansond 0:5e68215d973a 91 return didRead;
ansond 0:5e68215d973a 92 }
ansond 0:5e68215d973a 93
ansond 0:5e68215d973a 94 // Are we connected?
ansond 0:5e68215d973a 95 bool SocketIO::is_connected() {
ansond 0:5e68215d973a 96 bool isConnected = false;
ansond 0:5e68215d973a 97
ansond 0:5e68215d973a 98 // if we have an endpoint - get its connection status
ansond 0:5e68215d973a 99 if (this->ws != NULL) isConnected = this->ws->is_connected();
ansond 0:5e68215d973a 100
ansond 0:5e68215d973a 101 return isConnected;
ansond 0:5e68215d973a 102 }
ansond 0:5e68215d973a 103
ansond 0:5e68215d973a 104 // Private Methods
ansond 0:5e68215d973a 105
ansond 0:5e68215d973a 106 // prepare a SocketIO compatible JSON packet
ansond 0:5e68215d973a 107 char *SocketIO::prepareSocketIOJSONMessage(char *name, char *args, char *buffer) {
ansond 0:5e68215d973a 108 sprintf(buffer,"5:::{\"name\": \"%s\", \"args\": \"%s\"}",name, args);
ansond 0:5e68215d973a 109 return buffer;
ansond 0:5e68215d973a 110 }
ansond 0:5e68215d973a 111
ansond 0:5e68215d973a 112 // prepare the session URL
ansond 0:5e68215d973a 113 void SocketIO::prepareSessionURL() {
ansond 0:5e68215d973a 114 // allocate the buffer
ansond 0:5e68215d973a 115 this->url_session = new char[256];
ansond 0:5e68215d973a 116
ansond 0:5e68215d973a 117 // fill the buffer
ansond 0:5e68215d973a 118 sprintf(this->url_session,"ws://%s/%s/%s",this->url,this->ws_channel,this->session_key);
ansond 0:5e68215d973a 119 }
ansond 0:5e68215d973a 120
ansond 0:5e68215d973a 121 // attempt a connection via websockets
ansond 0:5e68215d973a 122 bool SocketIO::attemptWebSocketConnect() {
ansond 0:5e68215d973a 123 // attempt connect
ansond 0:5e68215d973a 124 int status = 0;
ansond 0:5e68215d973a 125 for(int i=0;i<10;++i) {
ansond 0:5e68215d973a 126 status = this->ws->connect();
ansond 0:5e68215d973a 127 if (status != 0) i = 10;
ansond 0:5e68215d973a 128 }
ansond 0:5e68215d973a 129
ansond 0:5e68215d973a 130 // set the socket.io connect command
ansond 0:5e68215d973a 131 if (this->ws->is_connected()) this->ws->send("1::");
ansond 0:5e68215d973a 132
ansond 0:5e68215d973a 133 // return connection status
ansond 0:5e68215d973a 134 return this->is_connected();
ansond 0:5e68215d973a 135 }
ansond 0:5e68215d973a 136
ansond 0:5e68215d973a 137 // prepare the session key URL
ansond 0:5e68215d973a 138 void SocketIO::prepareSessionKeyURL(char *myurl, int myversion) {
ansond 0:5e68215d973a 139 // save the base URL
ansond 0:5e68215d973a 140 this->url = myurl;
ansond 0:5e68215d973a 141
ansond 0:5e68215d973a 142 // set our version
ansond 0:5e68215d973a 143 this->version = myversion;
ansond 0:5e68215d973a 144
ansond 0:5e68215d973a 145 // build out the session key URL
ansond 0:5e68215d973a 146 this->url_session_key = new char[256];
ansond 0:5e68215d973a 147 time_t seconds = time(NULL);
ansond 0:5e68215d973a 148 sprintf(this->url_session_key,"http://%s/socket.io/%d/?t=%d",this->url,this->version,seconds);
ansond 0:5e68215d973a 149
ansond 0:5e68215d973a 150 // setup the session key and channel buffers
ansond 0:5e68215d973a 151 this->session_key = new char[128];
ansond 0:5e68215d973a 152 this->ws_channel = new char[128];
ansond 0:5e68215d973a 153 }
ansond 0:5e68215d973a 154
ansond 0:5e68215d973a 155 // parse the socket.io session key
ansond 0:5e68215d973a 156 void SocketIO::parseSessionKey(char *response, char *sessionkey, char *channel) {
ansond 0:5e68215d973a 157 int val1 = 0;
ansond 0:5e68215d973a 158 int val2 = 0;
ansond 0:5e68215d973a 159
ansond 0:5e68215d973a 160 // convert ":" to " "
ansond 0:5e68215d973a 161 for(int i=0;i<strlen(response);++i) if (response[i] == ':') response[i] = ' ';
ansond 0:5e68215d973a 162
ansond 0:5e68215d973a 163 // format: Session_ID YY ZZ CHANNEL
ansond 0:5e68215d973a 164 char t_sessionkey[128];
ansond 0:5e68215d973a 165 sscanf(response,"%s %d %d %s",t_sessionkey,&val1,&val2,channel);
ansond 0:5e68215d973a 166
ansond 0:5e68215d973a 167 // create
ansond 0:5e68215d973a 168 sprintf(sessionkey,"%s/%s",channel,t_sessionkey);
ansond 0:5e68215d973a 169 }
ansond 0:5e68215d973a 170
ansond 0:5e68215d973a 171 // acquire the session key for our session
ansond 0:5e68215d973a 172 bool SocketIO::acquireSessionKey() {
ansond 0:5e68215d973a 173 bool haveKey = false;
ansond 0:5e68215d973a 174 HTTPClient http;
ansond 0:5e68215d973a 175 char response[513];
ansond 0:5e68215d973a 176
ansond 0:5e68215d973a 177 // make sure we have buffers
ansond 0:5e68215d973a 178 if (this->session_key != NULL && this->ws_channel != NULL) {
ansond 0:5e68215d973a 179 // request our session key
ansond 0:5e68215d973a 180 int nread = http.get(this->url_session_key,response,512);
ansond 0:5e68215d973a 181
ansond 0:5e68215d973a 182 // parse the session key
ansond 0:5e68215d973a 183 if (!nread)
ansond 0:5e68215d973a 184 // parse into the session key
ansond 0:5e68215d973a 185 this->parseSessionKey(response,this->session_key,this->ws_channel);
ansond 0:5e68215d973a 186
ansond 0:5e68215d973a 187 // update our status
ansond 0:5e68215d973a 188 if (strlen(this->session_key) > 0) haveKey = true;
ansond 0:5e68215d973a 189 }
ansond 0:5e68215d973a 190
ansond 0:5e68215d973a 191 // return status
ansond 0:5e68215d973a 192 return haveKey;
ansond 0:5e68215d973a 193 }