Merge e101b3bace into 108b617eef
This commit is contained in:
commit
0070468336
|
|
@ -1,3 +1,10 @@
|
||||||
*.pyc
|
*.pyc
|
||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
|
ws_vc2010/Debug/
|
||||||
|
ws_vc2010/Release/
|
||||||
|
*.user
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.suo
|
||||||
|
ipch/
|
||||||
|
|
@ -291,7 +291,7 @@ function constructor() {
|
||||||
case 65507: // Ctrl, do not send directly
|
case 65507: // Ctrl, do not send directly
|
||||||
break;
|
break;
|
||||||
case 65293: // Carriage return, line feed
|
case 65293: // Carriage return, line feed
|
||||||
str = '\n'; break;
|
str = '\r\n'; break;
|
||||||
case 65288: // Backspace
|
case 65288: // Backspace
|
||||||
str = '\b'; break;
|
str = '\b'; break;
|
||||||
case 65307: // Escape
|
case 65307: // Escape
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,17 @@ struct md5_ctx
|
||||||
|
|
||||||
md5_uint32 total[2];
|
md5_uint32 total[2];
|
||||||
md5_uint32 buflen;
|
md5_uint32 buflen;
|
||||||
|
#ifdef _WIN32
|
||||||
|
char buffer[128];
|
||||||
|
#else
|
||||||
char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
|
char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define __THROW
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following three functions are build up the low level used in
|
* The following three functions are build up the low level used in
|
||||||
* the functions `md5_stream' and `md5_buffer'.
|
* the functions `md5_stream' and `md5_buffer'.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,320 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the project nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
|
||||||
|
* based on: http://csrc.nist.gov/fips/fip180-1.txt
|
||||||
|
* implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
typedef unsigned char u_int8_t;
|
||||||
|
typedef unsigned int u_int32_t;
|
||||||
|
typedef unsigned __int64 u_int64_t;
|
||||||
|
typedef void* caddr_t;
|
||||||
|
|
||||||
|
#undef __P
|
||||||
|
#ifndef __P
|
||||||
|
#if __STDC__
|
||||||
|
#define __P(protos) protos
|
||||||
|
#else
|
||||||
|
#define __P(protos) ()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct sha1_ctxt {
|
||||||
|
union {
|
||||||
|
u_int8_t b8[20];
|
||||||
|
u_int32_t b32[5];
|
||||||
|
} h;
|
||||||
|
union {
|
||||||
|
u_int8_t b8[8];
|
||||||
|
u_int64_t b64[1];
|
||||||
|
} c;
|
||||||
|
union {
|
||||||
|
u_int8_t b8[64];
|
||||||
|
u_int32_t b32[16];
|
||||||
|
} m;
|
||||||
|
u_int8_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* sanity check */
|
||||||
|
#if BYTE_ORDER != BIG_ENDIAN
|
||||||
|
# if BYTE_ORDER != LITTLE_ENDIAN
|
||||||
|
# define unsupported 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef unsupported
|
||||||
|
|
||||||
|
/* constant table */
|
||||||
|
static u_int32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 };
|
||||||
|
#define K(t) _K[(t) / 20]
|
||||||
|
|
||||||
|
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
|
||||||
|
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
|
||||||
|
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
|
||||||
|
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
|
||||||
|
|
||||||
|
#define S(n, x) (((x) << (n)) | ((x) >> (32 - n)))
|
||||||
|
|
||||||
|
#define H(n) (ctxt->h.b32[(n)])
|
||||||
|
#define COUNT (ctxt->count)
|
||||||
|
#define BCOUNT (ctxt->c.b64[0] / 8)
|
||||||
|
#define W(n) (ctxt->m.b32[(n)])
|
||||||
|
|
||||||
|
#define PUTBYTE(x) { \
|
||||||
|
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||||
|
COUNT++; \
|
||||||
|
COUNT %= 64; \
|
||||||
|
ctxt->c.b64[0] += 8; \
|
||||||
|
if (COUNT % 64 == 0) \
|
||||||
|
sha1_step(ctxt); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PUTPAD(x) { \
|
||||||
|
ctxt->m.b8[(COUNT % 64)] = (x); \
|
||||||
|
COUNT++; \
|
||||||
|
COUNT %= 64; \
|
||||||
|
if (COUNT % 64 == 0) \
|
||||||
|
sha1_step(ctxt); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha1_step __P((struct sha1_ctxt *));
|
||||||
|
|
||||||
|
static void
|
||||||
|
sha1_step(struct sha1_ctxt *ctxt)
|
||||||
|
{
|
||||||
|
u_int32_t a, b, c, d, e;
|
||||||
|
size_t t, s;
|
||||||
|
u_int32_t tmp;
|
||||||
|
|
||||||
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
|
struct sha1_ctxt tctxt;
|
||||||
|
|
||||||
|
memcpy(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
|
||||||
|
ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2];
|
||||||
|
ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0];
|
||||||
|
ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6];
|
||||||
|
ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4];
|
||||||
|
ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10];
|
||||||
|
ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8];
|
||||||
|
ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14];
|
||||||
|
ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12];
|
||||||
|
ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18];
|
||||||
|
ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16];
|
||||||
|
ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22];
|
||||||
|
ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20];
|
||||||
|
ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26];
|
||||||
|
ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24];
|
||||||
|
ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30];
|
||||||
|
ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28];
|
||||||
|
ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34];
|
||||||
|
ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32];
|
||||||
|
ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38];
|
||||||
|
ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36];
|
||||||
|
ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42];
|
||||||
|
ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40];
|
||||||
|
ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46];
|
||||||
|
ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44];
|
||||||
|
ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50];
|
||||||
|
ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48];
|
||||||
|
ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54];
|
||||||
|
ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52];
|
||||||
|
ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58];
|
||||||
|
ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56];
|
||||||
|
ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62];
|
||||||
|
ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
a = H(0); b = H(1); c = H(2); d = H(3); e = H(4);
|
||||||
|
|
||||||
|
for (t = 0; t < 20; t++) {
|
||||||
|
s = t & 0x0f;
|
||||||
|
if (t >= 16)
|
||||||
|
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||||
|
W((s+2) & 0x0f) ^ W(s));
|
||||||
|
|
||||||
|
tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
|
||||||
|
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||||
|
}
|
||||||
|
for (t = 20; t < 40; t++) {
|
||||||
|
s = t & 0x0f;
|
||||||
|
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||||
|
W((s+2) & 0x0f) ^ W(s));
|
||||||
|
tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
|
||||||
|
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||||
|
}
|
||||||
|
for (t = 40; t < 60; t++) {
|
||||||
|
s = t & 0x0f;
|
||||||
|
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||||
|
W((s+2) & 0x0f) ^ W(s));
|
||||||
|
tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
|
||||||
|
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||||
|
}
|
||||||
|
for (t = 60; t < 80; t++) {
|
||||||
|
s = t & 0x0f;
|
||||||
|
W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^
|
||||||
|
W((s+2) & 0x0f) ^ W(s));
|
||||||
|
tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
|
||||||
|
e = d; d = c; c = S(30, b); b = a; a = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
H(0) = H(0) + a;
|
||||||
|
H(1) = H(1) + b;
|
||||||
|
H(2) = H(2) + c;
|
||||||
|
H(3) = H(3) + d;
|
||||||
|
H(4) = H(4) + e;
|
||||||
|
|
||||||
|
bzero(&ctxt->m.b8[0], 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void
|
||||||
|
sha1_init(struct sha1_ctxt *ctxt)
|
||||||
|
{
|
||||||
|
bzero(ctxt, sizeof(struct sha1_ctxt));
|
||||||
|
H(0) = 0x67452301;
|
||||||
|
H(1) = 0xefcdab89;
|
||||||
|
H(2) = 0x98badcfe;
|
||||||
|
H(3) = 0x10325476;
|
||||||
|
H(4) = 0xc3d2e1f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sha1_pad(struct sha1_ctxt *ctxt)
|
||||||
|
{
|
||||||
|
size_t padlen; /*pad length in bytes*/
|
||||||
|
size_t padstart;
|
||||||
|
|
||||||
|
PUTPAD(0x80);
|
||||||
|
|
||||||
|
padstart = COUNT % 64;
|
||||||
|
padlen = 64 - padstart;
|
||||||
|
if (padlen < 8) {
|
||||||
|
bzero(&ctxt->m.b8[padstart], padlen);
|
||||||
|
COUNT += padlen;
|
||||||
|
COUNT %= 64;
|
||||||
|
sha1_step(ctxt);
|
||||||
|
padstart = COUNT % 64; /* should be 0 */
|
||||||
|
padlen = 64 - padstart; /* should be 64 */
|
||||||
|
}
|
||||||
|
bzero(&ctxt->m.b8[padstart], padlen - 8);
|
||||||
|
COUNT += (padlen - 8);
|
||||||
|
COUNT %= 64;
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]);
|
||||||
|
PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]);
|
||||||
|
PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]);
|
||||||
|
PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]);
|
||||||
|
#else
|
||||||
|
PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]);
|
||||||
|
PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]);
|
||||||
|
PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]);
|
||||||
|
PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sha1_loop(struct sha1_ctxt *ctxt, const u_int8_t *input, size_t len)
|
||||||
|
{
|
||||||
|
size_t gaplen;
|
||||||
|
size_t gapstart;
|
||||||
|
size_t off;
|
||||||
|
size_t copysiz;
|
||||||
|
|
||||||
|
off = 0;
|
||||||
|
|
||||||
|
while (off < len) {
|
||||||
|
gapstart = COUNT % 64;
|
||||||
|
gaplen = 64 - gapstart;
|
||||||
|
|
||||||
|
copysiz = (gaplen < len - off) ? gaplen : len - off;
|
||||||
|
memcpy(&ctxt->m.b8[gapstart], &input[off], copysiz);
|
||||||
|
COUNT += copysiz;
|
||||||
|
COUNT %= 64;
|
||||||
|
ctxt->c.b64[0] += copysiz * 8;
|
||||||
|
if (COUNT % 64 == 0)
|
||||||
|
sha1_step(ctxt);
|
||||||
|
off += copysiz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sha1_result(struct sha1_ctxt *ctxt, caddr_t digest0)
|
||||||
|
{
|
||||||
|
u_int8_t *digest;
|
||||||
|
|
||||||
|
digest = (u_int8_t *)digest0;
|
||||||
|
sha1_pad(ctxt);
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
memcpy(digest, &ctxt->h.b8[0], 20);
|
||||||
|
#else
|
||||||
|
digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2];
|
||||||
|
digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0];
|
||||||
|
digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6];
|
||||||
|
digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4];
|
||||||
|
digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10];
|
||||||
|
digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8];
|
||||||
|
digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14];
|
||||||
|
digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12];
|
||||||
|
digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18];
|
||||||
|
digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should look and work like the libcrypto implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
SHA1(const unsigned char *d, size_t n, unsigned char *md)
|
||||||
|
{
|
||||||
|
struct sha1_ctxt ctx;
|
||||||
|
|
||||||
|
sha1_init(&ctx);
|
||||||
|
sha1_loop(&ctx, d, n);
|
||||||
|
sha1_result(&ctx, (caddr_t)md);
|
||||||
|
|
||||||
|
return md;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /*unsupported*/
|
||||||
|
|
||||||
|
|
@ -11,29 +11,97 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <strings.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <Winsock2.h>
|
||||||
|
#include <WS2tcpip.h>
|
||||||
|
#include <osisock.h>
|
||||||
|
//#include <base64-decode.h>
|
||||||
|
//#define b64_ntop(in, ilen, out, osize) lws_b64_encode_string(in, ilen, out, osize)
|
||||||
|
//#define b64_pton(in, out, osize) lws_b64_decode_string(in, out, osize)
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#else
|
||||||
|
#include <strings.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <resolv.h> /* base64 encode/decode */
|
||||||
|
#endif
|
||||||
#include <signal.h> // daemonizing
|
#include <signal.h> // daemonizing
|
||||||
#include <fcntl.h> // daemonizing
|
#include <fcntl.h> // daemonizing
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <resolv.h> /* base64 encode/decode */
|
#include "md5.h"
|
||||||
#include "websocket.h"
|
#include "websocket.h"
|
||||||
|
|
||||||
const char server_handshake[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
|
const char server_handshake_hixie[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\
|
||||||
Upgrade: WebSocket\r\n\
|
Upgrade: WebSocket\r\n\
|
||||||
Connection: Upgrade\r\n\
|
Connection: Upgrade\r\n\
|
||||||
%sWebSocket-Origin: %s\r\n\
|
%sWebSocket-Origin: %.*s\r\n\
|
||||||
%sWebSocket-Location: %s://%s%s\r\n\
|
%sWebSocket-Location: %s://%.*s%.*s\r\n\
|
||||||
%sWebSocket-Protocol: sample\r\n\
|
%sWebSocket-Protocol: base64\r\n\
|
||||||
\r\n%s";
|
\r\n%s";
|
||||||
|
|
||||||
|
const char server_handshake_hybi[] = "HTTP/1.1 101 Switching Protocols\r\n\
|
||||||
|
Upgrade: websocket\r\n\
|
||||||
|
Connection: Upgrade\r\n\
|
||||||
|
Sec-WebSocket-Accept: %s\r\n\
|
||||||
|
Sec-WebSocket-Protocol: %.*s\r\n\
|
||||||
|
\r\n\
|
||||||
|
";
|
||||||
|
|
||||||
const char policy_response[] = "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\n";
|
const char policy_response[] = "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>\n";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the path from the handhake header.
|
||||||
|
*/
|
||||||
|
static int get_path(const char *handshake, const char* *value, size_t *len) {
|
||||||
|
const char *start, *end;
|
||||||
|
|
||||||
|
if ((strlen(handshake) < 92) || (memcmp(handshake, "GET ", 4) != 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = handshake+4;
|
||||||
|
end = strstr(start, " HTTP/1.1");
|
||||||
|
if (!end) { return 0; }
|
||||||
|
|
||||||
|
*value = start;
|
||||||
|
*len = end - start;
|
||||||
|
|
||||||
|
return *len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a header field from an HTTP header.
|
||||||
|
* Returns non-zero if successful, 0 if the header does not contain
|
||||||
|
* the specified field.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int get_header_field(const char *handshake, const char *name, const char* *value, size_t *len) {
|
||||||
|
char key[64];
|
||||||
|
const char *p, *q;
|
||||||
|
size_t lk;
|
||||||
|
|
||||||
|
lk = sprintf_s(key, sizeof(key), "\r\n%s: ", name );
|
||||||
|
p = strstr(handshake, key);
|
||||||
|
if (p) {
|
||||||
|
*value = p + lk;
|
||||||
|
q = strstr(*value, "\r\n");
|
||||||
|
if (!q) return 0;
|
||||||
|
return (*len = (q - *value));
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * skip_header(const char *handshake) {
|
||||||
|
const char *p;
|
||||||
|
p = strstr(handshake, "\r\n\r\n");
|
||||||
|
if (!p) return 0;
|
||||||
|
return p + 4;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global state
|
* Global state
|
||||||
*
|
*
|
||||||
|
|
@ -66,7 +134,7 @@ void fatal(char *msg)
|
||||||
/* resolve host with also IP address parsing */
|
/* resolve host with also IP address parsing */
|
||||||
int resolve_host(struct in_addr *sin_addr, const char *hostname)
|
int resolve_host(struct in_addr *sin_addr, const char *hostname)
|
||||||
{
|
{
|
||||||
if (!inet_aton(hostname, sin_addr)) {
|
if (!inet_pton(AF_INET, hostname, sin_addr)) {
|
||||||
struct addrinfo *ai, *cur;
|
struct addrinfo *ai, *cur;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
|
@ -178,7 +246,7 @@ ws_ctx_t *ws_socket_ssl(int socket, char * certfile, char * keyfile) {
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ws_socket_free(ws_ctx_t *ctx) {
|
void ws_socket_free(ws_ctx_t *ctx) {
|
||||||
if (ctx->ssl) {
|
if (ctx->ssl) {
|
||||||
SSL_free(ctx->ssl);
|
SSL_free(ctx->ssl);
|
||||||
ctx->ssl = NULL;
|
ctx->ssl = NULL;
|
||||||
|
|
@ -199,8 +267,7 @@ int ws_socket_free(ws_ctx_t *ctx) {
|
||||||
|
|
||||||
|
|
||||||
int encode(u_char const *src, size_t srclength, char *target, size_t targsize) {
|
int encode(u_char const *src, size_t srclength, char *target, size_t targsize) {
|
||||||
int i, sz = 0, len = 0;
|
int sz = 0, len = 0;
|
||||||
unsigned char chr;
|
|
||||||
target[sz++] = '\x00';
|
target[sz++] = '\x00';
|
||||||
len = b64_ntop(src, srclength, target+sz, targsize-sz);
|
len = b64_ntop(src, srclength, target+sz, targsize-sz);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
|
|
@ -213,8 +280,7 @@ int encode(u_char const *src, size_t srclength, char *target, size_t targsize) {
|
||||||
|
|
||||||
int decode(char *src, size_t srclength, u_char *target, size_t targsize) {
|
int decode(char *src, size_t srclength, u_char *target, size_t targsize) {
|
||||||
char *start, *end, cntstr[4];
|
char *start, *end, cntstr[4];
|
||||||
int i, len, framecount = 0, retlen = 0;
|
int len, framecount = 0, retlen = 0;
|
||||||
unsigned char chr;
|
|
||||||
if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) {
|
if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) {
|
||||||
handler_emsg("WebSocket framing error\n");
|
handler_emsg("WebSocket framing error\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -239,81 +305,32 @@ int decode(char *src, size_t srclength, u_char *target, size_t targsize) {
|
||||||
return retlen;
|
return retlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_handshake(char *handshake, headers_t *headers) {
|
int gen_md5(const char *handshake, char *target) {
|
||||||
char *start, *end;
|
|
||||||
|
|
||||||
if ((strlen(handshake) < 92) || (bcmp(handshake, "GET ", 4) != 0)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
start = handshake+4;
|
|
||||||
end = strstr(start, " HTTP/1.1");
|
|
||||||
if (!end) { return 0; }
|
|
||||||
strncpy(headers->path, start, end-start);
|
|
||||||
headers->path[end-start] = '\0';
|
|
||||||
|
|
||||||
start = strstr(handshake, "\r\nHost: ");
|
|
||||||
if (!start) { return 0; }
|
|
||||||
start += 8;
|
|
||||||
end = strstr(start, "\r\n");
|
|
||||||
strncpy(headers->host, start, end-start);
|
|
||||||
headers->host[end-start] = '\0';
|
|
||||||
|
|
||||||
start = strstr(handshake, "\r\nOrigin: ");
|
|
||||||
if (!start) { return 0; }
|
|
||||||
start += 10;
|
|
||||||
end = strstr(start, "\r\n");
|
|
||||||
strncpy(headers->origin, start, end-start);
|
|
||||||
headers->origin[end-start] = '\0';
|
|
||||||
|
|
||||||
start = strstr(handshake, "\r\n\r\n");
|
|
||||||
if (!start) { return 0; }
|
|
||||||
start += 4;
|
|
||||||
if (strlen(start) == 8) {
|
|
||||||
strncpy(headers->key3, start, 8);
|
|
||||||
headers->key3[8] = '\0';
|
|
||||||
|
|
||||||
start = strstr(handshake, "\r\nSec-WebSocket-Key1: ");
|
|
||||||
if (!start) { return 0; }
|
|
||||||
start += 22;
|
|
||||||
end = strstr(start, "\r\n");
|
|
||||||
strncpy(headers->key1, start, end-start);
|
|
||||||
headers->key1[end-start] = '\0';
|
|
||||||
|
|
||||||
start = strstr(handshake, "\r\nSec-WebSocket-Key2: ");
|
|
||||||
if (!start) { return 0; }
|
|
||||||
start += 22;
|
|
||||||
end = strstr(start, "\r\n");
|
|
||||||
strncpy(headers->key2, start, end-start);
|
|
||||||
headers->key2[end-start] = '\0';
|
|
||||||
} else {
|
|
||||||
headers->key1[0] = '\0';
|
|
||||||
headers->key2[0] = '\0';
|
|
||||||
headers->key3[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gen_md5(headers_t *headers, char *target) {
|
|
||||||
unsigned int i, spaces1 = 0, spaces2 = 0;
|
unsigned int i, spaces1 = 0, spaces2 = 0;
|
||||||
unsigned long num1 = 0, num2 = 0;
|
unsigned long num1 = 0, num2 = 0;
|
||||||
unsigned char buf[17];
|
unsigned char buf[17];
|
||||||
for (i=0; i < strlen(headers->key1); i++) {
|
const char *value;
|
||||||
if (headers->key1[i] == ' ') {
|
size_t len;
|
||||||
|
|
||||||
|
if (!get_header_field(handshake, "Sec-WebSocket-Key1", &value, &len)) return 0;
|
||||||
|
|
||||||
|
for (i=0; i < len; i++) {
|
||||||
|
if (value[i] == ' ') {
|
||||||
spaces1 += 1;
|
spaces1 += 1;
|
||||||
}
|
}
|
||||||
if ((headers->key1[i] >= 48) && (headers->key1[i] <= 57)) {
|
if ((value[i] >= 48) && (value[i] <= 57)) {
|
||||||
num1 = num1 * 10 + (headers->key1[i] - 48);
|
num1 = num1 * 10 + (value[i] - 48);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
num1 = num1 / spaces1;
|
num1 = num1 / spaces1;
|
||||||
|
|
||||||
for (i=0; i < strlen(headers->key2); i++) {
|
if (!get_header_field(handshake, "Sec-WebSocket-Key2", &value, &len)) return 0;
|
||||||
if (headers->key2[i] == ' ') {
|
for (i=0; i < len; i++) {
|
||||||
|
if (value[i] == ' ') {
|
||||||
spaces2 += 1;
|
spaces2 += 1;
|
||||||
}
|
}
|
||||||
if ((headers->key2[i] >= 48) && (headers->key2[i] <= 57)) {
|
if ((value[i] >= 48) && (value[i] <= 57)) {
|
||||||
num2 = num2 * 10 + (headers->key2[i] - 48);
|
num2 = num2 * 10 + (value[i] - 48);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
num2 = num2 / spaces2;
|
num2 = num2 / spaces2;
|
||||||
|
|
@ -329,7 +346,8 @@ int gen_md5(headers_t *headers, char *target) {
|
||||||
buf[6] = (num2 & 0xff00) >> 8;
|
buf[6] = (num2 & 0xff00) >> 8;
|
||||||
buf[7] = num2 & 0xff;
|
buf[7] = num2 & 0xff;
|
||||||
|
|
||||||
strncpy(buf+8, headers->key3, 8);
|
if (!(value = skip_header(handshake))) return 0;
|
||||||
|
strncpy(buf+8, value, 8);
|
||||||
buf[16] = '\0';
|
buf[16] = '\0';
|
||||||
|
|
||||||
md5_buffer(buf, 16, target);
|
md5_buffer(buf, 16, target);
|
||||||
|
|
@ -341,26 +359,28 @@ int gen_md5(headers_t *headers, char *target) {
|
||||||
|
|
||||||
|
|
||||||
ws_ctx_t *do_handshake(int sock) {
|
ws_ctx_t *do_handshake(int sock) {
|
||||||
char handshake[4096], response[4096], trailer[17];
|
char handshake[4096], response[4096], trailer[17], keynguid[1024+36+1], hash[20+1], accept[30+1];
|
||||||
char *scheme, *pre;
|
char *scheme, *pre, *protocol;
|
||||||
headers_t headers;
|
int len;
|
||||||
int len, ret;
|
|
||||||
ws_ctx_t * ws_ctx;
|
ws_ctx_t * ws_ctx;
|
||||||
|
const char *value;
|
||||||
|
size_t vlen;
|
||||||
|
size_t rlen;
|
||||||
|
|
||||||
// Peek, but don't read the data
|
// Peek, but don't read the data
|
||||||
len = recv(sock, handshake, 1024, MSG_PEEK);
|
len = recv(sock, handshake, 1024, MSG_PEEK);
|
||||||
handshake[len] = 0;
|
handshake[len] = 0;
|
||||||
|
printf("Handshake:\n%s\n", handshake);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
handler_msg("ignoring empty handshake\n");
|
handler_msg("ignoring empty handshake\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (bcmp(handshake, "<policy-file-request/>", 22) == 0) {
|
} else if (memcmp(handshake, "<policy-file-request/>", 22) == 0) {
|
||||||
len = recv(sock, handshake, 1024, 0);
|
len = recv(sock, handshake, 1024, 0);
|
||||||
handshake[len] = 0;
|
handshake[len] = 0;
|
||||||
handler_msg("sending flash policy response\n");
|
handler_msg("sending flash policy response\n");
|
||||||
send(sock, policy_response, sizeof(policy_response), 0);
|
send(sock, policy_response, sizeof(policy_response), 0);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if ((bcmp(handshake, "\x16", 1) == 0) ||
|
} else if (handshake[0] == '\x16' || handshake[0] == '\x80') {
|
||||||
(bcmp(handshake, "\x80", 1) == 0)) {
|
|
||||||
// SSL
|
// SSL
|
||||||
if (!settings.cert) {
|
if (!settings.cert) {
|
||||||
handler_msg("SSL connection but no cert specified\n");
|
handler_msg("SSL connection but no cert specified\n");
|
||||||
|
|
@ -390,37 +410,62 @@ ws_ctx_t *do_handshake(int sock) {
|
||||||
}
|
}
|
||||||
handshake[len] = 0;
|
handshake[len] = 0;
|
||||||
|
|
||||||
if (!parse_handshake(handshake, &headers)) {
|
// HyBi/IETF version of the protocol ?
|
||||||
handler_emsg("Invalid WS request\n");
|
if (get_header_field(handshake, "Sec-WebSocket-Version", &value, &vlen)) {
|
||||||
return NULL;
|
int ver;
|
||||||
}
|
const char *key, *protocol;
|
||||||
|
size_t kl, el, pl;
|
||||||
|
ver = atoi(value);
|
||||||
|
if (!get_header_field(handshake, "Sec-WebSocket-Protocol", &protocol, &pl)) return 0;
|
||||||
|
ws_ctx->protocol = strncmp(protocol, "base64", pl) == 0 ? base64 : binary;
|
||||||
|
if (!get_header_field(handshake, "Sec-WebSocket-Key", &key, &kl)) return 0;
|
||||||
|
strncpy_s(keynguid, sizeof(keynguid), key, kl);
|
||||||
|
strcat_s(keynguid, sizeof(keynguid), "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||||
|
SHA1((const unsigned char*)keynguid, strlen(keynguid), hash);
|
||||||
|
b64_ntop(hash, 20, accept, sizeof(accept));
|
||||||
|
rlen = sprintf(response, server_handshake_hybi, accept, pl, protocol);
|
||||||
|
}
|
||||||
|
else // Hixie version of the protocol (75 or 76)
|
||||||
|
{
|
||||||
|
const char *key3, *orig, *host, *path;
|
||||||
|
size_t kl, ol, hl, pl;
|
||||||
|
key3 = skip_header(handshake);
|
||||||
|
if (key3 && *key3) {
|
||||||
|
gen_md5(handshake, trailer);
|
||||||
|
pre = "Sec-";
|
||||||
|
handler_msg("using protocol version 76\n");
|
||||||
|
} else {
|
||||||
|
trailer[0] = '\0';
|
||||||
|
pre = "";
|
||||||
|
handler_msg("using protocol version 75\n");
|
||||||
|
}
|
||||||
|
ws_ctx->protocol = base64;
|
||||||
|
if (!get_header_field(handshake, "Origin", &orig, &ol)) return NULL;
|
||||||
|
if (!get_header_field(handshake, "Host", &host, &hl)) return NULL;
|
||||||
|
if (!get_path(handshake, &path, &pl)) return NULL;
|
||||||
|
rlen = sprintf(response, server_handshake_hixie, pre, ol, orig, pre, scheme,
|
||||||
|
hl, host, pl, path, pre, trailer);
|
||||||
|
}
|
||||||
|
printf("\nResponse:\n%s\n--------------------------\n", response);
|
||||||
|
|
||||||
if (headers.key3[0] != '\0') {
|
|
||||||
gen_md5(&headers, trailer);
|
|
||||||
pre = "Sec-";
|
|
||||||
handler_msg("using protocol version 76\n");
|
|
||||||
} else {
|
|
||||||
trailer[0] = '\0';
|
|
||||||
pre = "";
|
|
||||||
handler_msg("using protocol version 75\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(response, server_handshake, pre, headers.origin, pre, scheme,
|
|
||||||
headers.host, headers.path, pre, trailer);
|
|
||||||
//handler_msg("response: %s\n", response);
|
//handler_msg("response: %s\n", response);
|
||||||
ws_send(ws_ctx, response, strlen(response));
|
ws_send(ws_ctx, response, rlen);
|
||||||
|
|
||||||
return ws_ctx;
|
return ws_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_handler(sig) {
|
void signal_handler(sig) {
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case SIGHUP: break; // ignore for now
|
// TODO: Windows equivalents ?
|
||||||
case SIGPIPE: pipe_error = 1; break; // handle inline
|
//case SIGHUP: break; // ignore for now
|
||||||
|
//case SIGPIPE: pipe_error = 1; break; // handle inline
|
||||||
|
//---
|
||||||
case SIGTERM: exit(0); break;
|
case SIGTERM: exit(0); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
|
||||||
void daemonize(int keepfd) {
|
void daemonize(int keepfd) {
|
||||||
int pid, i;
|
int pid, i;
|
||||||
|
|
||||||
|
|
@ -455,11 +500,42 @@ void daemonize(int keepfd) {
|
||||||
dup(i); // Redirect stderr
|
dup(i); // Redirect stderr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // ! _WIN32
|
||||||
|
|
||||||
|
// TODO: move to websockify module ?
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
static DWORD WINAPI proxy_thread( LPVOID lpParameter )
|
||||||
|
{
|
||||||
|
int csock = (int) lpParameter;
|
||||||
|
ws_ctx_t *ws_ctx;
|
||||||
|
|
||||||
|
ws_ctx = do_handshake(csock);
|
||||||
|
if (ws_ctx == NULL) {
|
||||||
|
//handler_msg("No connection after handshake\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
settings.handler(ws_ctx);
|
||||||
|
// TODO: error handling
|
||||||
|
//if (pipe_error) {
|
||||||
|
// handler_emsg("Closing due to SIGPIPE\n");
|
||||||
|
//}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void start_server() {
|
void start_server() {
|
||||||
int lsock, csock, pid, clilen, sopt = 1, i;
|
int lsock, csock, pid, clilen, sopt = 1;
|
||||||
struct sockaddr_in serv_addr, cli_addr;
|
struct sockaddr_in serv_addr, cli_addr;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HANDLE hThread;
|
||||||
|
#else
|
||||||
ws_ctx_t *ws_ctx;
|
ws_ctx_t *ws_ctx;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Initialize buffers */
|
/* Initialize buffers */
|
||||||
bufsize = 65536;
|
bufsize = 65536;
|
||||||
|
|
@ -474,7 +550,7 @@ void start_server() {
|
||||||
|
|
||||||
lsock = socket(AF_INET, SOCK_STREAM, 0);
|
lsock = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (lsock < 0) { error("ERROR creating listener socket"); }
|
if (lsock < 0) { error("ERROR creating listener socket"); }
|
||||||
bzero((char *) &serv_addr, sizeof(serv_addr));
|
memset((char *) &serv_addr, 0, sizeof(serv_addr));
|
||||||
serv_addr.sin_family = AF_INET;
|
serv_addr.sin_family = AF_INET;
|
||||||
serv_addr.sin_port = htons(settings.listen_port);
|
serv_addr.sin_port = htons(settings.listen_port);
|
||||||
|
|
||||||
|
|
@ -489,18 +565,25 @@ void start_server() {
|
||||||
|
|
||||||
setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&sopt, sizeof(sopt));
|
setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&sopt, sizeof(sopt));
|
||||||
if (bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
if (bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
|
||||||
|
int err = WSAGetLastError();
|
||||||
fatal("ERROR on binding listener socket");
|
fatal("ERROR on binding listener socket");
|
||||||
}
|
}
|
||||||
listen(lsock,100);
|
listen(lsock,100);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
signal(SIGPIPE, signal_handler); // catch pipe
|
signal(SIGPIPE, signal_handler); // catch pipe
|
||||||
|
#endif
|
||||||
|
|
||||||
if (settings.daemon) {
|
if (settings.daemon) {
|
||||||
|
#ifndef _WIN32
|
||||||
daemonize(lsock);
|
daemonize(lsock);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
// Reep zombies
|
// Reep zombies
|
||||||
signal(SIGCHLD, SIG_IGN);
|
signal(SIGCHLD, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
printf("Waiting for connections on %s:%d\n",
|
printf("Waiting for connections on %s:%d\n",
|
||||||
settings.listen_host, settings.listen_port);
|
settings.listen_host, settings.listen_port);
|
||||||
|
|
@ -522,6 +605,14 @@ void start_server() {
|
||||||
* 20 for WS '\x00' / '\xff' and good measure */
|
* 20 for WS '\x00' / '\xff' and good measure */
|
||||||
dbufsize = (bufsize * 3)/4 - 20;
|
dbufsize = (bufsize * 3)/4 - 20;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
hThread = CreateThread(NULL, 0, proxy_thread, (LPVOID) csock, 0, NULL );
|
||||||
|
if (hThread == NULL) {
|
||||||
|
error("failed to create proxy thread");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
settings.handler_id += 1;
|
||||||
|
#else
|
||||||
handler_msg("forking handler process\n");
|
handler_msg("forking handler process\n");
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
|
||||||
|
|
@ -540,7 +631,10 @@ void start_server() {
|
||||||
} else { // parent process
|
} else { // parent process
|
||||||
settings.handler_id += 1;
|
settings.handler_id += 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
#else
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
if (ws_ctx) {
|
if (ws_ctx) {
|
||||||
ws_socket_free(ws_ctx);
|
ws_socket_free(ws_ctx);
|
||||||
|
|
@ -550,8 +644,9 @@ void start_server() {
|
||||||
}
|
}
|
||||||
handler_msg("handler exit\n");
|
handler_msg("handler exit\n");
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: can this ever be reached ?
|
||||||
handler_msg("wsproxy exit\n");
|
handler_msg("wsproxy exit\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
typedef enum { binary = 1, base64 } protocol_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
protocol_t protocol;
|
||||||
} ws_ctx_t;
|
} ws_ctx_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -18,15 +21,25 @@ typedef struct {
|
||||||
int daemon;
|
int daemon;
|
||||||
} settings_t;
|
} settings_t;
|
||||||
|
|
||||||
|
/*
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char path[1024+1];
|
char path[1024+1];
|
||||||
char host[1024+1];
|
char host[1024+1];
|
||||||
char origin[1024+1];
|
char origin[1024+1];
|
||||||
|
char protocols[512+1];
|
||||||
|
char key[1024+1];
|
||||||
char key1[1024+1];
|
char key1[1024+1];
|
||||||
char key2[1024+1];
|
char key2[1024+1];
|
||||||
char key3[8+1];
|
char key3[8+1];
|
||||||
|
char version[4+1];
|
||||||
} headers_t;
|
} headers_t;
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 2011-06-01 gygax@practicomp.ch Better way ?
|
||||||
|
#ifndef ssize_t
|
||||||
|
#define ssize_t size_t
|
||||||
|
#endif
|
||||||
|
//---
|
||||||
|
|
||||||
ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len);
|
ssize_t ws_recv(ws_ctx_t *ctx, void *buf, size_t len);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,19 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <realpath.h>
|
||||||
|
#else
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "websocket.h"
|
#include "websocket.h"
|
||||||
|
|
||||||
|
|
@ -39,23 +47,51 @@ char USAGE[] = "Usage: [options] " \
|
||||||
" --key KEY SSL key file (if separate from cert)\n" \
|
" --key KEY SSL key file (if separate from cert)\n" \
|
||||||
" --ssl-only disallow non-encrypted connections";
|
" --ssl-only disallow non-encrypted connections";
|
||||||
|
|
||||||
#define usage(fmt, args...) \
|
#define usage(fmt, ...) \
|
||||||
fprintf(stderr, "%s\n\n", USAGE); \
|
fprintf(stderr, "%s\n\n", USAGE); \
|
||||||
fprintf(stderr, fmt , ## args); \
|
fprintf(stderr, fmt , ## __VA_ARGS__); \
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
char target_host[256];
|
char target_host[256];
|
||||||
int target_port;
|
int target_port;
|
||||||
|
|
||||||
extern pipe_error;
|
extern int pipe_error;
|
||||||
extern settings_t settings;
|
extern settings_t settings;
|
||||||
extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
|
extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp;
|
||||||
extern unsigned int bufsize, dbufsize;
|
extern unsigned int bufsize, dbufsize;
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
|
||||||
|
void dump_buffer( char *buffer, size_t size, const char *title )
|
||||||
|
{
|
||||||
|
char line[4096];
|
||||||
|
unsigned i;
|
||||||
|
int ch;
|
||||||
|
unsigned cu;
|
||||||
|
assert( size < 4096 );
|
||||||
|
for ( i = 0; i < size; i ++ ) {
|
||||||
|
line[i] = buffer[i] >= 32 && buffer[i] <= 126 ? buffer[i] : ' ';
|
||||||
|
}
|
||||||
|
line[i] = 0;
|
||||||
|
printf( "%s, %u bytes: \"%s\"", title, (unsigned) size, line );
|
||||||
|
for ( i = 0; i < size; i ++ ) {
|
||||||
|
if ( i % 8 == 0 ) printf("\n"); else printf(" ");
|
||||||
|
ch = buffer[i];
|
||||||
|
cu = (ch < 0 ? 65536 + ch : *((unsigned*)&ch)) & 0xff;
|
||||||
|
ch = ch >= 32 && ch <= 126 ? ch : ' ';
|
||||||
|
printf( "'%c' ($%2.2x) (%3.3u)", ch, cu, cu );
|
||||||
|
}
|
||||||
|
if ( i % 8 != 0 ) printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define dump_buffer( b, s, t )
|
||||||
|
#endif
|
||||||
|
|
||||||
void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
fd_set rlist, wlist, elist;
|
fd_set rlist, wlist, elist;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int i, maxfd, client = ws_ctx->sockfd;
|
int maxfd, client = ws_ctx->sockfd;
|
||||||
unsigned int tstart, tend, cstart, cend, ret;
|
unsigned int tstart, tend, cstart, cend, ret;
|
||||||
ssize_t len, bytes;
|
ssize_t len, bytes;
|
||||||
|
|
||||||
|
|
@ -110,6 +146,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
|
|
||||||
if (FD_ISSET(target, &wlist)) {
|
if (FD_ISSET(target, &wlist)) {
|
||||||
len = tend-tstart;
|
len = tend-tstart;
|
||||||
|
dump_buffer( tbuf+tstart, len, "Sending to target" );
|
||||||
bytes = send(target, tbuf + tstart, len, 0);
|
bytes = send(target, tbuf + tstart, len, 0);
|
||||||
if (pipe_error) { break; }
|
if (pipe_error) { break; }
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
|
|
@ -128,6 +165,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
|
|
||||||
if (FD_ISSET(client, &wlist)) {
|
if (FD_ISSET(client, &wlist)) {
|
||||||
len = cend-cstart;
|
len = cend-cstart;
|
||||||
|
dump_buffer( cbuf+cstart, len, "Sending to client" );
|
||||||
bytes = ws_send(ws_ctx, cbuf + cstart, len);
|
bytes = ws_send(ws_ctx, cbuf + cstart, len);
|
||||||
if (pipe_error) { break; }
|
if (pipe_error) { break; }
|
||||||
if (len < 3) {
|
if (len < 3) {
|
||||||
|
|
@ -144,9 +182,14 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
|
|
||||||
if (FD_ISSET(target, &rlist)) {
|
if (FD_ISSET(target, &rlist)) {
|
||||||
bytes = recv(target, cbuf_tmp, dbufsize , 0);
|
bytes = recv(target, cbuf_tmp, dbufsize , 0);
|
||||||
|
dump_buffer( cbuf_tmp, bytes, "Received from target" );
|
||||||
if (pipe_error) { break; }
|
if (pipe_error) { break; }
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
handler_emsg("target closed connection\n");
|
if (bytes < 0) {
|
||||||
|
handler_emsg("error receiving from target");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
handler_emsg("target closed connection\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cstart = 0;
|
cstart = 0;
|
||||||
|
|
@ -167,6 +210,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
|
|
||||||
if (FD_ISSET(client, &rlist)) {
|
if (FD_ISSET(client, &rlist)) {
|
||||||
bytes = ws_recv(ws_ctx, tbuf_tmp, bufsize-1);
|
bytes = ws_recv(ws_ctx, tbuf_tmp, bufsize-1);
|
||||||
|
dump_buffer( tbuf_tmp, bytes, "Received from client" );
|
||||||
if (pipe_error) { break; }
|
if (pipe_error) { break; }
|
||||||
if (bytes <= 0) {
|
if (bytes <= 0) {
|
||||||
handler_emsg("client closed connection\n");
|
handler_emsg("client closed connection\n");
|
||||||
|
|
@ -185,6 +229,7 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
*/
|
*/
|
||||||
len = decode(tbuf_tmp, bytes, tbuf, bufsize-1);
|
len = decode(tbuf_tmp, bytes, tbuf, bufsize-1);
|
||||||
|
//if ( len == 1 && tbuf[0] == '\x0a' ) tbuf[0] = '\x0d';
|
||||||
/*
|
/*
|
||||||
printf("decoded: ");
|
printf("decoded: ");
|
||||||
for (i=0; i< len; i++) {
|
for (i=0; i< len; i++) {
|
||||||
|
|
@ -215,7 +260,7 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bzero((char *) &taddr, sizeof(taddr));
|
memset((char *) &taddr, 0, sizeof(taddr));
|
||||||
taddr.sin_family = AF_INET;
|
taddr.sin_family = AF_INET;
|
||||||
taddr.sin_port = htons(target_port);
|
taddr.sin_port = htons(target_port);
|
||||||
|
|
||||||
|
|
@ -228,7 +273,7 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
|
||||||
if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
|
if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) {
|
||||||
handler_emsg("Could not connect to target: %s\n",
|
handler_emsg("Could not connect to target: %s\n",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
close(tsock);
|
_close(tsock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,12 +283,40 @@ void proxy_handler(ws_ctx_t *ws_ctx) {
|
||||||
|
|
||||||
do_proxy(ws_ctx, tsock);
|
do_proxy(ws_ctx, tsock);
|
||||||
|
|
||||||
close(tsock);
|
#ifdef _WIN32
|
||||||
|
closesocket(tsock);
|
||||||
|
#else
|
||||||
|
_close(tsock);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
static int initWinSocks()
|
||||||
|
{
|
||||||
|
WORD wVersionRequested;
|
||||||
|
WSADATA wsaData;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
|
||||||
|
wVersionRequested = MAKEWORD(2, 2);
|
||||||
|
|
||||||
|
err = WSAStartup(wVersionRequested, &wsaData);
|
||||||
|
if (err != 0) {
|
||||||
|
/* Tell the user that we could not find a usable */
|
||||||
|
/* Winsock DLL. */
|
||||||
|
printf("WSAStartup failed with error: %d\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int fd, c, option_index = 0;
|
int c, option_index = 0;
|
||||||
static int ssl_only = 0, daemon = 0, verbose = 0;
|
static int ssl_only = 0, daemon = 0, verbose = 0;
|
||||||
char *found;
|
char *found;
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
|
|
@ -256,7 +329,11 @@ int main(int argc, char *argv[])
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
settings.cert = realpath("self.pem", NULL);
|
#ifdef _WIN32
|
||||||
|
if ( initWinSocks() != 0 ) return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
settings.cert = realpath("self.pem", NULL);
|
||||||
if (!settings.cert) {
|
if (!settings.cert) {
|
||||||
/* Make sure it's always set to something */
|
/* Make sure it's always set to something */
|
||||||
settings.cert = "self.pem";
|
settings.cert = "self.pem";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
* This code originally came from here
|
||||||
|
*
|
||||||
|
* http://base64.sourceforge.net/b64.c
|
||||||
|
*
|
||||||
|
* with the following license:
|
||||||
|
*
|
||||||
|
* LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person
|
||||||
|
* obtaining a copy of this software and associated
|
||||||
|
* documentation files (the "Software"), to deal in the
|
||||||
|
* Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
* sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall
|
||||||
|
* be included in all copies or substantial portions of the
|
||||||
|
* Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||||
|
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
|
||||||
|
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||||
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* VERSION HISTORY:
|
||||||
|
* Bob Trower 08/04/01 -- Create Version 0.00.00B
|
||||||
|
*
|
||||||
|
* I cleaned it up quite a bit to match the (linux kernel) style of the rest
|
||||||
|
* of libwebsockets; this version is under LGPL2 like the rest of libwebsockets
|
||||||
|
* since he explictly allows sublicensing, but I give the URL above so you can
|
||||||
|
* get the original with Bob's super-liberal terms directly if you prefer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
static const char decode[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW"
|
||||||
|
"$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size)
|
||||||
|
{
|
||||||
|
unsigned char triple[3];
|
||||||
|
int i;
|
||||||
|
int len;
|
||||||
|
int line = 0;
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
while (in_len) {
|
||||||
|
len = 0;
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (in_len) {
|
||||||
|
triple[i] = *in++;
|
||||||
|
len++;
|
||||||
|
in_len--;
|
||||||
|
} else
|
||||||
|
triple[i] = 0;
|
||||||
|
}
|
||||||
|
if (len) {
|
||||||
|
|
||||||
|
if (done + 4 >= out_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out++ = encode[triple[0] >> 2];
|
||||||
|
*out++ = encode[((triple[0] & 0x03) << 4) |
|
||||||
|
((triple[1] & 0xf0) >> 4)];
|
||||||
|
*out++ = (len > 1 ? encode[((triple[1] & 0x0f) << 2) |
|
||||||
|
((triple[2] & 0xc0) >> 6)] : '=');
|
||||||
|
*out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
|
||||||
|
|
||||||
|
done += 4;
|
||||||
|
line += 4;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (line >= 72) {
|
||||||
|
|
||||||
|
if (done + 2 >= out_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out++ = '\r';
|
||||||
|
*out++ = '\n';
|
||||||
|
done += 2;
|
||||||
|
line = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done + 1 >= out_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out++ = '\0';
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns length of decoded string in out, or -1 if out was too small
|
||||||
|
* according to out_size
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_b64_decode_string(const char *in, char *out, int out_size)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
int i;
|
||||||
|
int done = 0;
|
||||||
|
unsigned char v;
|
||||||
|
unsigned char quad[4];
|
||||||
|
|
||||||
|
while (*in) {
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
for (i = 0; i < 4 && *in; i++) {
|
||||||
|
|
||||||
|
v = 0;
|
||||||
|
while (*in && !v) {
|
||||||
|
|
||||||
|
v = *in++;
|
||||||
|
v = (v < 43 || v > 122) ? 0 : decode[v - 43];
|
||||||
|
if (v)
|
||||||
|
v = (v == '$') ? 0 : v - 61;
|
||||||
|
if (*in) {
|
||||||
|
len++;
|
||||||
|
if (v)
|
||||||
|
quad[i] = v - 1;
|
||||||
|
} else
|
||||||
|
quad[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!len)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (out_size < (done + len - 1))
|
||||||
|
/* out buffer is too small */
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (len >= 2)
|
||||||
|
*out++ = quad[0] << 2 | quad[1] >> 4;
|
||||||
|
if (len >= 3)
|
||||||
|
*out++ = quad[1] << 4 | quad[2] >> 2;
|
||||||
|
if (len >= 4)
|
||||||
|
*out++ = ((quad[2] << 6) & 0xc0) | quad[3];
|
||||||
|
|
||||||
|
done += len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done + 1 >= out_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*out++ = '\0';
|
||||||
|
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_b64_selftest(void)
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
int n;
|
||||||
|
int test;
|
||||||
|
static const char *plaintext[] = {
|
||||||
|
"sanity check base 64"
|
||||||
|
};
|
||||||
|
static const char *coded[] = {
|
||||||
|
"c2FuaXR5IGNoZWNrIGJhc2UgNjQ="
|
||||||
|
};
|
||||||
|
|
||||||
|
for (test = 0; test < sizeof plaintext / sizeof(plaintext[0]); test++) {
|
||||||
|
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
n = lws_b64_encode_string(plaintext[test],
|
||||||
|
strlen(plaintext[test]), buf, sizeof buf);
|
||||||
|
if (n != strlen(coded[test]) || strcmp(buf, coded[test])) {
|
||||||
|
fprintf(stderr, "Failed lws_b64 encode selftest "
|
||||||
|
"%d result '%s' %d\n", test, buf, n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
n = lws_b64_decode_string(coded[test], buf, sizeof buf);
|
||||||
|
if (n != strlen(plaintext[test]) ||
|
||||||
|
strcmp(buf, plaintext[test])) {
|
||||||
|
fprintf(stderr, "Failed lws_b64 decode selftest "
|
||||||
|
"%d result '%s' %d\n", test, buf, n);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef __BASE64_DECODE_H
|
||||||
|
#define __BASE64_DECODE_H
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_b64_encode_string(const char *in, int in_len, char *out, int out_size);
|
||||||
|
|
||||||
|
int
|
||||||
|
lws_b64_decode_string(const char *in, char *out, int out_size);
|
||||||
|
|
||||||
|
#endif // __BASE64_DECODE_H
|
||||||
|
|
@ -0,0 +1,326 @@
|
||||||
|
/* $NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1996 by Internet Software Consortium.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||||
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||||
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||||
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||||
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Portions Copyright (c) 1995 by International Business Machines, Inc.
|
||||||
|
*
|
||||||
|
* International Business Machines, Inc. (hereinafter called IBM) grants
|
||||||
|
* permission under its copyrights to use, copy, modify, and distribute this
|
||||||
|
* Software with or without fee, provided that the above copyright notice and
|
||||||
|
* all paragraphs of this notice appear in all copies, and that the name of IBM
|
||||||
|
* not be used in connection with the marketing of any product incorporating
|
||||||
|
* the Software or modifications thereof, without specific, written prior
|
||||||
|
* permission.
|
||||||
|
*
|
||||||
|
* To the extent it has a right to do so, IBM grants an immunity from suit
|
||||||
|
* under its patents, if any, for the use, sale or manufacture of products to
|
||||||
|
* the extent that such products are used for performing Domain Name System
|
||||||
|
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
|
||||||
|
* granted for any product per se or for any other function of any product.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
|
||||||
|
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
|
||||||
|
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
typedef unsigned long u_int32_t;
|
||||||
|
|
||||||
|
static const char Base64[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
static const char Pad64 = '=';
|
||||||
|
|
||||||
|
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||||
|
The following encoding technique is taken from RFC 1521 by Borenstein
|
||||||
|
and Freed. It is reproduced here in a slightly edited form for
|
||||||
|
convenience.
|
||||||
|
|
||||||
|
A 65-character subset of US-ASCII is used, enabling 6 bits to be
|
||||||
|
represented per printable character. (The extra 65th character, "=",
|
||||||
|
is used to signify a special processing function.)
|
||||||
|
|
||||||
|
The encoding process represents 24-bit groups of input bits as output
|
||||||
|
strings of 4 encoded characters. Proceeding from left to right, a
|
||||||
|
24-bit input group is formed by concatenating 3 8-bit input groups.
|
||||||
|
These 24 bits are then treated as 4 concatenated 6-bit groups, each
|
||||||
|
of which is translated into a single digit in the base64 alphabet.
|
||||||
|
|
||||||
|
Each 6-bit group is used as an index into an array of 64 printable
|
||||||
|
characters. The character referenced by the index is placed in the
|
||||||
|
output string.
|
||||||
|
|
||||||
|
Table 1: The Base64 Alphabet
|
||||||
|
|
||||||
|
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||||
|
0 A 17 R 34 i 51 z
|
||||||
|
1 B 18 S 35 j 52 0
|
||||||
|
2 C 19 T 36 k 53 1
|
||||||
|
3 D 20 U 37 l 54 2
|
||||||
|
4 E 21 V 38 m 55 3
|
||||||
|
5 F 22 W 39 n 56 4
|
||||||
|
6 G 23 X 40 o 57 5
|
||||||
|
7 H 24 Y 41 p 58 6
|
||||||
|
8 I 25 Z 42 q 59 7
|
||||||
|
9 J 26 a 43 r 60 8
|
||||||
|
10 K 27 b 44 s 61 9
|
||||||
|
11 L 28 c 45 t 62 +
|
||||||
|
12 M 29 d 46 u 63 /
|
||||||
|
13 N 30 e 47 v
|
||||||
|
14 O 31 f 48 w (pad) =
|
||||||
|
15 P 32 g 49 x
|
||||||
|
16 Q 33 h 50 y
|
||||||
|
|
||||||
|
Special processing is performed if fewer than 24 bits are available
|
||||||
|
at the end of the data being encoded. A full encoding quantum is
|
||||||
|
always completed at the end of a quantity. When fewer than 24 input
|
||||||
|
bits are available in an input group, zero bits are added (on the
|
||||||
|
right) to form an integral number of 6-bit groups. Padding at the
|
||||||
|
end of the data is performed using the '=' character.
|
||||||
|
|
||||||
|
Since all base64 input is an integral number of octets, only the
|
||||||
|
-------------------------------------------------
|
||||||
|
following cases can arise:
|
||||||
|
|
||||||
|
(1) the final quantum of encoding input is an integral
|
||||||
|
multiple of 24 bits; here, the final unit of encoded
|
||||||
|
output will be an integral multiple of 4 characters
|
||||||
|
with no "=" padding,
|
||||||
|
(2) the final quantum of encoding input is exactly 8 bits;
|
||||||
|
here, the final unit of encoded output will be two
|
||||||
|
characters followed by two "=" padding characters, or
|
||||||
|
(3) the final quantum of encoding input is exactly 16 bits;
|
||||||
|
here, the final unit of encoded output will be three
|
||||||
|
characters followed by one "=" padding character.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
b64_ntop(src, srclength, target, targsize)
|
||||||
|
u_char const *src;
|
||||||
|
size_t srclength;
|
||||||
|
char *target;
|
||||||
|
size_t targsize;
|
||||||
|
{
|
||||||
|
size_t datalength = 0;
|
||||||
|
u_char input[3];
|
||||||
|
u_char output[4];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
assert(src != NULL);
|
||||||
|
assert(target != NULL);
|
||||||
|
|
||||||
|
while (2 < srclength) {
|
||||||
|
input[0] = *src++;
|
||||||
|
input[1] = *src++;
|
||||||
|
input[2] = *src++;
|
||||||
|
srclength -= 3;
|
||||||
|
|
||||||
|
output[0] = (u_int32_t)input[0] >> 2;
|
||||||
|
output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
|
||||||
|
((u_int32_t)input[1] >> 4);
|
||||||
|
output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
|
||||||
|
((u_int32_t)input[2] >> 6);
|
||||||
|
output[3] = input[2] & 0x3f;
|
||||||
|
assert(output[0] < 64);
|
||||||
|
assert(output[1] < 64);
|
||||||
|
assert(output[2] < 64);
|
||||||
|
assert(output[3] < 64);
|
||||||
|
|
||||||
|
if (datalength + 4 > targsize)
|
||||||
|
return (-1);
|
||||||
|
target[datalength++] = Base64[output[0]];
|
||||||
|
target[datalength++] = Base64[output[1]];
|
||||||
|
target[datalength++] = Base64[output[2]];
|
||||||
|
target[datalength++] = Base64[output[3]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now we worry about padding. */
|
||||||
|
if (0 != srclength) {
|
||||||
|
/* Get what's left. */
|
||||||
|
input[0] = input[1] = input[2] = '\0';
|
||||||
|
for (i = 0; i < srclength; i++)
|
||||||
|
input[i] = *src++;
|
||||||
|
|
||||||
|
output[0] = (u_int32_t)input[0] >> 2;
|
||||||
|
output[1] = ((u_int32_t)(input[0] & 0x03) << 4) +
|
||||||
|
((u_int32_t)input[1] >> 4);
|
||||||
|
output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) +
|
||||||
|
((u_int32_t)input[2] >> 6);
|
||||||
|
assert(output[0] < 64);
|
||||||
|
assert(output[1] < 64);
|
||||||
|
assert(output[2] < 64);
|
||||||
|
|
||||||
|
if (datalength + 4 > targsize)
|
||||||
|
return (-1);
|
||||||
|
target[datalength++] = Base64[output[0]];
|
||||||
|
target[datalength++] = Base64[output[1]];
|
||||||
|
if (srclength == 1)
|
||||||
|
target[datalength++] = Pad64;
|
||||||
|
else
|
||||||
|
target[datalength++] = Base64[output[2]];
|
||||||
|
target[datalength++] = Pad64;
|
||||||
|
}
|
||||||
|
if (datalength >= targsize)
|
||||||
|
return (-1);
|
||||||
|
target[datalength] = '\0'; /* Returned value doesn't count \0. */
|
||||||
|
return (datalength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skips all whitespace anywhere.
|
||||||
|
converts characters, four at a time, starting at (or after)
|
||||||
|
src from base - 64 numbers into three 8 bit bytes in the target area.
|
||||||
|
it returns the number of data bytes stored at the target, or -1 on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
b64_pton(src, target, targsize)
|
||||||
|
char const *src;
|
||||||
|
u_char *target;
|
||||||
|
size_t targsize;
|
||||||
|
{
|
||||||
|
size_t tarindex;
|
||||||
|
int state, ch;
|
||||||
|
char *pos;
|
||||||
|
|
||||||
|
assert(src != NULL);
|
||||||
|
assert(target != NULL);
|
||||||
|
|
||||||
|
state = 0;
|
||||||
|
tarindex = 0;
|
||||||
|
|
||||||
|
while ((ch = (u_char) *src++) != '\0') {
|
||||||
|
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ch == Pad64)
|
||||||
|
break;
|
||||||
|
|
||||||
|
pos = strchr(Base64, ch);
|
||||||
|
if (pos == 0) /* A non-base64 character. */
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case 0:
|
||||||
|
if (target) {
|
||||||
|
if (tarindex >= targsize)
|
||||||
|
return (-1);
|
||||||
|
target[tarindex] = (pos - Base64) << 2;
|
||||||
|
}
|
||||||
|
state = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (target) {
|
||||||
|
if (tarindex + 1 >= targsize)
|
||||||
|
return (-1);
|
||||||
|
target[tarindex] |=
|
||||||
|
(u_int32_t)(pos - Base64) >> 4;
|
||||||
|
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||||
|
<< 4 ;
|
||||||
|
}
|
||||||
|
tarindex++;
|
||||||
|
state = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (target) {
|
||||||
|
if (tarindex + 1 >= targsize)
|
||||||
|
return (-1);
|
||||||
|
target[tarindex] |=
|
||||||
|
(u_int32_t)(pos - Base64) >> 2;
|
||||||
|
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||||
|
<< 6;
|
||||||
|
}
|
||||||
|
tarindex++;
|
||||||
|
state = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (target) {
|
||||||
|
if (tarindex >= targsize)
|
||||||
|
return (-1);
|
||||||
|
target[tarindex] |= (pos - Base64);
|
||||||
|
}
|
||||||
|
tarindex++;
|
||||||
|
state = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are done decoding Base-64 chars. Let's see if we ended
|
||||||
|
* on a byte boundary, and/or with erroneous trailing characters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ch == Pad64) { /* We got a pad char. */
|
||||||
|
ch = *src++; /* Skip it, get next. */
|
||||||
|
switch (state) {
|
||||||
|
case 0: /* Invalid = in first position */
|
||||||
|
case 1: /* Invalid = in second position */
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
case 2: /* Valid, means one byte of info */
|
||||||
|
/* Skip any number of spaces. */
|
||||||
|
for (; ch != '\0'; ch = (u_char) *src++)
|
||||||
|
if (!isspace(ch))
|
||||||
|
break;
|
||||||
|
/* Make sure there is another trailing = sign. */
|
||||||
|
if (ch != Pad64)
|
||||||
|
return (-1);
|
||||||
|
ch = *src++; /* Skip the = */
|
||||||
|
/* Fall through to "single trailing =" case. */
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
|
||||||
|
case 3: /* Valid, means two bytes of info */
|
||||||
|
/*
|
||||||
|
* We know this char is an =. Is there anything but
|
||||||
|
* whitespace after it?
|
||||||
|
*/
|
||||||
|
for (; ch != '\0'; ch = (u_char) *src++)
|
||||||
|
if (!isspace(ch))
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now make sure for cases 2 and 3 that the "extra"
|
||||||
|
* bits that slopped past the last full byte were
|
||||||
|
* zeros. If we don't check them, they become a
|
||||||
|
* subliminal channel.
|
||||||
|
*/
|
||||||
|
if (target && target[tarindex] != 0)
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* We ended by seeing the end of the string. Make sure we
|
||||||
|
* have no partial bytes lying around.
|
||||||
|
*/
|
||||||
|
if (state != 0)
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tarindex);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/* $NetBSD: getopt.c,v 1.16 1999/12/02 13:15:56 kleink Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1987, 1993, 1994
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define __P(x) x
|
||||||
|
#define _DIAGASSERT(x) assert(x)
|
||||||
|
|
||||||
|
#ifdef __weak_alias
|
||||||
|
__weak_alias(getopt,_getopt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int opterr = 1, /* if error message should be printed */
|
||||||
|
optind = 1, /* index into parent argv vector */
|
||||||
|
optopt, /* character checked for validity */
|
||||||
|
optreset; /* reset getopt */
|
||||||
|
char *optarg; /* argument associated with option */
|
||||||
|
|
||||||
|
static char * _progname __P((char *));
|
||||||
|
int getopt_internal __P((int, char * const *, const char *));
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_progname(nargv0)
|
||||||
|
char * nargv0;
|
||||||
|
{
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
|
_DIAGASSERT(nargv0 != NULL);
|
||||||
|
|
||||||
|
tmp = strrchr(nargv0, '/');
|
||||||
|
if (tmp)
|
||||||
|
tmp++;
|
||||||
|
else
|
||||||
|
tmp = nargv0;
|
||||||
|
return(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BADCH (int)'?'
|
||||||
|
#define BADARG (int)':'
|
||||||
|
#define EMSG ""
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt(nargc, nargv, ostr)
|
||||||
|
int nargc;
|
||||||
|
char * const nargv[];
|
||||||
|
const char *ostr;
|
||||||
|
{
|
||||||
|
static char *__progname = 0;
|
||||||
|
static char *place = EMSG; /* option letter processing */
|
||||||
|
char *oli; /* option letter list index */
|
||||||
|
__progname = __progname?__progname:_progname(*nargv);
|
||||||
|
|
||||||
|
_DIAGASSERT(nargv != NULL);
|
||||||
|
_DIAGASSERT(ostr != NULL);
|
||||||
|
|
||||||
|
if (optreset || !*place) { /* update scanning pointer */
|
||||||
|
optreset = 0;
|
||||||
|
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||||
|
place = EMSG;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (place[1] && *++place == '-' /* found "--" */
|
||||||
|
&& place[1] == '\0') {
|
||||||
|
++optind;
|
||||||
|
place = EMSG;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
} /* option letter okay? */
|
||||||
|
if ((optopt = (int)*place++) == (int)':' ||
|
||||||
|
!(oli = strchr(ostr, optopt))) {
|
||||||
|
/*
|
||||||
|
* if the user didn't specify '-' as an option,
|
||||||
|
* assume it means -1.
|
||||||
|
*/
|
||||||
|
if (optopt == (int)'-')
|
||||||
|
return (-1);
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
if (opterr && *ostr != ':')
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: illegal option -- %c\n", __progname, optopt);
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (*++oli != ':') { /* don't need argument */
|
||||||
|
optarg = NULL;
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
else { /* need an argument */
|
||||||
|
if (*place) /* no white space */
|
||||||
|
optarg = place;
|
||||||
|
else if (nargc <= ++optind) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if (*ostr == ':')
|
||||||
|
return (BADARG);
|
||||||
|
if (opterr)
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: option requires an argument -- %c\n",
|
||||||
|
__progname, optopt);
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
else /* white space */
|
||||||
|
optarg = nargv[optind];
|
||||||
|
place = EMSG;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
return (optopt); /* dump back option letter */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef __GETOPT_H__
|
||||||
|
#define __GETOPT_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int opterr; /* if error message should be printed */
|
||||||
|
extern int optind; /* index into parent argv vector */
|
||||||
|
extern int optopt; /* character checked for validity */
|
||||||
|
extern int optreset; /* reset getopt */
|
||||||
|
extern char *optarg; /* argument associated with option */
|
||||||
|
|
||||||
|
struct option
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
int has_arg;
|
||||||
|
int *flag;
|
||||||
|
int val;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define no_argument 0
|
||||||
|
#define required_argument 1
|
||||||
|
#define optional_argument 2
|
||||||
|
|
||||||
|
int getopt(int, char**, char*);
|
||||||
|
int getopt_long(int, char**, char*, struct option*, int*);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __GETOPT_H__ */
|
||||||
|
|
@ -0,0 +1,237 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1987, 1993, 1994, 1996
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "getopt.h"
|
||||||
|
|
||||||
|
extern int opterr; /* if error message should be printed */
|
||||||
|
extern int optind; /* index into parent argv vector */
|
||||||
|
extern int optopt; /* character checked for validity */
|
||||||
|
extern int optreset; /* reset getopt */
|
||||||
|
extern char *optarg; /* argument associated with option */
|
||||||
|
|
||||||
|
#define __P(x) x
|
||||||
|
#define _DIAGASSERT(x) assert(x)
|
||||||
|
|
||||||
|
static char * __progname __P((char *));
|
||||||
|
int getopt_internal __P((int, char * const *, const char *));
|
||||||
|
|
||||||
|
static char *
|
||||||
|
__progname(nargv0)
|
||||||
|
char * nargv0;
|
||||||
|
{
|
||||||
|
char * tmp;
|
||||||
|
|
||||||
|
_DIAGASSERT(nargv0 != NULL);
|
||||||
|
|
||||||
|
tmp = strrchr(nargv0, '/');
|
||||||
|
if (tmp)
|
||||||
|
tmp++;
|
||||||
|
else
|
||||||
|
tmp = nargv0;
|
||||||
|
return(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BADCH (int)'?'
|
||||||
|
#define BADARG (int)':'
|
||||||
|
#define EMSG ""
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_internal(nargc, nargv, ostr)
|
||||||
|
int nargc;
|
||||||
|
char * const *nargv;
|
||||||
|
const char *ostr;
|
||||||
|
{
|
||||||
|
static char *place = EMSG; /* option letter processing */
|
||||||
|
char *oli; /* option letter list index */
|
||||||
|
|
||||||
|
_DIAGASSERT(nargv != NULL);
|
||||||
|
_DIAGASSERT(ostr != NULL);
|
||||||
|
|
||||||
|
if (optreset || !*place) { /* update scanning pointer */
|
||||||
|
optreset = 0;
|
||||||
|
if (optind >= nargc || *(place = nargv[optind]) != '-') {
|
||||||
|
place = EMSG;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (place[1] && *++place == '-') { /* found "--" */
|
||||||
|
/* ++optind; */
|
||||||
|
place = EMSG;
|
||||||
|
return (-2);
|
||||||
|
}
|
||||||
|
} /* option letter okay? */
|
||||||
|
if ((optopt = (int)*place++) == (int)':' ||
|
||||||
|
!(oli = strchr(ostr, optopt))) {
|
||||||
|
/*
|
||||||
|
* if the user didn't specify '-' as an option,
|
||||||
|
* assume it means -1.
|
||||||
|
*/
|
||||||
|
if (optopt == (int)'-')
|
||||||
|
return (-1);
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
if (opterr && *ostr != ':')
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (*++oli != ':') { /* don't need argument */
|
||||||
|
optarg = NULL;
|
||||||
|
if (!*place)
|
||||||
|
++optind;
|
||||||
|
} else { /* need an argument */
|
||||||
|
if (*place) /* no white space */
|
||||||
|
optarg = place;
|
||||||
|
else if (nargc <= ++optind) { /* no arg */
|
||||||
|
place = EMSG;
|
||||||
|
if ((opterr) && (*ostr != ':'))
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: option requires an argument -- %c\n",
|
||||||
|
__progname(nargv[0]), optopt);
|
||||||
|
return (BADARG);
|
||||||
|
} else /* white space */
|
||||||
|
optarg = nargv[optind];
|
||||||
|
place = EMSG;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
return (optopt); /* dump back option letter */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* getopt --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt2(nargc, nargv, ostr)
|
||||||
|
int nargc;
|
||||||
|
char * const *nargv;
|
||||||
|
const char *ostr;
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
|
||||||
|
retval = -1;
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
return(retval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getopt_long --
|
||||||
|
* Parse argc/argv argument vector.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
getopt_long(nargc, nargv, options, long_options, index)
|
||||||
|
int nargc;
|
||||||
|
char ** nargv;
|
||||||
|
char * options;
|
||||||
|
struct option * long_options;
|
||||||
|
int * index;
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
_DIAGASSERT(nargv != NULL);
|
||||||
|
_DIAGASSERT(options != NULL);
|
||||||
|
_DIAGASSERT(long_options != NULL);
|
||||||
|
/* index may be NULL */
|
||||||
|
|
||||||
|
if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
|
||||||
|
char *current_argv = nargv[optind++] + 2, *has_equal;
|
||||||
|
int i, current_argv_len, match = -1;
|
||||||
|
|
||||||
|
if (*current_argv == '\0') {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||||
|
current_argv_len = has_equal - current_argv;
|
||||||
|
has_equal++;
|
||||||
|
} else
|
||||||
|
current_argv_len = strlen(current_argv);
|
||||||
|
|
||||||
|
for (i = 0; long_options[i].name; i++) {
|
||||||
|
if (strncmp(current_argv, long_options[i].name, current_argv_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strlen(long_options[i].name) == (unsigned)current_argv_len) {
|
||||||
|
match = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (match == -1)
|
||||||
|
match = i;
|
||||||
|
}
|
||||||
|
if (match != -1) {
|
||||||
|
if (long_options[match].has_arg == required_argument ||
|
||||||
|
long_options[match].has_arg == optional_argument) {
|
||||||
|
if (has_equal)
|
||||||
|
optarg = has_equal;
|
||||||
|
else
|
||||||
|
optarg = nargv[optind++];
|
||||||
|
}
|
||||||
|
if ((long_options[match].has_arg == required_argument)
|
||||||
|
&& (optarg == NULL)) {
|
||||||
|
/*
|
||||||
|
* Missing argument, leading :
|
||||||
|
* indicates no error should be generated
|
||||||
|
*/
|
||||||
|
if ((opterr) && (*options != ':'))
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: option requires an argument -- %s\n",
|
||||||
|
__progname(nargv[0]), current_argv);
|
||||||
|
return (BADARG);
|
||||||
|
}
|
||||||
|
} else { /* No matching argument */
|
||||||
|
if ((opterr) && (*options != ':'))
|
||||||
|
(void)fprintf(stderr,
|
||||||
|
"%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
|
||||||
|
return (BADCH);
|
||||||
|
}
|
||||||
|
if (long_options[match].flag) {
|
||||||
|
*long_options[match].flag = long_options[match].val;
|
||||||
|
retval = 0;
|
||||||
|
} else
|
||||||
|
retval = long_options[match].val;
|
||||||
|
if (index)
|
||||||
|
*index = match;
|
||||||
|
}
|
||||||
|
return(retval);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef __OSISOCK_H
|
||||||
|
#define __OSISOCK_H
|
||||||
|
|
||||||
|
#ifndef SHUT_RD
|
||||||
|
# define SHUT_RD SD_RECEIVE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SHUT_WR
|
||||||
|
# define SHUT_WR SD_SEND
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SHUT_RDWR
|
||||||
|
# define SHUT_RDWR SD_BOTH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // __OSISOCK_H
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "realpath.h"
|
||||||
|
|
||||||
|
char * realpath( const char * path, char * buffer )
|
||||||
|
{
|
||||||
|
char tmp[FILENAME_MAX];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = GetFullPathNameA( path, FILENAME_MAX, tmp, NULL );
|
||||||
|
if ( len >= 0 )
|
||||||
|
{
|
||||||
|
if ( buffer == NULL ) buffer = malloc(len+1);
|
||||||
|
strcpy_s( buffer, len + 1, tmp );
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
else return NULL;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __REALPATH_H
|
||||||
|
#define __REALPATH_H
|
||||||
|
|
||||||
|
extern char * realpath( const char * path, char * buffer );
|
||||||
|
|
||||||
|
#endif // __REALPATH_H
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef _UNISTD_H
|
||||||
|
#define _UNISTD_H 1
|
||||||
|
|
||||||
|
/* This file intended to serve as a drop-in replacement for
|
||||||
|
* unistd.h on Windows
|
||||||
|
* Please add functionality as neeeded
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <getopt.h> /* getopt from: http://www.pwilson.net/sample.html. */
|
||||||
|
|
||||||
|
#define srandom srand
|
||||||
|
#define random rand
|
||||||
|
|
||||||
|
#define W_OK (2)
|
||||||
|
#define R_OK (4)
|
||||||
|
|
||||||
|
#define access _access
|
||||||
|
#define ftruncate _chsize
|
||||||
|
|
||||||
|
#define ssize_t int
|
||||||
|
|
||||||
|
#define STDIN_FILENO 0
|
||||||
|
#define STDOUT_FILENO 1
|
||||||
|
#define STDERR_FILENO 2
|
||||||
|
|
||||||
|
#endif /* unistd.h */
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
Library requirements:
|
||||||
|
====================
|
||||||
|
|
||||||
|
OpenSSL 1.0.0. Do not forget to add to "VC++ Directories". Procedures vary depending on version Visual Studio.
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual C++ Express 2010
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ws_vc2010", "ws_vc2010.vcxproj", "{053A90E9-3827-49BA-9B59-C6772FD6F5C5}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{053A90E9-3827-49BA-9B59-C6772FD6F5C5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{053A90E9-3827-49BA-9B59-C6772FD6F5C5}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{053A90E9-3827-49BA-9B59-C6772FD6F5C5}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{053A90E9-3827-49BA-9B59-C6772FD6F5C5}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{053A90E9-3827-49BA-9B59-C6772FD6F5C5}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>ws_vc2010</RootNamespace>
|
||||||
|
<ProjectName>websockify</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>STDC_HEADERS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\other\win32\</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>Ws2_32.lib;ssleay32MTd.lib;libeay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>STDC_HEADERS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>$(SolutionDir)..\other\win32\</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>Ws2_32.lib;ssleay32MT.lib;libeay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\other\md5.c" />
|
||||||
|
<ClCompile Include="..\other\sha-1.c" />
|
||||||
|
<ClCompile Include="..\other\websocket.c" />
|
||||||
|
<ClCompile Include="..\other\websockify.c" />
|
||||||
|
<ClCompile Include="..\other\win32\base64.c" />
|
||||||
|
<ClCompile Include="..\other\win32\getopt.c" />
|
||||||
|
<ClCompile Include="..\other\win32\getopt_long.c" />
|
||||||
|
<ClCompile Include="..\other\win32\realpath.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\other\md5.h" />
|
||||||
|
<ClInclude Include="..\other\websocket.h" />
|
||||||
|
<ClInclude Include="..\other\win32\getopt.h" />
|
||||||
|
<ClInclude Include="..\other\win32\realpath.h" />
|
||||||
|
<ClInclude Include="..\other\win32\unistd.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\other\websocket.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\websockify.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\win32\getopt.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\win32\getopt_long.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\md5.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\win32\realpath.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\win32\base64.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\other\sha-1.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\other\md5.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\other\websocket.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\other\win32\getopt.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\other\win32\unistd.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\other\win32\realpath.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue