Okundu Omeni
/
wifi-https-ble-sm-uart-atcmd-5-13-1
this is using the mbed os version 5-13-1
source/WiFiManager.cpp
- Committer:
- ocomeni
- Date:
- 2019-07-19
- Branch:
- PassingRegression
- Revision:
- 129:590bdc2dcf5b
- Parent:
- 127:a21788227ca6
File content as of revision 129:590bdc2dcf5b:
#include "debug.h" #include "WiFiManager.h" #include "common_config.h" #define FILE_CODE "wifi" #define USE_EVENTS_FOR_HTTPS_REQUESTS WiFiManager::WiFiManager(wifi_config_t *wifi_config, WiFiInterface *wifi, internet_config_t *internet_config, events::EventQueue &event_queue, MemoryPool<wifi_cmd_message_t, 16> *aT2WiFimPool, Queue<wifi_cmd_message_t, 16> *aT2WiFiCmdQueue, MemoryPool<at_resp_message_t, 16> *wiFi2ATmPool, Queue<at_resp_message_t, 16> *wiFi2ATCmdQueue, MemoryPool<wifi_data_msg_t, PQDSZ> *aT2WiFiDatamPool, Queue<wifi_data_msg_t, PQDSZ> *aT2WiFiDataQueue, MemoryPool<at_data_msg_t, PQDSZ> *wiFi2ATDatamPool, Queue<at_data_msg_t, PQDSZ> *wiFi2ATDataQueue) : wifi_config(wifi_config), network(wifi), internet_config(internet_config), _event_queue(event_queue), _aT2WiFimPool(aT2WiFimPool), _aT2WiFiCmdQueue(aT2WiFiCmdQueue), _wiFi2ATmPool(wiFi2ATmPool), _wiFi2ATCmdQueue(wiFi2ATCmdQueue), _aT2WiFiDatamPool(aT2WiFiDatamPool), _aT2WiFiDataQueue(aT2WiFiDataQueue), _wiFi2ATDatamPool(wiFi2ATDatamPool), _wiFi2ATDataQueue(wiFi2ATDataQueue) { lastScanCount = 0; wifiCmd = WIFI_CMD_NONE; //internet_config.connectionScheme = ALWAYS_CONNECTED; // set default connection scheme is_connected = false; http_response = NULL; chunkNum = 0; socket = NULL; responseString = NULL; responseBytes = NULL; at_data_resp = NULL; https_connection_active = false; use_full_hostname = false; wifiBusy = 0; wifiWatchdogTimer.start(); watchdogCnt = 0; //_event_queue.call_every(10000, this, &WiFiManager::callWifiWatchDog); //keep_alive_id = _event_queue.call_every(CLOUD_KEEP_ALIVE_INTERVAL, this, &WiFiManager::callInternetKeepAlive); keep_alive_id = 0; https_token_valid = false; token_refresh_count = 0; //watchDogTick.attach(callback(this, &WiFiManager::callWifiWatchDogIsr), 10.0); // call flip function every 10 seconds } WiFiManager::~WiFiManager() { delete network; wifiWatchdogTimer.stop(); socket->close(); delete socket; free(aws_id_token); free(aws_refresh_token); } //#define DISABLE_WATCHDOG void WiFiManager::callWifiWatchDogIsr() { _event_queue.call_in(10, this, &WiFiManager::callWifiWatchDog); } void WiFiManager::callWifiWatchDog() { #ifdef DISABLE_WATCHDOG return; #else static int inactivity_monitor = 0; watchdogCnt++; if(watchdogCnt >= 6 && outputBuffersAvailable()) // every minute { char * respStr = (char *) malloc(120); sprintf(responseString, "\r\n[WiFi-MAN] WiFi Manager Alive : state = %d busy = %d httpsConnActive = %d\r\n", wifiCmd, wifiBusy, https_connection_active); sendThreadATresponseString(respStr, WIFI_WATCH_DOG); watchdogCnt = 0; } else if(wifiWatchdogTimer.read() > 30 && responseString==NULL) { if(wifiCmd == WIFI_CMD_NONE) inactivity_monitor++; char * respStr = (char *) malloc(120); sprintf(responseString, "\r\n[WiFi-MAN] Main Loop InActive : state = %d busy = %d httpsConnActive = %d\r\n", wifiCmd, wifiBusy, https_connection_active); sendThreadATresponseString(respStr, WIFI_WATCH_DOG); if(inactivity_monitor >= 3) { free_DataMsg(); inactivity_monitor = 0; } } #endif } void WiFiManager::callInternetKeepAlive() { if(https_connection_active) { setNextCommand(WIFI_CMD_INTERNET_KEEP_ALIVE); } else { setNextCommand(WIFI_CMD_TLS_CONNECT); } } void WiFiManager::keepSocketAlive() { // Send data nsapi_size_or_error_t error; //serr = socket->send("GET /nudgebox/v1 HTTP/1.0\r\nHost: https://dev2.dnanudge.io\r\n\r\n", 18); dbg_printf(LOG, "\n[WIFI MAN] KEEP ALIVE SERVER REQUEST\r\n"); char *httpsReq = new char[KEEPALIVE_MSG_SIZE]; sprintf(httpsReq,"%s\r\nAuthorization: %s\r\n\r\n", KEEPALIVE_MSG_HDR, aws_id_token); int hdrlen= strlen(httpsReq); dbg_printf(LOG, "\n[WIFI MAN] KEEP ALIVE MSG [len = %d]\r\n%s", hdrlen, httpsReq); memcpy(&httpsReq[hdrlen], KEEPALIVE_MSG_BDY,sizeof(KEEPALIVE_MSG_BDY)); error = socket->send(httpsReq, (hdrlen+sizeof(KEEPALIVE_MSG_BDY))); if(error < 0) { queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED); https_connection_active = false; socket->close(); delete socket; socket = NULL; return; } // Receive data char buf[500]; error = socket->recv(buf, 500); if(error >= 0 && strstr(buf, "HTTP/1.1 200")!= NULL) // received HTTP 200 OK status { dbg_printf(LOG, "\n[WIFI MAN] KEEP ALIVE SERVER RESPONSE: \r\n %s\r\n", buf); queueATresponse(AT_SOCKET_KEEP_ALIVE_OK); https_connection_active = true; } else { queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED); https_connection_active = false; socket->close(); delete socket; socket = NULL; } delete httpsReq; } void WiFiManager::CreateTokenHttpsRequest(char * httpsReq) { char *httpsBody = new char[200]; sprintf(httpsBody,"{\r\n\"AuthParameters\" : {\r\n" "\"USERNAME\" : \"%s\",\r\n\"PASSWORD\" : \"%s\"\r\n},\r\n" "\"AuthFlow\" : \"%s\",\r\n" "\"ClientId\" : \"%s\"\r\n}", UserName, Password, AuthFlow, ClientId); int bodyLen = strlen(httpsBody); sprintf(httpsReq,"%s\r\ncontent-length: %d" "\r\n\r\n%s", TOKEN_REQ_HDR, bodyLen, httpsBody); dbg_printf(LOG, "\n[WIFI MAN] Cloud Access Token REQUEST:\r\n%s\r\n", httpsReq); delete httpsBody; } void WiFiManager::GetCloudAccessToken() { int start = Kernel::get_ms_count(); // Send data nsapi_size_or_error_t error; dbg_printf(LOG, "\n[WIFI MAN] Get Cloud Access Token REQUEST\r\n"); // first free up access token memory to avoid leak freeAccessTokenMemory(); char *httpsReq = new char[500]; httpsReq[0] = NULL; CreateTokenHttpsRequest(httpsReq); if(strlen(httpsReq) == 0) { queueATresponse(AT_ACCESS_TOKEN_FAILED); return; } error = socket->send(httpsReq, strlen(httpsReq)+1); delete httpsReq; if(error < 0) { queueATresponse(AT_ACCESS_TOKEN_FAILED); return; } // Receive data // reserve large buffer from heap to hold response char *respBuf = new char[TOKEN_RESPONSE_SIZE]; error = socket->recv(respBuf, TOKEN_RESPONSE_SIZE); if(error >= 0 && strstr(respBuf, "HTTP/1.1 200")!= NULL) // received HTTP 200 OK status { dbg_printf(LOG, "\n[WIFI MAN] ACCESS TOKEN RESPONSE: \r\n %s\r\n", respBuf); // extract ID TOKEN char *sp1 = strstr(respBuf,ID_TOKEN_STR_START); char *sp2 = strstr(sp1+strlen(ID_TOKEN_STR_START),ACCESS_TOKEN_STR_END); int tokenLen = sp2-sp1-(strlen(ID_TOKEN_STR_START)); // reserve memomry on the heap for id token aws_id_token = new char[tokenLen+1]; strncpy(aws_id_token, sp1+(strlen(ID_TOKEN_STR_START)), tokenLen); dbg_printf(LOG, "\n[WIFI MAN] Token Length: %d \r\n IdToken: \r\n %s\r\n", tokenLen, aws_id_token); #ifdef EXTRACT_REFRESH_TOKEN // extract Refresh TOKEN sp1 = strstr(respBuf,REFRESH_TOKEN_STR_START); sp2 = strstr(sp1+strlen(REFRESH_TOKEN_STR_START),ACCESS_TOKEN_STR_END); tokenLen = sp2-sp1-(strlen(REFRESH_TOKEN_STR_START)); // reserve memomry on the heap for refresh token aws_refresh_token = new char[tokenLen+1]; strncpy(aws_refresh_token, sp1+(strlen(REFRESH_TOKEN_STR_START)), tokenLen); dbg_printf(LOG, "\n[WIFI MAN] Token Length: %d \r\nRefreshToken: \r\n %s\r\n", tokenLen, aws_refresh_token); #endif queueATresponse(AT_ACCESS_TOKEN_SUCCESS); token_refresh_count++; //https_connection_active = true; https_token_valid = true; // schedule the invalidation of the token for 59 minutes time _event_queue.call_in(TOKEN_VALID_PERIOD_MS, this, &WiFiManager::invalidateAccessToken); } else { dbg_printf(LOG, "\n[WIFI MAN] Failure Response: \r\n %s\r\n", respBuf); queueATresponse(AT_ACCESS_TOKEN_FAILED); //https_connection_active = false; } delete respBuf; int elapsed_ms = Kernel::get_ms_count() - start; dbg_printf(LOG, "\n[WIFI MAN] Access token Acquisition::\r\n Time Elapsed : %ld ms\r\n", elapsed_ms); socket->close(); delete socket; socket = NULL; } void WiFiManager::invalidateAccessToken() { https_token_valid = false; } void WiFiManager::freeAccessTokenMemory() { free(aws_id_token); aws_id_token = NULL; #ifdef EXTRACT_REFRESH_TOKEN free(aws_refresh_token); aws_refresh_token = NULL; #endif } void WiFiManager::sendThreadATresponseString(const char * buf, at_cmd_resp_t at_cmd) { if(at_data_resp != NULL) return; int strLen = strlen(buf) + 1; at_data_resp = new at_data_msg_t; // set string length at_data_resp->dataLen = strLen; memcpy(at_data_resp->buffer, buf, strLen); // package and send on wifi data queue at_data_resp->at_resp = at_cmd; bool queueResult = true; int wait_count = 0; do { if(!queueResult){ wait_count+=10; dbg_printf(LOG, "ATCMD Queue full waiting %d ms so far...\n", wait_count); wait_ms(10); } queueResult = queueWiFiDataResponse(*at_data_resp); }while(queueResult == false && wait_count<QUEUE_WAIT_TIMEOUT_MS); delete at_data_resp; at_data_resp = NULL; } bool WiFiManager::outputBuffersAvailable() { int timeout = 0; while(timeout < 100) { if(responseBytes==NULL && responseString==NULL && at_data_resp==NULL) { return true; } else { timeout += 10; wait_ms(10); } } if(responseBytes==NULL && responseString==NULL && at_data_resp==NULL) { return true; } else { return false; } } bool WiFiManager::queueATresponse(at_cmd_resp_t resp){ #ifndef USE_MALLOC_FOR_COMMAND_MEMORY_POOL at_resp_message_t *atResp = _wiFi2ATmPool->alloc(); #else at_resp_message_t *atResp = (at_resp_message_t *) malloc(sizeof(at_resp_message_t)); #endif if(atResp == NULL) return false; // queue full; atResp->at_resp = resp; _wiFi2ATCmdQueue->put(atResp); return true; } bool WiFiManager::queueWiFiDataResponse(at_data_msg_t at_resp){ at_data_msg_t *atData = _wiFi2ATDatamPool->alloc(); if(atData == NULL) return false; // queue full; atData->at_resp = at_resp.at_resp; atData->dataLen = at_resp.dataLen; memcpy(atData->buffer, at_resp.buffer, at_resp.dataLen); _wiFi2ATDataQueue->put(atData); dbg_printf(LOG, "[WIFI MAN] queued data size = %d : at_resp = %d\n", at_resp.dataLen, at_resp.at_resp); return true; } void WiFiManager::getWiFiInstance() { network = WiFiInterface::get_default_instance(); if (!network) { dbg_printf(LOG, "ERROR: No WiFiInterface found.\n"); } } void WiFiManager::runMain(){ nsapi_error_t error; bool result; dbg_printf(LOG, "\r\n [WIFI MAN] Thread Id = %X\r\n", (uint32_t)ThisThread::get_id()); while(true){ dequeueWiFiCommands(); dequeueATdataResponse(); wifiWatchdogTimer.reset(); switch(wifiCmd){ case WIFI_CMD_NONE: // IDLE STATE break; case WIFI_CMD_SCAN: wifiBusy = 1; error = scanNetworks(); wifiCmd = WIFI_CMD_NONE; queueATresponse(AT_SCAN_RESP); wifiBusy = 0; break; case WIFI_CMD_DETAILED_SCAN: { wifiBusy = 1; nsapi_size_or_error_t cnt_err; cnt_err = getAvailableAPs(lastScanCount); wifiCmd = WIFI_CMD_NONE; if(cnt_err >= 0) { queueATresponse(AT_DETAILED_SCAN_RESP); } wifiBusy = 0; break; } case WIFI_CMD_CONNECT: { if(is_connected) // already connected { wifiCmd = WIFI_CMD_NONE; break; } wifiBusy = 1; error = connect(); int secCount = 0; while(secCount++ < WIFI_CONNECT_TIMEOUT_SECS && is_connected==false){ wait(1); // wait 1 sec } wifiCmd = WIFI_CMD_NONE; if(is_connected==false){ if(outputBuffersAvailable() == false) // first free it { free(responseString); } dbg_printf(LOG, "[WIFI MAN] +++ WIFI CONNECTION TIMEOUT +++ \r\n"); //queueATresponse(AT_COMMAND_FAILED); responseString = (char *) malloc(100); sprintf(responseString, "\r\n+UUTIMEOUT\r\n"); sendATresponseString(AT_COMMAND_FAILED); } else { sendATresponseString(AT_CONNECT_RESP); } wifiBusy = 0; break; } case WIFI_CMD_DISCONNECT: { if(!is_connected) // already disconnected { wifiCmd = WIFI_CMD_NONE; break; } wifiBusy = 1; error = disconnect(); wifiCmd = WIFI_CMD_NONE; if(error >= 0) { int secCount = 0; while(secCount++ < WIFI_CONNECT_TIMEOUT_SECS && is_connected==true){ wait(1); // wait 1 sec } if(!is_connected) { sendATresponseString(AT_DISCONNECT_RESP); } else { dbg_printf(LOG, "[WIFI MAN] +++ WIFI DISCONNECTION TIMEOUT +++ \r\n"); //queueATresponse(AT_COMMAND_FAILED); responseString = (char *) malloc(100); sprintf(responseString, "\r\n+UUTIMEOUT\r\n"); sendATresponseString(AT_COMMAND_FAILED); } // attempt reconnection if always connected scheme is set if(internet_config->connectionScheme == ALWAYS_CONNECTED) { setNextCommand(WIFI_CMD_CONNECT); } } wifiBusy = 0; break; } case WIFI_CMD_CONFIG: wifiBusy = 1; set_WIFI_CONFIG(); wifiCmd = WIFI_CMD_NONE; queueATresponse(AT_CONFIG_RESP); wifiBusy = 0; break; case WIFI_CMD_INTERNET_CONFIG: { wifiBusy = 1; backgroundTaskCompleted = false; set_internet_config(); // Wait for callback semaphore #ifdef DNANUDGE_DEBUG callback_semaphore.wait(); #endif int msecCount = 0; while(!backgroundTaskCompleted && msecCount < 1000) { msecCount++; wait_ms(10); } if(backgroundTaskCompleted) { queueATresponse(AT_INTERNET_CONFIG_RESP); } backgroundTaskCompleted = false; wifiCmd = WIFI_CMD_NONE; //wifiCmd = WIFI_CMD_GET_TOKEN; break; } case WIFI_CMD_NETWORK_STATUS: wifiBusy = 1; if(outputBuffersAvailable()) { getNetworkStatus(); } sendATresponseString(AT_NETWORK_STATUS_RESP); wifiCmd = WIFI_CMD_NONE; wifiBusy = 0; break; case WIFI_CMD_WIFI_STATUS: wifiBusy = 1; if(outputBuffersAvailable()) { getWiFiStatus(); } sendATresponseString(AT_WIFI_STATUS_RESP); wifiCmd = WIFI_CMD_NONE; wifiBusy = 0; break; case WIFI_CMD_SEND_HTTPS_REQ: { wifiBusy = 1; if(!https_token_valid) // if this is the first time get token { wifiCmd = WIFI_CMD_NONE; fromWiFiCmd = WIFI_CMD_TLS_CONNECT; nextWiFiCmd = WIFI_CMD_SEND_HTTPS_REQ; setNextCommand(WIFI_CMD_GET_TOKEN); break; } // cancel keep alive event as not needed since new request has come in. if(keep_alive_id != 0) // only cancel if it has been activated { _event_queue.cancel(keep_alive_id); } #ifdef SEND_DEBUG_MESSAGES if(outputBuffersAvailable()) { responseString = (char *) malloc(100); sprintf(responseString, "\r\nHTTP REQUEST RECEIVED\r\n"); sendATresponseString(AT_EVENT); } #endif dbg_printf(LOG, "before call to send http request \n"); dbg_printf(LOG, "\r\n[WIFI-MAN] Received HTTPS request...\r\n"); print_memory_info(); // disable network interrupts during https request network->attach(NULL); #ifdef USE_EVENTS_FOR_HTTPS_REQUESTS // Events can be cancelled as long as they have not been dispatched. If the // event has already expired, cancel has no side-effects. int event_id = _event_queue.call(this, &WiFiManager::createSendHttpsRequest); waitForBackgroundTask(6000, 10); // six second timeout // backgroundTaskCompleted = false; // int msecCount = 0; // int oldChunkNum = chunkNum; // while(!backgroundTaskCompleted && msecCount < 6000) // { // msecCount+=10; // wait_ms(10); // if(oldChunkNum != chunkNum) // new payload received // { // oldChunkNum = chunkNum; // msecCount = 0; // } // } if(backgroundTaskCompleted) { //queueATresponse(AT_INTERNET_CONFIG_RESP); result = true; } else { //_event_queue.cancel(event_id); result = false; } backgroundTaskCompleted = false; #else result = createHttpsRequest(); #endif if(result == false && outputBuffersAvailable()) { responseString = (char *) malloc(100); if(http_result==TLS_CONNECTION_FAILED) { sprintf(responseString, "\r\nTLS CONNECTION FAILURE\r\n"); } else { sprintf(responseString, "\r\nHTTP REQUEST FAILED\r\n"); } sendATresponseString(AT_COMMAND_FAILED); } dbg_printf(LOG, "after call to send http request \n"); print_memory_info(); wifiCmd = WIFI_CMD_NONE; wifiBusy = 0; // enable keep alive after https request completes keep_alive_id = _event_queue.call_every(CLOUD_KEEP_ALIVE_INTERVAL, this, &WiFiManager::callInternetKeepAlive); // re-enable network interrupts after https request. network->attach(callback(this, &WiFiManager::status_callback)); break; } case WIFI_CMD_TLS_CONNECT: { dbg_printf(LOG, "\r\n[WIFI-MAN] ATTEMPTING TLS CONNECTION\r\n"); char* hostName = strstr(internet_config->url,"//"); wifiBusy = 1; if(hostName != NULL) { hostName += 2; //https_connection_active = createTLSconnection(hostName); _event_queue.call(this, &WiFiManager::createTLSconnThreadCall, (const char*)hostName); waitForBackgroundTask(6000, 10); // six second timeout if(backgroundTaskCompleted == false) { https_connection_active = false; queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED); delete socket; socket = NULL; } else { https_connection_active = true; } } if(fromWiFiCmd == WIFI_CMD_TLS_CONNECT) { wifiCmd = nextWiFiCmd; fromWiFiCmd = WIFI_CMD_NONE; nextWiFiCmd = WIFI_CMD_NONE; } else { wifiCmd = WIFI_CMD_NONE; } wifiBusy = 0; break; } case WIFI_CMD_INTERNET_KEEP_ALIVE: { wifiBusy = 1; if(!https_token_valid) // if this is the first time get token { wifiCmd = WIFI_CMD_NONE; fromWiFiCmd = WIFI_CMD_TLS_CONNECT; nextWiFiCmd = WIFI_CMD_INTERNET_KEEP_ALIVE; setNextCommand(WIFI_CMD_GET_TOKEN); break; } keepSocketAlive(); wifiCmd = WIFI_CMD_NONE; wifiBusy = 0; break; } case WIFI_CMD_GET_TOKEN: { wifiBusy = 1; _event_queue.call(this, &WiFiManager::createTLSconnThreadCall, AWS_HOST_NAME); waitForBackgroundTask(6000, 10); // six second timeout if(backgroundTaskCompleted == false) { queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED); delete socket; socket = NULL; } else { https_connection_active = false; GetCloudAccessToken(); wifiCmd = WIFI_CMD_NONE; setNextCommand(WIFI_CMD_TLS_CONNECT); //_event_queue.call_in(ONE_SECOND,this, &WiFiManager::setNextCommand, WIFI_CMD_TLS_CONNECT); //wifiCmd = WIFI_CMD_TLS_CONNECT; } //wifiBusy = 0; break; } case WIFI_CMD_WIFI_MAC_ADDR: { wifiBusy = 1; if(outputBuffersAvailable()) { getWiFiMACaddress(); sendATresponseString(AT_WIFI_MAC_RESP); } wifiCmd = WIFI_CMD_NONE; wifiBusy = 0; break; } case WIFI_CMD_SEND_HTTP_REQ: break; default: break; } wait_ms(WIFI_MAIN_LOOP_WAIT_TIME_MS); // } } void WiFiManager::createSendHttpsRequest() { backgroundTaskCompleted = createHttpsRequest(); } void WiFiManager::createTLSconnThreadCall(const char * hostName) { bool result; backgroundTaskCompleted = false; result = createTLSconnection(hostName); if(result) { // update remote peer details after socket connection updateRemotePeerDetails(); // send socket connection event before proceeding to send https request // give about 2 ms sendSocketConnectionEvent(); backgroundTaskCompleted = true; } } void WiFiManager::waitForBackgroundTask(int timeout_ms, int inc_ms) { backgroundTaskCompleted = false; int msecCount = 0; int oldChunkNum = chunkNum; while(!backgroundTaskCompleted && msecCount < timeout_ms) { msecCount+=inc_ms; wait_ms(inc_ms); if(oldChunkNum != chunkNum) // new payload received { oldChunkNum = chunkNum; msecCount = 0; } } } void WiFiManager::sendATresponseString(at_cmd_resp_t at_cmd) { int strLen = strlen(responseString) + 1; at_data_resp = new at_data_msg_t; // set string length at_data_resp->dataLen = strLen; memcpy(at_data_resp->buffer, responseString, strLen); free(responseString); responseString = NULL; // package and send on wifi data queue at_data_resp->at_resp = at_cmd; bool queueResult = true; int wait_count = 0; do { if(!queueResult){ wait_count+=10; dbg_printf(LOG, "ATCMD Queue full waiting %d ms so far...\n", wait_count); wait_ms(10); } queueResult = queueWiFiDataResponse(*at_data_resp); }while(queueResult == false && wait_count<QUEUE_WAIT_TIMEOUT_MS); delete at_data_resp; at_data_resp = NULL; } void WiFiManager::sendATresponseBytes(at_cmd_resp_t at_cmd, int len) { at_data_resp = new at_data_msg_t; // set string length at_data_resp->dataLen = len; memcpy(at_data_resp->buffer, responseBytes, len); delete responseBytes; responseBytes = NULL; // package and send on wifi data queue at_data_resp->at_resp = at_cmd; bool queueResult = true; int wait_count = 0; do { if(!queueResult){ wait_count+=10; wait_ms(10); dbg_printf(LOG, "ATCMD Queue full waited %d ms so far...\n", wait_count); } queueResult = queueWiFiDataResponse(*at_data_resp); }while(queueResult == false && wait_count<QUEUE_WAIT_TIMEOUT_MS); delete at_data_resp; at_data_resp = NULL; dbg_printf(LOG, "[WIFI-MAN] sendATresponseBytes completed successfully\r\n"); } bool WiFiManager::dequeueWiFiCommands(){ if(wifiCmd != WIFI_CMD_NONE || wifiBusy!=0) return false; // busy osEvent evt = _aT2WiFiCmdQueue->get(0); if(evt.status == osEventMessage){ wifi_cmd_message_t *cmd = (wifi_cmd_message_t*)evt.value.p; setNextCommand(cmd->wifi_cmd); #ifndef USE_MALLOC_FOR_COMMAND_MEMORY_POOL _aT2WiFimPool->free(cmd); cmd = NULL; #else free(cmd); cmd = NULL; #endif } return true; } bool WiFiManager::dequeueATdataResponse(){ if(wifiCmd != WIFI_CMD_NONE || wifiBusy!=0) return false; // busy osEvent evt = _aT2WiFiDataQueue->get(0); if(evt.status == osEventMessage){ data_msg = (wifi_data_msg_t*)evt.value.p; setNextCommand(data_msg->wifi_cmd); //_wiFi2ATDatamPool->free(data_msg); } return true; } bool WiFiManager::setNextCommand(wifi_cmd_t cmd) { dbg_printf(LOG, "\n [WIFI-MAN] About to set next WiFi manager command to %d\n", cmd); if(wifiCmd == WIFI_CMD_NONE){ wifiCmd = cmd; return true; // success } dbg_printf(LOG, "\n [WIFI-MAN] Busy : current state = %d \n", wifiCmd); return false; // wiFiManager busy } const char * WiFiManager::sec2str(nsapi_security_t sec) { switch (sec) { case NSAPI_SECURITY_NONE: return "None"; case NSAPI_SECURITY_WEP: return "WEP"; case NSAPI_SECURITY_WPA: return "WPA"; case NSAPI_SECURITY_WPA2: return "WPA2"; case NSAPI_SECURITY_WPA_WPA2: return "WPA/WPA2"; case NSAPI_SECURITY_UNKNOWN: default: return "Unknown"; } } nsapi_size_or_error_t WiFiManager::scanNetworks() { getWiFiInstance(); if(network == NULL) { dbg_printf(LOG, "\n [WIFI-MAN] Error instantiating WiFi!! \n"); return 0; } //nsapi_error_t error; dbg_printf(LOG, "\n [WIFI-MAN] About to start scan for WiFi networks\n"); lastScanCount = network->scan(NULL, 0); dbg_printf(LOG, "\n [WIFI-MAN] Scan for WiFi networks completed - \n"); return lastScanCount; } //nsapi_size_or_error_t WiFiManager::getAvailableAPs(WiFiAccessPoint * res, // nsapi_size_t ncount) nsapi_size_or_error_t WiFiManager::getAvailableAPs(nsapi_size_t ncount) { getWiFiInstance(); if(network == NULL) { dbg_printf(LOG, "\n [WIFI-MAN] Error instantiating WiFi!! \n"); return 0; } WiFiAccessPoint *ap; nsapi_size_or_error_t count; count = ncount; if (count <= 0) { dbg_printf(LOG, "[WIFI-MAN] scan() failed with return value: %d\n", count); return 0; } /* Limit number of network arbitrary to 15 */ count = count < 15 ? count : 15; ap = new WiFiAccessPoint[count]; count = network->scan(ap, count); if (count <= 0) { dbg_printf(LOG, "[WIFI-MAN] scan() failed with return value: %d\n", count); return 0; } for (int i = 0; i < count; i++) { dbg_printf(LOG, "[WIFI-MAN]: %s secured: %s BSSID: %hhX:%hhX:%hhX:%hhx:%hhx:%hhx RSSI: %hhd Ch: %hhd\n", ap[i].get_ssid(), sec2str(ap[i].get_security()), ap[i].get_bssid()[0], ap[i].get_bssid()[1], ap[i].get_bssid()[2], ap[i].get_bssid()[3], ap[i].get_bssid()[4], ap[i].get_bssid()[5], ap[i].get_rssi(), ap[i].get_channel()); } dbg_printf(LOG, "[WIFI-MAN] %d networks available.\n", count); delete[] ap; return count; } void WiFiManager::set_WIFI_CONFIG() { wifi_config_t *wifi_cfg= (wifi_config_t *) data_msg->buffer; if(wifi_cfg->ssid[0] != NULL)set_WIFI_SSID(wifi_cfg->ssid); if(wifi_cfg->pass[0] != NULL)set_WIFI_PASSWORD(wifi_cfg->pass); if(wifi_cfg->security != NSAPI_SECURITY_UNKNOWN)set_WIFI_SECURITY(wifi_cfg->security); free_DataMsg(); } void WiFiManager::set_WIFI_SSID(char * wifi_ssid) { strcpy(wifi_config->ssid, wifi_ssid); dbg_printf(LOG, "[WIFI-MAN] wifi_ssid set to %s\n", wifi_config->ssid); https_connection_active = false; // reset whenever any of the security credentials change delete socket; } void WiFiManager::set_WIFI_PASSWORD(char * wifi_pass) { strcpy(wifi_config->pass, wifi_pass); dbg_printf(LOG, "[WIFI-MAN] wifi_pass set to %s\n", "****************"); https_connection_active = false; // reset whenever any of the security credentials change delete socket; } void WiFiManager::set_WIFI_SECURITY(nsapi_security_t wifi_security) { wifi_config->security = wifi_security; dbg_printf(LOG, "[WIFI-MAN] wifi_security set to %s\n", sec2str(wifi_config->security)); https_connection_active = false; // reset whenever any of the security credentials change delete socket; } void WiFiManager::gethostbyname() { nsapi_value_or_error_t value_or_error; #ifdef DNANUDGE_DEBUG SocketAddress * addr = new SocketAddress; bool res; res = addr->set_ip_address("8.8.8.8"); if(res) { dbg_printf(LOG, "[WIFI-MAN] added ip address %s\r\n", addr->get_ip_address()); } else { dbg_printf(LOG, "[WIFI-MAN] Error adding ip address \r\n"); } network->add_dns_server(*addr); #endif char * serverAddress = new char[100]; char *p = strstr(internet_config->url, "//"); if(p != NULL && use_full_hostname == false) { strcpy(serverAddress,p+2); } else { strcpy(serverAddress,internet_config->url); } value_or_error = network->gethostbyname_async(serverAddress, callback(this, &WiFiManager::gethostbyname_callback), NSAPI_UNSPEC); if(value_or_error >= NSAPI_ERROR_OK) // success { dbg_printf(LOG, "[WIFI-MAN] hostname translation successful value_or_error = %d\r\n", value_or_error); //strcpy(responseString, UDDRP_WRITE_OK); //printBufferInHex(responseBytes, HOSTNAME_RESPONSE_LEN); //sendATresponseBytes(CONNECT_EVENT, HOSTNAME_RESPONSE_LEN); } else if(outputBuffersAvailable()) // -ve number means error { responseString = (char *) malloc(20); dbg_printf(LOG, "[WIFI-MAN] hostname translation failed\r\n"); strcpy(responseString, UDDRP_ERROR); sendATresponseString(AT_COMMAND_FAILED); } } void WiFiManager::set_internet_config() { internet_config_t *internet_cfg = (internet_config_t *) data_msg->buffer; internet_config->peer_id = internet_cfg->peer_id; strncpy(internet_config->url,internet_cfg->url, strlen(internet_cfg->url)+1); internet_config->connectionScheme = internet_cfg->connectionScheme; free_DataMsg(); dbg_printf(LOG, "[WIFI MAN] Internet configuration setup completed\n"); dbg_printf(LOG, "peer_id = %1d, url = %s, connScheme = %1d\n", internet_config->peer_id, internet_config->url, internet_config->connectionScheme); if(https_connection_active) { https_connection_active = false; // reset whenever any of the security credentials change socket->close(); // close socket before deleting memory delete socket; socket = NULL; } _event_queue.call_in(10, this, &WiFiManager::gethostbyname); } void WiFiManager::getNetworkStatus(){ responseString = (char *) malloc(MAX_RESPONSE_STRING_LEN); net_stat_id_t status_id; char * nextStrPtr = responseString; for(int i=0; i< NumNetworkStatus;i++){ status_id = netStatusIds[i]; // get current status id switch(status_id){ case IF_HW_ADDRESS: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, network->get_mac_address()); break; case NETWORK_IF_STATUS: sprintf(nextStrPtr, "\r\n%s%d,%d, %d\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, (uint8_t)is_connected); break; case INTERFACE_TYPE: sprintf(nextStrPtr, "\r\n%s%d,%d,%d\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, WIFI_STATION); break; case IPv4_ADDRESS: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, network->get_ip_address()); break; case SUBNET_MASK: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, network->get_netmask()); break; case GATEWAY_ADDRESS: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, network->get_gateway()); break; case PRIMARY_DNS_SERVER: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, DEFAULT_DNS_ADDRESS); break; case SECONDARY_DNS_SERVER: sprintf(nextStrPtr, "\r\n%s%d,%d,%s\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id, DEFAULT_DNS_ADDRESS); break; case IPv6_ADDRESS: sprintf(nextStrPtr, "\r\n%s%d,%d,::\r\n", NETWORK_STATUS, WIFI_CHANNEL, status_id); break; default: sprintf(nextStrPtr, "\r\n%s,::\r\n", NETWORK_STATUS); break; } nextStrPtr += strlen(nextStrPtr) ; // progress to end of current string } sprintf(nextStrPtr, "%s", UDDRP_WRITE_OK); } void WiFiManager::getWiFiMACaddress() { char * mp = new char[20]; sscanf(network->get_mac_address(),"%02s:%2s:%2s:%2s:%2s:%2s",&mp[0],&mp[2],&mp[4],&mp[6],&mp[8],&mp[10]); responseString = (char *) malloc(100); sprintf(responseString, "\r\n%s%d,%sOK\r\n", LOCAL_ADDRESS_RESP, WIFI_IF_ID, mp); delete mp; } void WiFiManager::getWiFiStatus(){ responseString = (char *) malloc(MAX_RESPONSE_STRING_LEN); wifi_stat_id_t status_id; char * nextStrPtr = responseString; for(int i=0; i< NumWiFiStatus;i++){ status_id = wifiStatusIds[i]; // get current status id switch(status_id){ case WIFI_SSID: sprintf(nextStrPtr, "\r\n%s%d,%s\r\n", WIFI_NETWORK_STATUS, status_id, wifi_config->ssid); break; case WIFI_BSSID: sprintf(nextStrPtr, "\r\n%s%d,%s\r\n", WIFI_NETWORK_STATUS, status_id, network->get_mac_address()); break; case WIFI__CURRENT_CHANNEL: sprintf(nextStrPtr, "\r\n%s%d,%d\r\n", WIFI_NETWORK_STATUS, status_id, DEFAULT_WIFI_CHANNEL); break; case WIFI_STA_STATUS: sprintf(nextStrPtr, "\r\n%s%d,%d\r\n", WIFI_NETWORK_STATUS, status_id, (uint8_t)is_connected); break; case WIFI_RSSI: sprintf(nextStrPtr, "\r\n%s%d,%d\r\n", WIFI_NETWORK_STATUS, status_id, network->get_rssi()); break; default: sprintf(nextStrPtr, "\r\n%s,::\r\n", WIFI_NETWORK_STATUS); break; } nextStrPtr += strlen(nextStrPtr) ; // progress to end of current string } sprintf(nextStrPtr, "%s", UDDRP_WRITE_OK); } void WiFiManager::free_DataMsg() { // free memory after processing _aT2WiFiDatamPool->free(data_msg); data_msg = NULL; } void WiFiManager::status_callback(nsapi_event_t status, intptr_t param) { dbg_printf(LOG, "[WIFI-MAN] about to call status_callback_event... \r\n"); _event_queue.call_in(50, this, &WiFiManager::status_callback_event, status, param); } void WiFiManager::status_callback_event(nsapi_event_t status, intptr_t param) { switch(param) { case NSAPI_STATUS_LOCAL_UP: dbg_printf(LOG, "[WIFI-MAN] Local IP address set!\r\n"); dbg_printf(LOG, "[WIFI-MAN] IP address: %s\n", network->get_ip_address()); break; case NSAPI_STATUS_GLOBAL_UP: dbg_printf(LOG, "Global IP address set!\r\n"); dbg_printf(LOG, "[WIFI-MAN] IP address: %s\n", network->get_ip_address()); dbg_printf(LOG, "[WIFI-MAN] Connected to the network %s\n", wifi_config->ssid); if(outputBuffersAvailable()) { responseString = (char *) malloc(MAX_RESPONSE_STRING_LEN); sprintf(responseString, "\r\n%s%d,%s,%d\r\n", WIFI_LINK_ENABLED, WIFI_CHANNEL, network->get_mac_address(), DEFAULT_WIFI_CHANNEL); wifiBusy = 0; is_connected = true; } break; case NSAPI_STATUS_DISCONNECTED: dbg_printf(LOG, "No connection to network!\r\n"); dbg_printf(LOG, "\n [WIFI-MAN] No connection to network!\n"); if(outputBuffersAvailable()) { responseString = (char *) malloc(100); sprintf(responseString, "\r\n%s%d,5\r\n", WIFI_LINK_DISABLED, WIFI_CHANNEL); //sendATresponseString(AT_EVENT); } wifiBusy = 0; is_connected = false; break; case NSAPI_STATUS_CONNECTING: dbg_printf(LOG, "Connecting to network!\r\n"); break; default: dbg_printf(LOG, "Not supported"); break; } } nsapi_error_t WiFiManager::connect() { getWiFiInstance(); if(network == NULL) { dbg_printf(LOG, "\n [WIFI-MAN] Error instantiating WiFi!! \n"); return 0; } nsapi_error_t error; dbg_printf(LOG, "\n [WIFI-MAN] About to connect to WiFi network\n"); network->attach(callback(this, &WiFiManager::status_callback)); error = network->set_blocking(false); if(error) { dbg_printf(LOG, "\n [WIFI-MAN] Could not set non-blocking mode for Wifi -- aborting!! - \n"); return error; } dbg_printf(LOG, "[WIFI-MAN] Connecting to network ssid = %s passwd = %s security = %s \r\n", wifi_config->ssid, "****************", sec2str(wifi_config->security)); error = network->connect(wifi_config->ssid, wifi_config->pass, wifi_config->security); dbg_printf(LOG, "[WIFI-MAN] network->connect called. error = %d\r\n", error); return error; } void WiFiManager::processGetHostByNameResult(nsapi_error_t result, SocketAddress *address) { dbg_printf(LOG, "gethostbyname_callback called... result = %d \r\n", result); print_memory_info(); if(outputBuffersAvailable()) { responseBytes = new uint8_t[HOSTNAME_RESPONSE_LEN]; //malloc(HOSTNAME_RESPONSE_LEN); int i = 0; responseBytes[i++] = IPv4_CONNECTION; // connect type IPv4 responseBytes[i++] = TCP_PROTOCOL; // Protocol = TCP if(is_connected && result>=0) { memcpy(&responseBytes[i], address->get_ip_bytes(), 4); // remote IPv4 address strcpy(internet_config->remote_IPv4Address, address->get_ip_address()); i +=4; uint16_t port = address->get_port(); internet_config->remote_port = port; memcpy(&responseBytes[i], &port, 2); // remote IPv4 port # i +=2; // local IPv4 address int ipAddr[4]; strcpy(internet_config->local_IPv4Address, network->get_ip_address()); sscanf(internet_config->local_IPv4Address, "%d.%d.%d.%d", &ipAddr[0], &ipAddr[1], &ipAddr[2], &ipAddr[3]); responseBytes[i++] = (uint8_t) ipAddr[0]; responseBytes[i++] = (uint8_t) ipAddr[1]; responseBytes[i++] = (uint8_t) ipAddr[2]; responseBytes[i++] = (uint8_t) ipAddr[3]; // local port number responseBytes[i++] = 0; responseBytes[i] = 0; printBufferInHex(responseBytes, HOSTNAME_RESPONSE_LEN); sendATresponseBytes(CONNECT_EVENT, HOSTNAME_RESPONSE_LEN); } else { // if unconnected set ip and port to zeroes memset(&responseBytes[i], 0x00, 6); delete responseBytes; dbg_printf(LOG, "\r\nHOSTNAME TRANSLATION FAILURE : error code = %d \r\n", result); if(responseString == NULL) { responseString = (char *) malloc(100); sprintf(responseString, "\r\nHOSTNAME TRANSLATION FAILURE : error code = %d \r\n", result); sendATresponseString(AT_EVENT); } use_full_hostname = not use_full_hostname; } wifiBusy = 0; backgroundTaskCompleted = true; } } void WiFiManager::gethostbyname_callback(nsapi_error_t res, SocketAddress *addr) { nsapi_error_t result = res; SocketAddress *address = new SocketAddress; address = addr; _event_queue.call(this, &WiFiManager::processGetHostByNameResult, result, address); #ifdef DNANUDGE_DEBUG callback_semaphore.release(); #endif } void WiFiManager::sendSocketConnectionEvent() { // responseString = (char *) malloc(MAX_RESPONSE_STRING_LEN); sprintf(responseString, "\r\n%s%d,%d,%d,%s,%d,%s,%d\r\n", PEER_CONNECTED_URC, IP_PEER_HANDLE, IPv4_CONNECTION, TCP_PROTOCOL, internet_config->local_IPv4Address, DEFAULT_LOCAL_PORT, internet_config->remote_IPv4Address, internet_config->remote_port); sendATresponseString(AT_EVENT); } nsapi_error_t WiFiManager::disconnect() { nsapi_error_t error; error = network->disconnect(); if(error < 0) { responseString = (char *) malloc(100); sprintf(responseString, "%s", UDDRP_ERROR); sendATresponseString(AT_EVENT); } return error; } #define MIX_HDR_AND_BODY void WiFiManager::sendResponseDownloadData(at_cmd_resp_t at_cmd, const uint8_t * buf, int bufLen) { at_data_resp = new at_data_msg_t; at_data_resp->at_resp = at_cmd; size_t bufSize = sizeof(at_data_resp->buffer); int pos = 0; at_data_resp->dataLen = 0; bool queueResult = true; int hdrLen = 0; int wait_count = 0; do { if(!queueResult){ wait_count++; dbg_printf(LOG, "[WIFI-MAN] ATCMD Queue full waiting %d ms so far...\n", wait_count*10); wait_ms(10); } else { if(http_response_hdr_sent == false && chunkNum==1){ // only do this for first chunk bool status = copyResponseHdr2Queue(buf); if(status == true){ dbg_printf(LOG, "[WIFI-MAN] Http Response header copied to response buffer [bytes = %d] \r\n",at_data_resp->dataLen); hdrLen = at_data_resp->dataLen; http_response_hdr_sent = true; } else { dbg_printf(LOG, "[WIFI-MAN] Http Response header copy failed\r\n"); } } int cpyLen = (bufLen - pos) > bufSize? bufSize : (bufLen - pos) ; dbg_printf(LOG, "[WIFI-MAN] Http Response body [bytes = %d] \r\n",cpyLen); at_data_resp->dataLen += cpyLen; memcpy(&at_data_resp->buffer[hdrLen], &buf[pos], cpyLen); dbg_printf(LOG, "[WIFI-MAN] Http Response header and body copied to response buffer [bytes = %d] \r\n",at_data_resp->dataLen); } queueResult = queueWiFiDataResponse(*at_data_resp); if(queueResult){ pos+= at_data_resp->dataLen; at_data_resp->dataLen = 0; hdrLen = 0; } }while(queueResult == false || pos < bufLen); dbg_printf(LOG, "[WIFI-MAN] response data queued - deleting data memory\r\n"); delete at_data_resp; at_data_resp = NULL; } bool WiFiManager::copyResponseHdr2Queue(const uint8_t * buf) { const char *arbPtr = (const char *)buf - MAX_HTTP_HDR_LEN; const char *hdrPtr; int len; bool hdrFound = false; int i; for(i=0;i<(MAX_HTTP_HDR_LEN-50);i++) { // get location of start of the http header string hdrPtr = strstr(&arbPtr[i], HTTP_HEADER_START_LINE); len = strlen(HTTP_HEADER_START_LINE); // validate that header string if((strstr(&arbPtr[i+len], HTTP_HEADER_START_LINE) == NULL || (strstr(&arbPtr[i+len], HTTP_HEADER_START_LINE) > (const char*)buf)) && // strstr(&arbPtr[i+len], HTTP_HEADER_CONTENT_TYPE) != NULL && strstr(&arbPtr[i+len], HTTP_HEADER_CONTENT_LEN) != NULL && hdrPtr != NULL) { hdrFound = true; break; } } // calculate header length int hdrLen = (const char*) buf -hdrPtr; // copy header memcpy(at_data_resp->buffer, (const uint8_t *) hdrPtr, hdrLen); dbg_printf(LOG, "[i = %d] This is the header\r\n%s\r\n", i, hdrPtr); if(hdrFound == false) { dbg_printf(LOG, "[WIFI-MAN] copy failed: HTTP header not found!!\r\n"); return false; } at_data_resp->dataLen = hdrLen; return true; } void WiFiManager::return_response(HttpResponse* res) { at_data_resp = new at_data_msg_t; int numChars = 0; // create message pointer for response header generation char * msgPtr = (char *)at_data_resp->buffer; // do status line numChars = sprintf(msgPtr, "HTTP/1.1 %d %s\r\n", res->get_status_code(), res->get_status_message().c_str()); msgPtr += numChars; for (size_t ix = 0; ix < res->get_headers_length(); ix++) { numChars = sprintf(msgPtr, "%s: %s\r\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str()); msgPtr += numChars; } numChars = sprintf(msgPtr, "\r\n\r\n"); msgPtr += numChars; // print out generated header dbg_printf(LOG, "[WiFi MAN] generated response header:\n"); dbg_printf(LOG, "%s\r\n", (char *)at_data_resp->buffer); // calculate header length at_data_resp->dataLen = (msgPtr - (char *)at_data_resp->buffer); // package and send on wifi data queue at_data_resp->at_resp = AT_HTTPS_RESP; bool queueResult = true; int wait_count = 0; do { if(!queueResult){ wait_count++; dbg_printf(LOG, "ATCMD Queue full waiting %d ms so far...\n", wait_count*10); wait_ms(10); } queueResult = queueWiFiDataResponse(*at_data_resp); }while(queueResult == false); delete at_data_resp; at_data_resp = NULL; } void WiFiManager::printBufferInHex(const uint8_t *buf, int pLen) { print_debug_hex(buf, pLen); } //#define TRY_PRINTF void WiFiManager::body_callback(const char *at, uint32_t length) { dbg_printf(LOG, "\n Chunked response: Chunk %d : Total Bytes = %d\n", chunkNum , length); chunkNum++; dbg_printf(LOG, "This is the start when response is excluded\r\n%s\r\nend of packet \r\n", at); if(http_response == NULL) { dbg_printf(LOG, "[WIFI-MAN] response pointer NULL!!\r\n"); } else { dbg_printf(LOG, "[WIFI-MAN] response pointer NULL not!!\r\n"); } #ifdef SEND_DEBUG_MESSAGES if(responseString == NULL && chunkNum==1) { responseString = (char *) malloc(100); sprintf(responseString, "\r\nHTTPS BODY CALLBACK RECEIVED:: length= %d\r\n", length); sendATresponseString(AT_EVENT); } #endif sendResponseDownloadData(AT_HTTPS_RESP_DOWNLOAD, (uint8_t *)at, length); } //#define ENABLE_MBED_TRACE bool WiFiManager::createTLSconnection(const char * hostName) { #ifdef ENABLE_MBED_TRACE mbed_trace_init(); #endif socket = new TLSSocket(); nsapi_error_t r; // make sure to check the return values for the calls below (should return NSAPI_ERROR_OK) r = socket->open(network); if(r != NSAPI_ERROR_OK) { dbg_printf(LOG, "TLS open failed!!\n"); return false; } dbg_printf(LOG, "TLS open passed!!\n"); r = socket->set_root_ca_cert(SSL_CA_PEM); if(r != NSAPI_ERROR_OK) { dbg_printf(LOG, "TLS set_root_ca_cert failed!!\n"); socket->close(); dbg_printf(LOG, "closing TLS socket!!\n"); return false; } dbg_printf(LOG, "TLS set_root_ca_cert passed!!\n"); int start_ms = _event_queue.tick(); int elapsed_ms; do{ r = socket->connect(hostName, 443); elapsed_ms = _event_queue.tick() - start_ms; if(r == NSAPI_ERROR_OK) { dbg_printf(LOG, "TLS connection successful for https site : %s" " \r\n[TLS conn elapsed_ms = %d]\n", hostName, elapsed_ms); return true; } }while(elapsed_ms < TLS_RETRY_TIMEOUT_MS); char errstr[100]; mbedtls_strerror(r, errstr, 100); dbg_printf(LOG, "TLS connect failed (err = %d) for hostname '%s' -- ERROR = %s !!\n", r, hostName, errstr); socket->close(); return false; } void WiFiManager::updateRemotePeerDetails() { dbg_printf(LOG, "Updating internet_config... \r\n"); nsapi_error_t error; SocketAddress * address = new SocketAddress; error = socket->getpeername(address); if(error>=0) { strcpy(internet_config->remote_IPv4Address, address->get_ip_address()); uint16_t port = address->get_port(); internet_config->remote_port = port; } else { strcpy(internet_config->remote_IPv4Address, ""); internet_config->remote_port = 0; } delete address; } void WiFiManager::sendDebugMessage() { #ifdef SEND_HTTPS_DEBUG_MESSAGES sendATresponseString(AT_EVENT); wait_ms(100); #else free(responseString); #endif } #define TESTING_HTTPS //#define DONT_USE_TLS_SOCKET bool WiFiManager::createHttpsRequest() { int starttime; int stoptime; // reset chunk #; chunkNum = 0; http_response_hdr_sent = false; dbg_printf(LOG, "\n[WIFI MAN] Http Request received:\n"); http_req_cfg = (http_request_t *) data_msg->buffer; #ifdef FULL_DEBUG_ENABLED dbg_printf(LOG, "\n[WIFI MAN] uri = %s\n", http_req_cfg->request_URI); dbg_printf(LOG, "\n[WIFI MAN] internet cfg url = %s\n", internet_config->url); #endif char full_url[100]; char host[60] ; strncpy(full_url,internet_config->url, strlen(internet_config->url)+1); //strncpy(host,http_req_cfg->hostName, strlen(http_req_cfg->hostName)+1); char *eu = strstr(internet_config->url,HTTPS_URL_PREFIX); if(eu == NULL) eu = internet_config->url; else eu += strlen(HTTPS_URL_PREFIX); char *eu2 = strstr(eu, "/"); // find the api path int hLen = eu2 != NULL ? eu2-eu-1: strlen(eu); strncpy(host,eu, hLen+1); strncat(full_url, http_req_cfg->request_URI, strlen(http_req_cfg->request_URI)+1); #ifdef FULL_DEBUG_ENABLED dbg_printf(LOG, "\n[WIFI MAN] server host name = %s\n", host); dbg_printf(LOG, "\n[WIFI MAN] server url+uri = %s\n", full_url); dbg_printf(LOG, "\n[WIFI MAN] Host = %s\n", http_req_cfg->hostName); dbg_printf(LOG, "\n[WIFI MAN] Accept = %s\n", http_req_cfg->AcceptVal); dbg_printf(LOG, "\n[WIFI MAN] Content-Type = %s\n", http_req_cfg->contentType); dbg_printf(LOG, "\n[WIFI MAN] contentLenstr = %s\n", http_req_cfg->contentLen); #endif int bodyLen; sscanf(http_req_cfg->contentLen, "%d", &bodyLen); #ifdef FULL_DEBUG_ENABLED dbg_printf(LOG, "contenLenstr = %s bodyLen = %d\n", http_req_cfg->contentLen, bodyLen); if(bodyLen > 10){ dbg_printf(LOG, "\n [WIFI MAN] Message Body:\n"); printBufferInHex(http_req_cfg->body, bodyLen); } #endif if(strstr(internet_config->url, "http:")!=NULL) // http request { http_request = new HttpRequest(network, http_req_cfg->method, full_url, callback(this, &WiFiManager::body_callback)); setHttpHeader("Host", http_req_cfg->hostName); setHttpHeader("Accept", http_req_cfg->AcceptVal); if(http_req_cfg->method == HTTP_GET){ dbg_printf(LOG, "HTTP_GET -- ignoring body\n"); http_response = http_request->send(NULL, 0); } else{ setHttpHeader("Content-Type", http_req_cfg->contentType); setHttpHeader("Content-Length", http_req_cfg->contentLen); http_response = http_request->send(http_req_cfg->body, bodyLen); } free_DataMsg(); if (!http_response) { char buf[100]; mbedtls_strerror(http_request->get_error(), buf, 100); dbg_printf(LOG, "HttpRequest failed (error code %s)\n", buf); delete http_request; // free the memory return false; } delete http_request; // free the memory dbg_printf(LOG, "\n----- HTTP POST response -----\n"); } else { mbed_stats_heap_t heap_stats; mbed_stats_heap_get(&heap_stats); dbg_printf(LOG, "Heap size: %lu / %lu bytes\r\n", heap_stats.current_size, heap_stats.reserved_size); starttime = Kernel::get_ms_count(); #ifndef DONT_USE_TLS_SOCKET if(https_connection_active == false){ bool tlsResult; tlsResult = createTLSconnection(host); #ifdef ENABLE_MBED_TRACE mbed_trace_free(); // free trace memory #endif stoptime = Kernel::get_ms_count(); dbg_printf(LOG, "\r\nTLS connection time : %d ms\r\n", (stoptime - starttime)); if(tlsResult == false){ delete socket; dbg_printf(LOG, "TLS Socket connection failed - deleting data msg\r\n"); free_DataMsg(); dbg_printf(LOG, "data msg deleted \r\n"); http_result = TLS_CONNECTION_FAILED; return false; } // update remote peer details after socket connection updateRemotePeerDetails(); // send socket connection event before proceeding to send https request // give about 2 ms sendSocketConnectionEvent(); } // Pass in `socket`, instead of `network` as first argument, and omit the `SSL_CA_PEM` argument stoptime = Kernel::get_ms_count(); dbg_printf(LOG, "\r\nTLS connection time : %d ms\r\n", (stoptime - starttime)); starttime = Kernel::get_ms_count(); https_request = new HttpsRequest(socket, http_req_cfg->method, full_url, callback(this, &WiFiManager::body_callback)); #ifdef SEND_DEBUG_MESSAGES responseString = (char *) malloc(100); sprintf(responseString, "\r\nHTTP REQUEST OBJECT CREATED\r\n"); sendDebugMessage(); #endif #else https_request = new HttpsRequest(network, SSL_CA_PEM, http_req_cfg->method, full_url, callback(this, &WiFiManager::body_callback)); #endif #ifdef TESTING_HTTPS dbg_printf(LOG, "http_req_cfg->method = %d\n", http_req_cfg->method); if(http_req_cfg->method == HTTP_GET){ dbg_printf(LOG, "HTTP_GET -- ignoring body\n"); setHttpsHeader("Host", host); setHttpsHeader("Accept", http_req_cfg->AcceptVal); http_response = https_request->send(NULL, 0); } else{ setHttpsHeader("Host", host); setHttpsHeader("Authorization", aws_id_token); setHttpsHeader("Accept", http_req_cfg->AcceptVal); setHttpsHeader("Content-Type", http_req_cfg->contentType); setHttpsHeader("Content-Length", http_req_cfg->contentLen); dbg_printf(LOG, "https headers setup - about to send request\r\n"); // Grab the heap statistics dbg_printf(LOG, "Heap size: %lu / %lu bytes\r\n", heap_stats.current_size, heap_stats.reserved_size); dbg_printf(LOG, "\n[WIFI MAN] Token Length: %d \r\n IdToken: \r\n %s\r\n", strlen(aws_id_token), aws_id_token); #ifdef PRINT_REQUEST_LOGS uint8_t *http_req_log_buf = (uint8_t*)calloc(2048, 1); https_request->set_request_log_buffer(http_req_log_buf, 2048); #endif http_response = https_request->send(http_req_cfg->body, bodyLen); } #else setHttpsHeader("Host", host); setHttpsHeader("Authorization", aws_id_token); setHttpsHeader("Accept", http_req_cfg->AcceptVal); setHttpsHeader("Content-Type", http_req_cfg->contentType); setHttpsHeader("Content-Length", http_req_cfg->contentLen); http_response = https_request->send(http_req_cfg->body, bodyLen); #endif #ifdef PRINT_REQUEST_LOGS printHttpRequestLogBuffer(); #endif nsapi_error_t error = https_request->get_error(); if(error < 0) { char buf[100]; mbedtls_strerror(error, buf, 100); printf("HttpsRequest failed (error code %s)\n", buf); delete https_request; // free the memory https_request = NULL; https_connection_active = false; // reset true whenever connection fails socket->close(); delete socket; socket = NULL; free_DataMsg(); http_result = HTTP_REQUEST_FAILED; return false; } https_connection_active = true; // set true whenever connection succeeds dbg_printf(LOG, "\n----- HTTPS POST response -----\r\n"); } if(http_response_hdr_sent == false) { socket->close(); delete socket; https_connection_active = false; #ifdef SEND_DEBUG_MESSAGES responseString = (char *) malloc(100); sprintf(responseString, "\r\n[WIFI-MAN] NO RESPONSE RECEIVED:: CLOSING CURRENT TLS CONNECTION.\r\n"); sendDebugMessage(); #endif //return_response(http_response); } free_DataMsg(); delete https_request; // free the request & response memory dbg_printf(LOG, "deleted https_request\r\n"); https_request = NULL; http_result = RESPONSE_OK; stoptime = Kernel::get_ms_count(); dbg_printf(LOG, "\r\nhttp request to response time : %d ms\r\n", (stoptime - starttime)); return true; } void WiFiManager::createHttpRequest(http_method method, const char* url, Callback<void(const char *at, uint32_t length)> body_callback) { http_request = new HttpRequest(network, method, url, body_callback);; } void WiFiManager::setHttpHeader(string key, string value) { http_request->set_header(key, value); } void WiFiManager::setHttpsHeader(string key, string value) { https_request->set_header(key, value); } void WiFiManager::printHttpRequestLogBuffer() { // after the request is done: #ifdef PRINT_BUFFER_IN_HEX dbg_printf(LOG, "\n----- Request buffer Hex-----\n"); for (size_t ix = 0; ix < https_request->get_request_log_buffer_length(); ix++) { if(ix%16 == 0)dbg_printf(LOG, "\n[%04x] ", ix); dbg_printf(LOG, "%02x ", http_req_log_buf[ix]); } #endif dbg_printf(LOG, "\n[ request size = %d bytes]\r\n", https_request->get_request_log_buffer_length()); dbg_printf(LOG, "----- Request buffer string -----\r\n%s ", (char *)http_req_log_buf); //wait_ms(100); free(http_req_log_buf); } void WiFiManager::sendHttpsRequest(const char * body, int bodyLen) { } void WiFiManager::sendHttpRequest(const char * body, int bodyLen) { }