diff --git a/.gitignore b/.gitignore index 1a9d961..dfde534 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ *.pyc *.o *.so +ws_vc2010/Debug/ +ws_vc2010/Release/ +*.user +*.opensdf +*.sdf +*.ipch \ No newline at end of file diff --git a/other/md5.h b/other/md5.h index b48545b..333f170 100644 --- a/other/md5.h +++ b/other/md5.h @@ -88,9 +88,17 @@ struct md5_ctx md5_uint32 total[2]; md5_uint32 buflen; +#ifdef _WIN32 + char buffer[128]; +#else 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 functions `md5_stream' and `md5_buffer'. diff --git a/other/websocket.c b/other/websocket.c index dc2e841..ba7942d 100644 --- a/other/websocket.c +++ b/other/websocket.c @@ -11,17 +11,28 @@ #include #include #include -#include #include +#ifdef _WIN32 +#include +#include +#include +#include +#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 #include #include #include #include +#include /* base64 encode/decode */ +#endif #include // daemonizing #include // daemonizing #include #include -#include /* base64 encode/decode */ +#include "md5.h" #include "websocket.h" const char server_handshake[] = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\ @@ -29,7 +40,7 @@ Upgrade: WebSocket\r\n\ Connection: Upgrade\r\n\ %sWebSocket-Origin: %s\r\n\ %sWebSocket-Location: %s://%s%s\r\n\ -%sWebSocket-Protocol: sample\r\n\ +%sWebSocket-Protocol: base64\r\n\ \r\n%s"; const char policy_response[] = "\n"; @@ -66,7 +77,7 @@ void fatal(char *msg) /* resolve host with also IP address parsing */ 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 hints; memset(&hints, 0, sizeof(hints)); @@ -178,7 +189,7 @@ ws_ctx_t *ws_socket_ssl(int socket, char * certfile, char * keyfile) { return ctx; } -int ws_socket_free(ws_ctx_t *ctx) { +void ws_socket_free(ws_ctx_t *ctx) { if (ctx->ssl) { SSL_free(ctx->ssl); ctx->ssl = NULL; @@ -199,8 +210,7 @@ int ws_socket_free(ws_ctx_t *ctx) { int encode(u_char const *src, size_t srclength, char *target, size_t targsize) { - int i, sz = 0, len = 0; - unsigned char chr; + int sz = 0, len = 0; target[sz++] = '\x00'; len = b64_ntop(src, srclength, target+sz, targsize-sz); if (len < 0) { @@ -213,8 +223,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) { char *start, *end, cntstr[4]; - int i, len, framecount = 0, retlen = 0; - unsigned char chr; + int len, framecount = 0, retlen = 0; if ((src[0] != '\x00') || (src[srclength-1] != '\xff')) { handler_emsg("WebSocket framing error\n"); return -1; @@ -242,7 +251,7 @@ int decode(char *src, size_t srclength, u_char *target, size_t targsize) { int parse_handshake(char *handshake, headers_t *headers) { char *start, *end; - if ((strlen(handshake) < 92) || (bcmp(handshake, "GET ", 4) != 0)) { + if ((strlen(handshake) < 92) || (memcmp(handshake, "GET ", 4) != 0)) { return 0; } start = handshake+4; @@ -344,7 +353,7 @@ ws_ctx_t *do_handshake(int sock) { char handshake[4096], response[4096], trailer[17]; char *scheme, *pre; headers_t headers; - int len, ret; + int len; ws_ctx_t * ws_ctx; // Peek, but don't read the data @@ -353,14 +362,13 @@ ws_ctx_t *do_handshake(int sock) { if (len == 0) { handler_msg("ignoring empty handshake\n"); return NULL; - } else if (bcmp(handshake, "", 22) == 0) { + } else if (memcmp(handshake, "", 22) == 0) { len = recv(sock, handshake, 1024, 0); handshake[len] = 0; handler_msg("sending flash policy response\n"); send(sock, policy_response, sizeof(policy_response), 0); return NULL; - } else if ((bcmp(handshake, "\x16", 1) == 0) || - (bcmp(handshake, "\x80", 1) == 0)) { + } else if (handshake[0] == '\x16' || handshake[0] == '\x80') { // SSL if (!settings.cert) { handler_msg("SSL connection but no cert specified\n"); @@ -415,12 +423,16 @@ ws_ctx_t *do_handshake(int sock) { void signal_handler(sig) { switch (sig) { - case SIGHUP: break; // ignore for now - case SIGPIPE: pipe_error = 1; break; // handle inline + // TODO: Windows equivalents ? + //case SIGHUP: break; // ignore for now + //case SIGPIPE: pipe_error = 1; break; // handle inline + //--- case SIGTERM: exit(0); break; } } +#ifndef _WIN32 + void daemonize(int keepfd) { int pid, i; @@ -455,11 +467,42 @@ void daemonize(int keepfd) { 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() { - int lsock, csock, pid, clilen, sopt = 1, i; + int lsock, csock, pid, clilen, sopt = 1; struct sockaddr_in serv_addr, cli_addr; +#ifdef _WIN32 + HANDLE hThread; +#else ws_ctx_t *ws_ctx; +#endif /* Initialize buffers */ bufsize = 65536; @@ -474,7 +517,7 @@ void start_server() { lsock = socket(AF_INET, SOCK_STREAM, 0); 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_port = htons(settings.listen_port); @@ -489,18 +532,25 @@ void start_server() { setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, (char *)&sopt, sizeof(sopt)); if (bind(lsock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + int err = WSAGetLastError(); fatal("ERROR on binding listener socket"); } listen(lsock,100); +#ifndef _WIN32 signal(SIGPIPE, signal_handler); // catch pipe +#endif if (settings.daemon) { +#ifndef _WIN32 daemonize(lsock); +#endif } +#ifndef _WIN32 // Reep zombies signal(SIGCHLD, SIG_IGN); +#endif printf("Waiting for connections on %s:%d\n", settings.listen_host, settings.listen_port); @@ -522,6 +572,14 @@ void start_server() { * 20 for WS '\x00' / '\xff' and good measure */ 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"); pid = fork(); @@ -540,7 +598,10 @@ void start_server() { } else { // parent process settings.handler_id += 1; } +#endif } +#ifdef _WIN32 +#else if (pid == 0) { if (ws_ctx) { ws_socket_free(ws_ctx); @@ -550,8 +611,9 @@ void start_server() { } handler_msg("handler exit\n"); } else { + // TODO: can this ever be reached ? handler_msg("wsproxy exit\n"); } - +#endif } diff --git a/other/websocket.h b/other/websocket.h index c428fa5..62c0e43 100644 --- a/other/websocket.h +++ b/other/websocket.h @@ -27,6 +27,11 @@ typedef struct { char key3[8+1]; } 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); diff --git a/other/websockify.c b/other/websockify.c index 42bb45e..5b2bef5 100644 --- a/other/websockify.c +++ b/other/websockify.c @@ -11,11 +11,17 @@ #include #include #include +#include +#ifdef WIN32 +#include +#include +#else #include #include #include #include #include +#endif #include #include "websocket.h" @@ -39,15 +45,15 @@ char USAGE[] = "Usage: [options] " \ " --key KEY SSL key file (if separate from cert)\n" \ " --ssl-only disallow non-encrypted connections"; -#define usage(fmt, args...) \ +#define usage(fmt, ...) \ fprintf(stderr, "%s\n\n", USAGE); \ - fprintf(stderr, fmt , ## args); \ + fprintf(stderr, fmt , ## __VA_ARGS__); \ exit(1); char target_host[256]; int target_port; -extern pipe_error; +extern int pipe_error; extern settings_t settings; extern char *tbuf, *cbuf, *tbuf_tmp, *cbuf_tmp; extern unsigned int bufsize, dbufsize; @@ -55,7 +61,7 @@ extern unsigned int bufsize, dbufsize; void do_proxy(ws_ctx_t *ws_ctx, int target) { fd_set rlist, wlist, elist; struct timeval tv; - int i, maxfd, client = ws_ctx->sockfd; + int maxfd, client = ws_ctx->sockfd; unsigned int tstart, tend, cstart, cend, ret; ssize_t len, bytes; @@ -146,7 +152,12 @@ void do_proxy(ws_ctx_t *ws_ctx, int target) { bytes = recv(target, cbuf_tmp, dbufsize , 0); if (pipe_error) { break; } if (bytes <= 0) { - handler_emsg("target closed connection\n"); + if (bytes < 0) { + int err = WSAGetLastError(); + handler_emsg("error receiving from target"); + } + else + handler_emsg("target closed connection\n"); break; } cstart = 0; @@ -215,7 +226,7 @@ void proxy_handler(ws_ctx_t *ws_ctx) { strerror(errno)); return; } - bzero((char *) &taddr, sizeof(taddr)); + memset((char *) &taddr, 0, sizeof(taddr)); taddr.sin_family = AF_INET; taddr.sin_port = htons(target_port); @@ -228,7 +239,7 @@ void proxy_handler(ws_ctx_t *ws_ctx) { if (connect(tsock, (struct sockaddr *) &taddr, sizeof(taddr)) < 0) { handler_emsg("Could not connect to target: %s\n", strerror(errno)); - close(tsock); + _close(tsock); return; } @@ -238,12 +249,40 @@ void proxy_handler(ws_ctx_t *ws_ctx) { 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 fd, c, option_index = 0; + int c, option_index = 0; static int ssl_only = 0, daemon = 0, verbose = 0; char *found; static struct option long_options[] = { @@ -256,7 +295,11 @@ int main(int argc, char *argv[]) {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) { /* Make sure it's always set to something */ settings.cert = "self.pem"; diff --git a/other/win32/base64-decode.c b/other/win32/base64-decode.c new file mode 100644 index 0000000..428b9c6 --- /dev/null +++ b/other/win32/base64-decode.c @@ -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 +#include + +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; +} diff --git a/other/win32/base64-decode.h b/other/win32/base64-decode.h new file mode 100644 index 0000000..61610b2 --- /dev/null +++ b/other/win32/base64-decode.h @@ -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 diff --git a/other/win32/getopt.c b/other/win32/getopt.c new file mode 100644 index 0000000..3bb21f6 --- /dev/null +++ b/other/win32/getopt.c @@ -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 +#include +#include +#include + +#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 */ +} + diff --git a/other/win32/getopt.h b/other/win32/getopt.h new file mode 100644 index 0000000..7137f03 --- /dev/null +++ b/other/win32/getopt.h @@ -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__ */ diff --git a/other/win32/getopt_long.c b/other/win32/getopt_long.c new file mode 100644 index 0000000..5bcf400 --- /dev/null +++ b/other/win32/getopt_long.c @@ -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 +#include +#include +#include +#include +#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); +} diff --git a/other/win32/osisock.h b/other/win32/osisock.h new file mode 100644 index 0000000..6ffadd7 --- /dev/null +++ b/other/win32/osisock.h @@ -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 diff --git a/other/win32/realpath.c b/other/win32/realpath.c new file mode 100644 index 0000000..9a10a64 --- /dev/null +++ b/other/win32/realpath.c @@ -0,0 +1,20 @@ +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/other/win32/realpath.h b/other/win32/realpath.h new file mode 100644 index 0000000..b65d838 --- /dev/null +++ b/other/win32/realpath.h @@ -0,0 +1,6 @@ +#ifndef __REALPATH_H +#define __REALPATH_H + +extern char * realpath( const char * path, char * buffer ); + +#endif // __REALPATH_H diff --git a/other/win32/unistd.h b/other/win32/unistd.h new file mode 100644 index 0000000..3568cc0 --- /dev/null +++ b/other/win32/unistd.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 +#include +#include /* 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 */ diff --git a/third-party/README.txt b/third-party/README.txt new file mode 100644 index 0000000..5f0b08d --- /dev/null +++ b/third-party/README.txt @@ -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. diff --git a/ws_vc2010/ipch/ws_vc2010-ee0b0192/websockify-f52ea2a2.ipch b/ws_vc2010/ipch/ws_vc2010-ee0b0192/websockify-f52ea2a2.ipch new file mode 100644 index 0000000..b9e5ee8 Binary files /dev/null and b/ws_vc2010/ipch/ws_vc2010-ee0b0192/websockify-f52ea2a2.ipch differ diff --git a/ws_vc2010/ws_vc2010.sln b/ws_vc2010/ws_vc2010.sln new file mode 100644 index 0000000..d46daf3 --- /dev/null +++ b/ws_vc2010/ws_vc2010.sln @@ -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 diff --git a/ws_vc2010/ws_vc2010.vcxproj b/ws_vc2010/ws_vc2010.vcxproj new file mode 100644 index 0000000..4617826 --- /dev/null +++ b/ws_vc2010/ws_vc2010.vcxproj @@ -0,0 +1,100 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {053A90E9-3827-49BA-9B59-C6772FD6F5C5} + Win32Proj + ws_vc2010 + websockify + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + STDC_HEADERS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\other\win32\ + + + Console + true + Ws2_32.lib;ssleay32MTd.lib;libeay32MTd.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + STDC_HEADERS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)..\other\win32\ + + + Console + true + true + true + Ws2_32.lib;ssleay32MT.lib;libeay32MT.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ws_vc2010/ws_vc2010.vcxproj.filters b/ws_vc2010/ws_vc2010.vcxproj.filters new file mode 100644 index 0000000..2985fb1 --- /dev/null +++ b/ws_vc2010/ws_vc2010.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file