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