WebSocket client library

Committer:
samux
Date:
Thu Aug 25 06:09:01 2011 +0000
Revision:
10:4f02275c34ee
Parent:
9:9fa055ed54b4
Child:
12:1f6b9451a608

        

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