aboutsummaryrefslogtreecommitdiff
path: root/src/opcodes.cpp
diff options
context:
space:
mode:
authorRichard Knight <q@1bpm.net>2024-04-09 22:58:44 +0100
committerRichard Knight <q@1bpm.net>2024-04-09 22:58:44 +0100
commitd4701791a2d04ff52bea456ebb34f4d79819f97e (patch)
treec582c6b10b271c550c9618cb0d818c5b27a98620 /src/opcodes.cpp
downloadcsound-curl-master.tar.gz
csound-curl-master.tar.bz2
csound-curl-master.zip
initialHEADmaster
Diffstat (limited to 'src/opcodes.cpp')
-rw-r--r--src/opcodes.cpp355
1 files changed, 355 insertions, 0 deletions
diff --git a/src/opcodes.cpp b/src/opcodes.cpp
new file mode 100644
index 0000000..5f27f60
--- /dev/null
+++ b/src/opcodes.cpp
@@ -0,0 +1,355 @@
+#include <plugin.h>
+#include "handling.h"
+#include <curl/curl.h>
+#include <atomic>
+
+const char* ciniterror = "cannot initialise CURL";
+
+static size_t write_callback(void* contents, size_t size, size_t nmemb, void *userp) {
+ ((std::string*)userp)->append((char*)contents, size * nmemb);
+ return size * nmemb;
+}
+
+class HTTPRequest {
+private:
+ csnd::Csound* csound;
+ CURL* curl;
+ char* url;
+
+ void curl_reset() {
+ curl_easy_reset(curl);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
+ }
+
+public:
+ CURLcode curlResult;
+ char* curlError;
+ long httpResponseCode;
+ std::string response;
+
+ HTTPRequest(csnd::Csound* csound, char* url) :
+ csound(csound),
+ url(url)
+ {
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ curl = curl_easy_init();
+ if (!curl) {
+ curl_global_cleanup();
+ throw std::runtime_error((char*) ciniterror);
+ }
+
+
+ }
+
+ ~HTTPRequest() {
+ curl_easy_cleanup(curl);
+ curl_global_cleanup();
+ }
+
+ void post(char* postdata) {
+ curl_reset();
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
+ curlResult = curl_easy_perform(curl);
+ if (curlResult != CURLE_OK) {
+ curlError = (char*) curl_easy_strerror(curlResult);
+ }
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpResponseCode);
+ }
+
+ void get() {
+ curl_reset();
+ curlResult = curl_easy_perform(curl);
+ if (curlResult != CURLE_OK) {
+ curlError = (char*) curl_easy_strerror(curlResult);
+ }
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpResponseCode);
+ }
+
+
+};
+
+
+class RequestThread : public csnd::Thread {
+ std::atomic_bool spinlock;
+ std::atomic_bool on;
+ int sleepTime;
+public:
+ HTTPRequest* req;
+ char* postdata;
+ bool dopost;
+ char* error;
+ bool errored;
+ bool done;
+ bool pending;
+ RequestThread(csnd::Csound* csound, char* url, bool dopost, char* postdata=NULL) :
+ Thread(csound),
+ done(false),
+ pending(false),
+ on(true),
+ spinlock(false),
+ postdata(postdata),
+ dopost(dopost),
+ sleepTime(10)
+ {
+ try {
+ req = new HTTPRequest(csound, url);
+ } catch (const std::exception &e) {
+ errored = true;
+ error = csound->strdup(req->curlError);
+ }
+ };
+
+ uintptr_t run() {
+ while (on) {
+ lock();
+ if (pending) {
+ try {
+ if (dopost) {
+ req->post(postdata);
+ } else {
+ req->get();
+ }
+
+ if (req->curlResult != CURLE_OK) {
+ errored = true;
+ error = csound->strdup(req->curlError);
+ }
+
+ done = true;
+ pending = false;
+ } catch (const std::exception &e) {
+ errored = true;
+ done = true;
+ pending = false;
+ error = csound->strdup((char*) e.what());
+ }
+ }
+ unlock();
+ csound->sleep(sleepTime);
+ }
+ return 0;
+ }
+
+ void lock() {
+ while (spinlock == true) {
+ csound->sleep(sleepTime);
+ }
+ spinlock = true;
+ }
+
+ void unlock() {
+ spinlock = false;
+ }
+
+ void stop() {
+ on = false;
+ }
+};
+
+
+struct curlpostk : csnd::Plugin<3, 2> {
+ static constexpr char const *otypes = "kkS";
+ static constexpr char const *itypes = "SS";
+ RequestThread request;
+
+ int init() {
+ csound->plugin_deinit(this);
+ STRINGDAT &url = inargs.str_data(0);
+ STRINGDAT &postdata = inargs.str_data(1);
+ csnd::constr(&request, csound, url.data, true, postdata.data);
+ return OK;
+ }
+
+ int deinit() {
+ request.stop();
+ request.join();
+ csnd::destr(&request);
+ return OK;
+ }
+
+ int kperf() {
+ outargs[0] = FL(0);
+ if (request.done) {
+ if (request.errored) {
+ return csound->perf_error(request.error, this);
+ }
+ outargs[0] = FL(1);
+ } else if (!request.pending) {
+ request.lock();
+ request.pending = true;
+ request.unlock();
+ }
+ outargs[1] = (MYFLT) request.req->httpResponseCode;
+ STRINGDAT &resultstring = outargs.str_data(2);
+ resultstring.data = csound->strdup((char*) request.req->response.c_str());
+ resultstring.size = request.req->response.size();
+ return OK;
+ }
+};
+
+
+struct curlgetk : csnd::Plugin<3, 1> {
+ static constexpr char const *otypes = "kkS";
+ static constexpr char const *itypes = "S";
+ RequestThread request;
+
+ int init() {
+ csound->plugin_deinit(this);
+ STRINGDAT &url = inargs.str_data(0);
+ csnd::constr(&request, csound, url.data, false);
+ return OK;
+ }
+
+ int deinit() {
+ request.stop();
+ request.join();
+ csnd::destr(&request);
+ return OK;
+ }
+
+ int kperf() {
+ outargs[0] = FL(0);
+ if (request.done) {
+ if (request.errored) {
+ return csound->perf_error(request.error, this);
+ }
+ outargs[0] = FL(1);
+ } else if (!request.pending) {
+ request.lock();
+ request.pending = true;
+ request.unlock();
+ }
+ outargs[1] = (MYFLT) request.req->httpResponseCode;
+ STRINGDAT &resultstring = outargs.str_data(2);
+ resultstring.data = csound->strdup((char*) request.req->response.c_str());
+ resultstring.size = request.req->response.size();
+ return OK;
+ }
+};
+
+
+
+struct curlpost : csnd::Plugin<2, 2> {
+ static constexpr char const *otypes = "iS";
+ static constexpr char const *itypes = "SS";
+
+ int init() {
+ STRINGDAT &url = inargs.str_data(0);
+ STRINGDAT &postdata = inargs.str_data(1);
+
+ HTTPRequest* req;
+ try {
+ req = new HTTPRequest(csound, url.data);
+ } catch (const std::exception &e) {
+ csound->init_error(csound->strdup((char*) e.what()));
+ }
+
+ req->post(postdata.data);
+
+ if (req->curlResult != CURLE_OK) {
+ return csound->init_error(csound->strdup(req->curlError));
+ }
+
+ outargs[0] = (MYFLT) req->httpResponseCode;
+ STRINGDAT &resultstring = outargs.str_data(1);
+ resultstring.data = csound->strdup((char*) req->response.c_str());
+ resultstring.size = req->response.size();
+
+ return OK;
+ }
+
+};
+
+
+struct curlget : csnd::Plugin<2, 1> {
+ static constexpr char const *otypes = "iS";
+ static constexpr char const *itypes = "S";
+
+ int init() {
+ STRINGDAT &url = inargs.str_data(0);
+
+ HTTPRequest* req;
+ try {
+ req = new HTTPRequest(csound, url.data);
+ } catch (const std::exception &e) {
+ csound->init_error(csound->strdup((char*) e.what()));
+ }
+
+ req->get();
+
+ if (req->curlResult != CURLE_OK) {
+ return csound->init_error(csound->strdup(req->curlError));
+ }
+
+ outargs[0] = (MYFLT) req->httpResponseCode;
+ STRINGDAT &resultstring = outargs.str_data(1);
+ resultstring.data = csound->strdup((char*) req->response.c_str());
+ resultstring.size = req->response.size();
+
+ return OK;
+ }
+
+};
+
+
+struct curlurlencode : csnd::Plugin<1, 1> {
+ static constexpr char const *otypes = "S";
+ static constexpr char const *itypes = "S";
+
+ int init() {
+ CURL* curl = curl_easy_init();
+ STRINGDAT &input = inargs.str_data(0);
+ STRINGDAT &output = outargs.str_data(0);
+ char* encoded = curl_easy_escape(curl, input.data, strlen(input.data));
+ output.data = csound->strdup(encoded);
+ output.size = strlen(output.data);
+ curl_free(encoded);
+ curl_easy_cleanup(curl);
+ return OK;
+ }
+};
+
+struct curlurlencodek : csnd::Plugin<1, 2> {
+ static constexpr char const *otypes = "S";
+ static constexpr char const *itypes = "Sk";
+ CURL* curl;
+
+ int init() {
+ csound->plugin_deinit(this);
+ curl = curl_easy_init();
+ return OK;
+ }
+
+ int kperf() {
+ if (inargs[1] == 1) {
+ STRINGDAT &input = inargs.str_data(0);
+ STRINGDAT &output = outargs.str_data(0);
+ char* encoded = curl_easy_escape(curl, input.data, strlen(input.data));
+ output.data = csound->strdup(encoded);
+ output.size = strlen(output.data);
+ curl_free(encoded);
+ }
+ return OK;
+ }
+
+ int deinit() {
+ curl_easy_cleanup(curl);
+ return OK;
+ }
+};
+
+
+#include <modload.h>
+void csnd::on_load(csnd::Csound *csound) {
+ csnd::plugin<curlpost>(csound, "curlpost", csnd::thread::i);
+ csnd::plugin<curlget>(csound, "curlget", csnd::thread::i);
+ csnd::plugin<curlpostk>(csound, "curlpostk", csnd::thread::ik);
+ csnd::plugin<curlgetk>(csound, "curlgetk", csnd::thread::ik);
+ csnd::plugin<curlurlencode>(csound, "curlurlencode", csnd::thread::i);
+ csnd::plugin<curlurlencodek>(csound, "curlurlencodek", csnd::thread::ik);
+}