xref: /unit/src/nxt_websocket_accept.c (revision 2140:423ecac30dba)
1 
2 /*
3  * Copyright (C) NGINX, Inc.
4  */
5 
6 #include <nxt_main.h>
7 #include <nxt_websocket.h>
8 #include <nxt_sha1.h>
9 
10 
11 static void
nxt_websocket_base64_encode(u_char * d,const uint8_t * s,size_t len)12 nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len)
13 {
14     u_char               c0, c1, c2;
15     static const u_char  basis[] =
16         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
17 
18     while (len > 2) {
19         c0 = s[0];
20         c1 = s[1];
21         c2 = s[2];
22 
23         *d++ = basis[c0 >> 2];
24         *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
25         *d++ = basis[((c1 & 0x0f) << 2) | (c2 >> 6)];
26         *d++ = basis[c2 & 0x3f];
27 
28         s += 3;
29         len -= 3;
30     }
31 
32     if (len > 0) {
33         c0 = s[0];
34         *d++ = basis[c0 >> 2];
35 
36         if (len == 1) {
37             *d++ = basis[(c0 & 0x03) << 4];
38             *d++ = '=';
39             *d++ = '=';
40 
41         } else {
42             c1 = s[1];
43 
44             *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
45             *d++ = basis[(c1 & 0x0f) << 2];
46 
47             *d++ = '=';
48         }
49     }
50 }
51 
52 
53 void
nxt_websocket_accept(u_char * accept,const void * key)54 nxt_websocket_accept(u_char *accept, const void *key)
55 {
56     u_char             bin_accept[20];
57     nxt_sha1_t         ctx;
58     static const char  accept_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
59 
60     nxt_sha1_init(&ctx);
61     nxt_sha1_update(&ctx, key, 24);
62     nxt_sha1_update(&ctx, accept_guid, nxt_length(accept_guid));
63     nxt_sha1_final(bin_accept, &ctx);
64 
65     nxt_websocket_base64_encode(accept, bin_accept, sizeof(bin_accept));
66 }
67 
68 
69