1743Smax.romanov@nginx.com
2743Smax.romanov@nginx.com /*
3743Smax.romanov@nginx.com * Copyright (C) NGINX, Inc.
4743Smax.romanov@nginx.com */
5743Smax.romanov@nginx.com
6743Smax.romanov@nginx.com #include <nxt_unit.h>
7743Smax.romanov@nginx.com #include <nxt_unit_request.h>
8743Smax.romanov@nginx.com #include <nxt_clang.h>
91669Smax.romanov@nginx.com #include <pthread.h>
101669Smax.romanov@nginx.com #include <string.h>
111669Smax.romanov@nginx.com #include <stdlib.h>
12743Smax.romanov@nginx.com
13743Smax.romanov@nginx.com
14743Smax.romanov@nginx.com #define CONTENT_TYPE "Content-Type"
15743Smax.romanov@nginx.com #define TEXT_PLAIN "text/plain"
16743Smax.romanov@nginx.com #define HELLO_WORLD "Hello world!\n"
17743Smax.romanov@nginx.com
18743Smax.romanov@nginx.com #define NEW_LINE "\n"
19743Smax.romanov@nginx.com
20743Smax.romanov@nginx.com #define REQUEST_DATA "Request data:\n"
21743Smax.romanov@nginx.com #define METHOD " Method: "
22743Smax.romanov@nginx.com #define PROTOCOL " Protocol: "
23743Smax.romanov@nginx.com #define REMOTE_ADDR " Remote addr: "
24743Smax.romanov@nginx.com #define LOCAL_ADDR " Local addr: "
25743Smax.romanov@nginx.com #define TARGET " Target: "
26743Smax.romanov@nginx.com #define PATH " Path: "
27743Smax.romanov@nginx.com #define QUERY " Query: "
28743Smax.romanov@nginx.com #define FIELDS " Fields:\n"
29743Smax.romanov@nginx.com #define FIELD_PAD " "
30743Smax.romanov@nginx.com #define FIELD_SEP ": "
31743Smax.romanov@nginx.com #define BODY " Body:\n"
32743Smax.romanov@nginx.com
33743Smax.romanov@nginx.com
341669Smax.romanov@nginx.com static int ready_handler(nxt_unit_ctx_t *ctx);
351669Smax.romanov@nginx.com static void *worker(void *main_ctx);
361669Smax.romanov@nginx.com static void greeting_app_request_handler(nxt_unit_request_info_t *req);
371669Smax.romanov@nginx.com static inline char *copy(char *p, const void *src, uint32_t len);
381669Smax.romanov@nginx.com
391669Smax.romanov@nginx.com
401669Smax.romanov@nginx.com static int thread_count;
411669Smax.romanov@nginx.com static pthread_t *threads;
421669Smax.romanov@nginx.com
431669Smax.romanov@nginx.com
441669Smax.romanov@nginx.com int
main(int argc,char ** argv)451669Smax.romanov@nginx.com main(int argc, char **argv)
46743Smax.romanov@nginx.com {
471669Smax.romanov@nginx.com int i, err;
481669Smax.romanov@nginx.com nxt_unit_ctx_t *ctx;
491669Smax.romanov@nginx.com nxt_unit_init_t init;
501669Smax.romanov@nginx.com
511669Smax.romanov@nginx.com if (argc == 3 && strcmp(argv[1], "-t") == 0) {
521669Smax.romanov@nginx.com thread_count = atoi(argv[2]);
531669Smax.romanov@nginx.com }
541669Smax.romanov@nginx.com
551669Smax.romanov@nginx.com memset(&init, 0, sizeof(nxt_unit_init_t));
561669Smax.romanov@nginx.com
571669Smax.romanov@nginx.com init.callbacks.request_handler = greeting_app_request_handler;
581669Smax.romanov@nginx.com init.callbacks.ready_handler = ready_handler;
591669Smax.romanov@nginx.com
601669Smax.romanov@nginx.com ctx = nxt_unit_init(&init);
611669Smax.romanov@nginx.com if (ctx == NULL) {
621669Smax.romanov@nginx.com return 1;
631669Smax.romanov@nginx.com }
641669Smax.romanov@nginx.com
651669Smax.romanov@nginx.com err = nxt_unit_run(ctx);
661669Smax.romanov@nginx.com
671669Smax.romanov@nginx.com nxt_unit_debug(ctx, "main worker finished with %d code", err);
681669Smax.romanov@nginx.com
691669Smax.romanov@nginx.com if (thread_count > 1) {
701669Smax.romanov@nginx.com for (i = 0; i < thread_count - 1; i++) {
711669Smax.romanov@nginx.com err = pthread_join(threads[i], NULL);
721669Smax.romanov@nginx.com
731676Svbart@nginx.com if (nxt_fast_path(err == 0)) {
741676Svbart@nginx.com nxt_unit_debug(ctx, "join thread #%d", i);
751676Svbart@nginx.com
761676Svbart@nginx.com } else {
771676Svbart@nginx.com nxt_unit_alert(ctx, "pthread_join(#%d) failed: %s (%d)",
781676Svbart@nginx.com i, strerror(err), err);
791676Svbart@nginx.com }
801669Smax.romanov@nginx.com }
811669Smax.romanov@nginx.com
821669Smax.romanov@nginx.com nxt_unit_free(ctx, threads);
831669Smax.romanov@nginx.com }
841669Smax.romanov@nginx.com
851669Smax.romanov@nginx.com nxt_unit_done(ctx);
861669Smax.romanov@nginx.com
871669Smax.romanov@nginx.com nxt_unit_debug(NULL, "main worker done");
881669Smax.romanov@nginx.com
891669Smax.romanov@nginx.com return 0;
901669Smax.romanov@nginx.com }
911669Smax.romanov@nginx.com
92743Smax.romanov@nginx.com
931669Smax.romanov@nginx.com static int
ready_handler(nxt_unit_ctx_t * ctx)941669Smax.romanov@nginx.com ready_handler(nxt_unit_ctx_t *ctx)
951669Smax.romanov@nginx.com {
961669Smax.romanov@nginx.com int i, err;
971669Smax.romanov@nginx.com
981669Smax.romanov@nginx.com nxt_unit_debug(ctx, "ready");
991669Smax.romanov@nginx.com
1001980Smax.romanov@nginx.com if (thread_count <= 1) {
1011669Smax.romanov@nginx.com return NXT_UNIT_OK;
1021669Smax.romanov@nginx.com }
1031669Smax.romanov@nginx.com
1041669Smax.romanov@nginx.com threads = nxt_unit_malloc(ctx, sizeof(pthread_t) * (thread_count - 1));
1051669Smax.romanov@nginx.com if (threads == NULL) {
1061669Smax.romanov@nginx.com return NXT_UNIT_ERROR;
1071669Smax.romanov@nginx.com }
1081669Smax.romanov@nginx.com
1091669Smax.romanov@nginx.com for (i = 0; i < thread_count - 1; i++) {
1101669Smax.romanov@nginx.com err = pthread_create(&threads[i], NULL, worker, ctx);
1111669Smax.romanov@nginx.com if (err != 0) {
1121669Smax.romanov@nginx.com return NXT_UNIT_ERROR;
1131669Smax.romanov@nginx.com }
1141669Smax.romanov@nginx.com }
1151669Smax.romanov@nginx.com
1161669Smax.romanov@nginx.com return NXT_UNIT_OK;
1171669Smax.romanov@nginx.com }
1181669Smax.romanov@nginx.com
1191669Smax.romanov@nginx.com
1201669Smax.romanov@nginx.com static void *
worker(void * main_ctx)1211669Smax.romanov@nginx.com worker(void *main_ctx)
1221669Smax.romanov@nginx.com {
1231669Smax.romanov@nginx.com int rc;
1241669Smax.romanov@nginx.com nxt_unit_ctx_t *ctx;
1251669Smax.romanov@nginx.com
1261669Smax.romanov@nginx.com ctx = nxt_unit_ctx_alloc(main_ctx, NULL);
1271669Smax.romanov@nginx.com if (ctx == NULL) {
1281669Smax.romanov@nginx.com return NULL;
1291669Smax.romanov@nginx.com }
1301669Smax.romanov@nginx.com
1311669Smax.romanov@nginx.com nxt_unit_debug(ctx, "start worker");
1321669Smax.romanov@nginx.com
1331669Smax.romanov@nginx.com rc = nxt_unit_run(ctx);
1341669Smax.romanov@nginx.com
1351669Smax.romanov@nginx.com nxt_unit_debug(ctx, "worker finished with %d code", rc);
1361669Smax.romanov@nginx.com
1371669Smax.romanov@nginx.com nxt_unit_done(ctx);
1381669Smax.romanov@nginx.com
1391676Svbart@nginx.com return (void *) (intptr_t) rc;
140743Smax.romanov@nginx.com }
141743Smax.romanov@nginx.com
142743Smax.romanov@nginx.com
143743Smax.romanov@nginx.com static void
greeting_app_request_handler(nxt_unit_request_info_t * req)144743Smax.romanov@nginx.com greeting_app_request_handler(nxt_unit_request_info_t *req)
145743Smax.romanov@nginx.com {
146743Smax.romanov@nginx.com int rc;
147743Smax.romanov@nginx.com char *p;
148743Smax.romanov@nginx.com ssize_t res;
149743Smax.romanov@nginx.com uint32_t i;
150743Smax.romanov@nginx.com nxt_unit_buf_t *buf;
151743Smax.romanov@nginx.com nxt_unit_field_t *f;
152743Smax.romanov@nginx.com nxt_unit_request_t *r;
153743Smax.romanov@nginx.com
154743Smax.romanov@nginx.com rc = nxt_unit_response_init(req, 200 /* Status code. */,
155743Smax.romanov@nginx.com 1 /* Number of response headers. */,
156743Smax.romanov@nginx.com nxt_length(CONTENT_TYPE)
157743Smax.romanov@nginx.com + nxt_length(TEXT_PLAIN)
158743Smax.romanov@nginx.com + nxt_length(HELLO_WORLD));
159743Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_UNIT_OK)) {
160743Smax.romanov@nginx.com goto fail;
161743Smax.romanov@nginx.com }
162743Smax.romanov@nginx.com
163743Smax.romanov@nginx.com rc = nxt_unit_response_add_field(req,
164743Smax.romanov@nginx.com CONTENT_TYPE, nxt_length(CONTENT_TYPE),
165743Smax.romanov@nginx.com TEXT_PLAIN, nxt_length(TEXT_PLAIN));
166743Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_UNIT_OK)) {
167743Smax.romanov@nginx.com goto fail;
168743Smax.romanov@nginx.com }
169743Smax.romanov@nginx.com
170743Smax.romanov@nginx.com rc = nxt_unit_response_add_content(req, HELLO_WORLD,
171743Smax.romanov@nginx.com nxt_length(HELLO_WORLD));
172743Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_UNIT_OK)) {
173743Smax.romanov@nginx.com goto fail;
174743Smax.romanov@nginx.com }
175743Smax.romanov@nginx.com
176743Smax.romanov@nginx.com rc = nxt_unit_response_send(req);
177743Smax.romanov@nginx.com if (nxt_slow_path(rc != NXT_UNIT_OK)) {
178743Smax.romanov@nginx.com goto fail;
179743Smax.romanov@nginx.com }
180743Smax.romanov@nginx.com
181743Smax.romanov@nginx.com r = req->request;
182743Smax.romanov@nginx.com
183743Smax.romanov@nginx.com buf = nxt_unit_response_buf_alloc(req, (req->request_buf->end
184743Smax.romanov@nginx.com - req->request_buf->start)
185743Smax.romanov@nginx.com + nxt_length(REQUEST_DATA)
186743Smax.romanov@nginx.com + nxt_length(METHOD)
187743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
188743Smax.romanov@nginx.com + nxt_length(PROTOCOL)
189743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
190743Smax.romanov@nginx.com + nxt_length(REMOTE_ADDR)
191743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
192743Smax.romanov@nginx.com + nxt_length(LOCAL_ADDR)
193743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
194743Smax.romanov@nginx.com + nxt_length(TARGET)
195743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
196743Smax.romanov@nginx.com + nxt_length(PATH)
197743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
198743Smax.romanov@nginx.com + nxt_length(QUERY)
199743Smax.romanov@nginx.com + nxt_length(NEW_LINE)
200743Smax.romanov@nginx.com + nxt_length(FIELDS)
201743Smax.romanov@nginx.com + r->fields_count * (
202743Smax.romanov@nginx.com nxt_length(FIELD_PAD)
203743Smax.romanov@nginx.com + nxt_length(FIELD_SEP))
204743Smax.romanov@nginx.com + nxt_length(BODY));
205743Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) {
206743Smax.romanov@nginx.com rc = NXT_UNIT_ERROR;
207743Smax.romanov@nginx.com
208743Smax.romanov@nginx.com goto fail;
209743Smax.romanov@nginx.com }
210743Smax.romanov@nginx.com
211743Smax.romanov@nginx.com p = buf->free;
212743Smax.romanov@nginx.com
213743Smax.romanov@nginx.com p = copy(p, REQUEST_DATA, nxt_length(REQUEST_DATA));
214743Smax.romanov@nginx.com
215743Smax.romanov@nginx.com p = copy(p, METHOD, nxt_length(METHOD));
216743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->method), r->method_length);
217743Smax.romanov@nginx.com *p++ = '\n';
218743Smax.romanov@nginx.com
219743Smax.romanov@nginx.com p = copy(p, PROTOCOL, nxt_length(PROTOCOL));
220743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->version), r->version_length);
221743Smax.romanov@nginx.com *p++ = '\n';
222743Smax.romanov@nginx.com
223743Smax.romanov@nginx.com p = copy(p, REMOTE_ADDR, nxt_length(REMOTE_ADDR));
224743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->remote), r->remote_length);
225743Smax.romanov@nginx.com *p++ = '\n';
226743Smax.romanov@nginx.com
227743Smax.romanov@nginx.com p = copy(p, LOCAL_ADDR, nxt_length(LOCAL_ADDR));
2282208Sa.clayton@nginx.com p = copy(p, nxt_unit_sptr_get(&r->local_addr), r->local_addr_length);
229743Smax.romanov@nginx.com *p++ = '\n';
230743Smax.romanov@nginx.com
231743Smax.romanov@nginx.com p = copy(p, TARGET, nxt_length(TARGET));
232743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->target), r->target_length);
233743Smax.romanov@nginx.com *p++ = '\n';
234743Smax.romanov@nginx.com
235743Smax.romanov@nginx.com p = copy(p, PATH, nxt_length(PATH));
236743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->path), r->path_length);
237743Smax.romanov@nginx.com *p++ = '\n';
238743Smax.romanov@nginx.com
239743Smax.romanov@nginx.com if (r->query.offset) {
240743Smax.romanov@nginx.com p = copy(p, QUERY, nxt_length(QUERY));
241743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&r->query), r->query_length);
242743Smax.romanov@nginx.com *p++ = '\n';
243743Smax.romanov@nginx.com }
244743Smax.romanov@nginx.com
245743Smax.romanov@nginx.com p = copy(p, FIELDS, nxt_length(FIELDS));
246743Smax.romanov@nginx.com
247743Smax.romanov@nginx.com for (i = 0; i < r->fields_count; i++) {
248743Smax.romanov@nginx.com f = r->fields + i;
249743Smax.romanov@nginx.com
250743Smax.romanov@nginx.com p = copy(p, FIELD_PAD, nxt_length(FIELD_PAD));
251743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&f->name), f->name_length);
252743Smax.romanov@nginx.com p = copy(p, FIELD_SEP, nxt_length(FIELD_SEP));
253743Smax.romanov@nginx.com p = copy(p, nxt_unit_sptr_get(&f->value), f->value_length);
254743Smax.romanov@nginx.com *p++ = '\n';
255743Smax.romanov@nginx.com }
256743Smax.romanov@nginx.com
257743Smax.romanov@nginx.com if (r->content_length > 0) {
258743Smax.romanov@nginx.com p = copy(p, BODY, nxt_length(BODY));
259743Smax.romanov@nginx.com
260*2476Salx@nginx.com res = nxt_unit_request_read(req, p, buf->end - p);
261*2476Salx@nginx.com p += res;
262743Smax.romanov@nginx.com
263743Smax.romanov@nginx.com }
264743Smax.romanov@nginx.com
265743Smax.romanov@nginx.com buf->free = p;
266743Smax.romanov@nginx.com
267743Smax.romanov@nginx.com rc = nxt_unit_buf_send(buf);
268743Smax.romanov@nginx.com
269743Smax.romanov@nginx.com fail:
270743Smax.romanov@nginx.com
271743Smax.romanov@nginx.com nxt_unit_request_done(req, rc);
272743Smax.romanov@nginx.com }
273743Smax.romanov@nginx.com
274743Smax.romanov@nginx.com
2751669Smax.romanov@nginx.com static inline char *
copy(char * p,const void * src,uint32_t len)2761669Smax.romanov@nginx.com copy(char *p, const void *src, uint32_t len)
2771669Smax.romanov@nginx.com {
2781669Smax.romanov@nginx.com memcpy(p, src, len);
279743Smax.romanov@nginx.com
2801669Smax.romanov@nginx.com return p + len;
281743Smax.romanov@nginx.com }
282