xref: /unit/src/nxt_websocket_accept.c (revision 2140:423ecac30dba)
11131Smax.romanov@nginx.com 
21131Smax.romanov@nginx.com /*
31131Smax.romanov@nginx.com  * Copyright (C) NGINX, Inc.
41131Smax.romanov@nginx.com  */
51131Smax.romanov@nginx.com 
61131Smax.romanov@nginx.com #include <nxt_main.h>
71131Smax.romanov@nginx.com #include <nxt_websocket.h>
81131Smax.romanov@nginx.com #include <nxt_sha1.h>
91131Smax.romanov@nginx.com 
101131Smax.romanov@nginx.com 
111131Smax.romanov@nginx.com static void
nxt_websocket_base64_encode(u_char * d,const uint8_t * s,size_t len)121131Smax.romanov@nginx.com nxt_websocket_base64_encode(u_char *d, const uint8_t *s, size_t len)
131131Smax.romanov@nginx.com {
14*2140Sandrew@digital-domain.net     u_char               c0, c1, c2;
15*2140Sandrew@digital-domain.net     static const u_char  basis[] =
161131Smax.romanov@nginx.com         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
171131Smax.romanov@nginx.com 
181131Smax.romanov@nginx.com     while (len > 2) {
191131Smax.romanov@nginx.com         c0 = s[0];
201131Smax.romanov@nginx.com         c1 = s[1];
211131Smax.romanov@nginx.com         c2 = s[2];
221131Smax.romanov@nginx.com 
231131Smax.romanov@nginx.com         *d++ = basis[c0 >> 2];
241131Smax.romanov@nginx.com         *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
251131Smax.romanov@nginx.com         *d++ = basis[((c1 & 0x0f) << 2) | (c2 >> 6)];
261131Smax.romanov@nginx.com         *d++ = basis[c2 & 0x3f];
271131Smax.romanov@nginx.com 
281131Smax.romanov@nginx.com         s += 3;
291131Smax.romanov@nginx.com         len -= 3;
301131Smax.romanov@nginx.com     }
311131Smax.romanov@nginx.com 
321131Smax.romanov@nginx.com     if (len > 0) {
331131Smax.romanov@nginx.com         c0 = s[0];
341131Smax.romanov@nginx.com         *d++ = basis[c0 >> 2];
351131Smax.romanov@nginx.com 
361131Smax.romanov@nginx.com         if (len == 1) {
371131Smax.romanov@nginx.com             *d++ = basis[(c0 & 0x03) << 4];
381131Smax.romanov@nginx.com             *d++ = '=';
391131Smax.romanov@nginx.com             *d++ = '=';
401131Smax.romanov@nginx.com 
411131Smax.romanov@nginx.com         } else {
421131Smax.romanov@nginx.com             c1 = s[1];
431131Smax.romanov@nginx.com 
441131Smax.romanov@nginx.com             *d++ = basis[((c0 & 0x03) << 4) | (c1 >> 4)];
451131Smax.romanov@nginx.com             *d++ = basis[(c1 & 0x0f) << 2];
461131Smax.romanov@nginx.com 
471131Smax.romanov@nginx.com             *d++ = '=';
481131Smax.romanov@nginx.com         }
491131Smax.romanov@nginx.com     }
501131Smax.romanov@nginx.com }
511131Smax.romanov@nginx.com 
521131Smax.romanov@nginx.com 
531131Smax.romanov@nginx.com void
nxt_websocket_accept(u_char * accept,const void * key)541131Smax.romanov@nginx.com nxt_websocket_accept(u_char *accept, const void *key)
551131Smax.romanov@nginx.com {
561131Smax.romanov@nginx.com     u_char             bin_accept[20];
571131Smax.romanov@nginx.com     nxt_sha1_t         ctx;
581131Smax.romanov@nginx.com     static const char  accept_guid[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
591131Smax.romanov@nginx.com 
601131Smax.romanov@nginx.com     nxt_sha1_init(&ctx);
611131Smax.romanov@nginx.com     nxt_sha1_update(&ctx, key, 24);
621131Smax.romanov@nginx.com     nxt_sha1_update(&ctx, accept_guid, nxt_length(accept_guid));
631131Smax.romanov@nginx.com     nxt_sha1_final(bin_accept, &ctx);
641131Smax.romanov@nginx.com 
651131Smax.romanov@nginx.com     nxt_websocket_base64_encode(accept, bin_accept, sizeof(bin_accept));
661131Smax.romanov@nginx.com }
671131Smax.romanov@nginx.com 
681131Smax.romanov@nginx.com 
69