1 
2 /*
3  * Copyright (C) NGINX, Inc.
4  */
5 
6 #include <string.h>
7 #include <stdlib.h>
8 
9 #include <nxt_unit.h>
10 #include <nxt_unit_request.h>
11 #include <nxt_clang.h>
12 #include <nxt_websocket.h>
13 #include <nxt_unit_websocket.h>
14 
15 
16 static void
ws_echo_request_handler(nxt_unit_request_info_t * req)17 ws_echo_request_handler(nxt_unit_request_info_t *req)
18 {
19     int         rc;
20     const char  *target;
21 
22     rc = NXT_UNIT_OK;
23     target = nxt_unit_sptr_get(&req->request->target);
24 
25     if (strcmp(target, "/") == 0) {
26         if (!nxt_unit_request_is_websocket_handshake(req)) {
27             goto notfound;
28         }
29 
30         rc = nxt_unit_response_init(req, 101, 0, 0);
31         if (nxt_slow_path(rc != NXT_UNIT_OK)) {
32             goto fail;
33         }
34 
35         nxt_unit_response_upgrade(req);
36         nxt_unit_response_send(req);
37 
38         return;
39     }
40 
41 notfound:
42 
43     rc = nxt_unit_response_init(req, 404, 0, 0);
44 
45 fail:
46 
47     nxt_unit_request_done(req, rc);
48 }
49 
50 
51 static void
ws_echo_websocket_handler(nxt_unit_websocket_frame_t * ws)52 ws_echo_websocket_handler(nxt_unit_websocket_frame_t *ws)
53 {
54     uint8_t                  opcode;
55     ssize_t                  size;
56     nxt_unit_request_info_t  *req;
57 
58     static size_t            buf_size = 0;
59     static uint8_t           *buf = NULL;
60 
61     if (buf_size < ws->content_length) {
62         buf = realloc(buf, ws->content_length);
63         buf_size = ws->content_length;
64     }
65 
66     req = ws->req;
67     opcode = ws->header->opcode;
68 
69     if (opcode == NXT_WEBSOCKET_OP_PONG) {
70         nxt_unit_websocket_done(ws);
71         return;
72     }
73 
74     size = nxt_unit_websocket_read(ws, buf, ws->content_length);
75 
76     nxt_unit_websocket_send(req, opcode, ws->header->fin, buf, size);
77     nxt_unit_websocket_done(ws);
78 
79     if (opcode == NXT_WEBSOCKET_OP_CLOSE) {
80         nxt_unit_request_done(req, NXT_UNIT_OK);
81     }
82 }
83 
84 
85 int
main()86 main()
87 {
88     nxt_unit_ctx_t   *ctx;
89     nxt_unit_init_t  init;
90 
91     memset(&init, 0, sizeof(nxt_unit_init_t));
92 
93     init.callbacks.request_handler = ws_echo_request_handler;
94     init.callbacks.websocket_handler = ws_echo_websocket_handler;
95 
96     ctx = nxt_unit_init(&init);
97     if (ctx == NULL) {
98         return 1;
99     }
100 
101     nxt_unit_run(ctx);
102     nxt_unit_done(ctx);
103 
104     return 0;
105 }
106