this is using the mbed os version 5-13-1
Diff: source/WiFiManager.cpp
- Branch:
- PassingRegression
- Revision:
- 128:3a641aaad2d9
- Parent:
- 127:a21788227ca6
--- a/source/WiFiManager.cpp Mon Jul 15 21:37:22 2019 +0000
+++ b/source/WiFiManager.cpp Fri Jul 19 20:34:49 2019 +0000
@@ -51,7 +51,8 @@
//_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_request_succeeded = false;
+ https_token_valid = false;
+ token_refresh_count = 0;
//watchDogTick.attach(callback(this, &WiFiManager::callWifiWatchDogIsr), 10.0); // call flip function every 10 seconds
}
@@ -121,7 +122,12 @@
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");
- error = socket->send(HELLO_MSG, sizeof(HELLO_MSG));
+ 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)
{
@@ -146,37 +152,48 @@
{
queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED);
https_connection_active = false;
+ socket->close();
+ delete socket;
+ socket = NULL;
}
+ delete httpsReq;
}
void WiFiManager::CreateTokenHttpsRequest(char * httpsReq)
{
-
- sprintf(httpsReq, "%s\r\n\r\n{\r\n\"AuthParameters\" : {\r\n"
+ 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}", TOKEN_REQ_HDR, UserName, Password, AuthFlow, ClientId);
+ "\"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_SOCKET_KEEP_ALIVE_FAILED);
+ queueATresponse(AT_ACCESS_TOKEN_FAILED);
return;
}
error = socket->send(httpsReq, strlen(httpsReq)+1);
-
+ delete httpsReq;
if(error < 0)
{
- queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED);
+ queueATresponse(AT_ACCESS_TOKEN_FAILED);
return;
}
@@ -187,33 +204,59 @@
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);
- // reserve memomry on the heap for tokens
- aws_id_token = new char[ID_TOKEN_SIZE];
- aws_refresh_token = new char[REFRESH_TOKEN_SIZE];
// extract ID TOKEN
char *sp1 = strstr(respBuf,ID_TOKEN_STR_START);
- char *sp2 = strstr(respBuf,ACCESS_TOKEN_STR_END);
- int tokenLen = sp2-sp1;
- strncpy(aws_id_token, sp1, tokenLen);
- dbg_printf(LOG, "\n[WIFI MAN] IdToken: \r\n %s\r\n", aws_id_token);
+ 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(respBuf,ACCESS_TOKEN_STR_END);
- tokenLen = sp2-sp1;
- strncpy(aws_refresh_token, sp1, tokenLen);
- dbg_printf(LOG, "\n[WIFI MAN] RefreshToken: \r\n %s\r\n", aws_refresh_token);
- queueATresponse(AT_SOCKET_KEEP_ALIVE_OK);
- https_connection_active = true;
+ 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
{
- queueATresponse(AT_SOCKET_KEEP_ALIVE_FAILED);
- https_connection_active = false;
+ 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;
@@ -426,6 +469,7 @@
}
backgroundTaskCompleted = false;
wifiCmd = WIFI_CMD_NONE;
+ //wifiCmd = WIFI_CMD_GET_TOKEN;
break;
}
case WIFI_CMD_NETWORK_STATUS:
@@ -450,12 +494,20 @@
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);
}
- wifiBusy = 1;
#ifdef SEND_DEBUG_MESSAGES
if(outputBuffersAvailable())
{
@@ -467,25 +519,27 @@
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();
- //network->attach(NULL);
+ // 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);
- 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;
- }
- }
+ 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);
@@ -513,46 +567,93 @@
}
sendATresponseString(AT_COMMAND_FAILED);
}
- if(https_request_succeeded == false)
- {
- https_request_succeeded = result;
- }
-
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);
- //network->attach(callback(this, &WiFiManager::status_callback));
+ // 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);
- if(https_connection_active == false)
+ //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;
+ }
}
- wifiCmd = WIFI_CMD_NONE;
+ 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())
{
@@ -562,6 +663,7 @@
wifiCmd = WIFI_CMD_NONE;
wifiBusy = 0;
break;
+ }
case WIFI_CMD_SEND_HTTP_REQ:
break;
default:
@@ -577,6 +679,38 @@
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;
@@ -701,7 +835,7 @@
dbg_printf(LOG, "\n [WIFI-MAN] Error instantiating WiFi!! \n");
return 0;
}
- nsapi_error_t error;
+ //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");
@@ -1314,7 +1448,7 @@
if(responseString == NULL && chunkNum==1)
{
responseString = (char *) malloc(100);
- sprintf(responseString, "\r\nHTTPS BODY CALLBACK RECEIVED\r\n");
+ sprintf(responseString, "\r\nHTTPS BODY CALLBACK RECEIVED:: length= %d\r\n", length);
sendATresponseString(AT_EVENT);
}
#endif
@@ -1346,17 +1480,23 @@
return false;
}
dbg_printf(LOG, "TLS set_root_ca_cert passed!!\n");
- r = socket->connect(hostName, 443);
- if(r != NSAPI_ERROR_OK)
- {
- 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;
- }
- dbg_printf(LOG, "TLS connection successful for https site : %s\n", hostName);
- return true;
+ 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;
}
@@ -1409,9 +1549,20 @@
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);
+ //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);
@@ -1509,27 +1660,38 @@
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", http_req_cfg->hostName);
+ setHttpsHeader("Host", host);
setHttpsHeader("Accept", http_req_cfg->AcceptVal);
http_response = https_request->send(NULL, 0);
}
else{
- setHttpsHeader("Host", http_req_cfg->hostName);
+ 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", http_req_cfg->hostName);
+ 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
+#endif
+#ifdef PRINT_REQUEST_LOGS
+ printHttpRequestLogBuffer();
+#endif
nsapi_error_t error = https_request->get_error();
if(error < 0)
{
@@ -1589,6 +1751,22 @@
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)
{
}