summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Colomar <alx.manpages@gmail.com>2022-08-30 13:37:41 +0200
committerAlejandro Colomar <alx.manpages@gmail.com>2022-08-30 15:37:40 +0200
commit66652c9984aefa6a1d8008f9fb225b82e018d5c5 (patch)
tree084c103e5e64c254df9b5b34d06bb1e591937fd4
Copy program from unit repo
Signed-off-by: Alejandro Colomar <alx.manpages@gmail.com>
-rw-r--r--nxt_unit_app_test.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/nxt_unit_app_test.c b/nxt_unit_app_test.c
new file mode 100644
index 0000000..8fda974
--- /dev/null
+++ b/nxt_unit_app_test.c
@@ -0,0 +1,281 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_unit.h>
+#include <nxt_unit_request.h>
+#include <nxt_clang.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#define CONTENT_TYPE "Content-Type"
+#define TEXT_PLAIN "text/plain"
+#define HELLO_WORLD "Hello world!\n"
+
+#define NEW_LINE "\n"
+
+#define REQUEST_DATA "Request data:\n"
+#define METHOD " Method: "
+#define PROTOCOL " Protocol: "
+#define REMOTE_ADDR " Remote addr: "
+#define LOCAL_ADDR " Local addr: "
+#define TARGET " Target: "
+#define PATH " Path: "
+#define QUERY " Query: "
+#define FIELDS " Fields:\n"
+#define FIELD_PAD " "
+#define FIELD_SEP ": "
+#define BODY " Body:\n"
+
+
+static int ready_handler(nxt_unit_ctx_t *ctx);
+static void *worker(void *main_ctx);
+static void greeting_app_request_handler(nxt_unit_request_info_t *req);
+static inline char *copy(char *p, const void *src, uint32_t len);
+
+
+static int thread_count;
+static pthread_t *threads;
+
+
+int
+main(int argc, char **argv)
+{
+ int i, err;
+ nxt_unit_ctx_t *ctx;
+ nxt_unit_init_t init;
+
+ if (argc == 3 && strcmp(argv[1], "-t") == 0) {
+ thread_count = atoi(argv[2]);
+ }
+
+ memset(&init, 0, sizeof(nxt_unit_init_t));
+
+ init.callbacks.request_handler = greeting_app_request_handler;
+ init.callbacks.ready_handler = ready_handler;
+
+ ctx = nxt_unit_init(&init);
+ if (ctx == NULL) {
+ return 1;
+ }
+
+ err = nxt_unit_run(ctx);
+
+ nxt_unit_debug(ctx, "main worker finished with %d code", err);
+
+ if (thread_count > 1) {
+ for (i = 0; i < thread_count - 1; i++) {
+ err = pthread_join(threads[i], NULL);
+
+ if (nxt_fast_path(err == 0)) {
+ nxt_unit_debug(ctx, "join thread #%d", i);
+
+ } else {
+ nxt_unit_alert(ctx, "pthread_join(#%d) failed: %s (%d)",
+ i, strerror(err), err);
+ }
+ }
+
+ nxt_unit_free(ctx, threads);
+ }
+
+ nxt_unit_done(ctx);
+
+ nxt_unit_debug(NULL, "main worker done");
+
+ return 0;
+}
+
+
+static int
+ready_handler(nxt_unit_ctx_t *ctx)
+{
+ int i, err;
+
+ nxt_unit_debug(ctx, "ready");
+
+ if (thread_count <= 1) {
+ return NXT_UNIT_OK;
+ }
+
+ threads = nxt_unit_malloc(ctx, sizeof(pthread_t) * (thread_count - 1));
+ if (threads == NULL) {
+ return NXT_UNIT_ERROR;
+ }
+
+ for (i = 0; i < thread_count - 1; i++) {
+ err = pthread_create(&threads[i], NULL, worker, ctx);
+ if (err != 0) {
+ return NXT_UNIT_ERROR;
+ }
+ }
+
+ return NXT_UNIT_OK;
+}
+
+
+static void *
+worker(void *main_ctx)
+{
+ int rc;
+ nxt_unit_ctx_t *ctx;
+
+ ctx = nxt_unit_ctx_alloc(main_ctx, NULL);
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ nxt_unit_debug(ctx, "start worker");
+
+ rc = nxt_unit_run(ctx);
+
+ nxt_unit_debug(ctx, "worker finished with %d code", rc);
+
+ nxt_unit_done(ctx);
+
+ return (void *) (intptr_t) rc;
+}
+
+
+static void
+greeting_app_request_handler(nxt_unit_request_info_t *req)
+{
+ int rc;
+ char *p;
+ ssize_t res;
+ uint32_t i;
+ nxt_unit_buf_t *buf;
+ nxt_unit_field_t *f;
+ nxt_unit_request_t *r;
+
+ rc = nxt_unit_response_init(req, 200 /* Status code. */,
+ 1 /* Number of response headers. */,
+ nxt_length(CONTENT_TYPE)
+ + nxt_length(TEXT_PLAIN)
+ + nxt_length(HELLO_WORLD));
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
+ rc = nxt_unit_response_add_field(req,
+ CONTENT_TYPE, nxt_length(CONTENT_TYPE),
+ TEXT_PLAIN, nxt_length(TEXT_PLAIN));
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
+ rc = nxt_unit_response_add_content(req, HELLO_WORLD,
+ nxt_length(HELLO_WORLD));
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
+ rc = nxt_unit_response_send(req);
+ if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+ goto fail;
+ }
+
+ r = req->request;
+
+ buf = nxt_unit_response_buf_alloc(req, (req->request_buf->end
+ - req->request_buf->start)
+ + nxt_length(REQUEST_DATA)
+ + nxt_length(METHOD)
+ + nxt_length(NEW_LINE)
+ + nxt_length(PROTOCOL)
+ + nxt_length(NEW_LINE)
+ + nxt_length(REMOTE_ADDR)
+ + nxt_length(NEW_LINE)
+ + nxt_length(LOCAL_ADDR)
+ + nxt_length(NEW_LINE)
+ + nxt_length(TARGET)
+ + nxt_length(NEW_LINE)
+ + nxt_length(PATH)
+ + nxt_length(NEW_LINE)
+ + nxt_length(QUERY)
+ + nxt_length(NEW_LINE)
+ + nxt_length(FIELDS)
+ + r->fields_count * (
+ nxt_length(FIELD_PAD)
+ + nxt_length(FIELD_SEP))
+ + nxt_length(BODY));
+ if (nxt_slow_path(buf == NULL)) {
+ rc = NXT_UNIT_ERROR;
+
+ goto fail;
+ }
+
+ p = buf->free;
+
+ p = copy(p, REQUEST_DATA, nxt_length(REQUEST_DATA));
+
+ p = copy(p, METHOD, nxt_length(METHOD));
+ p = copy(p, nxt_unit_sptr_get(&r->method), r->method_length);
+ *p++ = '\n';
+
+ p = copy(p, PROTOCOL, nxt_length(PROTOCOL));
+ p = copy(p, nxt_unit_sptr_get(&r->version), r->version_length);
+ *p++ = '\n';
+
+ p = copy(p, REMOTE_ADDR, nxt_length(REMOTE_ADDR));
+ p = copy(p, nxt_unit_sptr_get(&r->remote), r->remote_length);
+ *p++ = '\n';
+
+ p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR));
+ p = copy(p, nxt_unit_sptr_get(&r->local), r->local_length);
+ *p++ = '\n';
+
+ p = copy(p, TARGET, nxt_length(TARGET));
+ p = copy(p, nxt_unit_sptr_get(&r->target), r->target_length);
+ *p++ = '\n';
+
+ p = copy(p, PATH, nxt_length(PATH));
+ p = copy(p, nxt_unit_sptr_get(&r->path), r->path_length);
+ *p++ = '\n';
+
+ if (r->query.offset) {
+ p = copy(p, QUERY, nxt_length(QUERY));
+ p = copy(p, nxt_unit_sptr_get(&r->query), r->query_length);
+ *p++ = '\n';
+ }
+
+ p = copy(p, FIELDS, nxt_length(FIELDS));
+
+ for (i = 0; i < r->fields_count; i++) {
+ f = r->fields + i;
+
+ p = copy(p, FIELD_PAD, nxt_length(FIELD_PAD));
+ p = copy(p, nxt_unit_sptr_get(&f->name), f->name_length);
+ p = copy(p, FIELD_SEP, nxt_length(FIELD_SEP));
+ p = copy(p, nxt_unit_sptr_get(&f->value), f->value_length);
+ *p++ = '\n';
+ }
+
+ if (r->content_length > 0) {
+ p = copy(p, BODY, nxt_length(BODY));
+
+ res = nxt_unit_request_read(req, buf->free, buf->end - buf->free);
+ buf->free += res;
+
+ }
+
+ buf->free = p;
+
+ rc = nxt_unit_buf_send(buf);
+
+fail:
+
+ nxt_unit_request_done(req, rc);
+}
+
+
+static inline char *
+copy(char *p, const void *src, uint32_t len)
+{
+ memcpy(p, src, len);
+
+ return p + len;
+}