Added WebSocket protocol

Committer:
mauricioaschmitz
Date:
Wed Apr 19 21:26:46 2017 +0000
Revision:
0:6d4dbf28d4ee
Added WebSocket protocol

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mauricioaschmitz 0:6d4dbf28d4ee 1 #include "Websocket.h"
mauricioaschmitz 0:6d4dbf28d4ee 2 #include "Pmed_reset.h"
mauricioaschmitz 0:6d4dbf28d4ee 3 #include "Log.h"
mauricioaschmitz 0:6d4dbf28d4ee 4
mauricioaschmitz 0:6d4dbf28d4ee 5 #define MAX_TRY_WRITE 20
mauricioaschmitz 0:6d4dbf28d4ee 6 #define MAX_TRY_READ 10
mauricioaschmitz 0:6d4dbf28d4ee 7 #define MAX_TRY_CONNECT 50
mauricioaschmitz 0:6d4dbf28d4ee 8 #define WAIT_CONNECT_TIME 10000
mauricioaschmitz 0:6d4dbf28d4ee 9
mauricioaschmitz 0:6d4dbf28d4ee 10 //Debug is disabled by default
mauricioaschmitz 0:6d4dbf28d4ee 11 #if 0
mauricioaschmitz 0:6d4dbf28d4ee 12 #define DBG(x, ...) std::printf("[WebSocket : DBG]"x"\r\n", ##__VA_ARGS__);
mauricioaschmitz 0:6d4dbf28d4ee 13 #define WARN(x, ...) std::printf("[WebSocket : WARN]"x"\r\n", ##__VA_ARGS__);
mauricioaschmitz 0:6d4dbf28d4ee 14 #define ERR(x, ...) std::printf("[WebSocket : ERR]"x"\r\n", ##__VA_ARGS__);
mauricioaschmitz 0:6d4dbf28d4ee 15 #else
mauricioaschmitz 0:6d4dbf28d4ee 16 #define DBG(x, ...)
mauricioaschmitz 0:6d4dbf28d4ee 17 #define WARN(x, ...)
mauricioaschmitz 0:6d4dbf28d4ee 18 #define ERR(x, ...)
mauricioaschmitz 0:6d4dbf28d4ee 19 #endif
mauricioaschmitz 0:6d4dbf28d4ee 20
mauricioaschmitz 0:6d4dbf28d4ee 21 #define INFO(x, ...) printf("[WebSocket : INFO]"x"\r\n", ##__VA_ARGS__);
mauricioaschmitz 0:6d4dbf28d4ee 22
mauricioaschmitz 0:6d4dbf28d4ee 23 char * Websocket::captureMessage;
mauricioaschmitz 0:6d4dbf28d4ee 24 bool Websocket::haveMessage;
mauricioaschmitz 0:6d4dbf28d4ee 25 bool Websocket::isConect;
mauricioaschmitz 0:6d4dbf28d4ee 26 bool disconnectedWS = false;
mauricioaschmitz 0:6d4dbf28d4ee 27
mauricioaschmitz 0:6d4dbf28d4ee 28 void Websocket::Websocket_Thread(void const *arg)
mauricioaschmitz 0:6d4dbf28d4ee 29 {
mauricioaschmitz 0:6d4dbf28d4ee 30 //Log::writeEntry("WebSocket Thread Start");
mauricioaschmitz 0:6d4dbf28d4ee 31 printf("Thread WebSocket Iniciada\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 32 int i = 0, f = 0;
mauricioaschmitz 0:6d4dbf28d4ee 33 char *comando = NULL;
mauricioaschmitz 0:6d4dbf28d4ee 34 char *tomada = NULL;
mauricioaschmitz 0:6d4dbf28d4ee 35 char *canal = NULL;
mauricioaschmitz 0:6d4dbf28d4ee 36 char *limite = NULL;
mauricioaschmitz 0:6d4dbf28d4ee 37 char server[30];
mauricioaschmitz 0:6d4dbf28d4ee 38 char buffer[1024] = {};
mauricioaschmitz 0:6d4dbf28d4ee 39 //bool external = false;
mauricioaschmitz 0:6d4dbf28d4ee 40 strcpy(server, "ws://");
mauricioaschmitz 0:6d4dbf28d4ee 41 strcat(server, Settings::get_networkServer());
mauricioaschmitz 0:6d4dbf28d4ee 42 strcat(server, ":8080");
mauricioaschmitz 0:6d4dbf28d4ee 43
mauricioaschmitz 0:6d4dbf28d4ee 44 //printf("Servidor WS: %s", server);
mauricioaschmitz 0:6d4dbf28d4ee 45
mauricioaschmitz 0:6d4dbf28d4ee 46 Websocket ws(server);
mauricioaschmitz 0:6d4dbf28d4ee 47
mauricioaschmitz 0:6d4dbf28d4ee 48 while(1){
mauricioaschmitz 0:6d4dbf28d4ee 49 if(ws.is_connected()){
mauricioaschmitz 0:6d4dbf28d4ee 50 if (f == 0){
mauricioaschmitz 0:6d4dbf28d4ee 51 //Log::writeEntry("WebSocket Conectado.");
mauricioaschmitz 0:6d4dbf28d4ee 52 //printf("\nMensagem do MBED para servidor WebSocket em PHP\n\n");
mauricioaschmitz 0:6d4dbf28d4ee 53 //ws.send("#*MBEDStart*#Mensagem do MBED para servidor WebSocket em PHP\n"); //mensagem para registrar login do mbed no banco de dados (ainda por implementar)
mauricioaschmitz 0:6d4dbf28d4ee 54 f = 1;
mauricioaschmitz 0:6d4dbf28d4ee 55 }
mauricioaschmitz 0:6d4dbf28d4ee 56 if(disconnectedWS != false){
mauricioaschmitz 0:6d4dbf28d4ee 57 disconnectedWS = false;
mauricioaschmitz 0:6d4dbf28d4ee 58 }
mauricioaschmitz 0:6d4dbf28d4ee 59 if(haveMessage){
mauricioaschmitz 0:6d4dbf28d4ee 60 ws.send(captureMessage);
mauricioaschmitz 0:6d4dbf28d4ee 61 haveMessage = false;
mauricioaschmitz 0:6d4dbf28d4ee 62 captureMessage = NULL;
mauricioaschmitz 0:6d4dbf28d4ee 63 }
mauricioaschmitz 0:6d4dbf28d4ee 64 if (ws.read(buffer)) {
mauricioaschmitz 0:6d4dbf28d4ee 65 //ws.send("#*MBEDTest*#");
mauricioaschmitz 0:6d4dbf28d4ee 66 //printf("Recebido Mensagem WebSocket: %s\r\n", buffer);
mauricioaschmitz 0:6d4dbf28d4ee 67 comando = strtok(buffer, ":");
mauricioaschmitz 0:6d4dbf28d4ee 68 if(strcmp(comando, "test") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 69 //printf("\r\nRecebido por WebSocket o Comando de Teste.");
mauricioaschmitz 0:6d4dbf28d4ee 70 ws.send("#*MBEDTest*#");
mauricioaschmitz 0:6d4dbf28d4ee 71 //Log::writeEntry("Recebido por WebSocket o Comando de Teste.");
mauricioaschmitz 0:6d4dbf28d4ee 72 }
mauricioaschmitz 0:6d4dbf28d4ee 73 if(strcmp(comando, "capture") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 74 tomada = strtok(NULL, ":");
mauricioaschmitz 0:6d4dbf28d4ee 75 canal = strtok(NULL, " ");
mauricioaschmitz 0:6d4dbf28d4ee 76 /*
mauricioaschmitz 0:6d4dbf28d4ee 77 printf("Comando: %s\n", comando);
mauricioaschmitz 0:6d4dbf28d4ee 78 printf("Tomada: %s\n", tomada);
mauricioaschmitz 0:6d4dbf28d4ee 79 printf("Canal: %s\n", canal);
mauricioaschmitz 0:6d4dbf28d4ee 80 printf("Tamanho da string: %d\n", strlen(buffer));
mauricioaschmitz 0:6d4dbf28d4ee 81 */
mauricioaschmitz 0:6d4dbf28d4ee 82
mauricioaschmitz 0:6d4dbf28d4ee 83 EventDetector::externalCapture(atoi(tomada), canal[0]);
mauricioaschmitz 0:6d4dbf28d4ee 84 }
mauricioaschmitz 0:6d4dbf28d4ee 85 if(strcmp(comando, "reset") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 86 Pmed_reset("Reiniciando o MBED por WebSocket.");
mauricioaschmitz 0:6d4dbf28d4ee 87 }
mauricioaschmitz 0:6d4dbf28d4ee 88
mauricioaschmitz 0:6d4dbf28d4ee 89 if(strcmp(comando, "setLimit") == 0 || strcmp(comando, "setStandByLimit") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 90 tomada = strtok(NULL, ":");
mauricioaschmitz 0:6d4dbf28d4ee 91 canal = strtok(NULL, ":");
mauricioaschmitz 0:6d4dbf28d4ee 92 limite = strtok(NULL, " ");
mauricioaschmitz 0:6d4dbf28d4ee 93 for(i=0; (unsigned)i < _PRTGMD_SETTINGS_MAX_NUMBER_OF_OUTLETS_; i++){
mauricioaschmitz 0:6d4dbf28d4ee 94 if(atoi(tomada) == Settings::get_outlet(i)){
mauricioaschmitz 0:6d4dbf28d4ee 95 if(strcmp(comando, "setLimit") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 96 if(strcmp(canal, "p") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 97 printf("Entrou canal fase e setou limite %s para tomada %s\r\n", limite, tomada);
mauricioaschmitz 0:6d4dbf28d4ee 98 Settings::set_limit(i*2,strtod(limite, NULL));
mauricioaschmitz 0:6d4dbf28d4ee 99 }
mauricioaschmitz 0:6d4dbf28d4ee 100 if(strcmp(canal, "d") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 101 printf("Entrou canal fuga e setou limite %s para tomada %s\r\n", limite, tomada);
mauricioaschmitz 0:6d4dbf28d4ee 102 Settings::set_limit(i*2+1,strtod(limite, NULL));
mauricioaschmitz 0:6d4dbf28d4ee 103 }
mauricioaschmitz 0:6d4dbf28d4ee 104 }
mauricioaschmitz 0:6d4dbf28d4ee 105 if(strcmp(comando, "setStandByLimit") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 106 if(strcmp(canal, "p") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 107 printf("Entrou canal StandBy de fase e setou limite %s para tomada %s\r\n", limite, tomada);
mauricioaschmitz 0:6d4dbf28d4ee 108 Settings::set_standbyLimit(i*2,strtod(limite, NULL));
mauricioaschmitz 0:6d4dbf28d4ee 109 }
mauricioaschmitz 0:6d4dbf28d4ee 110 if(strcmp(canal, "d") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 111 printf("Entrou canal StandBy de fuga e setou limite %s para tomada %s\r\n", limite, tomada);
mauricioaschmitz 0:6d4dbf28d4ee 112 Settings::set_standbyLimit(i*2+1,strtod(limite, NULL));
mauricioaschmitz 0:6d4dbf28d4ee 113 }
mauricioaschmitz 0:6d4dbf28d4ee 114 }
mauricioaschmitz 0:6d4dbf28d4ee 115 break;
mauricioaschmitz 0:6d4dbf28d4ee 116 }else{
mauricioaschmitz 0:6d4dbf28d4ee 117 if(i == _PRTGMD_SETTINGS_MAX_NUMBER_OF_OUTLETS_ - 1){
mauricioaschmitz 0:6d4dbf28d4ee 118 printf("Tomada %d nao encontrada para atualizar limite!\r\n", atoi(tomada));
mauricioaschmitz 0:6d4dbf28d4ee 119 }
mauricioaschmitz 0:6d4dbf28d4ee 120 }
mauricioaschmitz 0:6d4dbf28d4ee 121 }
mauricioaschmitz 0:6d4dbf28d4ee 122 //printf("Comando: %s\n", comando);
mauricioaschmitz 0:6d4dbf28d4ee 123 //printf("Tomada: %d\n", atoi(tomada));
mauricioaschmitz 0:6d4dbf28d4ee 124 //printf("Canal: %s\n", canal);
mauricioaschmitz 0:6d4dbf28d4ee 125 //printf("Limite: %f\n", strtod(limite, NULL));
mauricioaschmitz 0:6d4dbf28d4ee 126 }
mauricioaschmitz 0:6d4dbf28d4ee 127 /*
mauricioaschmitz 0:6d4dbf28d4ee 128 if(strcmp(comando, "iniciar") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 129 printf("\n\nChegou o Iniciar!!!\n\n");
mauricioaschmitz 0:6d4dbf28d4ee 130 external = true;
mauricioaschmitz 0:6d4dbf28d4ee 131 }
mauricioaschmitz 0:6d4dbf28d4ee 132 if(strcmp(comando, "parar") == 0){
mauricioaschmitz 0:6d4dbf28d4ee 133 printf("\n\nChegou o Parar!!!\n\n");
mauricioaschmitz 0:6d4dbf28d4ee 134 external = false;
mauricioaschmitz 0:6d4dbf28d4ee 135 }
mauricioaschmitz 0:6d4dbf28d4ee 136 if(external){
mauricioaschmitz 0:6d4dbf28d4ee 137
mauricioaschmitz 0:6d4dbf28d4ee 138 }*/
mauricioaschmitz 0:6d4dbf28d4ee 139 }
mauricioaschmitz 0:6d4dbf28d4ee 140 /*
mauricioaschmitz 0:6d4dbf28d4ee 141 if (!ws.is_connected()){
mauricioaschmitz 0:6d4dbf28d4ee 142 printf("Caiu a conexao!!!\n");
mauricioaschmitz 0:6d4dbf28d4ee 143 Thread::wait(Settings::get_delayTry());
mauricioaschmitz 0:6d4dbf28d4ee 144 for(int i=0; i < MAX_TRY_CONNECT; i++){
mauricioaschmitz 0:6d4dbf28d4ee 145 Thread::wait(Settings::get_delayTry());
mauricioaschmitz 0:6d4dbf28d4ee 146 //if(ws.connect()){
mauricioaschmitz 0:6d4dbf28d4ee 147 // break;
mauricioaschmitz 0:6d4dbf28d4ee 148 //}
mauricioaschmitz 0:6d4dbf28d4ee 149 }
mauricioaschmitz 0:6d4dbf28d4ee 150 //Websocket ws("ws://192.168.103.101:8080");
mauricioaschmitz 0:6d4dbf28d4ee 151 ws.connect();
mauricioaschmitz 0:6d4dbf28d4ee 152 }*/
mauricioaschmitz 0:6d4dbf28d4ee 153 }else{
mauricioaschmitz 0:6d4dbf28d4ee 154 if(!disconnectedWS){
mauricioaschmitz 0:6d4dbf28d4ee 155 if(ws.close()){
mauricioaschmitz 0:6d4dbf28d4ee 156 disconnectedWS = true;
mauricioaschmitz 0:6d4dbf28d4ee 157 Log::writeEntry("WebSocket Desconectado.");
mauricioaschmitz 0:6d4dbf28d4ee 158 }
mauricioaschmitz 0:6d4dbf28d4ee 159 }
mauricioaschmitz 0:6d4dbf28d4ee 160 Thread::wait(WAIT_CONNECT_TIME);
mauricioaschmitz 0:6d4dbf28d4ee 161 if(ws.connect()){
mauricioaschmitz 0:6d4dbf28d4ee 162 //Log::writeEntry("WebSocket Conectado.");
mauricioaschmitz 0:6d4dbf28d4ee 163 printf("Thread WebSocket Conectou no Servidor %s\r\n", Settings::get_networkServer());
mauricioaschmitz 0:6d4dbf28d4ee 164 }
mauricioaschmitz 0:6d4dbf28d4ee 165 //Thread::wait(10000);
mauricioaschmitz 0:6d4dbf28d4ee 166 }
mauricioaschmitz 0:6d4dbf28d4ee 167 }
mauricioaschmitz 0:6d4dbf28d4ee 168
mauricioaschmitz 0:6d4dbf28d4ee 169 }
mauricioaschmitz 0:6d4dbf28d4ee 170
mauricioaschmitz 0:6d4dbf28d4ee 171 Websocket::Websocket(char const * url) {
mauricioaschmitz 0:6d4dbf28d4ee 172 fillFields(url);
mauricioaschmitz 0:6d4dbf28d4ee 173 socket.set_blocking(false, 400);
mauricioaschmitz 0:6d4dbf28d4ee 174 }
mauricioaschmitz 0:6d4dbf28d4ee 175
mauricioaschmitz 0:6d4dbf28d4ee 176 bool Websocket::wsIsConnected(){
mauricioaschmitz 0:6d4dbf28d4ee 177 return isConect;
mauricioaschmitz 0:6d4dbf28d4ee 178 }
mauricioaschmitz 0:6d4dbf28d4ee 179
mauricioaschmitz 0:6d4dbf28d4ee 180 void Websocket::fillFields(char const * url) {
mauricioaschmitz 0:6d4dbf28d4ee 181 int ret = parseURL(url, scheme, sizeof(scheme), host, sizeof(host), &port, path, sizeof(path));
mauricioaschmitz 0:6d4dbf28d4ee 182 if(ret)
mauricioaschmitz 0:6d4dbf28d4ee 183 {
mauricioaschmitz 0:6d4dbf28d4ee 184 ERR("URL parsing failed; please use: \"ws://ip-or-domain[:port]/path\"");
mauricioaschmitz 0:6d4dbf28d4ee 185 return;
mauricioaschmitz 0:6d4dbf28d4ee 186 }
mauricioaschmitz 0:6d4dbf28d4ee 187
mauricioaschmitz 0:6d4dbf28d4ee 188 if(port == 0) //TODO do handle WSS->443
mauricioaschmitz 0:6d4dbf28d4ee 189 {
mauricioaschmitz 0:6d4dbf28d4ee 190 port = 80;
mauricioaschmitz 0:6d4dbf28d4ee 191 }
mauricioaschmitz 0:6d4dbf28d4ee 192
mauricioaschmitz 0:6d4dbf28d4ee 193 if(strcmp(scheme, "ws"))
mauricioaschmitz 0:6d4dbf28d4ee 194 {
mauricioaschmitz 0:6d4dbf28d4ee 195 ERR("Wrong scheme, please use \"ws\" instead");
mauricioaschmitz 0:6d4dbf28d4ee 196 }
mauricioaschmitz 0:6d4dbf28d4ee 197 }
mauricioaschmitz 0:6d4dbf28d4ee 198
mauricioaschmitz 0:6d4dbf28d4ee 199 int Websocket::parseURL(const char* url, char* scheme, size_t maxSchemeLen, char* host, size_t maxHostLen, uint16_t* port, char* path, size_t maxPathLen) //Parse URL
mauricioaschmitz 0:6d4dbf28d4ee 200 {
mauricioaschmitz 0:6d4dbf28d4ee 201 char* schemePtr = (char*) url;
mauricioaschmitz 0:6d4dbf28d4ee 202 char* hostPtr = (char*) strstr(url, "://");
mauricioaschmitz 0:6d4dbf28d4ee 203 if(hostPtr == NULL)
mauricioaschmitz 0:6d4dbf28d4ee 204 {
mauricioaschmitz 0:6d4dbf28d4ee 205 WARN("Could not find host");
mauricioaschmitz 0:6d4dbf28d4ee 206 return -1; //URL is invalid
mauricioaschmitz 0:6d4dbf28d4ee 207 }
mauricioaschmitz 0:6d4dbf28d4ee 208
mauricioaschmitz 0:6d4dbf28d4ee 209 if( maxSchemeLen < hostPtr - schemePtr + 1 ) //including NULL-terminating char
mauricioaschmitz 0:6d4dbf28d4ee 210 {
mauricioaschmitz 0:6d4dbf28d4ee 211 WARN("Scheme str is too small (%d >= %d)", maxSchemeLen, hostPtr - schemePtr + 1);
mauricioaschmitz 0:6d4dbf28d4ee 212 return -1;
mauricioaschmitz 0:6d4dbf28d4ee 213 }
mauricioaschmitz 0:6d4dbf28d4ee 214 memcpy(scheme, schemePtr, hostPtr - schemePtr);
mauricioaschmitz 0:6d4dbf28d4ee 215 scheme[hostPtr - schemePtr] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 216
mauricioaschmitz 0:6d4dbf28d4ee 217 hostPtr+=3;
mauricioaschmitz 0:6d4dbf28d4ee 218
mauricioaschmitz 0:6d4dbf28d4ee 219 size_t hostLen = 0;
mauricioaschmitz 0:6d4dbf28d4ee 220
mauricioaschmitz 0:6d4dbf28d4ee 221 char* portPtr = strchr(hostPtr, ':');
mauricioaschmitz 0:6d4dbf28d4ee 222 if( portPtr != NULL )
mauricioaschmitz 0:6d4dbf28d4ee 223 {
mauricioaschmitz 0:6d4dbf28d4ee 224 hostLen = portPtr - hostPtr;
mauricioaschmitz 0:6d4dbf28d4ee 225 portPtr++;
mauricioaschmitz 0:6d4dbf28d4ee 226 if( sscanf(portPtr, "%hu", port) != 1)
mauricioaschmitz 0:6d4dbf28d4ee 227 {
mauricioaschmitz 0:6d4dbf28d4ee 228 WARN("Could not find port");
mauricioaschmitz 0:6d4dbf28d4ee 229 return -1;
mauricioaschmitz 0:6d4dbf28d4ee 230 }
mauricioaschmitz 0:6d4dbf28d4ee 231 }
mauricioaschmitz 0:6d4dbf28d4ee 232 else
mauricioaschmitz 0:6d4dbf28d4ee 233 {
mauricioaschmitz 0:6d4dbf28d4ee 234 *port=0;
mauricioaschmitz 0:6d4dbf28d4ee 235 }
mauricioaschmitz 0:6d4dbf28d4ee 236 char* pathPtr = strchr(hostPtr, '/');
mauricioaschmitz 0:6d4dbf28d4ee 237 if( hostLen == 0 )
mauricioaschmitz 0:6d4dbf28d4ee 238 {
mauricioaschmitz 0:6d4dbf28d4ee 239 hostLen = pathPtr - hostPtr;
mauricioaschmitz 0:6d4dbf28d4ee 240 }
mauricioaschmitz 0:6d4dbf28d4ee 241
mauricioaschmitz 0:6d4dbf28d4ee 242 if( maxHostLen < hostLen + 1 ) //including NULL-terminating char
mauricioaschmitz 0:6d4dbf28d4ee 243 {
mauricioaschmitz 0:6d4dbf28d4ee 244 WARN("Host str is too small (%d >= %d)", maxHostLen, hostLen + 1);
mauricioaschmitz 0:6d4dbf28d4ee 245 return -1;
mauricioaschmitz 0:6d4dbf28d4ee 246 }
mauricioaschmitz 0:6d4dbf28d4ee 247 memcpy(host, hostPtr, hostLen);
mauricioaschmitz 0:6d4dbf28d4ee 248 host[hostLen] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 249
mauricioaschmitz 0:6d4dbf28d4ee 250 size_t pathLen;
mauricioaschmitz 0:6d4dbf28d4ee 251 char* fragmentPtr = strchr(hostPtr, '#');
mauricioaschmitz 0:6d4dbf28d4ee 252 if(fragmentPtr != NULL)
mauricioaschmitz 0:6d4dbf28d4ee 253 {
mauricioaschmitz 0:6d4dbf28d4ee 254 pathLen = fragmentPtr - pathPtr;
mauricioaschmitz 0:6d4dbf28d4ee 255 }
mauricioaschmitz 0:6d4dbf28d4ee 256 else
mauricioaschmitz 0:6d4dbf28d4ee 257 {
mauricioaschmitz 0:6d4dbf28d4ee 258 pathLen = strlen(pathPtr);
mauricioaschmitz 0:6d4dbf28d4ee 259 }
mauricioaschmitz 0:6d4dbf28d4ee 260
mauricioaschmitz 0:6d4dbf28d4ee 261 if( maxPathLen < pathLen + 1 ) //including NULL-terminating char
mauricioaschmitz 0:6d4dbf28d4ee 262 {
mauricioaschmitz 0:6d4dbf28d4ee 263 WARN("Path str is too small (%d >= %d)", maxPathLen, pathLen + 1);
mauricioaschmitz 0:6d4dbf28d4ee 264 return -1;
mauricioaschmitz 0:6d4dbf28d4ee 265 }
mauricioaschmitz 0:6d4dbf28d4ee 266 memcpy(path, pathPtr, pathLen);
mauricioaschmitz 0:6d4dbf28d4ee 267 path[pathLen] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 268
mauricioaschmitz 0:6d4dbf28d4ee 269 return 0;
mauricioaschmitz 0:6d4dbf28d4ee 270 }
mauricioaschmitz 0:6d4dbf28d4ee 271
mauricioaschmitz 0:6d4dbf28d4ee 272
mauricioaschmitz 0:6d4dbf28d4ee 273 bool Websocket::connect() {
mauricioaschmitz 0:6d4dbf28d4ee 274 char cmd[200];
mauricioaschmitz 0:6d4dbf28d4ee 275
mauricioaschmitz 0:6d4dbf28d4ee 276 while (socket.connect(host, port) < 0) {
mauricioaschmitz 0:6d4dbf28d4ee 277 ERR("Unable to connect to (%s) on port (%d)", host, port);
mauricioaschmitz 0:6d4dbf28d4ee 278 Thread::wait(200);
mauricioaschmitz 0:6d4dbf28d4ee 279 return false;
mauricioaschmitz 0:6d4dbf28d4ee 280 }
mauricioaschmitz 0:6d4dbf28d4ee 281
mauricioaschmitz 0:6d4dbf28d4ee 282 // sent http header to upgrade to the ws protocol
mauricioaschmitz 0:6d4dbf28d4ee 283 sprintf(cmd, "GET %s HTTP/1.1\r\n", path);
mauricioaschmitz 0:6d4dbf28d4ee 284 write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 285
mauricioaschmitz 0:6d4dbf28d4ee 286 sprintf(cmd, "Host: %s:%d\r\n", host, port);
mauricioaschmitz 0:6d4dbf28d4ee 287 write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 288
mauricioaschmitz 0:6d4dbf28d4ee 289 sprintf(cmd, "Upgrade: WebSocket\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 290 write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 291
mauricioaschmitz 0:6d4dbf28d4ee 292 sprintf(cmd, "Connection: Upgrade\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 293 write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 294
mauricioaschmitz 0:6d4dbf28d4ee 295 sprintf(cmd, "Sec-WebSocket-Key: L159VM0TWUzyDxwJEIEzjw==\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 296 write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 297
mauricioaschmitz 0:6d4dbf28d4ee 298 sprintf(cmd, "Sec-WebSocket-Version: 13\r\n\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 299 int ret = write(cmd, strlen(cmd));
mauricioaschmitz 0:6d4dbf28d4ee 300 if ((unsigned)ret != strlen(cmd)) {
mauricioaschmitz 0:6d4dbf28d4ee 301 close();
mauricioaschmitz 0:6d4dbf28d4ee 302 ERR("Could not send request");
mauricioaschmitz 0:6d4dbf28d4ee 303 return false;
mauricioaschmitz 0:6d4dbf28d4ee 304 }
mauricioaschmitz 0:6d4dbf28d4ee 305
mauricioaschmitz 0:6d4dbf28d4ee 306 ret = read(cmd, 200, 100);
mauricioaschmitz 0:6d4dbf28d4ee 307 if (ret < 0) {
mauricioaschmitz 0:6d4dbf28d4ee 308 close();
mauricioaschmitz 0:6d4dbf28d4ee 309 ERR("Could not receive answer\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 310 return false;
mauricioaschmitz 0:6d4dbf28d4ee 311 }
mauricioaschmitz 0:6d4dbf28d4ee 312 cmd[ret] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 313 DBG("recv: %s\r\n", cmd);
mauricioaschmitz 0:6d4dbf28d4ee 314
mauricioaschmitz 0:6d4dbf28d4ee 315 if ( strstr(cmd, "DdLWT/1JcX+nQFHebYP+rqEx5xI=") == NULL ) {
mauricioaschmitz 0:6d4dbf28d4ee 316 ERR("Wrong answer from server, got \"%s\" instead\r\n", cmd);
mauricioaschmitz 0:6d4dbf28d4ee 317 do {
mauricioaschmitz 0:6d4dbf28d4ee 318 ret = read(cmd, 200, 100);
mauricioaschmitz 0:6d4dbf28d4ee 319 if (ret < 0) {
mauricioaschmitz 0:6d4dbf28d4ee 320 ERR("Could not receive answer\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 321 return false;
mauricioaschmitz 0:6d4dbf28d4ee 322 }
mauricioaschmitz 0:6d4dbf28d4ee 323 cmd[ret] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 324 printf("%s",cmd);
mauricioaschmitz 0:6d4dbf28d4ee 325 } while (ret > 0);
mauricioaschmitz 0:6d4dbf28d4ee 326 close();
mauricioaschmitz 0:6d4dbf28d4ee 327 return false;
mauricioaschmitz 0:6d4dbf28d4ee 328 }
mauricioaschmitz 0:6d4dbf28d4ee 329
mauricioaschmitz 0:6d4dbf28d4ee 330 //INFO("\r\nhost: %s\r\npath: %s\r\nport: %d\r\n\r\n", host, path, port);
mauricioaschmitz 0:6d4dbf28d4ee 331 return true;
mauricioaschmitz 0:6d4dbf28d4ee 332 }
mauricioaschmitz 0:6d4dbf28d4ee 333
mauricioaschmitz 0:6d4dbf28d4ee 334 int Websocket::sendLength(uint32_t len, char * msg) {
mauricioaschmitz 0:6d4dbf28d4ee 335
mauricioaschmitz 0:6d4dbf28d4ee 336 if (len < 126) {
mauricioaschmitz 0:6d4dbf28d4ee 337 msg[0] = len | (1<<7);
mauricioaschmitz 0:6d4dbf28d4ee 338 return 1;
mauricioaschmitz 0:6d4dbf28d4ee 339 } else if (len < 65535) {
mauricioaschmitz 0:6d4dbf28d4ee 340 msg[0] = 126 | (1<<7);
mauricioaschmitz 0:6d4dbf28d4ee 341 msg[1] = (len >> 8) & 0xff;
mauricioaschmitz 0:6d4dbf28d4ee 342 msg[2] = len & 0xff;
mauricioaschmitz 0:6d4dbf28d4ee 343 return 3;
mauricioaschmitz 0:6d4dbf28d4ee 344 } else {
mauricioaschmitz 0:6d4dbf28d4ee 345 msg[0] = 127 | (1<<7);
mauricioaschmitz 0:6d4dbf28d4ee 346 for (int i = 0; i < 8; i++) {
mauricioaschmitz 0:6d4dbf28d4ee 347 msg[i+1] = (len >> i*8) & 0xff;
mauricioaschmitz 0:6d4dbf28d4ee 348 }
mauricioaschmitz 0:6d4dbf28d4ee 349 return 9;
mauricioaschmitz 0:6d4dbf28d4ee 350 }
mauricioaschmitz 0:6d4dbf28d4ee 351 }
mauricioaschmitz 0:6d4dbf28d4ee 352
mauricioaschmitz 0:6d4dbf28d4ee 353 int Websocket::readChar(char * pC, bool block) {
mauricioaschmitz 0:6d4dbf28d4ee 354 return read(pC, 1, 1);
mauricioaschmitz 0:6d4dbf28d4ee 355 }
mauricioaschmitz 0:6d4dbf28d4ee 356
mauricioaschmitz 0:6d4dbf28d4ee 357 int Websocket::sendOpcode(uint8_t opcode, char * msg) {
mauricioaschmitz 0:6d4dbf28d4ee 358 msg[0] = 0x80 | (opcode & 0x0f);
mauricioaschmitz 0:6d4dbf28d4ee 359 return 1;
mauricioaschmitz 0:6d4dbf28d4ee 360 }
mauricioaschmitz 0:6d4dbf28d4ee 361
mauricioaschmitz 0:6d4dbf28d4ee 362 int Websocket::sendMask(char * msg) {
mauricioaschmitz 0:6d4dbf28d4ee 363 for (int i = 0; i < 4; i++) {
mauricioaschmitz 0:6d4dbf28d4ee 364 msg[i] = 0;
mauricioaschmitz 0:6d4dbf28d4ee 365 }
mauricioaschmitz 0:6d4dbf28d4ee 366 return 4;
mauricioaschmitz 0:6d4dbf28d4ee 367 }
mauricioaschmitz 0:6d4dbf28d4ee 368
mauricioaschmitz 0:6d4dbf28d4ee 369 int Websocket::send(char * str) {
mauricioaschmitz 0:6d4dbf28d4ee 370 char msg[strlen(str) + 15];
mauricioaschmitz 0:6d4dbf28d4ee 371 int idx = 0;
mauricioaschmitz 0:6d4dbf28d4ee 372 idx = sendOpcode(0x01, msg);
mauricioaschmitz 0:6d4dbf28d4ee 373 idx += sendLength(strlen(str), msg + idx);
mauricioaschmitz 0:6d4dbf28d4ee 374 idx += sendMask(msg + idx);
mauricioaschmitz 0:6d4dbf28d4ee 375 memcpy(msg+idx, str, strlen(str));
mauricioaschmitz 0:6d4dbf28d4ee 376 int res = write(msg, idx + strlen(str));
mauricioaschmitz 0:6d4dbf28d4ee 377 return res;
mauricioaschmitz 0:6d4dbf28d4ee 378 }
mauricioaschmitz 0:6d4dbf28d4ee 379
mauricioaschmitz 0:6d4dbf28d4ee 380
mauricioaschmitz 0:6d4dbf28d4ee 381 bool Websocket::read(char * message) {
mauricioaschmitz 0:6d4dbf28d4ee 382 int i = 0;
mauricioaschmitz 0:6d4dbf28d4ee 383 uint32_t len_msg;
mauricioaschmitz 0:6d4dbf28d4ee 384 char opcode = 0;
mauricioaschmitz 0:6d4dbf28d4ee 385 char c;
mauricioaschmitz 0:6d4dbf28d4ee 386 char mask[4] = {0, 0, 0, 0};
mauricioaschmitz 0:6d4dbf28d4ee 387 bool is_masked = false;
mauricioaschmitz 0:6d4dbf28d4ee 388 Timer tmr;
mauricioaschmitz 0:6d4dbf28d4ee 389
mauricioaschmitz 0:6d4dbf28d4ee 390 // read the opcode
mauricioaschmitz 0:6d4dbf28d4ee 391 tmr.start();
mauricioaschmitz 0:6d4dbf28d4ee 392 while (true) {
mauricioaschmitz 0:6d4dbf28d4ee 393 if (tmr.read() > 3) {
mauricioaschmitz 0:6d4dbf28d4ee 394 DBG("timeout ws\r\n");
mauricioaschmitz 0:6d4dbf28d4ee 395 return false;
mauricioaschmitz 0:6d4dbf28d4ee 396 }
mauricioaschmitz 0:6d4dbf28d4ee 397
mauricioaschmitz 0:6d4dbf28d4ee 398 if(!socket.is_connected())
mauricioaschmitz 0:6d4dbf28d4ee 399 {
mauricioaschmitz 0:6d4dbf28d4ee 400 WARN("Connection was closed by server");
mauricioaschmitz 0:6d4dbf28d4ee 401 return false;
mauricioaschmitz 0:6d4dbf28d4ee 402 }
mauricioaschmitz 0:6d4dbf28d4ee 403
mauricioaschmitz 0:6d4dbf28d4ee 404 socket.set_blocking(false, 1);
mauricioaschmitz 0:6d4dbf28d4ee 405 if (socket.receive(&opcode, 1) != 1) {
mauricioaschmitz 0:6d4dbf28d4ee 406 socket.set_blocking(false, 2000);
mauricioaschmitz 0:6d4dbf28d4ee 407 return false;
mauricioaschmitz 0:6d4dbf28d4ee 408 }
mauricioaschmitz 0:6d4dbf28d4ee 409
mauricioaschmitz 0:6d4dbf28d4ee 410 socket.set_blocking(false, 2000);
mauricioaschmitz 0:6d4dbf28d4ee 411
mauricioaschmitz 0:6d4dbf28d4ee 412 if (opcode == 0x81)
mauricioaschmitz 0:6d4dbf28d4ee 413 break;
mauricioaschmitz 0:6d4dbf28d4ee 414 }
mauricioaschmitz 0:6d4dbf28d4ee 415 DBG("opcode: 0x%X\r\n", opcode);
mauricioaschmitz 0:6d4dbf28d4ee 416
mauricioaschmitz 0:6d4dbf28d4ee 417 readChar(&c);
mauricioaschmitz 0:6d4dbf28d4ee 418 len_msg = c & 0x7f;
mauricioaschmitz 0:6d4dbf28d4ee 419 is_masked = c & 0x80;
mauricioaschmitz 0:6d4dbf28d4ee 420 if (len_msg == 126) {
mauricioaschmitz 0:6d4dbf28d4ee 421 readChar(&c);
mauricioaschmitz 0:6d4dbf28d4ee 422 len_msg = c << 8;
mauricioaschmitz 0:6d4dbf28d4ee 423 readChar(&c);
mauricioaschmitz 0:6d4dbf28d4ee 424 len_msg += c;
mauricioaschmitz 0:6d4dbf28d4ee 425 } else if (len_msg == 127) {
mauricioaschmitz 0:6d4dbf28d4ee 426 len_msg = 0;
mauricioaschmitz 0:6d4dbf28d4ee 427 for (int i = 0; i < 8; i++) {
mauricioaschmitz 0:6d4dbf28d4ee 428 readChar(&c);
mauricioaschmitz 0:6d4dbf28d4ee 429 len_msg += (c << (7-i)*8);
mauricioaschmitz 0:6d4dbf28d4ee 430 }
mauricioaschmitz 0:6d4dbf28d4ee 431 }
mauricioaschmitz 0:6d4dbf28d4ee 432
mauricioaschmitz 0:6d4dbf28d4ee 433 if (len_msg == 0) {
mauricioaschmitz 0:6d4dbf28d4ee 434 return false;
mauricioaschmitz 0:6d4dbf28d4ee 435 }
mauricioaschmitz 0:6d4dbf28d4ee 436 DBG("length: %d\r\n", len_msg);
mauricioaschmitz 0:6d4dbf28d4ee 437
mauricioaschmitz 0:6d4dbf28d4ee 438 if (is_masked) {
mauricioaschmitz 0:6d4dbf28d4ee 439 for (i = 0; i < 4; i++)
mauricioaschmitz 0:6d4dbf28d4ee 440 readChar(&c);
mauricioaschmitz 0:6d4dbf28d4ee 441 mask[i] = c;
mauricioaschmitz 0:6d4dbf28d4ee 442 }
mauricioaschmitz 0:6d4dbf28d4ee 443
mauricioaschmitz 0:6d4dbf28d4ee 444 int nb = read(message, len_msg, len_msg);
mauricioaschmitz 0:6d4dbf28d4ee 445 if (nb != len_msg)
mauricioaschmitz 0:6d4dbf28d4ee 446 return false;
mauricioaschmitz 0:6d4dbf28d4ee 447
mauricioaschmitz 0:6d4dbf28d4ee 448 for (i = 0; (unsigned)i < len_msg; i++) {
mauricioaschmitz 0:6d4dbf28d4ee 449 message[i] = message[i] ^ mask[i % 4];
mauricioaschmitz 0:6d4dbf28d4ee 450 }
mauricioaschmitz 0:6d4dbf28d4ee 451
mauricioaschmitz 0:6d4dbf28d4ee 452 message[len_msg] = '\0';
mauricioaschmitz 0:6d4dbf28d4ee 453
mauricioaschmitz 0:6d4dbf28d4ee 454 return true;
mauricioaschmitz 0:6d4dbf28d4ee 455 }
mauricioaschmitz 0:6d4dbf28d4ee 456
mauricioaschmitz 0:6d4dbf28d4ee 457 bool Websocket::close() {
mauricioaschmitz 0:6d4dbf28d4ee 458 //if (!is_connected())
mauricioaschmitz 0:6d4dbf28d4ee 459 //return false;
mauricioaschmitz 0:6d4dbf28d4ee 460
mauricioaschmitz 0:6d4dbf28d4ee 461 int ret = socket.close(true);
mauricioaschmitz 0:6d4dbf28d4ee 462 if (ret < 0) {
mauricioaschmitz 0:6d4dbf28d4ee 463 ERR("Could not disconnect");
mauricioaschmitz 0:6d4dbf28d4ee 464 return false;
mauricioaschmitz 0:6d4dbf28d4ee 465 }
mauricioaschmitz 0:6d4dbf28d4ee 466 return true;
mauricioaschmitz 0:6d4dbf28d4ee 467 }
mauricioaschmitz 0:6d4dbf28d4ee 468
mauricioaschmitz 0:6d4dbf28d4ee 469 bool Websocket::is_connected() {
mauricioaschmitz 0:6d4dbf28d4ee 470 isConect = socket.is_connected();
mauricioaschmitz 0:6d4dbf28d4ee 471 return socket.is_connected();
mauricioaschmitz 0:6d4dbf28d4ee 472 }
mauricioaschmitz 0:6d4dbf28d4ee 473
mauricioaschmitz 0:6d4dbf28d4ee 474 char* Websocket::getPath() {
mauricioaschmitz 0:6d4dbf28d4ee 475 return path;
mauricioaschmitz 0:6d4dbf28d4ee 476 }
mauricioaschmitz 0:6d4dbf28d4ee 477
mauricioaschmitz 0:6d4dbf28d4ee 478 int Websocket::write(char * str, int len) {
mauricioaschmitz 0:6d4dbf28d4ee 479 int res = 0, idx = 0;
mauricioaschmitz 0:6d4dbf28d4ee 480
mauricioaschmitz 0:6d4dbf28d4ee 481 for (int j = 0; j < MAX_TRY_WRITE; j++) {
mauricioaschmitz 0:6d4dbf28d4ee 482
mauricioaschmitz 0:6d4dbf28d4ee 483 if(!socket.is_connected())
mauricioaschmitz 0:6d4dbf28d4ee 484 {
mauricioaschmitz 0:6d4dbf28d4ee 485 WARN("Connection was closed by server");
mauricioaschmitz 0:6d4dbf28d4ee 486 break;
mauricioaschmitz 0:6d4dbf28d4ee 487 }
mauricioaschmitz 0:6d4dbf28d4ee 488
mauricioaschmitz 0:6d4dbf28d4ee 489 if ((res = socket.send_all(str + idx, len - idx)) == -1)
mauricioaschmitz 0:6d4dbf28d4ee 490 continue;
mauricioaschmitz 0:6d4dbf28d4ee 491
mauricioaschmitz 0:6d4dbf28d4ee 492 idx += res;
mauricioaschmitz 0:6d4dbf28d4ee 493
mauricioaschmitz 0:6d4dbf28d4ee 494 if (idx == len)
mauricioaschmitz 0:6d4dbf28d4ee 495 return len;
mauricioaschmitz 0:6d4dbf28d4ee 496 }
mauricioaschmitz 0:6d4dbf28d4ee 497
mauricioaschmitz 0:6d4dbf28d4ee 498 return (idx == 0) ? -1 : idx;
mauricioaschmitz 0:6d4dbf28d4ee 499 }
mauricioaschmitz 0:6d4dbf28d4ee 500
mauricioaschmitz 0:6d4dbf28d4ee 501 int Websocket::read(char * str, int len, int min_len) {
mauricioaschmitz 0:6d4dbf28d4ee 502 int res = 0, idx = 0;
mauricioaschmitz 0:6d4dbf28d4ee 503
mauricioaschmitz 0:6d4dbf28d4ee 504 for (int j = 0; j < MAX_TRY_WRITE; j++) {
mauricioaschmitz 0:6d4dbf28d4ee 505
mauricioaschmitz 0:6d4dbf28d4ee 506 if ((res = socket.receive_all(str + idx, len - idx)) == -1)
mauricioaschmitz 0:6d4dbf28d4ee 507 continue;
mauricioaschmitz 0:6d4dbf28d4ee 508
mauricioaschmitz 0:6d4dbf28d4ee 509 idx += res;
mauricioaschmitz 0:6d4dbf28d4ee 510
mauricioaschmitz 0:6d4dbf28d4ee 511 if (idx == len || (min_len != -1 && idx > min_len))
mauricioaschmitz 0:6d4dbf28d4ee 512 return idx;
mauricioaschmitz 0:6d4dbf28d4ee 513 }
mauricioaschmitz 0:6d4dbf28d4ee 514
mauricioaschmitz 0:6d4dbf28d4ee 515 return (idx == 0) ? -1 : idx;
mauricioaschmitz 0:6d4dbf28d4ee 516 }