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