http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/README.rst
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/README.rst
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/README.rst
new file mode 100644
index 0000000..5b1b147
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/README.rst
@@ -0,0 +1,76 @@
+==================
+Eventloop examples
+==================
+
+Overview and usage
+==================
+
+A few examples on how an event loop can be implemented with Duktape, mainly
+illlustrating how the Duktape interface works (not how event loops should be
+built otherwise).
+
+To test (Linux only, perhaps other Unix)::
+
+  $ make
+  $ ./evloop curses-timers.js     # run with Ecmascript eventloop
+  $ ./evloop -c curses-timers.js  # run with C eventloop
+
+Implementation approaches
+=========================
+
+There are several approaches to implementation timers.  Here we demonstrate
+two main approaches:
+
+1. Using a C eventloop which calls into Javascript.  All the event loop state
+   like timers, sockets, etc, is held in C structures.
+   (See ``c_eventloop.c`` and ``c_eventloop.js``.)
+
+2. Using an Ecmascript eventloop which never returns.  All the event loop state
+   can be managed with Ecmascript code instead of C structures.  The Ecmascript
+   eventloop calls a Duktape/C helper to do the lowest level poll() call.
+   (See ``ecma_eventloop.js``.)
+
+Services provided
+=================
+
+The event loop API provided by both examples is the same, and includes:
+
+* Timers: setTimeout, clearTimeout, setInterval, clearInterval
+
+* Sockets: simple network sockets
+
+In addition there are a few synchronous API bindings which are not event loop
+related:
+
+* File I/O
+
+* Curses, for doing beautiful character graphics
+
+Limitations
+===========
+
+This is **not** a production quality event loop.  This is on purpose, to
+keep the example somewhat simple.  Some shortcomings include:
+
+* A production quality event loop would track its internal state (active
+  timers and sockets) much more efficiently.  In general memory usage and
+  code footprint can be reduced.
+
+* Buffer churn caused by allocating a new buffer for every socket read
+  should be eliminated by reusing buffers where appropriate.  Although
+  churn doesn't increase memory footprint with reference counting, it
+  is slower than reusing buffers and might increase memory fragmentation.
+
+* There is no way to suspend reading or writing in the example.  Adding
+  them is straightforward: the poll set needs to be managed dynamically.
+
+* The example uses poll() while one should use epoll() on Linux, kqueue()
+  on BSD systems, etc.
+
+* Timers are not very accurate, e.g. setInterval() does not try to guarantee
+  a steady schedule.  Instead, the next interval is scheduled after the
+  current callback has finished.  This is not the best behavior for some
+  environments, but avoids bunching callbacks.
+
+* Error handling is mostly missing.  Debug prints don't interact well
+  with curses.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js
new file mode 100644
index 0000000..04b3392
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/basic-test.js
@@ -0,0 +1,17 @@
+/*
+ *  A few basic tests
+ */
+
+var count = 0;
+var intervalId;
+
+setTimeout(function (x) { print('timer 1', x); }, 1234, 'foo');
+setTimeout('print("timer 2");', 4321);
+setTimeout(function () { print('timer 3'); }, 2345);
+intervalId = setInterval(function (x, y) {
+    print('interval', ++count, x, y);
+    if (count >= 10) {
+        clearInterval(intervalId);
+    }
+}, 400, 'foo', 'bar');
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c
new file mode 100644
index 0000000..75d768b
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.c
@@ -0,0 +1,618 @@
+/*
+ *  C eventloop example.
+ *
+ *  Timer management is similar to eventloop.js but implemented in C.
+ *  In particular, timer insertion is an O(n) operation; in a real world
+ *  eventloop based on a heap insertion would be O(log N).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/time.h>
+#include <poll.h>
+
+#include "duktape.h"
+
+#define  MAX_TIMERS             4096     /* this is quite excessive for 
embedded use, but good for testing */
+#define  MIN_DELAY              1.0
+#define  MIN_WAIT               1.0
+#define  MAX_WAIT               60000.0
+#define  MAX_EXPIRYS            10
+
+#define  MAX_FDS                256
+
+typedef struct {
+       int64_t id;       /* numeric ID (returned from e.g. setTimeout); zero 
if unused */
+       double target;    /* next target time */
+       double delay;     /* delay/interval */
+       int oneshot;      /* oneshot=1 (setTimeout), repeated=0 (setInterval) */
+       int removed;      /* timer has been requested for removal */
+
+       /* The callback associated with the timer is held in the "global stash",
+        * in <stash>.eventTimers[String(id)].  The references must be deleted
+        * when a timer struct is deleted.
+        */
+} ev_timer;
+
+/* Active timers.  Dense list, terminates to end of list or first unused timer.
+ * The list is sorted by 'target', with lowest 'target' (earliest expiry) last
+ * in the list.  When a timer's callback is being called, the timer is moved
+ * to 'timer_expiring' as it needs special handling should the user callback
+ * delete that particular timer.
+ */
+static ev_timer timer_list[MAX_TIMERS];
+static ev_timer timer_expiring;
+static int timer_count;  /* last timer at timer_count - 1 */
+static int64_t timer_next_id = 1;
+
+/* Socket poll state. */
+static struct pollfd poll_list[MAX_FDS];
+static int poll_count = 0;
+
+/* Misc */
+static int exit_requested = 0;
+
+/* Get Javascript compatible 'now' timestamp (millisecs since 1970). */
+static double get_now(void) {
+       struct timeval tv;
+       int rc;
+
+       rc = gettimeofday(&tv, NULL);
+       if (rc != 0) {
+               /* Should never happen, so return whatever. */
+               return 0.0;
+       }
+       return ((double) tv.tv_sec) * 1000.0 + ((double) tv.tv_usec) / 1000.0;
+}
+
+static ev_timer *find_nearest_timer(void) {
+       /* Last timer expires first (list is always kept sorted). */
+       if (timer_count <= 0) {
+               return NULL;
+       }
+       return timer_list + timer_count - 1;
+}
+
+/* Bubble last timer on timer list backwards until it has been moved to
+ * its proper sorted position (based on 'target' time).
+ */
+static void bubble_last_timer(void) {
+       int i;
+       int n = timer_count;
+       ev_timer *t;
+       ev_timer tmp;
+
+       for (i = n - 1; i > 0; i--) {
+               /* Timer to bubble is at index i, timer to compare to is
+                * at i-1 (both guaranteed to exist).
+                */
+               t = timer_list + i;
+               if (t->target <= (t-1)->target) {
+                       /* 't' expires earlier than (or same time as) 't-1', so 
we're done. */
+                       break;
+               } else {
+                       /* 't' expires later than 't-1', so swap them and 
repeat. */
+                       memcpy((void *) &tmp, (void *) (t - 1), 
sizeof(ev_timer));
+                       memcpy((void *) (t - 1), (void *) t, sizeof(ev_timer));
+                       memcpy((void *) t, (void *) &tmp, sizeof(ev_timer));
+               }
+       }
+}
+
+static void expire_timers(duk_context *ctx) {
+       ev_timer *t;
+       int sanity = MAX_EXPIRYS;
+       double now;
+       int rc;
+
+       /* Because a user callback can mutate the timer list (by adding or 
deleting
+        * a timer), we expire one timer and then rescan from the end again.  
There
+        * is a sanity limit on how many times we do this per expiry round.
+        */
+
+       duk_push_global_stash(ctx);
+       duk_get_prop_string(ctx, -1, "eventTimers");
+
+       /* [ ... stash eventTimers ] */
+
+       now = get_now();
+       while (sanity-- > 0) {
+               /*
+                *  If exit has been requested, exit without running further
+                *  callbacks.
+                */
+
+               if (exit_requested) {
+#if 0
+                       fprintf(stderr, "exit requested, exiting timer expiry 
loop\n");
+                       fflush(stderr);
+#endif
+                       break;
+               }
+
+               /*
+                *  Expired timer(s) still exist?
+                */
+
+               if (timer_count <= 0) {
+                       break;
+               }
+               t = timer_list + timer_count - 1;
+               if (t->target > now) {
+                       break;
+               }
+
+               /*
+                *  Move the timer to 'expiring' for the duration of the 
callback.
+                *  Mark a one-shot timer deleted, compute a new target for an 
interval.
+                */
+
+               memcpy((void *) &timer_expiring, (void *) t, sizeof(ev_timer));
+               memset((void *) t, 0, sizeof(ev_timer));
+               timer_count--;
+               t = &timer_expiring;
+
+               if (t->oneshot) {
+                       t->removed = 1;
+               } else {
+                       t->target = now + t->delay;  /* XXX: or t->target + 
t->delay? */
+               }
+
+               /*
+                *  Call timer callback.  The callback can operate on the timer 
list:
+                *  add new timers, remove timers.  The callback can even 
remove the
+                *  expired timer whose callback we're calling.  However, 
because the
+                *  timer being expired has been moved to 'timer_expiring', we 
don't
+                *  need to worry about the timer's offset changing on the 
timer list.
+                */
+
+#if 0
+               fprintf(stderr, "calling user callback for timer id %d\n", 
(int) t->id);
+               fflush(stderr);
+#endif
+
+               duk_push_number(ctx, (double) t->id);
+               duk_get_prop(ctx, -2);  /* -> [ ... stash eventTimers func ] */
+               rc = duk_pcall(ctx, 0 /*nargs*/);  /* -> [ ... stash 
eventTimers retval ] */
+               if (rc != 0) {
+#if 0
+                       fprintf(stderr, "timer callback failed for timer %d: 
%s\n", (int) t->id, duk_to_string(ctx, -1));
+                       fflush(stderr);
+#endif
+               }
+               duk_pop(ctx);    /* ignore errors for now -> [ ... stash 
eventTimers ] */
+
+               if (t->removed) {
+                       /* One-shot timer (always removed) or removed by user 
callback. */
+#if 0
+                       fprintf(stderr, "deleting callback state for timer 
%d\n", (int) t->id);
+                       fflush(stderr);
+#endif
+                       duk_push_number(ctx, (double) t->id);
+                       duk_del_prop(ctx, -2);
+               } else {
+                       /* Interval timer, not removed by user callback.  Queue 
back to
+                        * timer list and bubble to its final sorted position.
+                        */
+#if 0
+                       fprintf(stderr, "queueing timer %d back into active 
list\n", (int) t->id);
+                       fflush(stderr);
+#endif
+                       if (timer_count >= MAX_TIMERS) {
+                               duk_error(ctx, DUK_ERR_RANGE_ERROR, "out of 
timer slots");
+                       }
+                       memcpy((void *) (timer_list + timer_count), (void *) t, 
sizeof(ev_timer));
+                       timer_count++;
+                       bubble_last_timer();
+               }
+       }
+
+       memset((void *) &timer_expiring, 0, sizeof(ev_timer));
+
+       duk_pop_2(ctx);  /* -> [ ... ] */
+}
+
+static void compact_poll_list(void) {
+       int i, j, n;
+
+       /* i = input index
+        * j = output index (initially same as i)
+        */
+
+       n = poll_count;
+       for (i = 0, j = 0; i < n; i++) {
+               struct pollfd *pfd = poll_list + i;
+               if (pfd->fd == 0) {
+                       /* keep output index the same */
+#if 0
+                       fprintf(stderr, "remove pollfd (index %d): fd=%d, 
events=%d, revents=%d\n",
+                               i, pfd->fd, pfd->events, pfd->revents),
+                       fflush(stderr);
+#endif
+
+                       continue;
+               }
+#if 0
+               fprintf(stderr, "keep pollfd (index %d -> %d): fd=%d, 
events=%d, revents=%d\n",
+                       i, j, pfd->fd, pfd->events, pfd->revents),
+               fflush(stderr);
+#endif
+               if (i != j) {
+                       /* copy only if indices have diverged */
+                       memcpy((void *) (poll_list + j), (void *) (poll_list + 
i), sizeof(struct pollfd));
+               }
+               j++;
+       }
+
+       if (j < poll_count) {
+               /* zeroize unused entries for sanity */
+               memset((void *) (poll_list + j), 0, (poll_count - j) * 
sizeof(struct pollfd));
+       }
+
+       poll_count = j;
+}
+
+int eventloop_run(duk_context *ctx) {
+       ev_timer *t;
+       double now;
+       double diff;
+       int timeout;
+       int rc;
+       int i, n;
+       int idx_eventloop;
+       int idx_fd_handler;
+
+       /* The Ecmascript poll handler is passed through EventLoop.fdPollHandler
+        * which c_eventloop.js sets before we come here.
+        */
+       duk_push_global_object(ctx);
+       duk_get_prop_string(ctx, -1, "EventLoop");
+       duk_get_prop_string(ctx, -1, "fdPollHandler");  /* -> [ global 
EventLoop fdPollHandler ] */
+       idx_fd_handler = duk_get_top_index(ctx);
+       idx_eventloop = idx_fd_handler - 1;
+
+       for (;;) {
+               /*
+                *  Expire timers.
+                */
+
+               expire_timers(ctx);
+
+               /*
+                *  If exit requested, bail out as fast as possible.
+                */
+
+               if (exit_requested) {
+#if 0
+                       fprintf(stderr, "exit requested, exiting event loop\n");
+                       fflush(stderr);
+#endif
+                       break;
+               }
+
+               /*
+                *  Compact poll list by removing pollfds with fd == 0.
+                */
+
+               compact_poll_list();
+
+               /*
+                *  Determine poll() timeout (as close to poll() as possible as
+                *  the wait is relative).
+                */
+
+               now = get_now();
+               t = find_nearest_timer();
+               if (t) {
+                       diff = t->target - now;
+                       if (diff < MIN_WAIT) {
+                               diff = MIN_WAIT;
+                       } else if (diff > MAX_WAIT) {
+                               diff = MAX_WAIT;
+                       }
+                       timeout = (int) diff;  /* clamping ensures that fits */
+               } else {
+                       if (poll_count == 0) {
+#if 0
+                               fprintf(stderr, "no timers and no sockets to 
poll, exiting\n");
+                               fflush(stderr);
+#endif
+                               break;
+                       }
+                       timeout = (int) MAX_WAIT;
+               }
+
+               /*
+                *  Poll for activity or timeout.
+                */
+
+#if 0
+               fprintf(stderr, "going to poll, timeout %d ms, pollfd count 
%d\n", timeout, poll_count);
+               fflush(stderr);
+#endif
+
+               rc = poll(poll_list, poll_count, timeout);
+#if 0
+               fprintf(stderr, "poll rc: %d\n", rc);
+               fflush(stderr);
+#endif
+               if (rc < 0) {
+                       /* error */
+               } else if (rc == 0) {
+                       /* timeout */
+               } else {
+                       /* 'rc' fds active */
+               }
+
+               /*
+                *  Check socket activity, handle all sockets.  Handling is 
offloaded to
+                *  Ecmascript code (fd + revents).
+                *
+                *  If FDs are removed from the poll list while we're 
processing callbacks,
+                *  the entries are simply marked unused (fd set to 0) without 
actually
+                *  removing them from the poll list.  This ensures indices are 
not
+                *  disturbed.  The poll list is compacted before next poll().
+                */
+
+               n = (rc == 0 ? 0 : poll_count);  /* if timeout, no need to 
check pollfd */
+               for (i = 0; i < n; i++) {
+                       struct pollfd *pfd = poll_list + i;
+
+                       if (pfd->fd == 0) {
+                               /* deleted, perhaps by previous callback */
+                               continue;
+                       }
+
+                       if (pfd->revents) {
+#if 0
+                               fprintf(stderr, "fd %d has revents: %d\n", 
(int) pfd->fd, (int) pfd->revents);
+                               fflush(stderr);
+#endif
+                               duk_dup(ctx, idx_fd_handler);
+                               duk_dup(ctx, idx_eventloop);
+                               duk_push_int(ctx, pfd->fd);
+                               duk_push_int(ctx, pfd->revents);
+                               rc = duk_pcall_method(ctx, 2 /*nargs*/);
+                               if (rc) {
+#if 0
+                                       fprintf(stderr, "fd callback failed for 
fd %d: %s\n", (int) pfd->fd, duk_to_string(ctx, -1));
+                                       fflush(stderr);
+#endif
+                               }
+                               duk_pop(ctx);
+
+                               pfd->revents = 0;
+                       }
+
+               }
+       }
+
+       duk_pop_n(ctx, 3);
+
+       return 0;
+}
+
+static int create_timer(duk_context *ctx) {
+       double delay;
+       int oneshot;
+       int idx;
+       int64_t timer_id;
+       double now;
+       ev_timer *t;
+
+       now = get_now();
+
+       /* indexes:
+        *   0 = function (callback)
+        *   1 = delay
+        *   2 = boolean: oneshot
+        */
+
+       delay = duk_require_number(ctx, 1);
+       if (delay < MIN_DELAY) {
+               delay = MIN_DELAY;
+       }
+       oneshot = duk_require_boolean(ctx, 2);
+
+       if (timer_count >= MAX_TIMERS) {
+               duk_error(ctx, DUK_ERR_RANGE_ERROR, "out of timer slots");
+       }
+       idx = timer_count++;
+       timer_id = timer_next_id++;
+       t = timer_list + idx;
+
+       memset((void *) t, 0, sizeof(ev_timer));
+       t->id = timer_id;
+       t->target = now + delay;
+       t->delay = delay;
+       t->oneshot = oneshot;
+       t->removed = 0;
+
+       /* Timer is now at the last position; use swaps to "bubble" it to its
+        * correct sorted position.
+        */
+
+       bubble_last_timer();
+
+       /* Finally, register the callback to the global stash 'eventTimers' 
object. */
+
+       duk_push_global_stash(ctx);
+       duk_get_prop_string(ctx, -1, "eventTimers");  /* -> [ func delay 
oneshot stash eventTimers ] */
+       duk_push_number(ctx, (double) timer_id);
+       duk_dup(ctx, 0);
+       duk_put_prop(ctx, -3);  /* eventTimers[timer_id] = callback */
+
+       /* Return timer id. */
+
+       duk_push_number(ctx, (double) timer_id);
+#if 0
+       fprintf(stderr, "created timer id: %d\n", (int) timer_id);
+       fflush(stderr);
+#endif
+       return 1;
+}
+
+static int delete_timer(duk_context *ctx) {
+       int i, n;
+       int64_t timer_id;
+       ev_timer *t;
+       int found = 0;
+
+       /* indexes:
+        *   0 = timer id
+        */
+
+       timer_id = (int64_t) duk_require_number(ctx, 0);
+
+       /*
+        *  Unlike insertion, deletion needs a full scan of the timer list
+        *  and an expensive remove.  If no match is found, nothing is deleted.
+        *  Caller gets a boolean return code indicating match.
+        *
+        *  When a timer is being expired and its user callback is running,
+        *  the timer has been moved to 'timer_expiring' and its deletion
+        *  needs special handling: just mark it to-be-deleted and let the
+        *  expiry code remove it.
+        */
+
+       t = &timer_expiring;
+       if (t->id == timer_id) {
+               t->removed = 1;
+               duk_push_true(ctx);
+#if 0
+               fprintf(stderr, "deleted expiring timer id: %d\n", (int) 
timer_id);
+               fflush(stderr);
+#endif
+               return 1;
+       }
+
+       n = timer_count;
+       for (i = 0; i < n; i++) {
+               t = timer_list + i;
+               if (t->id == timer_id) {
+                       found = 1;
+
+                       /* Shift elements downwards to keep the timer list dense
+                        * (no need if last element).
+                        */
+                       if (i < timer_count - 1) {
+                               memmove((void *) t, (void *) (t + 1), 
(timer_count - i - 1) * sizeof(ev_timer));
+                       }
+
+                       /* Zero last element for clarity. */
+                       memset((void *) (timer_list + n - 1), 0, 
sizeof(ev_timer));
+
+                       /* Update timer_count. */
+                       timer_count--;
+
+                       /* The C state is now up-to-date, but we still need to 
delete
+                        * the timer callback state from the global 'stash'.
+                        */
+
+                       duk_push_global_stash(ctx);
+                       duk_get_prop_string(ctx, -1, "eventTimers");  /* -> [ 
timer_id stash eventTimers ] */
+                       duk_push_number(ctx, (double) timer_id);
+                       duk_del_prop(ctx, -2);  /* delete eventTimers[timer_id] 
*/
+
+#if 0
+                       fprintf(stderr, "deleted timer id: %d\n", (int) 
timer_id);
+                       fflush(stderr);
+#endif
+                       break;
+               }
+       }
+
+#if 0
+       if (!found) {
+               fprintf(stderr, "trying to delete timer id %d, but not found; 
ignoring\n", (int) timer_id);
+               fflush(stderr);
+       }
+#endif
+
+       duk_push_boolean(ctx, found);
+       return 1;
+}
+
+static int listen_fd(duk_context *ctx) {
+       int fd = duk_require_int(ctx, 0);
+       int events = duk_require_int(ctx, 1);
+       int i, n;
+       struct pollfd *pfd;
+
+#if 0
+       fprintf(stderr, "listen_fd: fd=%d, events=%d\n", fd, events);
+       fflush(stderr);
+#endif
+       /* events == 0 means stop listening to the FD */
+
+       n = poll_count;
+       for (i = 0; i < n; i++) {
+               pfd = poll_list + i;
+               if (pfd->fd == fd) {
+#if 0
+                       fprintf(stderr, "listen_fd: fd found at index %d\n", i);
+                       fflush(stderr);
+#endif
+                       if (events == 0) {
+                               /* mark to-be-deleted, cleaned up by next poll 
*/
+                               pfd->fd = 0;
+                       } else {
+                               pfd->events = events;
+                       }
+                       return 0;
+               }
+       }
+
+       /* not found, append to list */
+#if 0
+       fprintf(stderr, "listen_fd: fd not found on list, add new entry\n");
+       fflush(stderr);
+#endif
+
+       if (poll_count >= MAX_FDS) {
+               duk_error(ctx, DUK_ERR_ERROR, "out of fd slots");
+       }
+
+       pfd = poll_list + poll_count;
+       pfd->fd = fd;
+       pfd->events = events;
+       pfd->revents = 0;
+       poll_count++;
+
+       return 0;
+}
+
+static int request_exit(duk_context *ctx) {
+       (void) ctx;
+       exit_requested = 1;
+       return 0;
+}
+
+static duk_function_list_entry eventloop_funcs[] = {
+       { "createTimer", create_timer, 3 },
+       { "deleteTimer", delete_timer, 1 },
+       { "listenFd", listen_fd, 2 },
+       { "requestExit", request_exit, 0 },
+       { NULL, NULL, 0 }
+};
+
+void eventloop_register(duk_context *ctx) {
+       memset((void *) timer_list, 0, MAX_TIMERS * sizeof(ev_timer));
+       memset((void *) &timer_expiring, 0, sizeof(ev_timer));
+       memset((void *) poll_list, 0, MAX_FDS * sizeof(struct pollfd));
+
+       /* Set global 'EventLoop'. */
+       duk_push_global_object(ctx);
+       duk_push_object(ctx);
+       duk_put_function_list(ctx, -1, eventloop_funcs);
+       duk_put_prop_string(ctx, -2, "EventLoop");
+       duk_pop(ctx);
+
+       /* Initialize global stash 'eventTimers'. */
+       duk_push_global_stash(ctx);
+       duk_push_object(ctx);
+       duk_put_prop_string(ctx, -2, "eventTimers");
+       duk_pop(ctx);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js
new file mode 100644
index 0000000..b9e2d63
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/c_eventloop.js
@@ -0,0 +1,179 @@
+/*
+ *  C eventloop example (c_eventloop.c).
+ *
+ *  Ecmascript code to initialize the exposed API (setTimeout() etc) when
+ *  using the C eventloop.
+ *
+ *  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Timers
+ */
+
+/*
+ *  Timer API
+ */
+
+function setTimeout(func, delay) {
+    var cb_func;
+    var bind_args;
+    var timer_id;
+
+    if (typeof delay !== 'number') {
+        throw new TypeError('delay is not a number');
+    }
+
+    if (typeof func === 'string') {
+        // Legacy case: callback is a string.
+        cb_func = eval.bind(this, func);
+    } else if (typeof func !== 'function') {
+        throw new TypeError('callback is not a function/string');
+    } else if (arguments.length > 2) {
+        // Special case: callback arguments are provided.
+        bind_args = Array.prototype.slice.call(arguments, 2);  // [ arg1, 
arg2, ... ]
+        bind_args.unshift(this);  // [ global(this), arg1, arg2, ... ]
+        cb_func = func.bind.apply(func, bind_args);
+    } else {
+        // Normal case: callback given as a function without arguments.
+        cb_func = func;
+    }
+
+    timer_id = EventLoop.createTimer(cb_func, delay, true /*oneshot*/);
+
+    return timer_id;
+}
+
+function clearTimeout(timer_id) {
+    if (typeof timer_id !== 'number') {
+        throw new TypeError('timer ID is not a number');
+    }
+    var success = EventLoop.deleteTimer(timer_id);  /* retval ignored */
+}
+
+function setInterval(func, delay) {
+    var cb_func;
+    var bind_args;
+    var timer_id;
+
+    if (typeof delay !== 'number') {
+        throw new TypeError('delay is not a number');
+    }
+
+    if (typeof func === 'string') {
+        // Legacy case: callback is a string.
+        cb_func = eval.bind(this, func);
+    } else if (typeof func !== 'function') {
+        throw new TypeError('callback is not a function/string');
+    } else if (arguments.length > 2) {
+        // Special case: callback arguments are provided.
+        bind_args = Array.prototype.slice.call(arguments, 2);  // [ arg1, 
arg2, ... ]
+        bind_args.unshift(this);  // [ global(this), arg1, arg2, ... ]
+        cb_func = func.bind.apply(func, bind_args);
+    } else {
+        // Normal case: callback given as a function without arguments.
+        cb_func = func;
+    }
+
+    timer_id = EventLoop.createTimer(cb_func, delay, false /*oneshot*/);
+
+    return timer_id;
+}
+
+function clearInterval(timer_id) {
+    if (typeof timer_id !== 'number') {
+        throw new TypeError('timer ID is not a number');
+    }
+    EventLoop.deleteTimer(timer_id);
+}
+
+function requestEventLoopExit() {
+    EventLoop.requestExit();
+}
+
+/*
+ *  Socket handling
+ *
+ *  Ideally this would be implemented more in C than here for more speed
+ *  and smaller footprint: C code would directly maintain the callback state
+ *  and such.
+ *
+ *  Also for more optimal I/O, the buffer churn caused by allocating and
+ *  freeing a lot of buffer values could be eliminated by reusing buffers.
+ *  Socket reads would then go into a pre-allocated buffer, for instance.
+ */
+
+EventLoop.socketListening = {};
+EventLoop.socketReading = {};
+EventLoop.socketConnecting = {};
+
+EventLoop.fdPollHandler = function(fd, revents) {
+    var data;
+    var cb;
+    var rc;
+    var acc_res;
+
+    //print('activity on fd', fd, 'revents', revents);
+
+    if (revents & Poll.POLLIN) {
+        cb = this.socketReading[fd];
+        if (cb) {
+            data = Socket.read(fd);  // no size control now
+            //print('READ', Duktape.enc('jx', data));
+            if (data.length === 0) {
+                this.close(fd);
+                return;
+            }
+            cb(fd, data);
+        } else {
+            cb = this.socketListening[fd];
+            if (cb) {
+                acc_res = Socket.accept(fd);
+                //print('ACCEPT:', Duktape.enc('jx', acc_res));
+                cb(acc_res.fd, acc_res.addr, acc_res.port);
+            } else {
+                //print('UNKNOWN');
+            }
+        }
+    }
+
+    if (revents & Poll.POLLOUT) {
+        // Connected
+        cb = this.socketConnecting[fd];
+        if (cb) {
+            delete this.socketConnecting[fd];
+            cb(fd);
+        }
+    }
+
+    if ((revents & ~(Poll.POLLIN | Poll.POLLOUT)) !== 0) {
+        //print('unexpected revents, close fd');
+        this.close(fd);
+    }
+}
+
+EventLoop.server = function(address, port, cb_accepted) {
+    var fd = Socket.createServerSocket(address, port);
+    this.socketListening[fd] = cb_accepted;
+    this.listenFd(fd, Poll.POLLIN);
+}
+
+EventLoop.connect = function(address, port, cb_connected) {
+    var fd = Socket.connect(address, port);
+    this.socketConnecting[fd] = cb_connected;
+    this.listenFd(fd, Poll.POLLOUT);
+}
+
+EventLoop.close = function(fd) {
+    EventLoop.listenFd(fd, 0);
+    delete this.socketListening[fd];
+    delete this.socketReading[fd];
+    delete this.socketConnecting[fd];
+    Socket.close(fd);
+}
+
+EventLoop.setReader = function(fd, cb_read) {
+    this.socketReading[fd] = cb_read;
+    this.listenFd(fd, Poll.POLLIN);
+}
+
+EventLoop.write = function(fd, data) {
+    // This simple example doesn't have support for write blocking / draining
+    var rc = Socket.write(fd, Duktape.Buffer(data));
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js
new file mode 100644
index 0000000..ff87784
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/client-socket-test.js
@@ -0,0 +1,24 @@
+
+var HOST = 'localhost';
+var PORT = 80;
+var EXIT_TIMEOUT = 300e3;
+
+print('automatic exit after ' + (EXIT_TIMEOUT / 1e3) + ' seconds');
+setTimeout(function () {
+    print('exit timer');
+    EventLoop.requestExit();
+}, EXIT_TIMEOUT);
+
+EventLoop.connect(HOST, PORT, function (fd) {
+    print('connected to ' + HOST + ':' + PORT + ', fd', fd);
+    EventLoop.setReader(fd, function (fd, data) {
+        print('read from fd', fd);
+        print(data);
+        EventLoop.close(fd);
+    });
+    EventLoop.write(fd, "GET / HTTP/1.1\r\n" +
+                        "Host: " + HOST + "\r\n" +
+                        "User-Agent: client-socket-test.js\r\n" +
+                        "\r\n");
+});
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js
new file mode 100644
index 0000000..4508665
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/curses-timers.js
@@ -0,0 +1,79 @@
+/*
+ *  Test using timers and intervals with curses.
+ */
+
+if (typeof Ncurses !== 'object') {
+    throw new Error('Ncurses required');
+}
+
+function fillScreen(ch) {
+    var size, w, h;
+    var i, j;
+
+    size = Ncurses.getmaxyx();
+    h = size[0];
+    w = size[1];
+
+    for (i = 0; i < h; i++) {
+        for (j = 0; j < w; j++) {
+            Ncurses.mvprintw(i, j, ch);
+        }
+    }
+    Ncurses.refresh();
+}
+
+function main() {
+    var i, j;
+    var counters = [];
+    var size, w, h;
+
+    Ncurses.initscr();
+    size = Ncurses.getmaxyx();
+    h = size[0];
+    w = size[1];
+
+    fillScreen('.');
+
+    setInterval(function () {
+        Ncurses.mvprintw(1, 4, new Date().toISOString());
+        Ncurses.refresh();
+    }, 1000);
+
+    function addCounter(row, index, interval) {
+        counters[index] = 0;
+        setInterval(function () {
+            counters[index]++;
+            Ncurses.mvprintw(row, 4, '' + Date.now() + ' ' + counters[index]);
+            Ncurses.refresh();
+        }, interval);
+    }
+
+    function addRandomChar(row, col, interval) {
+        setTimeout(function () {
+            Ncurses.mvprintw(row, col, String.fromCharCode(Math.random() * 64 
+ 0x20));
+            Ncurses.refresh();
+        }, interval);
+    }
+
+    for (i = 0; i < h - 5; i++) {
+        addCounter(3 + i, i, 363 * i + 400);
+    }
+
+    /* Here the inserts take a lot of time because the underlying timer manager
+     * data structure has O(n) insertion performance.
+     */
+    for (i = 0; i < h - 5; i++) {
+        for (j = 0; j < w - 50; j++) {
+            // Math.exp(0)...Math.exp(8) is an uneven distribution between 
1...~2980.
+            addRandomChar(3 + i, 28 + j, 58000 - Math.exp(Math.random() * 8) * 
20);
+        }
+    }
+
+    setTimeout(function () {
+        Ncurses.endwin();
+        Ncurses.delscreen();
+        requestEventLoopExit();
+    }, 120e3);
+}
+
+main();

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js
new file mode 100644
index 0000000..bad4e4d
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ecma_eventloop.js
@@ -0,0 +1,466 @@
+/*
+ *  Pure Ecmascript eventloop example.
+ *
+ *  Timer state handling is inefficient in this trivial example.  Timers are
+ *  kept in an array sorted by their expiry time which works well for expiring
+ *  timers, but has O(n) insertion performance.  A better implementation would
+ *  use a heap or some other efficient structure for managing timers so that
+ *  all operations (insert, remove, get nearest timer) have good performance.
+ *
+ *  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Timers
+ */
+
+/*
+ *  Event loop
+ *
+ *  Timers are sorted by 'target' property which indicates expiry time of
+ *  the timer.  The timer expiring next is last in the array, so that
+ *  removals happen at the end, and inserts for timers expiring in the
+ *  near future displace as few elements in the array as possible.
+ */
+
+EventLoop = {
+    // timers
+    timers: [],         // active timers, sorted (nearest expiry last)
+    expiring: null,     // set to timer being expired (needs special handling 
in clearTimeout/clearInterval)
+    nextTimerId: 1,
+    minimumDelay: 1,
+    minimumWait: 1,
+    maximumWait: 60000,
+    maxExpirys: 10,
+
+    // sockets
+    socketListening: {},  // fd -> callback
+    socketReading: {},    // fd -> callback
+    socketConnecting: {}, // fd -> callback
+
+    // misc
+    exitRequested: false
+};
+
+EventLoop.dumpState = function() {
+    print('TIMER STATE:');
+    this.timers.forEach(function(t) {
+        print('    ' + Duktape.enc('jx', t));
+    });
+    if (this.expiring) {
+        print('    EXPIRING: ' + Duktape.enc('jx', this.expiring));
+    }
+}
+
+// Get timer with lowest expiry time.  Since the active timers list is
+// sorted, it's always the last timer.
+EventLoop.getEarliestTimer = function() {
+    var timers = this.timers;
+    n = timers.length;
+    return (n > 0 ? timers[n - 1] : null);
+}
+
+EventLoop.getEarliestWait = function() {
+    var t = this.getEarliestTimer();
+    return (t ? t.target - Date.now() : null);
+}
+
+EventLoop.insertTimer = function(timer) {
+    var timers = this.timers;
+    var i, n, t;
+
+    /*
+     *  Find 'i' such that we want to insert *after* timers[i] at index i+1.
+     *  If no such timer, for-loop terminates with i-1, and we insert at 
-1+1=0.
+     */
+
+    n = timers.length;
+    for (i = n - 1; i >= 0; i--) {
+        t = timers[i];
+        if (timer.target <= t.target) {
+            // insert after 't', to index i+1
+            break;
+        }
+    }
+
+    timers.splice(i + 1 /*start*/, 0 /*deleteCount*/, timer);
+}
+
+// Remove timer/interval with a timer ID.  The timer/interval can reside
+// either on the active list or it may be an expired timer (this.expiring)
+// whose user callback we're running when this function gets called.
+EventLoop.removeTimerById = function(timer_id) {
+    var timers = this.timers;
+    var i, n, t;
+
+    t = this.expiring;
+    if (t) {
+        if (t.id === timer_id) {
+            // Timer has expired and we're processing its callback.  User
+            // callback has requested timer deletion.  Mark removed, so
+            // that the timer is not reinserted back into the active list.
+            // This is actually a common case because an interval may very
+            // well cancel itself.
+            t.removed = true;
+            return;
+        }
+    }
+
+    n = timers.length;
+    for (i = 0; i < n; i++) {
+        t = timers[i];
+        if (t.id === timer_id) {
+            // Timer on active list: mark removed (not really necessary, but
+            // nice for dumping), and remove from active list.
+            t.removed = true;
+            this.timers.splice(i /*start*/, 1 /*deleteCount*/);
+            return;
+        }
+    }
+
+   // no such ID, ignore
+}
+
+EventLoop.processTimers = function() {
+    var now = Date.now();
+    var timers = this.timers;
+    var sanity = this.maxExpirys;
+    var n, t;
+
+    /*
+     *  Here we must be careful with mutations: user callback may add and
+     *  delete an arbitrary number of timers.
+     *
+     *  Current solution is simple: check whether the timer at the end of
+     *  the list has expired.  If not, we're done.  If it has expired,
+     *  remove it from the active list, record it in this.expiring, and call
+     *  the user callback.  If user code deletes the this.expiring timer,
+     *  there is special handling which just marks the timer deleted so
+     *  it won't get inserted back into the active list.
+     *
+     *  This process is repeated at most maxExpirys times to ensure we don't
+     *  get stuck forever; user code could in principle add more and more
+     *  already expired timers.
+     */
+
+    while (sanity-- > 0) {
+        // If exit requested, don't call any more callbacks.  This allows
+        // a callback to do cleanups and request exit, and can be sure that
+        // no more callbacks are processed.
+
+        if (this.exitRequested) {
+            //print('exit requested, exit');
+            break;
+        }
+
+        // Timers to expire?
+
+        n = timers.length;
+        if (n <= 0) {
+            break;
+        }
+        t = timers[n - 1];
+        if (now <= t.target) {
+            // Timer has not expired, and no other timer could have expired
+            // either because the list is sorted.
+            break;
+        }
+        timers.pop();
+
+        // Remove the timer from the active list and process it.  The user
+        // callback may add new timers which is not a problem.  The callback
+        // may also delete timers which is not a problem unless the timer
+        // being deleted is the timer whose callback we're running; this is
+        // why the timer is recorded in this.expiring so that clearTimeout()
+        // and clearInterval() can detect this situation.
+
+        if (t.oneshot) {
+            t.removed = true;  // flag for removal
+        } else {
+            t.target = now + t.delay;
+        }
+        this.expiring = t;
+        try {
+            t.cb();
+        } catch (e) {
+            print('timer callback failed, ignored: ' + e);
+        }
+        this.expiring = null;
+
+        // If the timer was one-shot, it's marked 'removed'.  If the user 
callback
+        // requested deletion for the timer, it's also marked 'removed'.  If 
the
+        // timer is an interval (and is not marked removed), insert it back 
into
+        // the timer list.
+
+        if (!t.removed) {
+            // Reinsert interval timer to correct sorted position.  The timer
+            // must be an interval timer because one-shot timers are marked
+            // 'removed' above.
+            this.insertTimer(t);
+        }
+    }
+}
+
+EventLoop.run = function() {
+    var wait;
+    var POLLIN = Poll.POLLIN;
+    var POLLOUT = Poll.POLLOUT;
+    var poll_set;
+    var poll_count;
+    var fd;
+    var t, rev;
+    var rc;
+    var acc_res;
+
+    for (;;) {
+        /*
+         *  Process expired timers.
+         */
+
+        this.processTimers();
+        //this.dumpState();
+
+        /*
+         *  Exit check (may be requested by a user callback)
+         */
+
+        if (this.exitRequested) {
+            //print('exit requested, exit');
+            break;
+        }
+
+        /*
+         *  Create poll socket list.  This is a very naive approach.
+         *  On Linux, one could use e.g. epoll() and manage socket lists
+         *  incrementally.
+         */
+
+        poll_set = {};
+        poll_count = 0;
+        for (fd in this.socketListening) {
+            poll_set[fd] = { events: POLLIN, revents: 0 };
+            poll_count++;
+        }
+        for (fd in this.socketReading) {
+            poll_set[fd] = { events: POLLIN, revents: 0 };
+            poll_count++;
+        }
+        for (fd in this.socketConnecting) {
+            poll_set[fd] = { events: POLLOUT, revents: 0 };
+            poll_count++;
+        }
+        //print(new Date(), 'poll_set IN:', Duktape.enc('jx', poll_set));
+
+        /*
+         *  Wait timeout for timer closest to expiry.  Since the poll
+         *  timeout is relative, get this as close to poll() as possible.
+         */
+
+        wait = this.getEarliestWait();
+        if (wait === null) {
+            if (poll_count === 0) {
+                print('no active timers and no sockets to poll, exit');
+                break;
+            } else {
+                wait = this.maximumWait;
+            }
+        } else {
+            wait = Math.min(this.maximumWait, Math.max(this.minimumWait, 
wait));
+        }
+
+        /*
+         *  Do the actual poll.
+         */
+
+        try {
+            Poll.poll(poll_set, wait);
+        } catch (e) {
+            // Eat errors silently.  When resizing curses window an EINTR
+            // happens now.
+        }
+
+        /*
+         *  Process all sockets so that nothing is left unhandled for the
+         *  next round.
+         */
+
+        //print(new Date(), 'poll_set OUT:', Duktape.enc('jx', poll_set));
+        for (fd in poll_set) {
+            t = poll_set[fd];
+            rev = t.revents;
+
+            if (rev & POLLIN) {
+                cb = this.socketReading[fd];
+                if (cb) {
+                    data = Socket.read(fd);  // no size control now
+                    //print('READ', Duktape.enc('jx', data));
+                    if (data.length === 0) {
+                        //print('zero read for fd ' + fd + ', closing 
forcibly');
+                        rc = Socket.close(fd);  // ignore result
+                        delete this.socketListening[fd];
+                        delete this.socketReading[fd];
+                    } else {
+                        cb(fd, data);
+                    }
+                } else {
+                    cb = this.socketListening[fd];
+                    if (cb) {
+                        acc_res = Socket.accept(fd);
+                        //print('ACCEPT:', Duktape.enc('jx', acc_res));
+                        cb(acc_res.fd, acc_res.addr, acc_res.port);
+                    } else {
+                        //print('UNKNOWN');
+                    }
+                }
+            }
+
+            if (rev & POLLOUT) {
+                cb = this.socketConnecting[fd];
+                if (cb) {
+                    delete this.socketConnecting[fd];
+                    cb(fd);
+                } else {
+                    //print('UNKNOWN POLLOUT');
+                }
+            }
+
+            if ((rev & ~(POLLIN | POLLOUT)) !== 0) {
+                //print('revents ' + t.revents + ' for fd ' + fd + ', closing 
forcibly');
+                rc = Socket.close(fd);  // ignore result
+                delete this.socketListening[fd];
+                delete this.socketReading[fd];
+            }
+        }
+    }
+}
+
+EventLoop.requestExit = function() {
+    this.exitRequested = true;
+}
+
+EventLoop.server = function(address, port, cb_accepted) {
+    var fd = Socket.createServerSocket(address, port);
+    this.socketListening[fd] = cb_accepted;
+}
+
+EventLoop.connect = function(address, port, cb_connected) {
+    var fd = Socket.connect(address, port);
+    this.socketConnecting[fd] = cb_connected;
+}
+
+EventLoop.close = function(fd) {
+    delete this.socketReading[fd];
+    delete this.socketListening[fd];
+}
+
+EventLoop.setReader = function(fd, cb_read) {
+    this.socketReading[fd] = cb_read;
+}
+
+EventLoop.write = function(fd, data) {
+    // This simple example doesn't have support for write blocking / draining
+    var rc = Socket.write(fd, Duktape.Buffer(data));
+}
+
+/*
+ *  Timer API
+ *
+ *  These interface with the singleton EventLoop.
+ */
+
+function setTimeout(func, delay) {
+    var cb_func;
+    var bind_args;
+    var timer_id;
+    var evloop = EventLoop;
+
+    if (typeof delay !== 'number') {
+        throw new TypeError('delay is not a number');
+    }
+    delay = Math.max(evloop.minimumDelay, delay);
+
+    if (typeof func === 'string') {
+        // Legacy case: callback is a string.
+        cb_func = eval.bind(this, func);
+    } else if (typeof func !== 'function') {
+        throw new TypeError('callback is not a function/string');
+    } else if (arguments.length > 2) {
+        // Special case: callback arguments are provided.
+        bind_args = Array.prototype.slice.call(arguments, 2);  // [ arg1, 
arg2, ... ]
+        bind_args.unshift(this);  // [ global(this), arg1, arg2, ... ]
+        cb_func = func.bind.apply(func, bind_args);
+    } else {
+        // Normal case: callback given as a function without arguments.
+        cb_func = func;
+    }
+
+    timer_id = evloop.nextTimerId++;
+
+    evloop.insertTimer({
+        id: timer_id,
+        oneshot: true,
+        cb: cb_func,
+        delay: delay,
+        target: Date.now() + delay
+    });
+
+    return timer_id;
+}
+
+function clearTimeout(timer_id) {
+    var evloop = EventLoop;
+
+    if (typeof timer_id !== 'number') {
+        throw new TypeError('timer ID is not a number');
+    }
+    evloop.removeTimerById(timer_id);
+}
+
+function setInterval(func, delay) {
+    var cb_func;
+    var bind_args;
+    var timer_id;
+    var evloop = EventLoop;
+
+    if (typeof delay !== 'number') {
+        throw new TypeError('delay is not a number');
+    }
+    delay = Math.max(evloop.minimumDelay, delay);
+
+    if (typeof func === 'string') {
+        // Legacy case: callback is a string.
+        cb_func = eval.bind(this, func);
+    } else if (typeof func !== 'function') {
+        throw new TypeError('callback is not a function/string');
+    } else if (arguments.length > 2) {
+        // Special case: callback arguments are provided.
+        bind_args = Array.prototype.slice.call(arguments, 2);  // [ arg1, 
arg2, ... ]
+        bind_args.unshift(this);  // [ global(this), arg1, arg2, ... ]
+        cb_func = func.bind.apply(func, bind_args);
+    } else {
+        // Normal case: callback given as a function without arguments.
+        cb_func = func;
+    }
+
+    timer_id = evloop.nextTimerId++;
+
+    evloop.insertTimer({
+        id: timer_id,
+        oneshot: false,
+        cb: cb_func,
+        delay: delay,
+        target: Date.now() + delay
+    });
+
+    return timer_id;
+}
+
+function clearInterval(timer_id) {
+    var evloop = EventLoop;
+
+    if (typeof timer_id !== 'number') {
+        throw new TypeError('timer ID is not a number');
+    }
+    evloop.removeTimerById(timer_id);
+}
+
+/* custom call */
+function requestEventLoopExit() {
+    EventLoop.requestExit();
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/fileio.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/fileio.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/fileio.c
new file mode 100644
index 0000000..df94cd4
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/fileio.c
@@ -0,0 +1,69 @@
+/*
+ *  File I/O binding example.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "duktape.h"
+
+static int fileio_readfile(duk_context *ctx) {
+       const char *filename = duk_to_string(ctx, 0);
+       FILE *f = NULL;
+       long len;
+       void *buf;
+       size_t got;
+
+       if (!filename) {
+               goto error;
+       }
+
+       f = fopen(filename, "rb");
+       if (!f) {
+               goto error;
+       }
+
+       if (fseek(f, 0, SEEK_END) != 0) {
+               goto error;
+       }
+
+       len = ftell(f);
+
+       if (fseek(f, 0, SEEK_SET) != 0) {
+               goto error;
+       }
+
+       buf = duk_push_fixed_buffer(ctx, (size_t) len);
+
+       got = fread(buf, 1, len, f);
+       if (got != (size_t) len) {
+               goto error;
+       }
+
+       fclose(f);
+       f = NULL;
+
+       return 1;
+
+ error:
+       if (f) {
+               fclose(f);
+       }
+
+       return DUK_RET_ERROR;
+}
+
+static duk_function_list_entry fileio_funcs[] = {
+       { "readfile", fileio_readfile, 1 },
+       { NULL, NULL, 0 }
+};
+
+void fileio_register(duk_context *ctx) {
+       /* Set global 'FileIo'. */
+       duk_push_global_object(ctx);
+       duk_push_object(ctx);
+       duk_put_function_list(ctx, -1, fileio_funcs);
+       duk_put_prop_string(ctx, -2, "FileIo");
+       duk_pop(ctx);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/main.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/main.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/main.c
new file mode 100644
index 0000000..7627921
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/main.c
@@ -0,0 +1,256 @@
+/*
+ *  Main for evloop command line tool.
+ *
+ *  Runs a given script from file or stdin inside an eventloop.  The
+ *  script can then access setTimeout() etc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef NO_SIGNAL
+#include <signal.h>
+#endif
+
+#include "duktape.h"
+
+extern void poll_register(duk_context *ctx);
+extern void ncurses_register(duk_context *ctx);
+extern void socket_register(duk_context *ctx);
+extern void fileio_register(duk_context *ctx);
+extern void eventloop_register(duk_context *ctx);
+extern int eventloop_run(duk_context *ctx);  /* Duktape/C function, safe 
called */
+
+static int c_evloop = 0;
+
+#ifndef NO_SIGNAL
+static void my_sighandler(int x) {
+       fprintf(stderr, "Got signal %d\n", x);
+       fflush(stderr);
+}
+static void set_sigint_handler(void) {
+       (void) signal(SIGINT, my_sighandler);
+}
+#endif  /* NO_SIGNAL */
+
+/* Print error to stderr and pop error. */
+static void print_error(duk_context *ctx, FILE *f) {
+       if (duk_is_object(ctx, -1) && duk_has_prop_string(ctx, -1, "stack")) {
+               /* XXX: print error objects specially */
+               /* XXX: pcall the string coercion */
+               duk_get_prop_string(ctx, -1, "stack");
+               if (duk_is_string(ctx, -1)) {
+                       fprintf(f, "%s\n", duk_get_string(ctx, -1));
+                       fflush(f);
+                       duk_pop_2(ctx);
+                       return;
+               } else {
+                       duk_pop(ctx);
+               }
+       }
+       duk_to_string(ctx, -1);
+       fprintf(f, "%s\n", duk_get_string(ctx, -1));
+       fflush(f);
+       duk_pop(ctx);
+}
+
+int wrapped_compile_execute(duk_context *ctx) {
+       int comp_flags = 0;
+       int rc;
+
+       /* Compile input and place it into global _USERCODE */
+       duk_compile(ctx, comp_flags);
+       duk_push_global_object(ctx);
+       duk_insert(ctx, -2);  /* [ ... global func ] */
+       duk_put_prop_string(ctx, -2, "_USERCODE");
+       duk_pop(ctx);
+#if 0
+       printf("compiled usercode\n");
+#endif
+
+       /* Start a zero timer which will call _USERCODE from within
+        * the event loop.
+        */
+       fprintf(stderr, "set _USERCODE timer\n");
+       fflush(stderr);
+       duk_eval_string(ctx, "setTimeout(function() { _USERCODE(); }, 0);");
+       duk_pop(ctx);
+
+       /* Finally, launch eventloop.  This call only returns after the
+        * eventloop terminates.
+        */
+       if (c_evloop) {
+               fprintf(stderr, "calling eventloop_run()\n");
+               fflush(stderr);
+               rc = duk_safe_call(ctx, eventloop_run, 0 /*nargs*/, 1 
/*nrets*/);
+               if (rc != 0) {
+                       fprintf(stderr, "eventloop_run() failed: %s\n", 
duk_to_string(ctx, -1));
+                       fflush(stderr);
+               }
+               duk_pop(ctx);
+       } else {
+               fprintf(stderr, "calling EventLoop.run()\n");
+               fflush(stderr);
+               duk_eval_string(ctx, "EventLoop.run();");
+               duk_pop(ctx);
+       }
+
+       return 0;
+}
+
+int handle_fh(duk_context *ctx, FILE *f, const char *filename) {
+       char *buf = NULL;
+       int len;
+       int got;
+       int rc;
+       int retval = -1;
+
+       if (fseek(f, 0, SEEK_END) < 0) {
+               goto error;
+       }
+       len = (int) ftell(f);
+       if (fseek(f, 0, SEEK_SET) < 0) {
+               goto error;
+       }
+       buf = (char *) malloc(len);
+       if (!buf) {
+               goto error;
+       }
+
+       got = fread((void *) buf, (size_t) 1, (size_t) len, f);
+
+       duk_push_lstring(ctx, buf, got);
+       duk_push_string(ctx, filename);
+
+       free(buf);
+       buf = NULL;
+
+       rc = duk_safe_call(ctx, wrapped_compile_execute, 2 /*nargs*/, 1 
/*nret*/);
+       if (rc != DUK_EXEC_SUCCESS) {
+               print_error(ctx, stderr);
+               goto error;
+       } else {
+               duk_pop(ctx);
+               retval = 0;
+       }
+       /* fall thru */
+
+ error:
+       if (buf) {
+               free(buf);
+       }
+       return retval;
+}
+
+int handle_file(duk_context *ctx, const char *filename) {
+       FILE *f = NULL;
+       int retval;
+
+       f = fopen(filename, "rb");
+       if (!f) {
+               fprintf(stderr, "failed to open source file: %s\n", filename);
+               fflush(stderr);
+               goto error;
+       }
+
+       retval = handle_fh(ctx, f, filename);
+
+       fclose(f);
+       return retval;
+
+ error:
+       return -1;
+}
+
+int handle_stdin(duk_context *ctx) {
+       int retval;
+
+       retval = handle_fh(ctx, stdin, "stdin");
+
+       return retval;
+}
+
+int main(int argc, char *argv[]) {
+       duk_context *ctx = NULL;
+       int retval = 0;
+       const char *filename = NULL;
+       int i;
+
+#ifndef NO_SIGNAL
+       set_sigint_handler();
+
+       /* This is useful at the global level; libraries should avoid SIGPIPE 
though */
+       /*signal(SIGPIPE, SIG_IGN);*/
+#endif
+
+       for (i = 1; i < argc; i++) {
+               char *arg = argv[i];
+               if (!arg) {
+                       goto usage;
+               }
+               if (strcmp(arg, "-c") == 0) {
+                       c_evloop = 1;
+               } else if (strlen(arg) > 1 && arg[0] == '-') {
+                       goto usage;
+               } else {
+                       if (filename) {
+                               goto usage;
+                       }
+                       filename = arg;
+               }
+       }
+       if (!filename) {
+               goto usage;
+       }
+
+       ctx = duk_create_heap_default();
+
+       poll_register(ctx);
+       ncurses_register(ctx);
+       socket_register(ctx);
+       fileio_register(ctx);
+
+       if (c_evloop) {
+               fprintf(stderr, "Using C based eventloop (omit -c to use 
Ecmascript based eventloop)\n");
+               fflush(stderr);
+
+               eventloop_register(ctx);
+               duk_eval_file(ctx, "c_eventloop.js");
+       } else {
+               fprintf(stderr, "Using Ecmascript based eventloop (give -c to 
use C based eventloop)\n");
+               fflush(stderr);
+
+               duk_eval_file(ctx, "ecma_eventloop.js");
+       }
+
+       fprintf(stderr, "Executing code from: '%s'\n", filename);
+       fflush(stderr);
+
+       if (strcmp(filename, "-") == 0) {
+               if (handle_stdin(ctx) != 0) {
+                       retval = 1;
+                       goto cleanup;
+               }
+       } else {
+               if (handle_file(ctx, filename) != 0) {
+                       retval = 1;
+                       goto cleanup;
+               }
+       }
+
+ cleanup:
+       if (ctx) {
+               duk_destroy_heap(ctx);
+       }
+
+       return retval;
+
+ usage:
+       fprintf(stderr, "Usage: evloop [-c] <filename>\n");
+       fprintf(stderr, "\n");
+       fprintf(stderr, "Uses an Ecmascript based eventloop (ecma_eventloop.js) 
by default.\n");
+       fprintf(stderr, "If -c option given, uses a C based eventloop 
(c_eventloop.{c,js}).\n");
+       fprintf(stderr, "If <filename> is '-', the entire STDIN executed.\n");
+       fflush(stderr);
+       exit(1);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c
new file mode 100644
index 0000000..7734fcc
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/ncurses.c
@@ -0,0 +1,105 @@
+/*
+ *  Ncurses bindings example.
+ *
+ *  VALGRIND NOTE: when you use ncurses, there seems to be no way to get a
+ *  clean valgrind run.  Even if ncurses state is properly shut down, there
+ *  will still be some residual leaks.
+ *
+ *  Debian: install libncurses5-dev
+ */
+
+#include <curses.h>
+#include "duktape.h"
+
+static int ncurses_initscr(duk_context *ctx) {
+       WINDOW *win;
+
+       win = initscr();
+       duk_push_pointer(ctx, (void *) win);
+       return 1;
+}
+
+static int ncurses_endwin(duk_context *ctx) {
+       int rc;
+
+       rc = endwin();
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static int ncurses_delscreen(duk_context *ctx) {
+       /* XXX: no screen management now */
+       (void) ctx;
+       return 0;
+}
+
+static int ncurses_getmaxyx(duk_context *ctx) {
+       int row, col;
+
+       getmaxyx(stdscr, row, col);
+
+       duk_push_array(ctx);
+       duk_push_int(ctx, row);
+       duk_put_prop_index(ctx, -2, 0);
+       duk_push_int(ctx, col);
+       duk_put_prop_index(ctx, -2, 1);
+       return 1;
+}
+
+static int ncurses_printw(duk_context *ctx) {
+       int rc;
+       const char *str;
+
+       str = duk_to_string(ctx, 0);
+       rc = printw("%s", str);
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static int ncurses_mvprintw(duk_context *ctx) {
+       int y = duk_to_int(ctx, 0);
+       int x = duk_to_int(ctx, 1);
+       const char *str = duk_to_string(ctx, 2);
+       int rc;
+
+       rc = mvprintw(y, x, "%s", str);
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static int ncurses_refresh(duk_context *ctx) {
+       int rc;
+
+       rc = refresh();
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static int ncurses_getch(duk_context *ctx) {
+       int rc;
+
+       rc = getch();
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static duk_function_list_entry ncurses_funcs[] = {
+       { "initscr", ncurses_initscr, 0 },
+       { "endwin", ncurses_endwin, 0 },
+       { "delscreen", ncurses_delscreen, 0 },
+       { "getmaxyx", ncurses_getmaxyx, 0 },
+       { "printw", ncurses_printw, 1 },
+       { "mvprintw", ncurses_mvprintw, 3 },
+       { "refresh", ncurses_refresh, 0 },
+       { "getch", ncurses_getch, 0 },
+       { NULL, NULL, 0 }
+};
+
+void ncurses_register(duk_context *ctx) {
+       /* Set global 'Ncurses'. */
+       duk_push_global_object(ctx);
+       duk_push_object(ctx);
+       duk_put_function_list(ctx, -1, ncurses_funcs);
+       duk_put_prop_string(ctx, -2, "Ncurses");
+       duk_pop(ctx);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/poll.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/poll.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/poll.c
new file mode 100644
index 0000000..c78745d
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/poll.c
@@ -0,0 +1,111 @@
+/*
+ *  C wrapper for poll().
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <poll.h>
+#include <time.h>
+
+#include "duktape.h"
+
+static int poll_poll(duk_context *ctx) {
+       int timeout = duk_to_int(ctx, 1);
+       int i, n, nchanged;
+       int fd, rc;
+       struct pollfd fds[20];
+       struct timespec ts;
+
+       memset(fds, 0, sizeof(fds));
+
+       n = 0;
+       duk_enum(ctx, 0, 0 /*enum_flags*/);
+       while (duk_next(ctx, -1, 0)) {
+               if ((size_t) n >= sizeof(fds) / sizeof(struct pollfd)) {
+                       return -1;
+               }
+
+               /* [... enum key] */
+               duk_dup_top(ctx);  /* -> [... enum key key] */
+               duk_get_prop(ctx, 0);  /* -> [... enum key val] */
+               fd = duk_to_int(ctx, -2);
+
+               duk_push_string(ctx, "events");
+               duk_get_prop(ctx, -2);  /* -> [... enum key val events] */
+
+               fds[n].fd = fd;
+               fds[n].events = duk_to_int(ctx, -1);
+               fds[n].revents = 0;
+
+               duk_pop_n(ctx, 3);  /* -> [... enum] */
+
+               n++;
+       }
+       /* leave enum on stack */
+
+       memset(&ts, 0, sizeof(ts));
+       ts.tv_nsec = (timeout % 1000) * 1000000;
+       ts.tv_sec = timeout / 1000;
+
+       /*rc = ppoll(fds, n, &ts, NULL);*/
+       rc = poll(fds, n, timeout);
+       if (rc < 0) {
+               duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), 
errno);
+       }
+
+       duk_push_array(ctx);
+       nchanged = 0;
+       for (i = 0; i < n; i++) {
+               /* update revents */
+
+               if (fds[i].revents) {
+                       duk_push_int(ctx, fds[i].fd);  /* -> [... retarr fd] */
+                       duk_put_prop_index(ctx, -2, nchanged);
+                       nchanged++;
+               }
+
+               duk_push_int(ctx, fds[i].fd);  /* -> [... retarr key] */
+               duk_get_prop(ctx, 0);  /* -> [... retarr val] */
+               duk_push_string(ctx, "revents");
+               duk_push_int(ctx, fds[i].revents);  /* -> [... retarr val 
"revents" fds[i].revents] */
+               duk_put_prop(ctx, -3);  /* -> [... retarr val] */
+               duk_pop(ctx);
+       }
+
+       /* [retarr] */
+
+       return 1;
+}
+
+static duk_function_list_entry poll_funcs[] = {
+       { "poll", poll_poll, 2 },
+       { NULL, NULL, 0 }
+};
+
+static duk_number_list_entry poll_consts[] = {
+       { "POLLIN", (double) POLLIN },
+       { "POLLPRI", (double) POLLPRI },
+       { "POLLOUT", (double) POLLOUT },
+#if 0
+       /* Linux 2.6.17 and upwards, requires _GNU_SOURCE etc, not added
+        * now because we don't use it.
+        */
+       { "POLLRDHUP", (double) POLLRDHUP },
+#endif
+       { "POLLERR", (double) POLLERR },
+       { "POLLHUP", (double) POLLHUP },
+       { "POLLNVAL", (double) POLLNVAL },
+       { NULL, 0.0 }
+};
+
+void poll_register(duk_context *ctx) {
+       /* Set global 'Poll' with functions and constants. */
+       duk_push_global_object(ctx);
+       duk_push_object(ctx);
+       duk_put_function_list(ctx, -1, poll_funcs);
+       duk_put_number_list(ctx, -1, poll_consts);
+       duk_put_prop_string(ctx, -2, "Poll");
+       duk_pop(ctx);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js
new file mode 100644
index 0000000..68510af
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/server-socket-test.js
@@ -0,0 +1,34 @@
+
+var HOST = 'localhost'
+var PORT = 12345;
+var EXIT_TIMEOUT = 300e3;
+
+print('automatic exit after ' + (EXIT_TIMEOUT / 1e3) + ' seconds');
+setTimeout(function () {
+    print('exit timer');
+    EventLoop.requestExit();
+}, EXIT_TIMEOUT);
+
+print('listen on ' + HOST + ':' + PORT);
+EventLoop.server(HOST, PORT, function (fd, addr, port) {
+    print('new connection on fd ' + fd + ' from ' + addr + ':' + port);
+    EventLoop.setReader(fd, function (fd, data) {
+        var b, i, n, x;
+
+        // Handle socket data carefully: if you convert it to a string,
+        // it may not be valid UTF-8 etc.  Here we operate on the data
+        // directly in the buffer.
+
+        b = data.valueOf();  // ensure we get a plain buffer
+        n = b.length;
+        for (i = 0; i < n; i++) {
+            x = b[i];
+            if (x >= 0x61 && x <= 0x7a) {
+                b[i] = x - 0x20;  // uppercase
+            }
+        }
+
+        print('read data on fd ' + fd + ', length ' + data.length);
+        EventLoop.write(fd, data);
+    });
+});

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/socket.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/socket.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/socket.c
new file mode 100644
index 0000000..a1587fa
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/eventloop/socket.c
@@ -0,0 +1,286 @@
+/*
+ *  TCP sockets binding example.
+ */
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <time.h>
+
+#include "duktape.h"
+
+#define  ERROR_FROM_ERRNO(ctx)  do { \
+               duk_error(ctx, DUK_ERR_ERROR, "%s (errno=%d)", strerror(errno), 
errno); \
+       } while (0)
+
+static void set_nonblocking(duk_context *ctx, int fd) {
+       int rc;
+       int flags;
+
+       rc = fcntl(fd, F_GETFL);
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+       flags = rc;
+
+       flags |= O_NONBLOCK;
+
+       rc = fcntl(fd, F_SETFL, flags);
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+}
+
+static void set_reuseaddr(duk_context *ctx, int fd) {
+       int val;
+       int rc;
+
+       val = 1;
+       rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &val, 
sizeof(val));
+       if (rc != 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+}
+
+#ifdef __APPLE__
+static void set_nosigpipe(duk_context *ctx, int fd) {
+       int val;
+       int rc;
+
+       val = 1;
+       rc = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const void *) &val, 
sizeof(val));
+       if (rc != 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+}
+#endif
+
+static int socket_create_server_socket(duk_context *ctx) {
+       const char *addr = duk_to_string(ctx, 0);
+       int port = duk_to_int(ctx, 1);
+       int sock;
+       struct sockaddr_in sockaddr;
+       struct hostent *ent;
+       struct in_addr **addr_list;
+       struct in_addr *addr_inet;
+       int i;
+       int rc;
+
+       sock = socket(AF_INET, SOCK_STREAM, 0);
+       if (sock < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       set_nonblocking(ctx, sock);
+       set_reuseaddr(ctx, sock);
+#ifdef __APPLE__
+       set_nosigpipe(ctx, sock);
+#endif
+
+       ent = gethostbyname(addr);
+       if (!ent) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       addr_list = (struct in_addr **) ent->h_addr_list;
+       addr_inet = NULL;
+       for (i = 0; addr_list[i]; i++) {
+               addr_inet = addr_list[i];
+               break;
+       }
+       if (!addr_inet) {
+               duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr);
+       }
+
+       memset(&sockaddr, 0, sizeof(sockaddr));
+       sockaddr.sin_family = AF_INET;
+       sockaddr.sin_port = htons(port);
+       sockaddr.sin_addr = *addr_inet;
+
+       rc = bind(sock, (const struct sockaddr *) &sockaddr, sizeof(sockaddr));
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       rc = listen(sock, 10 /*backlog*/);
+       if (rc < 0) {
+               (void) close(sock);
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       duk_push_int(ctx, sock);
+       return 1;
+}
+
+static int socket_close(duk_context *ctx) {
+       int sock = duk_to_int(ctx, 0);
+       int rc;
+
+       rc = close(sock);
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+       return 0;
+}
+
+static int socket_accept(duk_context *ctx) {
+       int sock = duk_to_int(ctx, 0);
+       int rc;
+       struct sockaddr_in addr;
+       socklen_t addrlen;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addrlen = sizeof(addr);
+
+       rc = accept(sock, (struct sockaddr *) &addr, &addrlen);
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       set_nonblocking(ctx, sock);
+#ifdef __APPLE__
+       set_nosigpipe(ctx, sock);
+#endif
+
+       if (addrlen == sizeof(addr)) {
+               uint32_t tmp = ntohl(addr.sin_addr.s_addr);
+
+               duk_push_object(ctx);
+
+               duk_push_string(ctx, "fd");
+               duk_push_int(ctx, rc);
+               duk_put_prop(ctx, -3);
+               duk_push_string(ctx, "addr");
+               duk_push_sprintf(ctx, "%d.%d.%d.%d", ((tmp >> 24) & 0xff), 
((tmp >> 16) & 0xff), ((tmp >> 8) & 0xff), (tmp & 0xff));
+               duk_put_prop(ctx, -3);
+               duk_push_string(ctx, "port");
+               duk_push_int(ctx, ntohs(addr.sin_port));
+               duk_put_prop(ctx, -3);
+
+               return 1;
+       }
+
+       return 0;
+}
+
+static int socket_connect(duk_context *ctx) {
+       const char *addr = duk_to_string(ctx, 0);
+       int port = duk_to_int(ctx, 1);
+       int sock;
+       struct sockaddr_in sockaddr;
+       struct hostent *ent;
+       struct in_addr **addr_list;
+       struct in_addr *addr_inet;
+       int i;
+       int rc;
+
+       sock = socket(AF_INET, SOCK_STREAM, 0);
+       if (sock < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       set_nonblocking(ctx, sock);
+#ifdef __APPLE__
+       set_nosigpipe(ctx, sock);
+#endif
+
+       ent = gethostbyname(addr);
+       if (!ent) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       addr_list = (struct in_addr **) ent->h_addr_list;
+       addr_inet = NULL;
+       for (i = 0; addr_list[i]; i++) {
+               addr_inet = addr_list[i];
+               break;
+       }
+       if (!addr_inet) {
+               duk_error(ctx, DUK_ERR_ERROR, "cannot resolve %s", addr);
+       }
+
+       memset(&sockaddr, 0, sizeof(sockaddr));
+       sockaddr.sin_family = AF_INET;
+       sockaddr.sin_port = htons(port);
+       sockaddr.sin_addr = *addr_inet;
+
+       rc = connect(sock, (const struct sockaddr *) &sockaddr, (socklen_t) 
sizeof(sockaddr));
+       if (rc < 0) {
+               if (errno == EINPROGRESS) {
+#if 0
+                       fprintf(stderr, "connect() returned EINPROGRESS as 
expected, need to poll writability\n");
+                       fflush(stderr);
+#endif
+               } else {
+                       ERROR_FROM_ERRNO(ctx);
+               }
+       }
+
+       duk_push_int(ctx, sock);
+       return 1;
+}
+
+static int socket_read(duk_context *ctx) {
+       int sock = duk_to_int(ctx, 0);
+       char readbuf[1024];
+       int rc;
+       void *data;
+
+       rc = recvfrom(sock, (void *) readbuf, sizeof(readbuf), 0, NULL, NULL);
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       data = duk_push_fixed_buffer(ctx, rc);
+       memcpy(data, readbuf, rc);
+       return 1;
+}
+
+static int socket_write(duk_context *ctx) {
+       int sock = duk_to_int(ctx, 0);
+       const char *data;
+       size_t len;
+       ssize_t rc;
+
+       data = duk_to_buffer(ctx, 1, &len);
+
+       /* MSG_NOSIGNAL: avoid SIGPIPE */
+#ifdef __APPLE__
+       rc = sendto(sock, (void *) data, len, 0, NULL, 0);
+#else
+       rc = sendto(sock, (void *) data, len, MSG_NOSIGNAL, NULL, 0);
+#endif
+       if (rc < 0) {
+               ERROR_FROM_ERRNO(ctx);
+       }
+
+       duk_push_int(ctx, rc);
+       return 1;
+}
+
+static duk_function_list_entry socket_funcs[] = {
+       { "createServerSocket", socket_create_server_socket, 2 },
+       { "close", socket_close, 1 },
+       { "accept", socket_accept, 1 },
+       { "connect", socket_connect, 2 },
+       { "read", socket_read, 1 },
+       { "write", socket_write, 2 },
+       { NULL, NULL, 0 }
+};
+
+void socket_register(duk_context *ctx) {
+       /* Set global 'Socket'. */
+       duk_push_global_object(ctx);
+       duk_push_object(ctx);
+       duk_put_function_list(ctx, -1, socket_funcs);
+       duk_put_prop_string(ctx, -2, "Socket");
+       duk_pop(ctx);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/README.rst
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/README.rst
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/README.rst
new file mode 100644
index 0000000..1933094
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/README.rst
@@ -0,0 +1,5 @@
+===========================
+Duktape guide example files
+===========================
+
+Examples used in the Duktape guide.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/fib.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/fib.js 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/fib.js
new file mode 100644
index 0000000..2b2982f
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/fib.js
@@ -0,0 +1,16 @@
+// fib.js
+function fib(n) {
+    if (n == 0) { return 0; }
+    if (n == 1) { return 1; }
+    return fib(n-1) + fib(n-2);
+}
+
+function test() {
+    var res = [];
+    for (i = 0; i < 20; i++) {
+        res.push(fib(i));
+    }
+    print(res.join(' '));
+}
+
+test();

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/prime.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/prime.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/prime.js
new file mode 100644
index 0000000..8959754
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/prime.js
@@ -0,0 +1,32 @@
+// prime.js
+
+// Pure Ecmascript version of low level helper
+function primeCheckEcmascript(val, limit) {
+    for (var i = 2; i <= limit; i++) {
+        if ((val % i) == 0) { return false; }
+    }
+    return true;
+}
+
+// Select available helper at load time
+var primeCheckHelper = (this.primeCheckNative || primeCheckEcmascript);
+
+// Check 'val' for primality
+function primeCheck(val) {
+    if (val == 1 || val == 2) { return true; }
+    var limit = Math.ceil(Math.sqrt(val));
+    while (limit * limit < val) { limit += 1; }
+    return primeCheckHelper(val, limit);
+}
+
+// Find primes below one million ending in '9999'.
+function primeTest() {
+    var res = [];
+
+    print('Have native helper: ' + (primeCheckHelper !== 
primeCheckEcmascript));
+    for (var i = 1; i < 1000000; i++) {
+        if (primeCheck(i) && (i % 10000) == 9999) { res.push(i); }
+    } 
+    print(res.join(' '));
+}
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/primecheck.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/primecheck.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/primecheck.c
new file mode 100644
index 0000000..36fa5d6
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/primecheck.c
@@ -0,0 +1,52 @@
+/* primecheck.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "duktape.h"
+
+static duk_ret_t native_prime_check(duk_context *ctx) {
+    int val = duk_require_int(ctx, 0);
+    int lim = duk_require_int(ctx, 1);
+    int i;
+
+    for (i = 2; i <= lim; i++) {
+        if (val % i == 0) {
+            duk_push_false(ctx);
+            return 1;
+        }
+    }
+
+    duk_push_true(ctx);
+    return 1;
+}
+
+int main(int argc, const char *argv[]) {
+    duk_context *ctx = NULL;
+
+    ctx = duk_create_heap_default();
+    if (!ctx) {
+        printf("Failed to create a Duktape heap.\n");
+        exit(1);
+    }
+
+    duk_push_global_object(ctx);
+    duk_push_c_function(ctx, native_prime_check, 2 /*nargs*/);
+    duk_put_prop_string(ctx, -2, "primeCheckNative");
+
+    if (duk_peval_file(ctx, "prime.js") != 0) {
+        printf("Error: %s\n", duk_safe_to_string(ctx, -1));
+        goto finished;
+    }
+    duk_pop(ctx);  /* ignore result */
+
+    duk_get_prop_string(ctx, -1, "primeTest");
+    if (duk_pcall(ctx, 0) != 0) {
+        printf("Error: %s\n", duk_safe_to_string(ctx, -1));
+    }
+    duk_pop(ctx);  /* ignore result */
+
+ finished:
+    duk_destroy_heap(ctx);
+
+    exit(0);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/process.js
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/process.js
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/process.js
new file mode 100644
index 0000000..62b5011
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/process.js
@@ -0,0 +1,12 @@
+// process.js
+function processLine(line) {
+    return line.trim()
+        .replace(/[<>&"'\u0000-\u001F\u007E-\uFFFF]/g, function(x) {
+            // escape HTML characters
+            return '&#' + x.charCodeAt(0) + ';'
+         })
+        .replace(/\*(.*?)\*/g, function(x, m) {
+            // automatically bold text between stars
+            return '<b>' + m + '</b>';
+         });
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/processlines.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/processlines.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/processlines.c
new file mode 100644
index 0000000..f91bdff
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/processlines.c
@@ -0,0 +1,59 @@
+/* processlines.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "duktape.h"
+
+int main(int argc, const char *argv[]) {
+    duk_context *ctx = NULL;
+    char line[4096];
+    char idx;
+    int ch;
+
+    ctx = duk_create_heap_default();
+    if (!ctx) {
+        printf("Failed to create a Duktape heap.\n");
+        exit(1);
+    }
+
+    if (duk_peval_file(ctx, "process.js") != 0) {
+        printf("Error: %s\n", duk_safe_to_string(ctx, -1));
+        goto finished;
+    }
+    duk_pop(ctx);  /* ignore result */
+
+    memset(line, 0, sizeof(line));
+    idx = 0;
+    for (;;) {
+        if (idx >= sizeof(line)) {
+            printf("Line too long\n");
+            exit(1);
+        }
+
+        ch = fgetc(stdin);
+        if (ch == 0x0a) {
+            line[idx++] = '\0';
+
+            duk_push_global_object(ctx);
+            duk_get_prop_string(ctx, -1 /*index*/, "processLine");
+            duk_push_string(ctx, line);
+            if (duk_pcall(ctx, 1 /*nargs*/) != 0) {
+                printf("Error: %s\n", duk_safe_to_string(ctx, -1));
+            } else {
+                printf("%s\n", duk_safe_to_string(ctx, -1));
+            }
+            duk_pop(ctx);  /* pop result/error */
+
+            idx = 0;
+        } else if (ch == EOF) {
+            break;
+        } else {
+            line[idx++] = (char) ch;
+        }
+    }
+
+ finished:
+    duk_destroy_heap(ctx);
+
+    exit(0);
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/uppercase.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/uppercase.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/uppercase.c
new file mode 100644
index 0000000..03d0869
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/guide/uppercase.c
@@ -0,0 +1,42 @@
+/* uppercase.c */
+#include <stdio.h>
+#include <stdlib.h>
+#include "duktape.h"
+
+static int dummy_upper_case(duk_context *ctx) {
+    size_t sz;
+    const char *val = duk_require_lstring(ctx, 0, &sz);
+    size_t i;
+
+    /* We're going to need 'sz' additional entries on the stack. */
+    duk_require_stack(ctx, sz);
+
+    for (i = 0; i < sz; i++) {
+        char ch = val[i];
+        if (ch >= 'a' && ch <= 'z') {
+            ch = ch - 'a' + 'A';
+        }
+        duk_push_lstring(ctx, (const char *) &ch, 1);
+    }
+
+    duk_concat(ctx, sz);
+    return 1;
+}
+
+int main(int argc, char *argv[]) {
+    duk_context *ctx;
+
+    if (argc < 2) { exit(1); }
+
+    ctx = duk_create_heap_default();
+    if (!ctx) { exit(1); }
+
+    duk_push_c_function(ctx, dummy_upper_case, 1);
+    duk_push_string(ctx, argv[1]);
+    duk_call(ctx, 1);
+    printf("%s -> %s\n", argv[1], duk_to_string(ctx, -1));
+    duk_pop(ctx);
+
+    duk_destroy_heap(ctx);
+    return 0;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/README.rst
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/README.rst
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/README.rst
new file mode 100644
index 0000000..7afef53
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/README.rst
@@ -0,0 +1,5 @@
+===================
+Hello world example
+===================
+
+Very simple example, most useful for compilation tests.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/hello.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/hello.c 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/hello.c
new file mode 100644
index 0000000..9113d2f
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/hello/hello.c
@@ -0,0 +1,38 @@
+/*
+ *  Very simple example program
+ */
+
+#include "duktape.h"
+
+int adder(duk_context *ctx) {
+       int i;
+       int n = duk_get_top(ctx);  /* #args */
+       double res = 0.0;
+
+       for (i = 0; i < n; i++) {
+               res += duk_to_number(ctx, i);
+       }
+
+       duk_push_number(ctx, res);
+       return 1;  /* one return value */
+}
+
+int main(int argc, char *argv[]) {
+       duk_context *ctx = duk_create_heap_default();
+
+       (void) argc; (void) argv;  /* suppress warning */
+
+       duk_eval_string(ctx, "print('Hello world!');");
+
+       duk_push_global_object(ctx);
+       duk_push_c_function(ctx, adder, DUK_VARARGS);
+       duk_put_prop_string(ctx, -2, "adder");
+       duk_pop(ctx);  /* pop global */
+
+       duk_eval_string(ctx, "print('2+3=' + adder(2, 3));");
+       duk_pop(ctx);  /* pop eval result */
+
+       duk_destroy_heap(ctx);
+
+       return 0;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/README.rst
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/README.rst
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/README.rst
new file mode 100644
index 0000000..5ab43a8
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/README.rst
@@ -0,0 +1,5 @@
+================
+Jxpretty example
+================
+
+Simple command line utility to pretty print JSON in the JX format.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c
new file mode 100644
index 0000000..1e483ef
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/jxpretty/jxpretty.c
@@ -0,0 +1,63 @@
+/*
+ *  Pretty print JSON from stdin into indented JX.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "duktape.h"
+
+static duk_ret_t do_jxpretty(duk_context *ctx) {
+       FILE *f = stdin;
+       char buf[4096];
+       size_t ret;
+
+       for (;;) {
+               if (ferror(f)) {
+                       duk_error(ctx, DUK_ERR_ERROR, "ferror() on stdin");
+               }
+               if (feof(f)) {
+                       break;
+               }
+
+               ret = fread(buf, 1, sizeof(buf), f);
+#if 0
+               fprintf(stderr, "Read: %ld\n", (long) ret);
+               fflush(stderr);
+#endif
+               if (ret == 0) {
+                       break;
+               }
+
+               duk_require_stack(ctx, 1);
+               duk_push_lstring(ctx, (const char *) buf, ret);
+       }
+
+       duk_concat(ctx, duk_get_top(ctx));
+
+       duk_eval_string(ctx, "(function (v) { print(Duktape.enc('jx', 
JSON.parse(v), null, 4)); })");
+       duk_insert(ctx, -2);
+       duk_call(ctx, 1);
+
+       return 0;
+}
+
+int main(int argc, char *argv[]) {
+       duk_context *ctx;
+       duk_int_t rc;
+
+       /* suppress warnings */
+       (void) argc;
+       (void) argv;
+
+       ctx = duk_create_heap_default();
+
+       rc = duk_safe_call(ctx, do_jxpretty, 0 /*nargs*/, 1 /*nrets*/);
+       if (rc) {
+               fprintf(stderr, "ERROR: %s\n", duk_safe_to_string(ctx, -1));
+               fflush(stderr);
+       }
+
+       duk_destroy_heap(ctx);
+
+       return 0;
+}

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/README.rst
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/README.rst
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/README.rst
new file mode 100644
index 0000000..24df0a2
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/README.rst
@@ -0,0 +1,5 @@
+===============
+Sandbox example
+===============
+
+Very simple, minimal sandboxing example.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/df353561/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c
----------------------------------------------------------------------
diff --git 
a/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c
 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c
new file mode 100644
index 0000000..915faa9
--- /dev/null
+++ 
b/thirdparty/civetweb-1.10/src/third_party/duktape-1.5.2/examples/sandbox/sandbox.c
@@ -0,0 +1,252 @@
+/*
+ *  Sandboxing example
+ *
+ *  Uses custom memory allocation functions which keep track of total amount
+ *  of memory allocated, imposing a maximum total allocation size.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "duktape.h"
+
+/*
+ *  Memory allocator which backs to standard library memory functions but
+ *  keeps a small header to track current allocation size.
+ *
+ *  Many other sandbox allocation models are useful, e.g. preallocated pools.
+ */
+
+typedef struct {
+       /* The double value in the union is there to ensure alignment is
+        * good for IEEE doubles too.  In many 32-bit environments 4 bytes
+        * would be sufficiently aligned and the double value is unnecessary.
+        */
+       union {
+               size_t sz;
+               double d;
+       } u;
+} alloc_hdr;
+
+static size_t total_allocated = 0;
+static size_t max_allocated = 256 * 1024;  /* 256kB sandbox */
+
+static void sandbox_dump_memstate(void) {
+#if 0
+       fprintf(stderr, "Total allocated: %ld\n", (long) total_allocated);
+       fflush(stderr);
+#endif
+}
+
+static void *sandbox_alloc(void *udata, duk_size_t size) {
+       alloc_hdr *hdr;
+
+       (void) udata;  /* Suppress warning. */
+
+       if (size == 0) {
+               return NULL;
+       }
+
+       if (total_allocated + size > max_allocated) {
+               fprintf(stderr, "Sandbox maximum allocation size reached, %ld 
requested in sandbox_alloc\n",
+                       (long) size);
+               fflush(stderr);
+               return NULL;
+       }
+
+       hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr));
+       if (!hdr) {
+               return NULL;
+       }
+       hdr->u.sz = size;
+       total_allocated += size;
+       sandbox_dump_memstate();
+       return (void *) (hdr + 1);
+}
+
+static void *sandbox_realloc(void *udata, void *ptr, duk_size_t size) {
+       alloc_hdr *hdr;
+       size_t old_size;
+       void *t;
+
+       (void) udata;  /* Suppress warning. */
+
+       /* Handle the ptr-NULL vs. size-zero cases explicitly to minimize
+        * platform assumptions.  You can get away with much less in specific
+        * well-behaving environments.
+        */
+
+       if (ptr) {
+               hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr));
+               old_size = hdr->u.sz;
+
+               if (size == 0) {
+                       total_allocated -= old_size;
+                       free((void *) hdr);
+                       sandbox_dump_memstate();
+                       return NULL;
+               } else {
+                       if (total_allocated - old_size + size > max_allocated) {
+                               fprintf(stderr, "Sandbox maximum allocation 
size reached, %ld requested in sandbox_realloc\n",
+                                       (long) size);
+                               fflush(stderr);
+                               return NULL;
+                       }
+
+                       t = realloc((void *) hdr, size + sizeof(alloc_hdr));
+                       if (!t) {
+                               return NULL;
+                       }
+                       hdr = (alloc_hdr *) t;
+                       total_allocated -= old_size;
+                       total_allocated += size;
+                       hdr->u.sz = size;
+                       sandbox_dump_memstate();
+                       return (void *) (hdr + 1);
+               }
+       } else {
+               if (size == 0) {
+                       return NULL;
+               } else {
+                       if (total_allocated + size > max_allocated) {
+                               fprintf(stderr, "Sandbox maximum allocation 
size reached, %ld requested in sandbox_realloc\n",
+                                       (long) size);
+                               fflush(stderr);
+                               return NULL;
+                       }
+
+                       hdr = (alloc_hdr *) malloc(size + sizeof(alloc_hdr));
+                       if (!hdr) {
+                               return NULL;
+                       }
+                       hdr->u.sz = size;
+                       total_allocated += size;
+                       sandbox_dump_memstate();
+                       return (void *) (hdr + 1);
+               }
+       }
+}
+
+static void sandbox_free(void *udata, void *ptr) {
+       alloc_hdr *hdr;
+
+       (void) udata;  /* Suppress warning. */
+
+       if (!ptr) {
+               return;
+       }
+       hdr = (alloc_hdr *) (((char *) ptr) - sizeof(alloc_hdr));
+       total_allocated -= hdr->u.sz;
+       free((void *) hdr);
+       sandbox_dump_memstate();
+}
+
+/*
+ *  Sandbox setup and test
+ */
+
+static duk_ret_t do_sandbox_test(duk_context *ctx) {
+       FILE *f;
+       char buf[4096];
+       size_t ret;
+       const char *globobj;
+
+       /*
+        *  Setup sandbox
+        */
+
+       globobj =
+               "({\n"
+               "    print: print,\n"
+               "    Math: {\n"
+               "        max: Math.max\n"
+               "    }\n"
+               "})\n";
+#if 1
+       fprintf(stderr, "Sandbox global 
object:\n----------------\n%s----------------\n", globobj);
+       fflush(stderr);
+#endif
+       duk_eval_string(ctx, globobj);
+       duk_set_global_object(ctx);
+
+       /*
+        *  Execute code from specified file
+        */
+
+       f = fopen(duk_require_string(ctx, -1), "rb");
+       if (!f) {
+               duk_error(ctx, DUK_ERR_ERROR, "failed to open file");
+       }
+
+       for (;;) {
+               if (ferror(f)) {
+                       fclose(f);
+                       duk_error(ctx, DUK_ERR_ERROR, "ferror when reading 
file");
+               }
+               if (feof(f)) {
+                       break;
+               }
+
+               ret = fread(buf, 1, sizeof(buf), f);
+               if (ret == 0) {
+                       break;
+               }
+
+               duk_push_lstring(ctx, (const char *) buf, ret);
+       }
+
+       duk_concat(ctx, duk_get_top(ctx) - 1);  /* -1 for filename */
+
+       /* -> [ ... filename source ] */
+
+       duk_insert(ctx, -2);
+
+       /* -> [ ... source filename ] */
+
+       duk_compile(ctx, 0 /*flags*/);  /* Compile as program */
+       duk_call(ctx, 0 /*nargs*/);
+
+       return 0;
+}
+
+/*
+ *  Main
+ */
+
+static void sandbox_fatal(duk_context *ctx, duk_errcode_t code, const char 
*msg) {
+       (void) ctx;  /* Suppress warning. */
+       fprintf(stderr, "FATAL %ld: %s\n", (long) code, (msg ? msg : "no 
message"));
+       fflush(stderr);
+       exit(1);  /* must not return */
+}
+
+int main(int argc, char *argv[]) {
+       duk_context *ctx;
+       duk_int_t rc;
+
+       if (argc < 2) {
+               fprintf(stderr, "Usage: sandbox <test.js>\n");
+               fflush(stderr);
+               exit(1);
+       }
+
+       ctx = duk_create_heap(sandbox_alloc,
+                             sandbox_realloc,
+                             sandbox_free,
+                             NULL,
+                             sandbox_fatal);
+
+       duk_push_string(ctx, argv[1]);
+       rc = duk_safe_call(ctx, do_sandbox_test, 1 /*nargs*/, 1 /*nrets*/);
+       if (rc) {
+               fprintf(stderr, "ERROR: %s\n", duk_safe_to_string(ctx, -1));
+               fflush(stderr);
+       }
+
+       duk_destroy_heap(ctx);
+
+       /* Should be zero. */
+       fprintf(stderr, "Final allocation: %ld\n", (long) total_allocated);
+       fflush(stderr);
+
+       return 1;
+}

Reply via email to