WebSocket client library

Committer:
samux
Date:
Wed Aug 24 11:35:49 2011 +0000
Revision:
7:b15978708360
Parent:
6:01a1eb7c0145
Child:
8:ecd914cffdf6

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 0:21fe3b05249f 1 #include "Websocket.h"
samux 6:01a1eb7c0145 2 #include <string>
samux 0:21fe3b05249f 3
samux 6:01a1eb7c0145 4 Websocket::Websocket(char * url, Wifly * wifi) {
samux 6:01a1eb7c0145 5 this->wifi = wifi;
samux 6:01a1eb7c0145 6 wifi_use = true;
samux 6:01a1eb7c0145 7 eth_use = false;
samux 6:01a1eb7c0145 8 fillFields(wifi_use, url);
samux 6:01a1eb7c0145 9 }
samux 6:01a1eb7c0145 10
samux 6:01a1eb7c0145 11 void Websocket::fillFields(bool wifi, char * url) {
samux 0:21fe3b05249f 12 char *res = NULL;
samux 6:01a1eb7c0145 13 char *res1 = NULL;
samux 6:01a1eb7c0145 14
samux 0:21fe3b05249f 15 char buf[30];
samux 0:21fe3b05249f 16 strcpy(buf, url);
samux 6:01a1eb7c0145 17
samux 0:21fe3b05249f 18 res = strtok(buf, ":");
samux 6:01a1eb7c0145 19 if (strcmp(res, "ws"))
samux 0:21fe3b05249f 20 {
samux 0:21fe3b05249f 21 this->ip_domain = NULL;
samux 0:21fe3b05249f 22 this->path = NULL;
samux 6:01a1eb7c0145 23 printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n");
samux 6:01a1eb7c0145 24 }
samux 6:01a1eb7c0145 25 else
samux 0:21fe3b05249f 26 {
samux 6:01a1eb7c0145 27 //ip_domain and port
samux 6:01a1eb7c0145 28 res = strtok(NULL, "/");
samux 6:01a1eb7c0145 29
samux 6:01a1eb7c0145 30 //path
samux 6:01a1eb7c0145 31 res1 = strtok(NULL, " ");
samux 6:01a1eb7c0145 32 if (res1 != NULL) {
samux 6:01a1eb7c0145 33 path = (char *) malloc (sizeof(char) * strlen(res1));
samux 6:01a1eb7c0145 34 strcpy(this->path, res1);
samux 6:01a1eb7c0145 35 }
samux 6:01a1eb7c0145 36
samux 6:01a1eb7c0145 37 //ip_domain
samux 6:01a1eb7c0145 38 res = strtok(res, ":");
samux 7:b15978708360 39
samux 7:b15978708360 40 //port
samux 7:b15978708360 41 res1 = strtok(NULL, " ");
samux 7:b15978708360 42 //port
samux 7:b15978708360 43 if (res1 != NULL) {
samux 7:b15978708360 44 port = (char *) malloc (sizeof(char) * strlen(res1));
samux 7:b15978708360 45 strcpy(this->port, res1);
samux 7:b15978708360 46 } else {
samux 7:b15978708360 47 port = (char *) malloc (sizeof(char) * 3);
samux 7:b15978708360 48 strcpy(this->port, "80");
samux 7:b15978708360 49 }
samux 7:b15978708360 50
samux 6:01a1eb7c0145 51 if (res != NULL) {
samux 0:21fe3b05249f 52 ip_domain = (char *) malloc (sizeof(char) * strlen(res));
samux 0:21fe3b05249f 53 strcpy(this->ip_domain, res);
samux 6:01a1eb7c0145 54 //if we use ethernet, we must decode ip address or use dnsresolver
samux 6:01a1eb7c0145 55 if (!wifi) {
samux 6:01a1eb7c0145 56 strcpy(buf, res);
samux 6:01a1eb7c0145 57 //we try to decode the ip address
samux 6:01a1eb7c0145 58 if (buf[0] >= '0' && buf[0] <= '9') {
samux 6:01a1eb7c0145 59 res = strtok(buf, ".");
samux 6:01a1eb7c0145 60 int i = 0;
samux 6:01a1eb7c0145 61 int ip[4];
samux 6:01a1eb7c0145 62 while (res != NULL) {
samux 6:01a1eb7c0145 63 ip[i] = atoi(res);
samux 6:01a1eb7c0145 64 res = strtok(NULL, ".");
samux 6:01a1eb7c0145 65 i++;
samux 6:01a1eb7c0145 66 }
samux 6:01a1eb7c0145 67 server_ip = IpAddr(ip[0], ip[1], ip[2], ip[3]);
samux 6:01a1eb7c0145 68 printf("server=%i.%i.%i.%i\n",server_ip[0],server_ip[1],server_ip[2],server_ip[3]);
samux 6:01a1eb7c0145 69 }
samux 6:01a1eb7c0145 70 //we must use dnsresolver to find the ip address
samux 6:01a1eb7c0145 71 else {
samux 6:01a1eb7c0145 72 DNSResolver dr;
samux 6:01a1eb7c0145 73 server_ip = dr.resolveName(buf);
samux 6:01a1eb7c0145 74 printf("server=%i.%i.%i.%i\n",server_ip[0],server_ip[1],server_ip[2],server_ip[3]);
samux 6:01a1eb7c0145 75 }
samux 6:01a1eb7c0145 76 }
samux 0:21fe3b05249f 77 }
samux 0:21fe3b05249f 78 }
samux 0:21fe3b05249f 79 }
samux 0:21fe3b05249f 80
samux 6:01a1eb7c0145 81
samux 6:01a1eb7c0145 82 Websocket::Websocket(char * url) {
samux 6:01a1eb7c0145 83 wifi_use = false;
samux 6:01a1eb7c0145 84 eth_use = true;
samux 6:01a1eb7c0145 85 eth_writeable = false;
samux 6:01a1eb7c0145 86 eth_readable = false;
samux 6:01a1eb7c0145 87 eth_connected = false;
samux 6:01a1eb7c0145 88 fillFields(wifi_use, url);
samux 6:01a1eb7c0145 89 }
samux 6:01a1eb7c0145 90
samux 6:01a1eb7c0145 91
samux 6:01a1eb7c0145 92
samux 6:01a1eb7c0145 93
samux 6:01a1eb7c0145 94 bool Websocket::connect() {
samux 0:21fe3b05249f 95 char cmd[50];
samux 6:01a1eb7c0145 96 if ( wifi_use ) {
samux 6:01a1eb7c0145 97 wifi->Send("exit\r", "NO");
samux 6:01a1eb7c0145 98 //enter in cmd mode
samux 6:01a1eb7c0145 99 while (!wifi->Send("$$$", "CMD")) {
samux 6:01a1eb7c0145 100 printf("cannot enter in CMD mode\r\n");
samux 6:01a1eb7c0145 101 wifi->exit();
samux 6:01a1eb7c0145 102 }
samux 6:01a1eb7c0145 103
samux 6:01a1eb7c0145 104
samux 6:01a1eb7c0145 105 //open the connection
samux 6:01a1eb7c0145 106 sprintf(cmd, "open %s %s\r\n", ip_domain, port);
samux 6:01a1eb7c0145 107 if (!wifi->Send(cmd, "OPEN")) {
samux 6:01a1eb7c0145 108 printf("Websocket::connect cannot open\r\n");
samux 6:01a1eb7c0145 109 return false;
samux 6:01a1eb7c0145 110 }
samux 6:01a1eb7c0145 111
samux 6:01a1eb7c0145 112
samux 6:01a1eb7c0145 113 //send websocket HTTP header
samux 6:01a1eb7c0145 114 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path);
samux 6:01a1eb7c0145 115 wifi->Send(cmd, "NO");
samux 6:01a1eb7c0145 116
samux 6:01a1eb7c0145 117 sprintf(cmd, "Host: %s:%s\r\n", ip_domain, port);
samux 6:01a1eb7c0145 118 wifi->Send(cmd, "NO");
samux 6:01a1eb7c0145 119
samux 6:01a1eb7c0145 120 wifi->Send("Upgrade: WebSocket\r\n", "NO");
samux 6:01a1eb7c0145 121
samux 6:01a1eb7c0145 122 sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain, port);
samux 6:01a1eb7c0145 123 wifi->Send(cmd, "NO");
samux 6:01a1eb7c0145 124
samux 6:01a1eb7c0145 125
samux 6:01a1eb7c0145 126 wifi->Send("Connection: Upgrade\r\n", "NO");
samux 6:01a1eb7c0145 127 wifi->Send("Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n", "NO");
samux 6:01a1eb7c0145 128 wifi->Send("Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n", "NO");
samux 6:01a1eb7c0145 129 if (!wifi->Send("^n:ds[4U", "8jKS'y:G*Co,Wxa-"))
samux 6:01a1eb7c0145 130 return false;
samux 6:01a1eb7c0145 131
samux 6:01a1eb7c0145 132 printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain, this->path, this->port);
samux 6:01a1eb7c0145 133 return true;
samux 6:01a1eb7c0145 134 } else if ( eth_use ) {
samux 6:01a1eb7c0145 135 int i = 0;
samux 6:01a1eb7c0145 136
samux 6:01a1eb7c0145 137 EthernetErr ethErr = eth.setup();
samux 6:01a1eb7c0145 138 if (ethErr) {
samux 6:01a1eb7c0145 139 printf("Error %d in setup.\r\n", ethErr);
samux 6:01a1eb7c0145 140 return false;
samux 6:01a1eb7c0145 141 }
samux 6:01a1eb7c0145 142
samux 6:01a1eb7c0145 143 printf("setup OK\r\n");
samux 6:01a1eb7c0145 144
samux 6:01a1eb7c0145 145 IpAddr ipt = eth.getIp();
samux 6:01a1eb7c0145 146 printf("mbed IP Address is %d.%d.%d.%d\r\n", ipt[0], ipt[1], ipt[2], ipt[3]);
samux 6:01a1eb7c0145 147
samux 6:01a1eb7c0145 148 sock.setOnEvent(this, &Websocket::onTCPSocketEvent);
samux 6:01a1eb7c0145 149 Host server (server_ip, atoi(port));
samux 6:01a1eb7c0145 150 TCPSocketErr bindErr = sock.connect(server);
samux 6:01a1eb7c0145 151 if (bindErr) {
samux 6:01a1eb7c0145 152 printf("binderr: %d", bindErr);
samux 6:01a1eb7c0145 153 return false;
samux 6:01a1eb7c0145 154 }
samux 7:b15978708360 155 printf("port: %d\r\n", atoi(port));
samux 6:01a1eb7c0145 156
samux 6:01a1eb7c0145 157
samux 6:01a1eb7c0145 158 Timer tmr;
samux 6:01a1eb7c0145 159 tmr.start();
samux 6:01a1eb7c0145 160 char msg[10];
samux 0:21fe3b05249f 161
samux 6:01a1eb7c0145 162 while (true) {
samux 6:01a1eb7c0145 163 Net::poll();
samux 6:01a1eb7c0145 164 if (tmr.read() > 0.1) {
samux 6:01a1eb7c0145 165 tmr.reset();
samux 6:01a1eb7c0145 166 if (eth_connected) {
samux 6:01a1eb7c0145 167 switch (i) {
samux 6:01a1eb7c0145 168 case 0:
samux 6:01a1eb7c0145 169 sprintf(cmd, "GET /%s HTTP/1.1\r\n", path);
samux 6:01a1eb7c0145 170 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 171 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 172 i++;
samux 6:01a1eb7c0145 173 break;
samux 6:01a1eb7c0145 174 case 1:
samux 6:01a1eb7c0145 175 sprintf(cmd, "Host: %s:%s\r\n", ip_domain, port);
samux 6:01a1eb7c0145 176 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 177 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 178 i++;
samux 6:01a1eb7c0145 179 break;
samux 6:01a1eb7c0145 180 case 2:
samux 6:01a1eb7c0145 181 sprintf(cmd, "Upgrade: WebSocket\r\n");
samux 6:01a1eb7c0145 182 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 183 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 184 i++;
samux 6:01a1eb7c0145 185 break;
samux 6:01a1eb7c0145 186 case 3:
samux 6:01a1eb7c0145 187 sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain, port);
samux 6:01a1eb7c0145 188 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 189 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 190 i++;
samux 6:01a1eb7c0145 191 break;
samux 6:01a1eb7c0145 192 case 4:
samux 6:01a1eb7c0145 193 sprintf(cmd, "Connection: Upgrade\r\n");
samux 6:01a1eb7c0145 194 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 195 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 196 i++;
samux 6:01a1eb7c0145 197 break;
samux 6:01a1eb7c0145 198 case 5:
samux 6:01a1eb7c0145 199 sprintf(cmd, "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n");
samux 6:01a1eb7c0145 200 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 201 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 202 i++;
samux 6:01a1eb7c0145 203 break;
samux 6:01a1eb7c0145 204 case 6:
samux 6:01a1eb7c0145 205 sprintf(cmd, "Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n");
samux 6:01a1eb7c0145 206 sock.send(cmd, strlen(cmd));
samux 7:b15978708360 207 printf("cmd: %s\r\n", cmd);
samux 6:01a1eb7c0145 208 i++;
samux 6:01a1eb7c0145 209 break;
samux 6:01a1eb7c0145 210 case 7:
samux 6:01a1eb7c0145 211 sock.send("^n:ds[4U", 8);
samux 6:01a1eb7c0145 212 i++;
samux 6:01a1eb7c0145 213 break;
samux 6:01a1eb7c0145 214 case 8:
samux 6:01a1eb7c0145 215 if(eth_readable)
samux 6:01a1eb7c0145 216 {
samux 6:01a1eb7c0145 217 string checking;
samux 6:01a1eb7c0145 218 size_t found = string::npos;
samux 6:01a1eb7c0145 219 sock.recv(msg, 10);
samux 6:01a1eb7c0145 220 Net::poll();
samux 6:01a1eb7c0145 221 checking = msg;
samux 6:01a1eb7c0145 222 found = checking.find("HTTP");
samux 6:01a1eb7c0145 223 if(found != string::npos)
samux 6:01a1eb7c0145 224 {
samux 7:b15978708360 225 printf("checking: %s\r\n", checking);
samux 6:01a1eb7c0145 226 i++;
samux 6:01a1eb7c0145 227 break;
samux 6:01a1eb7c0145 228 }
samux 6:01a1eb7c0145 229 else
samux 6:01a1eb7c0145 230 return false;
samux 6:01a1eb7c0145 231 }
samux 6:01a1eb7c0145 232 break;
samux 6:01a1eb7c0145 233
samux 6:01a1eb7c0145 234 default:
samux 6:01a1eb7c0145 235 break;
samux 6:01a1eb7c0145 236 }
samux 6:01a1eb7c0145 237 }
samux 6:01a1eb7c0145 238 if (i==9)
samux 6:01a1eb7c0145 239 {
samux 6:01a1eb7c0145 240 printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain, this->path, this->port);
samux 6:01a1eb7c0145 241 return true;
samux 6:01a1eb7c0145 242 }
samux 6:01a1eb7c0145 243 }
samux 6:01a1eb7c0145 244 }
samux 6:01a1eb7c0145 245
samux 0:21fe3b05249f 246 }
samux 0:21fe3b05249f 247 return true;
samux 0:21fe3b05249f 248 }
samux 0:21fe3b05249f 249
samux 6:01a1eb7c0145 250 void Websocket::Send(char * str) {
samux 0:21fe3b05249f 251 char cmd[100];
samux 6:01a1eb7c0145 252 if (wifi_use) {
samux 6:01a1eb7c0145 253 wifi->putc('\x00');
samux 6:01a1eb7c0145 254 sprintf(cmd, "%s%c", str, '\xff');
samux 6:01a1eb7c0145 255 wifi->Send(cmd, "NO");
samux 6:01a1eb7c0145 256 } else if (eth_use) {
samux 6:01a1eb7c0145 257 sprintf(cmd, "%c%s%c", 0x00, str, 0xff);
samux 6:01a1eb7c0145 258 Net::poll();
samux 6:01a1eb7c0145 259 sock.send(cmd, strlen(cmd + 1) + 1);
samux 6:01a1eb7c0145 260 }
samux 0:21fe3b05249f 261 }
samux 0:21fe3b05249f 262
samux 6:01a1eb7c0145 263 bool Websocket::read(char * message) {
samux 0:21fe3b05249f 264 int i = 0;
samux 0:21fe3b05249f 265 char char_read;
samux 6:01a1eb7c0145 266
samux 6:01a1eb7c0145 267 if (!wifi->readable()) {
samux 0:21fe3b05249f 268 message = NULL;
samux 0:21fe3b05249f 269 return false;
samux 0:21fe3b05249f 270 }
samux 6:01a1eb7c0145 271
samux 6:01a1eb7c0145 272 if (wifi->getc() != 0x00) {
samux 0:21fe3b05249f 273 message = NULL;
samux 0:21fe3b05249f 274 return false;
samux 0:21fe3b05249f 275 }
samux 6:01a1eb7c0145 276
samux 0:21fe3b05249f 277 while ( (char_read = wifi->getc()) != 0xff)
samux 0:21fe3b05249f 278 message[i++] = char_read;
samux 6:01a1eb7c0145 279
samux 0:21fe3b05249f 280 return true;
samux 0:21fe3b05249f 281 }
samux 0:21fe3b05249f 282
samux 6:01a1eb7c0145 283 bool Websocket::close() {
samux 6:01a1eb7c0145 284 if (!wifi->CmdMode()) {
samux 0:21fe3b05249f 285 printf("Websocket::close: cannot enter in cmd mode\r\n");
samux 0:21fe3b05249f 286 return false;
samux 0:21fe3b05249f 287 }
samux 6:01a1eb7c0145 288
samux 0:21fe3b05249f 289 wifi->Send("close\r", "NO");
samux 6:01a1eb7c0145 290
samux 6:01a1eb7c0145 291 if (!wifi->exit())
samux 0:21fe3b05249f 292 return false;
samux 6:01a1eb7c0145 293
samux 0:21fe3b05249f 294 return true;
samux 0:21fe3b05249f 295 }
samux 0:21fe3b05249f 296
samux 0:21fe3b05249f 297
samux 0:21fe3b05249f 298
samux 6:01a1eb7c0145 299 bool Websocket::connected() {
samux 6:01a1eb7c0145 300 if (wifi_use) {
samux 6:01a1eb7c0145 301 char str[10];
samux 6:01a1eb7c0145 302
samux 6:01a1eb7c0145 303 wait(0.25);
samux 6:01a1eb7c0145 304 if (!wifi->CmdMode()) {
samux 6:01a1eb7c0145 305 printf("Websocket::connected: cannot enter in cmd mode\r\n");
samux 0:21fe3b05249f 306 return false;
samux 3:9b00db719afa 307 }
samux 6:01a1eb7c0145 308 wait(0.25);
samux 6:01a1eb7c0145 309
samux 6:01a1eb7c0145 310 wifi->Send("show c\r\n", "NO");
samux 6:01a1eb7c0145 311 wifi->read(str);
samux 6:01a1eb7c0145 312
samux 6:01a1eb7c0145 313 if (str[3] == '1') {
samux 6:01a1eb7c0145 314 if (!wifi->exit()) {
samux 6:01a1eb7c0145 315 printf("Websocket::connected: cannot exit\r\n");
samux 6:01a1eb7c0145 316 return false;
samux 6:01a1eb7c0145 317 }
samux 6:01a1eb7c0145 318 return true;
samux 6:01a1eb7c0145 319 }
samux 6:01a1eb7c0145 320 if (!wifi->exit())
samux 6:01a1eb7c0145 321 printf("Websocket::connected: cannot exit\r\n");
samux 6:01a1eb7c0145 322 return false;
samux 6:01a1eb7c0145 323 }
samux 6:01a1eb7c0145 324 else if (eth_use)
samux 6:01a1eb7c0145 325 return eth_connected;
samux 6:01a1eb7c0145 326
samux 6:01a1eb7c0145 327 return true;
samux 6:01a1eb7c0145 328 }
samux 6:01a1eb7c0145 329
samux 6:01a1eb7c0145 330
samux 6:01a1eb7c0145 331
samux 6:01a1eb7c0145 332
samux 6:01a1eb7c0145 333
samux 6:01a1eb7c0145 334 void Websocket::onTCPSocketEvent(TCPSocketEvent e) {
samux 6:01a1eb7c0145 335 switch (e) {
samux 6:01a1eb7c0145 336 case TCPSOCKET_CONNECTED:
samux 6:01a1eb7c0145 337 eth_connected = true;
samux 6:01a1eb7c0145 338 printf("TCP Socket Connected\r\n");
samux 6:01a1eb7c0145 339 break;
samux 6:01a1eb7c0145 340 case TCPSOCKET_WRITEABLE:
samux 6:01a1eb7c0145 341 eth_writeable = true;
samux 6:01a1eb7c0145 342 break;
samux 6:01a1eb7c0145 343 case TCPSOCKET_READABLE:
samux 6:01a1eb7c0145 344 printf("TCP Socket Readable\r\n");
samux 6:01a1eb7c0145 345 eth_readable = true;
samux 6:01a1eb7c0145 346 break;
samux 6:01a1eb7c0145 347 case TCPSOCKET_CONTIMEOUT:
samux 6:01a1eb7c0145 348 printf("TCP Socket Timeout\r\n");
samux 6:01a1eb7c0145 349 eth_connected = false;
samux 6:01a1eb7c0145 350 break;
samux 6:01a1eb7c0145 351 case TCPSOCKET_CONRST:
samux 6:01a1eb7c0145 352 printf("TCP Socket CONRST\r\n");
samux 6:01a1eb7c0145 353 eth_connected = false;
samux 6:01a1eb7c0145 354 break;
samux 6:01a1eb7c0145 355 case TCPSOCKET_CONABRT:
samux 6:01a1eb7c0145 356 printf("TCP Socket CONABRT\r\n");
samux 6:01a1eb7c0145 357 eth_connected = false;
samux 6:01a1eb7c0145 358 break;
samux 6:01a1eb7c0145 359 case TCPSOCKET_ERROR:
samux 6:01a1eb7c0145 360 printf("TCP Socket Error\r\n");
samux 6:01a1eb7c0145 361 eth_connected = false;
samux 6:01a1eb7c0145 362 break;
samux 6:01a1eb7c0145 363 case TCPSOCKET_DISCONNECTED:
samux 6:01a1eb7c0145 364 eth_connected = false;
samux 6:01a1eb7c0145 365 break;
samux 6:01a1eb7c0145 366 default:
samux 6:01a1eb7c0145 367 printf("DEFAULT\r\n");
samux 0:21fe3b05249f 368 }
samux 6:01a1eb7c0145 369 }
samux 6:01a1eb7c0145 370
samux 6:01a1eb7c0145 371