Websocket client. You can only use this class with a Wifly module. If you want to use websockets over ethernet, take a look at the Websocket class.
Websocket.cpp@2:06909bc328c0, 2011-10-20 (annotated)
- Committer:
- samux
- Date:
- Thu Oct 20 09:41:56 2011 +0000
- Revision:
- 2:06909bc328c0
- Parent:
- 0:08afdb5fb5ca
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
samux | 0:08afdb5fb5ca | 1 | #include "Websocket.h" |
samux | 0:08afdb5fb5ca | 2 | #include <string> |
samux | 0:08afdb5fb5ca | 3 | |
samux | 0:08afdb5fb5ca | 4 | Websocket::Websocket(char * url, Wifly * wifi) { |
samux | 0:08afdb5fb5ca | 5 | this->wifi = wifi; |
samux | 0:08afdb5fb5ca | 6 | netif = WIF; |
samux | 0:08afdb5fb5ca | 7 | fillFields(url); |
samux | 0:08afdb5fb5ca | 8 | } |
samux | 0:08afdb5fb5ca | 9 | |
samux | 0:08afdb5fb5ca | 10 | |
samux | 0:08afdb5fb5ca | 11 | void Websocket::fillFields(char * url) { |
samux | 0:08afdb5fb5ca | 12 | char *res = NULL; |
samux | 0:08afdb5fb5ca | 13 | char *res1 = NULL; |
samux | 0:08afdb5fb5ca | 14 | |
samux | 0:08afdb5fb5ca | 15 | char buf[50]; |
samux | 0:08afdb5fb5ca | 16 | strcpy(buf, url); |
samux | 0:08afdb5fb5ca | 17 | |
samux | 0:08afdb5fb5ca | 18 | res = strtok(buf, ":"); |
samux | 0:08afdb5fb5ca | 19 | if (strcmp(res, "ws")) { |
samux | 0:08afdb5fb5ca | 20 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 21 | printf("\r\nFormat error: please use: \"ws://ip-or-domain[:port]/path\"\r\n\r\n"); |
samux | 0:08afdb5fb5ca | 22 | #endif |
samux | 0:08afdb5fb5ca | 23 | } else { |
samux | 0:08afdb5fb5ca | 24 | //ip_domain and port |
samux | 0:08afdb5fb5ca | 25 | res = strtok(NULL, "/"); |
samux | 0:08afdb5fb5ca | 26 | |
samux | 0:08afdb5fb5ca | 27 | //path |
samux | 0:08afdb5fb5ca | 28 | res1 = strtok(NULL, " "); |
samux | 0:08afdb5fb5ca | 29 | if (res1 != NULL) |
samux | 0:08afdb5fb5ca | 30 | path = res1; |
samux | 0:08afdb5fb5ca | 31 | |
samux | 0:08afdb5fb5ca | 32 | //ip_domain |
samux | 0:08afdb5fb5ca | 33 | res = strtok(res, ":"); |
samux | 0:08afdb5fb5ca | 34 | |
samux | 0:08afdb5fb5ca | 35 | //port |
samux | 0:08afdb5fb5ca | 36 | res1 = strtok(NULL, " "); |
samux | 0:08afdb5fb5ca | 37 | //port |
samux | 0:08afdb5fb5ca | 38 | port = (res1 != NULL) ? res1 : "80"; |
samux | 0:08afdb5fb5ca | 39 | |
samux | 0:08afdb5fb5ca | 40 | if (res != NULL) |
samux | 0:08afdb5fb5ca | 41 | ip_domain = res; |
samux | 0:08afdb5fb5ca | 42 | } |
samux | 0:08afdb5fb5ca | 43 | } |
samux | 0:08afdb5fb5ca | 44 | |
samux | 0:08afdb5fb5ca | 45 | |
samux | 0:08afdb5fb5ca | 46 | bool Websocket::connect() { |
samux | 0:08afdb5fb5ca | 47 | char cmd[50]; |
samux | 0:08afdb5fb5ca | 48 | if (netif == WIF) { |
samux | 0:08afdb5fb5ca | 49 | wifi->send("exit\r", "NO"); |
samux | 0:08afdb5fb5ca | 50 | //enter in cmd mode |
samux | 0:08afdb5fb5ca | 51 | while (!wifi->send("$$$", "CMD")) { |
samux | 0:08afdb5fb5ca | 52 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 53 | printf("cannot enter in CMD mode\r\n"); |
samux | 0:08afdb5fb5ca | 54 | #endif |
samux | 0:08afdb5fb5ca | 55 | wifi->exit(); |
samux | 0:08afdb5fb5ca | 56 | } |
samux | 0:08afdb5fb5ca | 57 | |
samux | 0:08afdb5fb5ca | 58 | |
samux | 0:08afdb5fb5ca | 59 | //open the connection |
samux | 0:08afdb5fb5ca | 60 | sprintf(cmd, "open %s %s\r\n", ip_domain.c_str(), port.c_str()); |
samux | 0:08afdb5fb5ca | 61 | if (!wifi->send(cmd, "OPEN*")) { |
samux | 0:08afdb5fb5ca | 62 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 63 | printf("Websocket::connect cannot open\r\n"); |
samux | 0:08afdb5fb5ca | 64 | #endif |
samux | 0:08afdb5fb5ca | 65 | return false; |
samux | 0:08afdb5fb5ca | 66 | } |
samux | 0:08afdb5fb5ca | 67 | |
samux | 0:08afdb5fb5ca | 68 | |
samux | 0:08afdb5fb5ca | 69 | //send websocket HTTP header |
samux | 0:08afdb5fb5ca | 70 | sprintf(cmd, "GET /%s HTTP/1.1\r\n", path.c_str()); |
samux | 0:08afdb5fb5ca | 71 | wifi->send(cmd, "NO"); |
samux | 0:08afdb5fb5ca | 72 | |
samux | 0:08afdb5fb5ca | 73 | sprintf(cmd, "Host: %s:%s\r\n", ip_domain.c_str(), port.c_str()); |
samux | 0:08afdb5fb5ca | 74 | wifi->send(cmd, "NO"); |
samux | 0:08afdb5fb5ca | 75 | |
samux | 0:08afdb5fb5ca | 76 | wifi->send("Upgrade: WebSocket\r\n", "NO"); |
samux | 0:08afdb5fb5ca | 77 | |
samux | 0:08afdb5fb5ca | 78 | sprintf(cmd, "Origin: http:%s:%s\r\n", ip_domain.c_str(), port.c_str()); |
samux | 0:08afdb5fb5ca | 79 | wifi->send(cmd, "NO"); |
samux | 0:08afdb5fb5ca | 80 | |
samux | 0:08afdb5fb5ca | 81 | |
samux | 0:08afdb5fb5ca | 82 | wifi->send("Connection: Upgrade\r\n", "NO"); |
samux | 0:08afdb5fb5ca | 83 | wifi->send("Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n", "NO"); |
samux | 0:08afdb5fb5ca | 84 | wifi->send("Sec-WebSocket-key2: 12998 5 Y3 1 .P00\r\n\r\n", "NO"); |
samux | 0:08afdb5fb5ca | 85 | if (!wifi->send("^n:ds[4U", "8jKS'y:G*Co,Wxa-")) |
samux | 0:08afdb5fb5ca | 86 | return false; |
samux | 0:08afdb5fb5ca | 87 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 88 | printf("\r\nip_domain: %s\r\npath: /%s\r\nport: %s\r\n\r\n",this->ip_domain.c_str(), this->path.c_str(), this->port.c_str()); |
samux | 0:08afdb5fb5ca | 89 | #endif |
samux | 0:08afdb5fb5ca | 90 | return true; |
samux | 0:08afdb5fb5ca | 91 | } |
samux | 0:08afdb5fb5ca | 92 | //the program shouldn't be here |
samux | 0:08afdb5fb5ca | 93 | return false; |
samux | 0:08afdb5fb5ca | 94 | } |
samux | 0:08afdb5fb5ca | 95 | |
samux | 0:08afdb5fb5ca | 96 | void Websocket::send(char * str) { |
samux | 0:08afdb5fb5ca | 97 | if (netif == WIF) { |
samux | 0:08afdb5fb5ca | 98 | wifi->putc('\x00'); |
samux | 0:08afdb5fb5ca | 99 | wifi->send(str, "NO"); |
samux | 0:08afdb5fb5ca | 100 | wifi->putc('\xff'); |
samux | 0:08afdb5fb5ca | 101 | } |
samux | 0:08afdb5fb5ca | 102 | } |
samux | 0:08afdb5fb5ca | 103 | |
samux | 0:08afdb5fb5ca | 104 | bool Websocket::read(char * message) { |
samux | 0:08afdb5fb5ca | 105 | int i = 0; |
samux | 0:08afdb5fb5ca | 106 | |
samux | 0:08afdb5fb5ca | 107 | if (netif == WIF) { |
samux | 0:08afdb5fb5ca | 108 | if (!wifi->read(message)) |
samux | 0:08afdb5fb5ca | 109 | return false; |
samux | 0:08afdb5fb5ca | 110 | |
samux | 0:08afdb5fb5ca | 111 | //we check if the first byte is 0x00 |
samux | 0:08afdb5fb5ca | 112 | if (message == NULL || message[0] != 0x00) { |
samux | 0:08afdb5fb5ca | 113 | message = NULL; |
samux | 0:08afdb5fb5ca | 114 | return false; |
samux | 0:08afdb5fb5ca | 115 | } |
samux | 0:08afdb5fb5ca | 116 | |
samux | 0:08afdb5fb5ca | 117 | while (message[i + 1] != 0xff && i < strlen(message + 1)) |
samux | 0:08afdb5fb5ca | 118 | i++; |
samux | 0:08afdb5fb5ca | 119 | |
samux | 0:08afdb5fb5ca | 120 | if (message[i+1] == 0xff) { |
samux | 0:08afdb5fb5ca | 121 | message[i+1] = 0; |
samux | 0:08afdb5fb5ca | 122 | memcpy(message, message + 1, strlen(message + 1) + 1); |
samux | 0:08afdb5fb5ca | 123 | return true; |
samux | 0:08afdb5fb5ca | 124 | } else { |
samux | 0:08afdb5fb5ca | 125 | message = NULL; |
samux | 0:08afdb5fb5ca | 126 | return false; |
samux | 0:08afdb5fb5ca | 127 | } |
samux | 0:08afdb5fb5ca | 128 | } |
samux | 0:08afdb5fb5ca | 129 | //the program shouldn't be here |
samux | 0:08afdb5fb5ca | 130 | return false; |
samux | 0:08afdb5fb5ca | 131 | } |
samux | 0:08afdb5fb5ca | 132 | |
samux | 0:08afdb5fb5ca | 133 | bool Websocket::close() { |
samux | 0:08afdb5fb5ca | 134 | if (netif == WIF) { |
samux | 0:08afdb5fb5ca | 135 | if (!wifi->cmdMode()) { |
samux | 0:08afdb5fb5ca | 136 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 137 | printf("Websocket::close: cannot enter in cmd mode\r\n"); |
samux | 0:08afdb5fb5ca | 138 | #endif |
samux | 0:08afdb5fb5ca | 139 | return false; |
samux | 0:08afdb5fb5ca | 140 | } |
samux | 0:08afdb5fb5ca | 141 | |
samux | 0:08afdb5fb5ca | 142 | wifi->send("close\r", "NO"); |
samux | 0:08afdb5fb5ca | 143 | |
samux | 0:08afdb5fb5ca | 144 | if (!wifi->exit()) |
samux | 0:08afdb5fb5ca | 145 | return false; |
samux | 0:08afdb5fb5ca | 146 | } |
samux | 0:08afdb5fb5ca | 147 | //the program shouldn't be here |
samux | 0:08afdb5fb5ca | 148 | return false; |
samux | 0:08afdb5fb5ca | 149 | } |
samux | 0:08afdb5fb5ca | 150 | |
samux | 0:08afdb5fb5ca | 151 | |
samux | 0:08afdb5fb5ca | 152 | |
samux | 0:08afdb5fb5ca | 153 | bool Websocket::connected() { |
samux | 0:08afdb5fb5ca | 154 | if (netif == WIF) { |
samux | 0:08afdb5fb5ca | 155 | char str[10]; |
samux | 0:08afdb5fb5ca | 156 | |
samux | 0:08afdb5fb5ca | 157 | wait(0.25); |
samux | 0:08afdb5fb5ca | 158 | if (!wifi->cmdMode()) { |
samux | 0:08afdb5fb5ca | 159 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 160 | printf("Websocket::connected: cannot enter in cmd mode\r\n"); |
samux | 0:08afdb5fb5ca | 161 | #endif |
samux | 0:08afdb5fb5ca | 162 | return false; |
samux | 0:08afdb5fb5ca | 163 | } |
samux | 0:08afdb5fb5ca | 164 | wait(0.25); |
samux | 0:08afdb5fb5ca | 165 | |
samux | 0:08afdb5fb5ca | 166 | wifi->send("show c\r\n", "NO", str); |
samux | 0:08afdb5fb5ca | 167 | |
samux | 0:08afdb5fb5ca | 168 | if (str[3] == '1') { |
samux | 0:08afdb5fb5ca | 169 | if (!wifi->exit()) { |
samux | 0:08afdb5fb5ca | 170 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 171 | printf("Websocket::connected: cannot exit\r\n"); |
samux | 0:08afdb5fb5ca | 172 | #endif |
samux | 0:08afdb5fb5ca | 173 | return false; |
samux | 0:08afdb5fb5ca | 174 | } |
samux | 0:08afdb5fb5ca | 175 | return true; |
samux | 0:08afdb5fb5ca | 176 | } |
samux | 0:08afdb5fb5ca | 177 | if (!wifi->exit()) { |
samux | 0:08afdb5fb5ca | 178 | #ifdef DEBUG |
samux | 0:08afdb5fb5ca | 179 | printf("Websocket::connected: cannot exit\r\n"); |
samux | 0:08afdb5fb5ca | 180 | #endif |
samux | 0:08afdb5fb5ca | 181 | } |
samux | 0:08afdb5fb5ca | 182 | return false; |
samux | 0:08afdb5fb5ca | 183 | } |
samux | 0:08afdb5fb5ca | 184 | //the program shouldn't be here |
samux | 0:08afdb5fb5ca | 185 | return false; |
samux | 0:08afdb5fb5ca | 186 | } |
samux | 0:08afdb5fb5ca | 187 | |
samux | 0:08afdb5fb5ca | 188 | std::string Websocket::getPath() |
samux | 0:08afdb5fb5ca | 189 | { |
samux | 0:08afdb5fb5ca | 190 | return path; |
samux | 0:08afdb5fb5ca | 191 | } |
samux | 0:08afdb5fb5ca | 192 | |
samux | 0:08afdb5fb5ca | 193 | |
samux | 0:08afdb5fb5ca | 194 | |
samux | 0:08afdb5fb5ca | 195 |