cURL asynchronous requests
This commit is contained in:
parent
f43203f5ae
commit
e3a3902143
|
@ -39,6 +39,21 @@ void set_heap_offset(int offset)
|
||||||
/* Initialize a Pudding instance */
|
/* Initialize a Pudding instance */
|
||||||
Pudding::Pudding()
|
Pudding::Pudding()
|
||||||
{
|
{
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
/* Initialize cURL and store result. Initialize the multi request handler. */
|
||||||
|
curl_init_result = curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
|
if (curl_init_result != CURLE_OK)
|
||||||
|
{
|
||||||
|
std::ostringstream message;
|
||||||
|
message << "cURL failed to initialize and will not be available " << curl_easy_strerror(curl_init_result);
|
||||||
|
sb::Log::log(message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
curl_multi_handle.reset(curl_multi_init());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* subscribe to command events */
|
/* subscribe to command events */
|
||||||
get_delegate().subscribe(&Pudding::respond, this);
|
get_delegate().subscribe(&Pudding::respond, this);
|
||||||
get_delegate().subscribe(&Pudding::respond, this, SDL_MOUSEMOTION);
|
get_delegate().subscribe(&Pudding::respond, this, SDL_MOUSEMOTION);
|
||||||
|
@ -589,7 +604,7 @@ void Pudding::incorporate_nutritionix_api(const std::vector<std::uint8_t>& json_
|
||||||
sb::Log::log(json_formatted.str(), sb::Log::DEBUG);
|
sb::Log::log(json_formatted.str(), sb::Log::DEBUG);
|
||||||
|
|
||||||
/* test that should determine if a Nutritionix response is not empty */
|
/* test that should determine if a Nutritionix response is not empty */
|
||||||
if (!(json.contains("message") && json["message"] == NUTRITIONIX_NOT_FOUND))
|
if (json.contains("foods"))
|
||||||
{
|
{
|
||||||
nlohmann::json food = json["foods"][0];
|
nlohmann::json food = json["foods"][0];
|
||||||
std::ostringstream message;
|
std::ostringstream message;
|
||||||
|
@ -820,22 +835,29 @@ void Pudding::web_get_bytes(std::string url, const web_callback& callback, const
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
CURL *curl;
|
if (curl_init_result != CURLE_OK)
|
||||||
CURLcode result;
|
|
||||||
result = curl_global_init(CURL_GLOBAL_DEFAULT);
|
|
||||||
if (result != CURLE_OK)
|
|
||||||
{
|
{
|
||||||
std::cout << "cURL initialization failed " << curl_easy_strerror(result) << std::endl;
|
std::ostringstream message;
|
||||||
|
message << "cURL unavailable " << curl_easy_strerror(curl_init_result);
|
||||||
|
sb::Log::log(message);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
curl = curl_easy_init();
|
CURL* curl_easy_handle = curl_easy_init();
|
||||||
if (curl)
|
|
||||||
|
if (curl_easy_handle)
|
||||||
{
|
{
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
curl_easy_setopt(curl_easy_handle, CURLOPT_URL, url.c_str());
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_response);
|
curl_easy_setopt(curl_easy_handle, CURLOPT_WRITEFUNCTION, curl_write_response);
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, request);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, configuration()["api"]["user-agent"].get<std::string>().c_str());
|
/* WRITEDATA is set to the request object, so the storage in the request object can receive the transfer data */
|
||||||
|
curl_easy_setopt(curl_easy_handle, CURLOPT_WRITEDATA, request);
|
||||||
|
|
||||||
|
/* PRIVATE is also set to the request object, so the request can call the response function when the multi handle has
|
||||||
|
* determined that all the transfer packets are complete */
|
||||||
|
curl_easy_setopt(curl_easy_handle, CURLOPT_PRIVATE, request);
|
||||||
|
|
||||||
|
curl_easy_setopt(curl_easy_handle, CURLOPT_USERAGENT, configuration()["api"]["user-agent"].get<std::string>().c_str());
|
||||||
|
|
||||||
/* Pass submitted headers to cURL */
|
/* Pass submitted headers to cURL */
|
||||||
struct curl_slist* list = nullptr;
|
struct curl_slist* list = nullptr;
|
||||||
|
@ -849,26 +871,18 @@ void Pudding::web_get_bytes(std::string url, const web_callback& callback, const
|
||||||
list = curl_slist_append(list, pair.c_str());
|
list = curl_slist_append(list, pair.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
|
curl_easy_setopt(curl_easy_handle, CURLOPT_HTTPHEADER, list);
|
||||||
|
|
||||||
result = curl_easy_perform(curl);
|
/* Add the easy handle to the multi handle, so it can be processed asynchronously in the update loop */
|
||||||
curl_slist_free_all(list);
|
curl_multi_add_handle(curl_multi_handle.get(), curl_easy_handle);
|
||||||
|
|
||||||
if (result != CURLE_OK)
|
|
||||||
{
|
|
||||||
std::cout << "cURL request failed " << curl_easy_strerror(result) << std::endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "cURL initialization failed" << std::endl;
|
std::ostringstream message;
|
||||||
|
message << "cURL request initialization failed for " << url;
|
||||||
|
sb::Log::log(message);
|
||||||
}
|
}
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
}
|
}
|
||||||
curl_global_cleanup();
|
|
||||||
|
|
||||||
/* Call the user supplied callback */
|
|
||||||
request->respond();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1334,6 +1348,28 @@ void Pudding::update()
|
||||||
previous_barcode = current_barcode;
|
previous_barcode = current_barcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
/* Calling multi perform will perform transfers on handles cURL has determined are ready for transfer. Any handles that have transferred
|
||||||
|
* all their necessary data will cause a CURLMSG_DONE message to be in the message queue. If a handle is done, call the request callback
|
||||||
|
* that has been attached to it, remove the handle, and clean it up. */
|
||||||
|
int running_handles;
|
||||||
|
curl_multi_perform(curl_multi_handle.get(), &running_handles);
|
||||||
|
CURLMsg* message_queue;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int message_count;
|
||||||
|
message_queue = curl_multi_info_read(curl_multi_handle.get(), &message_count);
|
||||||
|
if (message_queue && (message_queue->msg == CURLMSG_DONE))
|
||||||
|
{
|
||||||
|
Request* request;
|
||||||
|
curl_easy_getinfo(message_queue->easy_handle, CURLINFO_PRIVATE, &request);
|
||||||
|
request->respond();
|
||||||
|
curl_multi_remove_handle(curl_multi_handle.get(), message_queue->easy_handle);
|
||||||
|
curl_easy_cleanup(message_queue->easy_handle);
|
||||||
|
}
|
||||||
|
} while(message_queue);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Delete and erase finished requests from the vector using iterators to erase while reading the vector */
|
/* Delete and erase finished requests from the vector using iterators to erase while reading the vector */
|
||||||
for (auto iter = requests.begin(); iter != requests.end();)
|
for (auto iter = requests.begin(); iter != requests.end();)
|
||||||
{
|
{
|
||||||
|
@ -1378,6 +1414,13 @@ void Pudding::update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pudding::~Pudding()
|
||||||
|
{
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
|
curl_global_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Request::Request(const web_callback& callback, const std::string& url) : callback(callback), request_url(url) {}
|
Request::Request(const web_callback& callback, const std::string& url) : callback(callback), request_url(url) {}
|
||||||
|
|
||||||
void Request::store(const std::uint8_t* buffer, const std::size_t& size)
|
void Request::store(const std::uint8_t* buffer, const std::size_t& size)
|
||||||
|
|
|
@ -13,6 +13,18 @@
|
||||||
/* Needed for functions in glm/gtx/ */
|
/* Needed for functions in glm/gtx/ */
|
||||||
#define GLM_ENABLE_EXPERIMENTAL
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
|
||||||
|
/* Standard library includes */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <functional>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
/* cURL and cv::VideoCapture are not available for Emscripten, so use alternatives for Emscripten builds */
|
/* cURL and cv::VideoCapture are not available for Emscripten, so use alternatives for Emscripten builds */
|
||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
#include <emscripten/fetch.h>
|
#include <emscripten/fetch.h>
|
||||||
|
@ -24,16 +36,6 @@ using namespace emscripten;
|
||||||
#include "opencv2/highgui.hpp"
|
#include "opencv2/highgui.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <functional>
|
|
||||||
#include <chrono>
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
#include "SDL_image.h"
|
#include "SDL_image.h"
|
||||||
#include "sdl2-gfx/SDL2_gfxPrimitives.h"
|
#include "sdl2-gfx/SDL2_gfxPrimitives.h"
|
||||||
|
@ -429,6 +431,9 @@ private:
|
||||||
int effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0;
|
int effect_id = EFFECT_NONE, pudding_triangle_vertex_count = 0, pudding_fan_vertex_count = 0;
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
cv::VideoCapture capture;
|
cv::VideoCapture capture;
|
||||||
|
std::unique_ptr<CURLM, decltype(&curl_multi_cleanup)> curl_multi_handle = std::unique_ptr<CURLM, decltype(&curl_multi_cleanup)>(
|
||||||
|
nullptr, curl_multi_cleanup);
|
||||||
|
CURLcode curl_init_result;
|
||||||
#endif
|
#endif
|
||||||
cv::Mat camera_frame, contrasted_frame, sharpened_frame, zbar_frame, blurred, low_contrast_mask;
|
cv::Mat camera_frame, contrasted_frame, sharpened_frame, zbar_frame, blurred, low_contrast_mask;
|
||||||
zbar::ImageScanner image_scanner;
|
zbar::ImageScanner image_scanner;
|
||||||
|
@ -591,6 +596,7 @@ public:
|
||||||
Item& current_item();
|
Item& current_item();
|
||||||
void update();
|
void update();
|
||||||
virtual std::string class_name() const { return "Pudding"; }
|
virtual std::string class_name() const { return "Pudding"; }
|
||||||
|
~Pudding();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue