WebSocket client library

Committer:
samux
Date:
Tue Aug 30 11:47:56 2011 +0000
Revision:
14:c5ac3e26998f
Parent:
13:3b058372cad9
Child:
15:79bfbc0ad6bc

        

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