in HTTPS_MutualAuth/Azsphere/main.c [239:418]
static void PerformWebPageDownload(void)
{
CURL *curlHandle = NULL;
CURLcode res = 0;
MemoryBlock block = {.data = NULL, .size = 0, .paused = false};
char *certificatePath = NULL;
char *clientCertPath = NULL;
char *clientKeyPath = NULL;
printedEntireResponse = false;
if (IsNetworkReady() == false) {
goto exitLabel;
}
Log_Debug("\n -===- START-OF-DOWNLOAD -===-\n");
// Init the cURL library.
if ((res = curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) {
LogCurlError("curl_global_init", res);
goto exitLabel;
}
if ((curlHandle = curl_easy_init()) == NULL) {
Log_Debug("curl_easy_init() failed\n");
goto cleanupLabel;
}
// Set the cURL handle to allow access to the cURL handle in callbacks.
block.curlHandle = curlHandle;
// Specify URL to download.
// Important: Any change in the domain name must be reflected in the AllowedConnections
// capability in app_manifest.json.
#warning Change the following line to specify the server address and delete this warning!
if ((res = curl_easy_setopt(curlHandle, CURLOPT_URL, "https://CHANGE.THIS:5000/")) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_URL", res);
goto cleanupLabel;
}
// Set output level to verbose.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 1L)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_VERBOSE", res);
goto cleanupLabel;
}
// Get the full path to the certificate file used to authenticate the HTTPS server identity.
certificatePath = Storage_GetAbsolutePathInImagePackage("certs/ca-bundle.pem");
if (certificatePath == NULL) {
Log_Debug("The certificate path could not be resolved: errno=%d (%s)\n", errno,
strerror(errno));
goto cleanupLabel;
}
// Set the path for the certificate file that cURL uses to validate the server certificate.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_CAINFO, certificatePath)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_CAINFO", res);
goto cleanupLabel;
}
clientCertPath= Storage_GetAbsolutePathInImagePackage("certs/device-cert.pem");
if (clientCertPath == NULL) {
Log_Debug("The client certificate path could not be resolved: errno=%d (%s)\n", errno,
strerror(errno));
goto cleanupLabel;
}
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSLCERT, clientCertPath)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_SSLCERT", res);
goto cleanupLabel;
}
clientKeyPath= Storage_GetAbsolutePathInImagePackage("certs/device-key.pem");
if (clientKeyPath == NULL) {
Log_Debug("The client key path could not be resolved: errno=%d (%s)\n", errno,
strerror(errno));
goto cleanupLabel;
}
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSLKEY, clientKeyPath)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_SSLKEY", res);
goto cleanupLabel;
}
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYPEER, 1L)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_SSL_VERIFYPEER", res);
goto cleanupLabel;
}
if ((res = curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYHOST, 1L)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_SSL_VERIFYHOST", res);
goto cleanupLabel;
}
// Let cURL follow any HTTP 3xx redirects.
// Important: Any redirection to different domain names requires that domain name to be added to
// app_manifest.json.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_FOLLOWLOCATION, 1L)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_FOLLOWLOCATION", res);
goto cleanupLabel;
}
// Set up callback for cURL to use when downloading data.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, StoreDownloadedDataCallback)) !=
CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_WRITEFUNCTION", res);
goto cleanupLabel;
}
// Set the custom parameter of the callback to the memory block.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, (void *)&block)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_WRITEDATA", res);
goto cleanupLabel;
}
// Specify a user agent.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_USERAGENT, "libcurl-agent/1.0")) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_USERAGENT", res);
goto cleanupLabel;
}
// Set up callback for cURL to report transfer information.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_XFERINFOFUNCTION, TransferInfoCallback)) !=
CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_XFERINFOFUNCTION", res);
goto cleanupLabel;
}
// Set the custom parameter of the callback to the memory block. It is not used by cURL but is
// only passed along from the application to the callback.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_XFERINFODATA, (void *)&block)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_XFERINFODATA", res);
goto cleanupLabel;
}
// Turn on the progress meter. This enables CURLOPT_XFERINFOFUNCTION callbacks.
if ((res = curl_easy_setopt(curlHandle, CURLOPT_NOPROGRESS, 0L)) != CURLE_OK) {
LogCurlError("curl_easy_setopt CURLOPT_NOPROGRESS", res);
goto cleanupLabel;
}
// Configure the cURL handle to use the proxy.
if (!bypassProxy) {
if (Networking_Curl_SetDefaultProxy(curlHandle) != 0) {
Log_Debug("Networking_Curl_SetDefaultProxy failed: errno=%d (%s)\n", errno,
strerror(errno));
exitCode = ExitCode_CurlSetDefaultProxy_Failed;
goto cleanupLabel;
}
}
// When using libcurl, as with other networking applications, the Azure Sphere OS will
// allocate socket buffers which are attributed to your application's RAM usage. You can tune
// the size of these buffers to reduce the RAM footprint of your application as appropriate.
// Refer to https://learn.microsoft.com/azure-sphere/app-development/ram-usage-best-practices
// for further details.
// Perform the download of the web page.
if ((res = curl_easy_perform(curlHandle)) != CURLE_OK) {
LogCurlError("curl_easy_perform", res);
} else {
if (!printedEntireResponse) {
// Log the remaining downloaded content if it wasn't logged in TransferInfoCallback.
PrintResponseAndResetData(&block);
}
}
cleanupLabel:
// Clean up allocated memory.
free(block.data);
free(certificatePath);
// Clean up sample's cURL resources.
curl_easy_cleanup(curlHandle);
// Clean up cURL library's resources.
curl_global_cleanup();
Log_Debug("\n -===- END-OF-DOWNLOAD -===-\n");
exitLabel:
return;
}