commit ab592d2a594c0b0b65ada770bc83931b069167b4
parent f4f8b1e8b02d434a81940ce40e3d79a1fba49691
Author: Joris Vink <joris@coders.se>
Date: Sun, 3 Aug 2014 17:44:36 +0200
Move task_curl example to tasks and into the new build framework
Diffstat:
6 files changed, 255 insertions(+), 306 deletions(-)
diff --git a/contrib/examples/task_curl/build.sh b/contrib/examples/task_curl/build.sh
@@ -1,50 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2013 Joris Vink <joris@coders.se>
-#
-# Kore module build script, use this as a base for building
-# your own modules for kore.
-
-# The name of the module you will be building
-MODULE=task_curl.so
-
-# The directory containing your module source.
-SOURCE_DIR=.
-
-# Compiler settings.
-CC=gcc
-CFLAGS="-I. -I/usr/local/include -Wall -Wstrict-prototypes \
- -Wmissing-prototypes -Wmissing-declarations -Wshadow \
- -Wpointer-arith -Wcast-qual -Wsign-compare -g"
-
-OSNAME=$(uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z)
-if [ "${OSNAME}" = "darwin" ]; then
- LDFLAGS="-dynamiclib -undefined suppress -flat_namespace -lcurl"
-else
- LDFLAGS="-L/usr/local/lib -shared -lcurl"
-fi
-
-MODULE_BUILD_DATE=$(date +"%Y-%m-%d %H:%M:%S")
-
-### Begin building ####
-echo "Building module ${MODULE}..."
-rm -f ${MODULE}
-
-if [ ! -d .objs ]; then
- mkdir .objs;
-fi
-rm -f .objs/*
-
-for src in `find ${SOURCE_DIR} -type f -name \*.c`; do
- base=`basename $src`;
- ${CC} ${CFLAGS} -fPIC -c $src -o .objs/${base}.o
- if [ $? -ne 0 ]; then
- echo "Build error, check above messages for clues.";
- exit 1;
- fi
-done
-
-${CC} ${LDFLAGS} `find .objs -name \*.o -type f` -o ${MODULE}
-echo "Building completed!"
-
-rm -rf .objs
diff --git a/contrib/examples/task_curl/example.c b/contrib/examples/task_curl/example.c
@@ -1,225 +0,0 @@
-/*
- * Copyright (c) 2014 Joris Vink <joris@coders.se>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * In this example, we use the background tasks available in Kore
- * to fire off a POST to our /post_back page handler containing
- * the user argument that was passed to us in our GET request to /.
- *
- * This illustrates how Kore its background tasks in effect work and
- * how to operate on the channel in order to pass data back and forth.
- *
- * You need libcurl installed for this to build (including headers)
- *
- * Compile using build.sh, afterwards start using:
- * # kore -nc module.conf (depending on where kore is installed)
- *
- * Test using:
- * # curl -k https://127.0.0.1:4443/?user=foobar
- *
- * If the result echo'd back matches what you specified, its all green.
- */
-
-#include <curl/curl.h>
-
-#include <kore/kore.h>
-#include <kore/http.h>
-#include <kore/tasks.h>
-
-int run_curl(struct kore_task *);
-int post_back(struct http_request *);
-int page_handler(struct http_request *);
-size_t curl_write_cb(char *, size_t, size_t, void *);
-
-int
-page_handler(struct http_request *req)
-{
- u_int32_t len;
- char *user, result[64];
-
- /*
- * Lets check if a task has been created yet, this is important
- * as we only want to fire this off once and we will be called
- * again once it has been created.
- */
- if (req->task == NULL) {
- /* Grab the user argument */
- http_populate_arguments(req);
- if (!http_argument_get_string("user", &user, &len)) {
- http_response(req, 500, "ERROR\n", 6);
- return (KORE_RESULT_OK);
- }
-
- /*
- * Create a new task that will execute the run_curl()
- * function and bind it to our request.
- *
- * Binding a task to a request means Kore will reschedule
- * the page handler for that request to refire after the
- * task has completed or when it writes on the task channel.
- */
- kore_task_create(&req->task, run_curl);
- kore_task_bind_request(req->task, req);
-
- /*
- * Start the task and write the user we received in our
- * GET request to its channel.
- */
- kore_task_run(req->task);
- kore_task_channel_write(req->task, user, len);
-
- /*
- * Tell Kore to retry us later.
- */
- return (KORE_RESULT_RETRY);
- }
-
- /*
- * Our page handler is scheduled to be called when either the
- * task finishes or has written data onto the channel.
- *
- * In order to distuingish between the two we can inspect the
- * state of the task.
- */
- if (kore_task_state(req->task) != KORE_TASK_STATE_FINISHED) {
- http_request_sleep(req);
- return (KORE_RESULT_RETRY);
- }
-
- /*
- * Task is finished, check the result.
- */
- if (kore_task_result(req->task) != KORE_RESULT_OK) {
- kore_task_destroy(req->task);
- http_response(req, 500, NULL, 0);
- return (KORE_RESULT_OK);
- }
-
- /*
- * Lets read what our task has written to the channel.
- *
- * kore_task_channel_read() will return the amount of bytes
- * that it received for that read. If the returned bytes is
- * larger then the buffer you passed this is a sign of truncation
- * and should be treated carefully.
- */
- len = kore_task_channel_read(req->task, result, sizeof(result));
- if (len > sizeof(result)) {
- http_response(req, 500, NULL, 0);
- } else {
- http_response(req, 200, result, len);
- }
-
- /* We good, destroy the task. */
- kore_task_destroy(req->task);
-
- return (KORE_RESULT_OK);
-}
-
-int
-post_back(struct http_request *req)
-{
- u_int32_t len;
- char *user;
-
- if (req->method != HTTP_METHOD_POST) {
- http_response(req, 500, NULL, 0);
- return (KORE_RESULT_OK);
- }
-
- http_populate_arguments(req);
- if (!http_argument_get_string("user", &user, &len)) {
- http_response(req, 500, NULL, 0);
- return (KORE_RESULT_OK);
- }
-
- /* Simply echo the supplied user argument back. */
- http_response(req, 200, user, len);
-
- return (KORE_RESULT_OK);
-}
-
-/*
- * This is the function that is executed by our task which is created
- * in the page_handler() callback.
- *
- * It sets up a CURL POST request to /post_back passing along the
- * user argument which it receives from its channel from page_handler().
- */
-int
-run_curl(struct kore_task *t)
-{
- int l;
- struct kore_buf *b;
- u_int32_t len;
- CURLcode res;
- u_int8_t *data;
- CURL *curl;
- char user[64], fields[128];
-
- /*
- * Read the channel in order to obtain the user argument
- * that was written to it by page_handler().
- */
- len = kore_task_channel_read(t, user, sizeof(user));
- if (len > sizeof(user))
- return (KORE_RESULT_ERROR);
-
- l = snprintf(fields, sizeof(fields), "user=%.*s", len, user);
- if (l == -1 || (size_t)l >= sizeof(fields))
- return (KORE_RESULT_ERROR);
-
- if ((curl = curl_easy_init()) == NULL)
- return (KORE_RESULT_ERROR);
-
- b = kore_buf_create(128);
-
- /* Do CURL magic. */
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, b);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
- curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
- curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1:4443/post_back");
-
- res = curl_easy_perform(curl);
- if (res != CURLE_OK) {
- kore_buf_free(b);
- curl_easy_cleanup(curl);
- return (KORE_RESULT_ERROR);
- }
-
- /*
- * Grab the response from the CURL request and write the
- * result back to the task channel.
- */
- data = kore_buf_release(b, &len);
- kore_task_channel_write(t, data, len);
- kore_mem_free(data);
-
- return (KORE_RESULT_OK);
-}
-
-size_t
-curl_write_cb(char *ptr, size_t size, size_t nmemb, void *udata)
-{
- struct kore_buf *b = udata;
-
- kore_buf_append(b, ptr, size * nmemb);
- return (size * nmemb);
-}
diff --git a/contrib/examples/task_curl/module.conf b/contrib/examples/task_curl/module.conf
@@ -1,31 +0,0 @@
-# Configuration for the contrib/examples/task_curl example.
-
-bind 127.0.0.1 4443
-chroot # configure this (ex: /home/joris/src/kore)
-runas # configure this (ex: joris)
-
-workers 1
-pidfile kore.pid
-
-load ./task_curl.so
-
-ssl_no_compression
-
-validator v_user regex ^[a-z]*$
-
-domain 127.0.0.1 {
- certfile # configure this (ex: cert/server.crt)
- certkey # configure this (ex: cert/server.key)
- accesslog kore_access.log
-
- static / page_handler
- static /post_back post_back
-
- params get / {
- validate user v_user
- }
-
- params post /post_back {
- validate user v_user
- }
-}
diff --git a/contrib/examples/tasks/README b/contrib/examples/tasks/README
@@ -0,0 +1,3 @@
+Compile this example using:
+
+# env KORE_LDFLAGS="-I/path/to/libcurl -lcurl"
diff --git a/contrib/examples/tasks/conf/tasks.conf b/contrib/examples/tasks/conf/tasks.conf
@@ -0,0 +1,27 @@
+# Kore config for tasks example
+
+bind 127.0.0.1 8888
+pidfile kore.pid
+
+load ./tasks.so
+
+ssl_no_compression
+
+validator v_user regex ^[a-z]*$
+
+domain 127.0.0.1 {
+ certfile cert/server.crt
+ certkey cert/server.key
+ accesslog kore_access.log
+
+ static / page_handler
+ static /post_back post_back
+
+ params get / {
+ validate user v_user
+ }
+
+ params post /post_back {
+ validate user v_user
+ }
+}
diff --git a/contrib/examples/tasks/src/tasks.c b/contrib/examples/tasks/src/tasks.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2014 Joris Vink <joris@coders.se>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * In this example, we use the background tasks available in Kore
+ * to fire off a POST to our /post_back page handler containing
+ * the user argument that was passed to us in our GET request to /.
+ *
+ * This illustrates how Kore its background tasks in effect work and
+ * how to operate on the channel in order to pass data back and forth.
+ *
+ * You need libcurl installed for this to build (including headers)
+ *
+ * Compile using build.sh, afterwards start using:
+ * # kore -nc module.conf (depending on where kore is installed)
+ *
+ * Test using:
+ * # curl -k https://127.0.0.1:4443/?user=foobar
+ *
+ * If the result echo'd back matches what you specified, its all green.
+ */
+
+#include <curl/curl.h>
+
+#include <kore/kore.h>
+#include <kore/http.h>
+#include <kore/tasks.h>
+
+int run_curl(struct kore_task *);
+int post_back(struct http_request *);
+int page_handler(struct http_request *);
+size_t curl_write_cb(char *, size_t, size_t, void *);
+
+int
+page_handler(struct http_request *req)
+{
+ u_int32_t len;
+ char *user, result[64];
+
+ /*
+ * Lets check if a task has been created yet, this is important
+ * as we only want to fire this off once and we will be called
+ * again once it has been created.
+ */
+ if (req->task == NULL) {
+ /* Grab the user argument */
+ http_populate_arguments(req);
+ if (!http_argument_get_string("user", &user, &len)) {
+ http_response(req, 500, "ERROR\n", 6);
+ return (KORE_RESULT_OK);
+ }
+
+ /*
+ * Create a new task that will execute the run_curl()
+ * function and bind it to our request.
+ *
+ * Binding a task to a request means Kore will reschedule
+ * the page handler for that request to refire after the
+ * task has completed or when it writes on the task channel.
+ */
+ kore_task_create(&req->task, run_curl);
+ kore_task_bind_request(req->task, req);
+
+ /*
+ * Start the task and write the user we received in our
+ * GET request to its channel.
+ */
+ kore_task_run(req->task);
+ kore_task_channel_write(req->task, user, len);
+
+ /*
+ * Tell Kore to retry us later.
+ */
+ return (KORE_RESULT_RETRY);
+ }
+
+ /*
+ * Our page handler is scheduled to be called when either the
+ * task finishes or has written data onto the channel.
+ *
+ * In order to distuingish between the two we can inspect the
+ * state of the task.
+ */
+ if (kore_task_state(req->task) != KORE_TASK_STATE_FINISHED) {
+ http_request_sleep(req);
+ return (KORE_RESULT_RETRY);
+ }
+
+ /*
+ * Task is finished, check the result.
+ */
+ if (kore_task_result(req->task) != KORE_RESULT_OK) {
+ kore_task_destroy(req->task);
+ http_response(req, 500, NULL, 0);
+ return (KORE_RESULT_OK);
+ }
+
+ /*
+ * Lets read what our task has written to the channel.
+ *
+ * kore_task_channel_read() will return the amount of bytes
+ * that it received for that read. If the returned bytes is
+ * larger then the buffer you passed this is a sign of truncation
+ * and should be treated carefully.
+ */
+ len = kore_task_channel_read(req->task, result, sizeof(result));
+ if (len > sizeof(result)) {
+ http_response(req, 500, NULL, 0);
+ } else {
+ http_response(req, 200, result, len);
+ }
+
+ /* We good, destroy the task. */
+ kore_task_destroy(req->task);
+
+ return (KORE_RESULT_OK);
+}
+
+int
+post_back(struct http_request *req)
+{
+ u_int32_t len;
+ char *user;
+
+ if (req->method != HTTP_METHOD_POST) {
+ http_response(req, 500, NULL, 0);
+ return (KORE_RESULT_OK);
+ }
+
+ http_populate_arguments(req);
+ if (!http_argument_get_string("user", &user, &len)) {
+ http_response(req, 500, NULL, 0);
+ return (KORE_RESULT_OK);
+ }
+
+ /* Simply echo the supplied user argument back. */
+ http_response(req, 200, user, len);
+
+ return (KORE_RESULT_OK);
+}
+
+/*
+ * This is the function that is executed by our task which is created
+ * in the page_handler() callback.
+ *
+ * It sets up a CURL POST request to /post_back passing along the
+ * user argument which it receives from its channel from page_handler().
+ */
+int
+run_curl(struct kore_task *t)
+{
+ int l;
+ struct kore_buf *b;
+ u_int32_t len;
+ CURLcode res;
+ u_int8_t *data;
+ CURL *curl;
+ char user[64], fields[128];
+
+ /*
+ * Read the channel in order to obtain the user argument
+ * that was written to it by page_handler().
+ */
+ len = kore_task_channel_read(t, user, sizeof(user));
+ if (len > sizeof(user))
+ return (KORE_RESULT_ERROR);
+
+ l = snprintf(fields, sizeof(fields), "user=%.*s", len, user);
+ if (l == -1 || (size_t)l >= sizeof(fields))
+ return (KORE_RESULT_ERROR);
+
+ if ((curl = curl_easy_init()) == NULL)
+ return (KORE_RESULT_ERROR);
+
+ b = kore_buf_create(128);
+
+ /* Do CURL magic. */
+ curl_easy_setopt(curl, CURLOPT_POST, 1);
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, b);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
+ curl_easy_setopt(curl, CURLOPT_URL, "https://127.0.0.1:8888/post_back");
+
+ res = curl_easy_perform(curl);
+ if (res != CURLE_OK) {
+ kore_buf_free(b);
+ curl_easy_cleanup(curl);
+ return (KORE_RESULT_ERROR);
+ }
+
+ /*
+ * Grab the response from the CURL request and write the
+ * result back to the task channel.
+ */
+ data = kore_buf_release(b, &len);
+ kore_task_channel_write(t, data, len);
+ kore_mem_free(data);
+
+ return (KORE_RESULT_OK);
+}
+
+size_t
+curl_write_cb(char *ptr, size_t size, size_t nmemb, void *udata)
+{
+ struct kore_buf *b = udata;
+
+ kore_buf_append(b, ptr, size * nmemb);
+ return (size * nmemb);
+}