aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/jnetlib
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/jnetlib')
-rw-r--r--Src/replicant/jnetlib/VERSION1
-rw-r--r--Src/replicant/jnetlib/asyncdns.cpp314
-rw-r--r--Src/replicant/jnetlib/asyncdns.h66
-rw-r--r--Src/replicant/jnetlib/connection.cpp533
-rw-r--r--Src/replicant/jnetlib/connection.h168
-rw-r--r--Src/replicant/jnetlib/headers.cpp119
-rw-r--r--Src/replicant/jnetlib/headers.h20
-rw-r--r--Src/replicant/jnetlib/httpget.cpp845
-rw-r--r--Src/replicant/jnetlib/httpget.h139
-rw-r--r--Src/replicant/jnetlib/httpserv.cpp234
-rw-r--r--Src/replicant/jnetlib/httpserv.h71
-rw-r--r--Src/replicant/jnetlib/httpuserv.cpp216
-rw-r--r--Src/replicant/jnetlib/httpuserv.h55
-rw-r--r--Src/replicant/jnetlib/jnetlib-replicant.rc76
-rw-r--r--Src/replicant/jnetlib/jnetlib-replicant.vcproj491
-rw-r--r--Src/replicant/jnetlib/jnetlib.cpp630
-rw-r--r--Src/replicant/jnetlib/jnetlib.h177
-rw-r--r--Src/replicant/jnetlib/jnetlib.sln54
-rw-r--r--Src/replicant/jnetlib/jnetlib.vcxproj281
-rw-r--r--Src/replicant/jnetlib/jnetlib.vcxproj.filters137
-rw-r--r--Src/replicant/jnetlib/jnetlib_defines.h66
-rw-r--r--Src/replicant/jnetlib/listen.cpp131
-rw-r--r--Src/replicant/jnetlib/listen.h44
-rw-r--r--Src/replicant/jnetlib/multicastlisten.cpp123
-rw-r--r--Src/replicant/jnetlib/multicastlisten.h26
-rw-r--r--Src/replicant/jnetlib/netinc.h84
-rw-r--r--Src/replicant/jnetlib/resource.h14
-rw-r--r--Src/replicant/jnetlib/sslconnection.cpp329
-rw-r--r--Src/replicant/jnetlib/sslconnection.h61
-rw-r--r--Src/replicant/jnetlib/udpconnection.cpp384
-rw-r--r--Src/replicant/jnetlib/udpconnection.h151
-rw-r--r--Src/replicant/jnetlib/util.cpp185
-rw-r--r--Src/replicant/jnetlib/util.h40
-rw-r--r--Src/replicant/jnetlib/version.rc239
34 files changed, 6304 insertions, 0 deletions
diff --git a/Src/replicant/jnetlib/VERSION b/Src/replicant/jnetlib/VERSION
new file mode 100644
index 00000000..ea710abb
--- /dev/null
+++ b/Src/replicant/jnetlib/VERSION
@@ -0,0 +1 @@
+1.2 \ No newline at end of file
diff --git a/Src/replicant/jnetlib/asyncdns.cpp b/Src/replicant/jnetlib/asyncdns.cpp
new file mode 100644
index 00000000..2a680216
--- /dev/null
+++ b/Src/replicant/jnetlib/asyncdns.cpp
@@ -0,0 +1,314 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: asyncdns.cpp - JNL portable asynchronous DNS implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "asyncdns.h"
+#include <time.h>
+#ifdef _WIN32
+#include <strsafe.h>
+#endif
+
+enum
+{
+ MODE_RESOLVE=0,
+ MODE_REVERSE=1,
+};
+
+
+struct cache_entry
+{
+ time_t last_used; // timestamp.
+ bool resolved;
+ int mode; // 1=reverse
+ unsigned short port;
+ char hostname[256];
+ addrinfo *addr;
+ int sockettype;
+};
+
+JNL_AsyncDNS::JNL_AsyncDNS(int max_cache_entries)
+{
+ m_thread_kill=1;
+ m_thread=0;
+ m_cache_size=max_cache_entries;
+ m_cache=(cache_entry *)malloc(sizeof(cache_entry)*m_cache_size);
+ memset(m_cache, 0, sizeof(cache_entry)*m_cache_size);
+}
+
+JNL_AsyncDNS::~JNL_AsyncDNS()
+{
+ m_thread_kill=1;
+
+#ifdef _WIN32
+ if (m_thread)
+ {
+ WaitForSingleObject(m_thread,INFINITE);
+ CloseHandle(m_thread);
+ }
+#else
+ if (m_thread)
+ {
+ void *p;
+ pthread_join(m_thread,&p);
+ }
+#endif//!_WIN32
+ // free all the addrinfo stuff
+ for (int x = 0; x < m_cache_size; x ++)
+ {
+ if (m_cache[x].addr)
+ freeaddrinfo(m_cache[x].addr);
+ }
+
+ free(m_cache);
+}
+
+int JNL_AsyncDNS::resolvenow(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ addrinfo hints;
+ memset(&hints,0,sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ if (hostname)
+ hints.ai_flags = AI_NUMERICHOST;
+ else
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ hints.ai_socktype = sockettype;
+
+ char portString[32] = {0};
+ sprintf(portString, "%u", (unsigned int)port);
+
+ if (getaddrinfo(hostname, portString, &hints, addr) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ hints.ai_flags = 0;
+ if (getaddrinfo(hostname, portString, &hints, addr) == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+ }
+}
+
+#ifdef _WIN32
+unsigned long WINAPI JNL_AsyncDNS::_threadfunc(LPVOID _d)
+#else
+unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
+#endif
+{
+ int nowinsock=JNL::open_socketlib();
+ JNL_AsyncDNS *_this=(JNL_AsyncDNS*)_d;
+ int x;
+ for (x = 0; x < _this->m_cache_size && !_this->m_thread_kill; x ++)
+ {
+ if (_this->m_cache[x].last_used && !_this->m_cache[x].resolved)
+ {
+ if (!nowinsock)
+ {
+ if (_this->m_cache[x].mode==0)
+ {
+ addrinfo *res=0;
+ if (resolvenow(_this->m_cache[x].hostname, _this->m_cache[x].port, &res, _this->m_cache[x].sockettype) == 0)
+ {
+ _this->m_cache[x].addr=res;
+ }
+ else
+ {
+ _this->m_cache[x].addr=0;//INADDR_NONE;
+ }
+ }
+ else if (_this->m_cache[x].mode==1)
+ {
+ /*
+ hostent *ent;
+ // TODO: replace with getnameinfo for IPv6
+ ent=gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
+ if (ent)
+ lstrcpyn(_this->m_cache[x].hostname, ent->h_name, 256);
+ else
+ _this->m_cache[x].hostname[0]=0;
+ */
+ }
+ _this->m_cache[x].resolved=true;
+ }
+ else
+ {
+ if (_this->m_cache[x].mode==0)
+ {
+ _this->m_cache[x].addr=0;//INADDR_NONE;
+ _this->m_cache[x].resolved=true;
+ }
+ else if (_this->m_cache[x].mode==1)
+ {
+ _this->m_cache[x].hostname[0]=0;
+ _this->m_cache[x].resolved=true;
+ }
+ }
+ }
+ }
+ if (!nowinsock) JNL::close_socketlib();
+ _this->m_thread_kill=1;
+
+ return 0;
+}
+
+int JNL_AsyncDNS::resolve(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ // return 0 on success, 1 on wait, -1 on unresolvable
+ int x;
+
+ for (x = 0; x < m_cache_size; x ++)
+ {
+ if (!strcasecmp(m_cache[x].hostname,hostname) && port == m_cache[x].port && m_cache[x].mode==0 && m_cache[x].sockettype==sockettype)
+ {
+ m_cache[x].last_used=time(0);
+ if (m_cache[x].resolved)
+ {
+ if (m_cache[x].addr == 0)//INADDR_NONE)
+ {
+ return DNS_RESOLVE_UNRESOLVABLE;
+ }
+ *addr =m_cache[x].addr;
+ return DNS_RESOLVE_SUCCESS;
+ }
+ makesurethreadisrunning();
+ return DNS_RESOLVE_WAIT;
+ }
+ }
+ // add to resolve list
+ int oi=-1;
+ for (x = 0; x < m_cache_size; x ++)
+ {
+ if (!m_cache[x].last_used)
+ {
+ oi=x;
+ break;
+ }
+ if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
+ {
+ oi=x;
+ }
+ }
+ if (oi == -1)
+ {
+ return DNS_RESOLVE_UNRESOLVABLE;
+ }
+#ifdef _WIN32
+ StringCchCopyA(m_cache[oi].hostname, 256, hostname);
+#elif defined(__APPLE__)
+ strlcpy(m_cache[oi].hostname, hostname, 255);
+#else
+ strncpy(m_cache[oi].hostname, hostname, 255);
+ m_cache[oi].hostname[255]=0;
+#endif
+ m_cache[oi].port=port;
+ m_cache[oi].mode=0;
+ m_cache[oi].addr=0;//INADDR_NONE;
+ m_cache[oi].resolved=false;
+ m_cache[oi].last_used=time(0);
+ m_cache[oi].sockettype=sockettype;
+
+ makesurethreadisrunning();
+ return DNS_RESOLVE_WAIT;
+}
+
+/*
+int JNL_AsyncDNS::reverse(unsigned long addr, char *hostname, size_t hostnameSize)
+{
+// return 0 on success, 1 on wait, -1 on unresolvable
+int x;
+if (addr == INADDR_NONE)
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+#ifndef NO_DNS_SUPPORT
+for (x = 0; x < m_cache_size; x ++)
+{
+if (m_cache[x].addr==addr && m_cache[x].mode==1)
+{
+m_cache[x].last_used=time(0);
+if (m_cache[x].resolved)
+{
+if (!m_cache[x].hostname[0])
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+lstrcpyn(hostname,m_cache[x].hostname, hostnameSize);
+return DNS_REVERSE_SUCCESS;
+}
+makesurethreadisrunning();
+return DNS_REVERSE_WAIT;
+}
+}
+// add to resolve list
+int oi=-1;
+for (x = 0; x < m_cache_size; x ++)
+{
+if (!m_cache[x].last_used)
+{
+oi=x;
+break;
+}
+if ((oi==-1 || m_cache[x].last_used < m_cache[oi].last_used) && m_cache[x].resolved)
+{
+oi=x;
+}
+}
+if (oi == -1)
+{
+return DNS_REVERSE_UNRESOLVABLE;
+}
+m_cache[oi].addr=addr;
+m_cache[oi].hostname[0]=0;
+m_cache[oi].resolved=false;
+m_cache[oi].mode=1;
+m_cache[oi].last_used=time(0);
+
+makesurethreadisrunning();
+return DNS_REVERSE_WAIT;
+#else
+return DNS_REVERSE_UNRESOLVABLE;
+#endif
+}
+*/
+
+void JNL_AsyncDNS::makesurethreadisrunning(void)
+{
+ if (m_thread_kill)
+ {
+#ifdef _WIN32
+ if (m_thread)
+ {
+ WaitForSingleObject(m_thread,INFINITE);
+ CloseHandle(m_thread);
+ }
+ DWORD id;
+ m_thread_kill=0;
+ m_thread=CreateThread(NULL,0,_threadfunc,(LPVOID)this,0,&id);
+ if (!m_thread)
+ {
+#else
+ if (m_thread)
+ {
+ void *p;
+ pthread_join(m_thread,&p);
+ }
+ m_thread_kill=0;
+ if (pthread_create(&m_thread,NULL,(void *(*) (void *))_threadfunc,(void*)this) != 0)
+ {
+#endif
+ m_thread_kill=1;
+ }
+ }
+}
+
diff --git a/Src/replicant/jnetlib/asyncdns.h b/Src/replicant/jnetlib/asyncdns.h
new file mode 100644
index 00000000..b346eccd
--- /dev/null
+++ b/Src/replicant/jnetlib/asyncdns.h
@@ -0,0 +1,66 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: asyncdns.h - JNL portable asynchronous DNS interface
+** License: see jnetlib.h
+**
+** Usage:
+** 1. Create JNL_AsyncDNS object, optionally with the number of cache entries.
+** 2. call resolve() to resolve a hostname into an address. The return value of
+** resolve is 0 on success (host successfully resolved), 1 on wait (meaning
+** try calling resolve() with the same hostname in a few hundred milliseconds
+** or so), or -1 on error (i.e. the host can't resolve).
+** 3. call reverse() to do reverse dns (ala resolve()).
+** 4. enjoy.
+*/
+
+#ifndef _ASYNCDNS_H_
+#define _ASYNCDNS_H_
+
+#include "netinc.h"
+
+struct cache_entry;
+
+#define JNL_AUTODNS ((JNL_AsyncDNS *)-1)
+enum
+{
+ DNS_RESOLVE_UNRESOLVABLE = -1,
+ DNS_RESOLVE_SUCCESS = 0,
+ DNS_RESOLVE_WAIT = 1,
+};
+
+enum
+{
+ DNS_REVERSE_UNRESOLVABLE = -1,
+ DNS_REVERSE_SUCCESS = 0,
+ DNS_REVERSE_WAIT = 1,
+};
+
+class JNL_AsyncDNS
+{
+public:
+ JNL_AsyncDNS( int max_cache_entries = 64 );
+ ~JNL_AsyncDNS();
+
+ int resolve( const char *hostname, unsigned short port, addrinfo **addr, int sockettype ); // return 0 on success, 1 on wait, -1 on unresolvable
+ static int resolvenow( const char *hostname, unsigned short port, addrinfo **addr, int sockettype ); // return 0 on success, -1 on unresolvable
+ //int reverse(unsigned long addr, char *hostname, size_t hostnameSize); // return 0 on success, 1 on wait, -1 on unresolvable. hostname must be at least 256 bytes.
+
+private:
+ cache_entry *m_cache;
+ int m_cache_size;
+ volatile int m_thread_kill;
+
+#ifdef _WIN32
+ HANDLE m_thread;
+ static unsigned long WINAPI _threadfunc( LPVOID _d );
+#else
+ pthread_t m_thread;
+ static unsigned int _threadfunc( void *_d );
+#endif
+
+ void makesurethreadisrunning( void );
+};
+
+#endif //_ASYNCDNS_H_
diff --git a/Src/replicant/jnetlib/connection.cpp b/Src/replicant/jnetlib/connection.cpp
new file mode 100644
index 00000000..4aacdd47
--- /dev/null
+++ b/Src/replicant/jnetlib/connection.cpp
@@ -0,0 +1,533 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: connection.cpp - JNL TCP connection implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "connection.h"
+#include "asyncdns.h"
+#include "foundation\error.h"
+
+
+#ifndef min
+#define min(X,Y) ((X) < (Y) ? (X) : (Y))
+#endif
+
+JNL_Connection::JNL_Connection()
+{
+ init();
+}
+
+JNL_Connection::JNL_Connection(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
+{
+ init();
+ open(dns, sendbufsize, recvbufsize);
+}
+
+
+void JNL_Connection::init()
+{
+ m_errorstr="";
+ address=0;
+ m_dns=0;
+ m_dns_owned=false;
+ m_socket=-1;
+ m_remote_port=0;
+ m_state=STATE_NOCONNECTION;
+ m_host[0]=0;
+ saddr=0;
+}
+
+JNL_Connection::~JNL_Connection()
+{
+ /*
+ ** Joshua Teitelbaum 1/27/2006
+ ** virtualization for ssl, calling socket_shtudown()
+ */
+ socket_shutdown();
+
+ if (!saddr) // free it if it was passed to us (by JNL_Listen, presumably)
+ free(address); // TODO: change this if we ever do round-robin DNS connecting or in any way change how we handle 'address'
+
+ if (m_dns_owned)
+ delete m_dns;
+}
+
+void JNL_Connection::set_dns(JNL_AsyncDNS *dns)
+{
+ if (m_dns_owned)
+ delete static_cast<JNL_AsyncDNS *>(m_dns);
+
+ m_dns=dns;
+ m_dns_owned=false;
+}
+
+void JNL_Connection::open(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
+{
+ if (dns != JNL_AUTODNS && dns)
+ {
+ m_dns=dns;
+ m_dns_owned=false;
+ }
+ else if (!m_dns)
+ {
+ m_dns=new JNL_AsyncDNS;
+ m_dns_owned=true;
+ }
+
+ recv_buffer.reserve(recvbufsize);
+ send_buffer.reserve(sendbufsize);
+}
+
+void JNL_Connection::connect(SOCKET s, sockaddr *addr, socklen_t length)
+{
+ close(1);
+ m_socket=s;
+ address=(sockaddr *)malloc(length);
+ memcpy(address, addr, length);
+
+ m_remote_port=0;
+ if (m_socket != -1)
+ {
+ SET_SOCK_BLOCK(m_socket,0);
+ m_state=STATE_CONNECTED;
+ }
+ else
+ {
+ m_errorstr="invalid socket passed to connect";
+ m_state=STATE_ERROR;
+ }
+
+}
+
+void JNL_Connection::connect(const char *hostname, int port)
+{
+ close(1);
+ m_remote_port=(unsigned short)port;
+
+#ifdef _WIN32
+ lstrcpynA(m_host, hostname, sizeof(m_host));
+#elif defined(__APPLE__)
+ strlcpy(m_host, hostname, sizeof(m_host));
+#else
+ strncpy(m_host, hostname, sizeof(m_host)-1);
+ m_host[sizeof(m_host)-1]=0;
+#endif
+
+
+ //memset(&m_saddr,0,sizeof(m_saddr));
+ if (!m_host[0])
+ {
+ m_errorstr="empty hostname";
+ m_state=STATE_ERROR;
+ }
+ else
+ {
+ m_state=STATE_RESOLVING;
+ }
+}
+
+/*
+** Joshua Teitelbaum 1/27/2006
+** socket_shutdown
+** virtualization for ssl
+*/
+/* Virtual */
+void JNL_Connection::socket_shutdown()
+{
+ if (m_socket >= 0)
+ {
+ ::shutdown(m_socket, SHUT_RDWR);
+ ::closesocket(m_socket);
+
+ m_socket=-1;
+ }
+}
+/*
+** Joshua Teitelbaum 1/27/2006
+** socket_recv
+** virtualization for ssl
+*/
+/* Virtual */
+ssize_t JNL_Connection::socket_recv(char *buf, size_t len, int options)
+{
+ return ::recv(m_socket,buf,(int)len,options);
+}
+/*
+** Joshua Teitelbaum 1/27/2006
+** socket_send
+** virtualization for ssl
+*/
+/* Virtual */
+ssize_t JNL_Connection::socket_send(const char *buf, size_t len, int options)
+{
+ return ::send(m_socket,buf,(int)len,options);
+}
+
+int JNL_Connection::socket_connect()
+{
+ return ::connect(m_socket, saddr->ai_addr, (int)saddr->ai_addrlen);
+}
+
+void JNL_Connection::run(size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
+{
+ socklen_t socket_buffer_size=0;
+ socklen_t socket_buffer_size_len = sizeof(socket_buffer_size);
+ socklen_t send_buffer_size;
+ socklen_t recv_buffer_size;
+
+ size_t bytes_allowed_to_send=(max_send_bytes==(size_t)-1)?send_buffer.size():max_send_bytes;
+ size_t bytes_allowed_to_recv=(max_recv_bytes==(size_t)-1)?recv_buffer.avail():max_recv_bytes;
+
+ if (bytes_sent) *bytes_sent=0;
+ if (bytes_rcvd) *bytes_rcvd=0;
+
+ switch (m_state)
+ {
+ case STATE_RESOLVING:
+ if (saddr==0)
+ {
+ int a=m_dns->resolve(m_host, m_remote_port, &saddr, SOCK_STREAM);
+ if (!a)
+ {
+ m_state=STATE_RESOLVED;
+ }
+ else if (a == 1)
+ {
+ m_state=STATE_RESOLVING;
+ break;
+ }
+ else
+ {
+ m_errorstr="resolving hostname";
+ m_state=STATE_ERROR;
+
+ return;
+ }
+ }
+ // fall through
+ case STATE_RESOLVED:
+ m_socket=::socket(saddr->ai_family, saddr->ai_socktype, saddr->ai_protocol);
+ if (m_socket==-1)
+ {
+ m_errorstr="creating socket";
+ m_state=STATE_ERROR;
+ }
+ else
+ {
+ SET_SOCK_BLOCK(m_socket,0);
+ }
+
+ socket_buffer_size=0;
+ socket_buffer_size_len = sizeof(socket_buffer_size);
+ getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
+ send_buffer_size = (int)(send_buffer.avail()+send_buffer.size());
+ if (send_buffer_size > 65536)
+ send_buffer_size=65536;
+ if (socket_buffer_size < send_buffer_size)
+ setsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&send_buffer_size, sizeof(send_buffer_size));
+ getsockopt(m_socket, SOL_SOCKET, SO_SNDBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
+
+ getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
+ recv_buffer_size = (int)recv_buffer.avail();
+ if (recv_buffer_size > 65536)
+ recv_buffer_size=65536;
+ if (socket_buffer_size < recv_buffer_size)
+ setsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&recv_buffer_size, sizeof(recv_buffer_size));
+ getsockopt(m_socket, SOL_SOCKET, SO_RCVBUF, (char *)&socket_buffer_size, &socket_buffer_size_len);
+
+ /*
+ ** Joshua Teitelbaum 1/27/2006
+ ** virtualization for ssl
+ */
+ if(!socket_connect())
+ {
+ address=saddr->ai_addr;
+ m_state=STATE_CONNECTED;
+
+ on_socket_connected();
+ }
+ else if (ERRNO!=JNL_EINPROGRESS)
+ {
+ m_errorstr="Connecting to host";
+ m_state=STATE_ERROR;
+ }
+ else
+ {
+ m_state=STATE_CONNECTING;
+ }
+ break;
+ case STATE_CONNECTING:
+ {
+ fd_set f[3];
+ FD_ZERO(&f[0]);
+ FD_ZERO(&f[1]);
+ FD_ZERO(&f[2]);
+ FD_SET(m_socket,&f[0]);
+ FD_SET(m_socket,&f[1]);
+ FD_SET(m_socket,&f[2]);
+ struct timeval tv;
+ memset(&tv,0,sizeof(tv));
+ if (select((int)m_socket+1,&f[0],&f[1],&f[2],&tv)==-1)
+ {
+ m_errorstr="Connecting to host (calling select())";
+ m_state=STATE_ERROR;
+ }
+ else if (FD_ISSET(m_socket,&f[1]))
+ {
+ m_state=STATE_CONNECTED;
+ on_socket_connected();
+ }
+ else if (FD_ISSET(m_socket,&f[2]))
+ {
+ m_errorstr="Connecting to host";
+ m_state=STATE_ERROR;
+ }
+ }
+ break;
+ case STATE_CONNECTED:
+ case STATE_CLOSING:
+ /* --- send --- */
+ {
+ size_t sent = send_buffer.drain(this, bytes_allowed_to_send);
+ if (bytes_sent)
+ *bytes_sent+=sent;
+
+ if (m_state == STATE_CLOSED)
+ break;
+
+ /* --- receive --- */
+ size_t received = recv_buffer.fill(this, bytes_allowed_to_recv);
+ if (bytes_rcvd)
+ *bytes_rcvd+=received;
+ }
+
+ if (m_state == STATE_CLOSING)
+ {
+ if (send_buffer.empty()) m_state = STATE_CLOSED;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void JNL_Connection::on_socket_connected(void)
+{
+ return;
+}
+
+void JNL_Connection::close(int quick)
+{
+ if (quick || m_state == STATE_RESOLVING || m_state == STATE_CONNECTING)
+ {
+ m_state=STATE_CLOSED;
+ /*
+ ** Joshua Teitelbaum 1/27/2006
+ ** virualization for ssl
+ */
+ socket_shutdown();
+
+ m_socket=-1;
+
+ recv_buffer.clear();
+ send_buffer.clear();
+
+ m_remote_port=0;
+ m_host[0]=0;
+ //memset(&m_saddr,0,sizeof(m_saddr));
+ }
+ else
+ {
+ if (m_state == STATE_CONNECTED)
+ m_state=STATE_CLOSING;
+ }
+}
+
+size_t JNL_Connection::send_bytes_in_queue(void)
+{
+ return send_buffer.size();
+}
+
+size_t JNL_Connection::send_bytes_available(void)
+{
+ return send_buffer.avail();
+}
+
+int JNL_Connection::send(const void *data, size_t length)
+{
+ if (length > send_bytes_available())
+ return -1;
+
+ send_buffer.write(data, length);
+ return 0;
+}
+
+int JNL_Connection::send_string(const char *line)
+{
+ return send(line,strlen(line));
+}
+
+size_t JNL_Connection::recv_bytes_available(void)
+{
+ return recv_buffer.size();
+}
+
+size_t JNL_Connection::peek_bytes(void *data, size_t maxlength)
+{
+ if (data)
+ return recv_buffer.peek(data, maxlength);
+ else
+ return min(maxlength, recv_bytes_available());
+}
+
+size_t JNL_Connection::recv_bytes(void *data, size_t maxlength)
+{
+ if (data)
+ return recv_buffer.read(data, maxlength);
+ else
+ return recv_buffer.advance(maxlength);
+}
+
+int JNL_Connection::recv_lines_available(void)
+{
+ int l = (int)recv_bytes_available();
+ int lcount = 0;
+ int lastch = 0;
+
+ for (int pos = 0; pos < l; pos ++)
+ {
+ char t;
+ if (recv_buffer.at(pos, &t, 1) != 1)
+ return lcount;
+
+ if ((t=='\r' || t=='\n') &&( (lastch != '\r' && lastch != '\n') || lastch==t ))
+ lcount++;
+
+ lastch=t;
+ }
+
+ return lcount;
+}
+
+int JNL_Connection::recv_line(char *line, size_t maxlength)
+{
+ while (maxlength--)
+ {
+ char t;
+ if (recv_buffer.read(&t, 1) == 0)
+ {
+ *line=0;
+ return 0;
+ }
+
+ if (t == '\r' || t == '\n')
+ {
+ char r;
+ if (recv_buffer.peek(&r, 1) != 0)
+ {
+ if ((r == '\r' || r == '\n') && r != t)
+ recv_buffer.advance(1);
+ }
+
+ *line=0;
+ return 0;
+
+ }
+
+ *line++=t;
+ }
+
+ return 1;
+}
+
+unsigned long JNL_Connection::get_interface(void)
+{
+ if (m_socket==-1)
+ return 0;
+
+ struct sockaddr_in sin;
+ memset(&sin,0,sizeof(sin));
+ socklen_t len=sizeof(sin);
+
+ if (::getsockname(m_socket,(struct sockaddr *)&sin,&len))
+ return 0;
+
+ return (unsigned long) sin.sin_addr.s_addr;
+}
+
+unsigned long JNL_Connection::get_remote()
+{
+ // TODO: IPv6
+ if (address)
+ {
+ sockaddr_in *ipv4 = (sockaddr_in *)address;
+ return ipv4->sin_addr.s_addr;
+ }
+
+ return 0;
+
+}
+
+unsigned short JNL_Connection::get_remote_port()
+{
+ return m_remote_port;
+}
+
+/* RingBuffer client function */
+size_t JNL_Connection::Read(void *dest, size_t len)
+{
+ if (!len)
+ return 0;
+
+ int res=(int)socket_recv((char *)dest,len,0);
+
+ if (res == 0 || (res < 0 && ERRNO != JNL_EWOULDBLOCK))
+ {
+ m_state=STATE_CLOSED;
+ return 0;
+ }
+
+ if (res > 0)
+ return res;
+ else
+ return 0;
+}
+
+/* RingBuffer client function */
+size_t JNL_Connection::Write(const void *dest, size_t len)
+{
+ if (!len)
+ return 0;
+
+ int res=(int)socket_send((const char *)dest,len,0);
+
+ if (res==-1 && ERRNO != JNL_EWOULDBLOCK)
+ {
+ return 0;
+ // m_state=STATE_CLOSED;
+ }
+
+ if (res > 0)
+ return res;
+ else
+ return 0;
+}
+
+int JNL_Connection::set_recv_buffer_size(size_t new_buffer_size)
+{
+ return recv_buffer.expand(new_buffer_size);
+}
+
+void JNL_Connection::reuse()
+{
+ if (m_state == STATE_CLOSED)
+ {
+ m_state = STATE_CONNECTED;
+ recv_buffer.clear();
+ }
+}
diff --git a/Src/replicant/jnetlib/connection.h b/Src/replicant/jnetlib/connection.h
new file mode 100644
index 00000000..9d32cab2
--- /dev/null
+++ b/Src/replicant/jnetlib/connection.h
@@ -0,0 +1,168 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: connection.h - JNL TCP connection interface
+** License: see jnetlib.h
+**
+** Usage:
+** 1. Create a JNL_Connection object, optionally specifying a JNL_AsyncDNS
+** object to use (or NULL for none, or WAC_NETWORK_CONNECTION_AUTODNS for auto),
+** and the send and receive buffer sizes.
+** 2. Call connect() to have it connect to a host/port (the hostname will be
+** resolved if possible).
+** 3. call run() with the maximum send/recv amounts, and optionally parameters
+** so you can tell how much has been send/received. You want to do this a lot, while:
+** 4. check get_state() to check the state of the connection. The states are:
+** JNL_Connection::STATE_ERROR
+** - an error has occured on the connection. the connection has closed,
+** and you can no longer write to the socket (there still might be
+** data in the receive buffer - use recv_bytes_available()).
+** JNL_Connection::STATE_NOCONNECTION
+** - no connection has been made yet. call connect() already! :)
+** JNL_Connection::STATE_RESOLVING
+** - the connection is still waiting for a JNL_AsycnDNS to resolve the
+** host.
+** JNL_Connection::STATE_CONNECTING
+** - the asynchronous call to connect() is still running.
+** JNL_Connection::STATE_CONNECTED
+** - the connection has connected, all is well.
+** JNL_Connection::STATE_CLOSING
+** - the connection is closing. This happens after a call to close,
+** without the quick parameter set. This means that the connection
+** will close once the data in the send buffer is sent (data could
+** still be being received when it would be closed). After it is
+** closed, the state will transition to:
+** JNL_Connection::STATE_CLOSED
+** - the connection has closed, generally without error. There still
+** might be data in the receieve buffer, use recv_bytes_available().
+** 5. Use send() and send_string() to send data. You can use
+** send_bytes_in_queue() to see how much has yet to go out, or
+** send_bytes_available() to see how much you can write. If you use send()
+** or send_string() and not enough room is available, both functions will
+** return error ( < 0)
+** 6. Use recv() and recv_line() to get data. If you want to see how much data
+** there is, use recv_bytes_available() and recv_lines_available(). If you
+** call recv() and not enough data is available, recv() will return how much
+** data was actually read. See comments at the function defs.
+**
+** 7. To close, call close(1) for a quick close, or close() for a close that will
+** make the socket close after sending all the data sent.
+**
+** 8. delete ye' ol' object.
+*/
+
+#ifndef _CONNECTION_H_
+#define _CONNECTION_H_
+
+#include "netinc.h"
+#include "asyncdns.h"
+#include "../nu/RingBuffer.h"
+#include "jnetlib_defines.h"
+#include <stddef.h>
+#include "nswasabi/ReferenceCounted.h"
+
+#if defined(_MSC_VER) && (_MSC_VER < 1200)
+typedef int intptr_t;
+#endif
+
+
+#define PACKET_SIZE 16384
+
+class JNL_Connection : private Filler, private Drainer, public ReferenceCountedBase<JNL_Connection>
+{
+public:
+ typedef enum
+ {
+ STATE_ERROR = JNL_CONNECTION_STATE_ERROR,
+ STATE_NOCONNECTION = JNL_CONNECTION_STATE_NOCONNECTION,
+ STATE_RESOLVING = JNL_CONNECTION_STATE_RESOLVING,
+ STATE_CONNECTING = JNL_CONNECTION_STATE_CONNECTING,
+ STATE_CONNECTED = JNL_CONNECTION_STATE_CONNECTED,
+ STATE_CLOSING = JNL_CONNECTION_STATE_CLOSING,
+ STATE_CLOSED = JNL_CONNECTION_STATE_CLOSED,
+ STATE_RESOLVED = JNL_CONNECTION_STATE_RESOLVED,
+ } state;
+
+ /*
+ ** Joshua Teitelbaum, 1/27/2006 adding virtual
+ */
+ JNL_Connection();
+ JNL_Connection(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize);
+ virtual ~JNL_Connection();
+
+ void open( JNL_AsyncDNS *dns = JNL_AUTODNS, size_t sendbufsize = 8192, size_t recvbufsize = 8192 );
+ void connect( const char *hostname, int port );
+ virtual void connect( SOCKET sock, sockaddr *addr, socklen_t length /* of addr */ ); // used by the listen object, usually not needed by users.
+
+ int set_recv_buffer_size(size_t new_buffer_size);
+ /*
+ ** Joshua Teitelbaum 2/2/2006
+ ** Need to make this virtual to ensure SSL can init properly
+ */
+ virtual void run( size_t max_send_bytes = -1, size_t max_recv_bytes = -1, size_t *bytes_sent = NULL, size_t *bytes_rcvd = NULL );
+
+ int get_state() { return m_state; }
+ char *get_errstr() { return m_errorstr; }
+
+ void close( int quick = 0 );
+ void flush_send( void ) { send_buffer.clear(); }
+
+ size_t send_bytes_in_queue( void );
+ size_t send_bytes_available( void );
+ int send( const void *data, size_t length ); // returns -1 if not enough room
+ inline int send_bytes( const void *data, size_t length ) { return send( data, length ); }
+ int send_string( const char *line ); // returns -1 if not enough room
+
+ size_t recv_bytes_available( void );
+ size_t recv_bytes( void *data, size_t maxlength ); // returns actual bytes read
+ unsigned int recv_int( void );
+ int recv_lines_available( void );
+ int recv_line( char *line, size_t maxlength ); // returns 0 if the line was terminated with a \r or \n, 1 if not.
+ // (i.e. if you specify maxlength=10, and the line is 12 bytes long
+ // it will return 1. or if there is no \r or \n and that's all the data
+ // the connection has.)
+ size_t peek_bytes( void *data, size_t maxlength ); // returns bytes peeked
+
+ unsigned long get_interface( void ); // this returns the interface the connection is on
+ unsigned long get_remote( void ); // remote host ip.
+ unsigned short get_remote_port( void ); // this returns the remote port of connection
+
+ void set_dns( JNL_AsyncDNS *dns );
+ void reuse();
+
+protected:
+ SOCKET m_socket;
+ unsigned short m_remote_port;
+
+ RingBuffer recv_buffer;
+ RingBuffer send_buffer;
+
+ addrinfo *saddr;
+ sockaddr *address;
+
+ char m_host[256];
+
+ JNL_AsyncDNS *m_dns;
+ bool m_dns_owned;
+
+ state m_state;
+ char *m_errorstr;
+
+ /*
+ ** Joshua Teitelbaum 1/27/2006 Adding new BSD socket analogues for SSL compatibility
+ */
+ virtual void socket_shutdown();
+ virtual ssize_t socket_recv( char *buf, size_t len, int options );
+ virtual ssize_t socket_send( const char *buf, size_t len, int options );
+ virtual int socket_connect();
+ virtual void on_socket_connected();
+
+private:
+ void init(); // constructor helper function
+
+ // functions for RingBuffer
+ size_t Read( void *dest, size_t len ) override;
+ size_t Write( const void *dest, size_t len ) override;
+};
+#endif // _Connection_H_
diff --git a/Src/replicant/jnetlib/headers.cpp b/Src/replicant/jnetlib/headers.cpp
new file mode 100644
index 00000000..7e702cd2
--- /dev/null
+++ b/Src/replicant/jnetlib/headers.cpp
@@ -0,0 +1,119 @@
+#include "foundation/error.h"
+#include "foundation/types.h"
+
+#include "headers.h"
+#include "netinc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+JNL_Headers::JNL_Headers()
+{
+ m_recvheaders = NULL;
+ m_recvheaders_size = 0;
+}
+
+JNL_Headers::~JNL_Headers()
+{
+ if ( m_recvheaders )
+ free( m_recvheaders );
+}
+
+void JNL_Headers::Reset()
+{
+ if ( m_recvheaders )
+ free( m_recvheaders );
+
+ m_recvheaders = NULL;
+ m_recvheaders_size = 0;
+}
+
+const char *JNL_Headers::GetAllHeaders()
+{
+ // double null terminated, null delimited list
+ if ( m_recvheaders )
+ return m_recvheaders;
+ else
+ return "\0\0";
+}
+
+const char *JNL_Headers::GetHeader( const char *headername )
+{
+ char *ret = NULL;
+
+ if ( headername[ 0 ] == 0 || !m_recvheaders )
+ return NULL;
+
+ size_t headername_size = strlen( headername );
+ char *buf = (char *)malloc( headername_size + 2 );
+ strcpy( buf, headername );
+
+ if ( buf[ headername_size - 1 ] != ':' )
+ {
+ buf[ headername_size++ ] = ':';
+ buf[ headername_size ] = 0;
+ }
+
+ char *p = m_recvheaders;
+ while ( p && *p )
+ {
+ if ( !strncasecmp( buf, p, headername_size ) )
+ {
+ ret = p + headername_size;
+ while ( ret && *ret && *ret == ' ' )
+ ret++;
+
+ break;
+ }
+
+ p += strlen( p ) + 1;
+ }
+
+ free( buf );
+
+ return ret;
+}
+
+int JNL_Headers::Add( const char *buf )
+{
+ if ( !m_recvheaders )
+ {
+ m_recvheaders_size = strlen( buf ) + 1;
+ if ( m_recvheaders_size == 0 || m_recvheaders_size == (size_t)-1 ) // check for overflow
+ {
+ return NErr_OutOfMemory;
+ }
+
+ m_recvheaders = (char *)malloc( m_recvheaders_size + 1 );
+ if ( m_recvheaders )
+ {
+ strcpy( m_recvheaders, buf ); // safe because we malloc'd specifically above
+ m_recvheaders[ m_recvheaders_size ] = 0;
+ }
+ else
+ {
+ return NErr_OutOfMemory;
+ }
+ }
+ else
+ {
+ size_t oldsize = m_recvheaders_size;
+ m_recvheaders_size += strlen( buf ) + 1;
+ if ( m_recvheaders_size + 1 < oldsize ) // check for overflow
+ {
+ return NErr_OutOfMemory;
+ }
+
+ char *n = (char *)realloc( m_recvheaders, m_recvheaders_size + 1 );
+ if ( !n )
+ {
+ return NErr_OutOfMemory;
+ }
+
+ strcpy( n + oldsize, buf ); // safe because we malloc specifially for the size
+ n[ m_recvheaders_size ] = 0; // double null terminate
+ m_recvheaders = n;
+ }
+
+ return NErr_Success;
+}
diff --git a/Src/replicant/jnetlib/headers.h b/Src/replicant/jnetlib/headers.h
new file mode 100644
index 00000000..9412ac74
--- /dev/null
+++ b/Src/replicant/jnetlib/headers.h
@@ -0,0 +1,20 @@
+#pragma once
+
+
+// TODO: benski> change this to use a smarter data structure.
+// this initial implementation is known to work, however
+class JNL_Headers
+{
+public:
+ JNL_Headers();
+ ~JNL_Headers();
+
+ const char *GetAllHeaders();
+ const char *GetHeader( const char *header_name );
+ int Add( const char *buf );
+ void Reset();
+
+private:
+ char *m_recvheaders;
+ size_t m_recvheaders_size;
+}; \ No newline at end of file
diff --git a/Src/replicant/jnetlib/httpget.cpp b/Src/replicant/jnetlib/httpget.cpp
new file mode 100644
index 00000000..d3a83452
--- /dev/null
+++ b/Src/replicant/jnetlib/httpget.cpp
@@ -0,0 +1,845 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: httpget.cpp - JNL HTTP GET implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "httpget.h"
+#include "foundation/error.h"
+
+#ifdef USE_SSL
+#include "sslconnection.h"
+#endif
+
+#include <stdio.h>
+
+#define STRSAFE_NO_DEPRECATE
+
+#include "nu/strsafe.h"
+#include "nu/AutoLock.h"
+
+char *JNL_HTTPGet::g_proxy = 0;
+
+static nu::LockGuard proxy_guard;
+
+char *JNL_HTTPGet::get_proxy()
+{
+ nu::AutoLock auto_lock( proxy_guard );
+
+ if ( g_proxy )
+ return _strdup( g_proxy );
+ else
+ return 0;
+}
+
+void JNL_HTTPGet::set_proxy( const char *proxy )
+{
+ nu::AutoLock auto_lock( proxy_guard );
+
+ free( g_proxy );
+
+ if ( proxy )
+ g_proxy = _strdup( proxy );
+ else
+ g_proxy = 0;
+}
+
+JNL_HTTPGet::JNL_HTTPGet( size_t recvbufsize, size_t sendbufsize )
+{
+ persistent = false;
+ accept_all_reply_codes = false;
+ zlibStream = 0;
+ allowCompression = false;
+ m_dns = JNL_AUTODNS;
+ m_con = NULL;
+ m_http_proxylpinfo = 0;
+ m_http_proxyhost = 0;
+ m_http_proxyport = 0;
+ m_sendbufsize = sendbufsize;
+ m_sendheaders = NULL;
+
+ reinit();
+
+ m_recvbufsize = recvbufsize;
+
+ char *p = get_proxy();
+ if ( p )
+ {
+ char *r = NULL;
+ do_parse_url( p, &m_http_proxyhost, &m_http_proxyport, &r, &m_http_proxylpinfo );
+
+ free( r );
+ free( p );
+ }
+}
+
+JNL_HTTPGet::~JNL_HTTPGet()
+{
+ deinit();
+ free( m_sendheaders );
+ free( m_http_proxylpinfo );
+ free( m_http_proxyhost );
+}
+
+void JNL_HTTPGet::reinit()
+{
+ m_errstr = 0;
+ m_recvheaders = NULL;
+ m_recvheaders_size = 0;
+ m_http_state = 0;
+ m_http_port = 0;
+ m_http_url = 0;
+ m_reply = 0;
+ m_http_host = m_http_lpinfo = m_http_request = NULL;
+}
+
+void JNL_HTTPGet::deinit( bool full )
+{
+ if ( !persistent || full || ( m_con && m_con->get_state() == JNL_Connection::STATE_ERROR ) )
+ {
+ delete m_con;
+ m_con = NULL;
+ }
+
+ free( m_recvheaders );
+ free( m_http_url );
+ free( m_http_host );
+ free( m_http_lpinfo );
+ free( m_http_request );
+ free( m_errstr );
+ free( m_reply );
+
+ if ( zlibStream )
+ inflateEnd( zlibStream );
+
+ free( zlibStream );
+ zlibStream = 0;
+
+ reinit();
+}
+
+void JNL_HTTPGet::set_sendbufsize(size_t sendbufsize)
+{
+ m_sendbufsize = sendbufsize;
+}
+
+int JNL_HTTPGet::set_recv_buffer_size( size_t new_buffer_size )
+{
+ if ( m_con )
+ {
+ int ret = m_con->set_recv_buffer_size( new_buffer_size );
+ if ( ret == NErr_NoAction )// this will get returned if new_buffer_size is smaller than existing.
+ return NErr_Success;
+ else if ( ret != NErr_Success )
+ return ret;
+ }
+
+ m_recvbufsize = new_buffer_size;
+ return NErr_Success;
+}
+
+void JNL_HTTPGet::addheader( const char *header )
+{
+ if ( strstr( header, "\r" ) || strstr( header, "\n" ) )
+ return;
+
+ if ( !m_sendheaders )
+ {
+ size_t len = strlen( header ) + 3;
+ m_sendheaders = (char *)malloc( len );
+ if ( m_sendheaders )
+ {
+ char *itr = m_sendheaders;
+ StringCchCopyExA( itr, len, header, &itr, &len, 0 );
+ StringCchCatExA( itr, len, "\r\n", &itr, &len, 0 );
+ }
+ }
+ else
+ {
+ size_t len = strlen( header ) + strlen( m_sendheaders ) + 1 + 2;
+ char *t = (char *)malloc( len );
+ if ( t )
+ {
+ char *newHeaders = t;
+ StringCchCopyExA( t, len, m_sendheaders, &t, &len, 0 );
+ StringCchCatExA( t, len, header, &t, &len, 0 );
+ StringCchCatExA( t, len, "\r\n", &t, &len, 0 );
+ free( m_sendheaders );
+ m_sendheaders = newHeaders;
+ }
+ }
+}
+
+void JNL_HTTPGet::addheadervalue( const char *header, const char *value )
+{
+ size_t additional = strlen( header ) + 2 + strlen( value ) + 2 + 1;
+
+ if ( !m_sendheaders )
+ {
+ m_sendheaders = (char *)malloc( additional );
+ if ( m_sendheaders )
+ {
+ char *p = m_sendheaders;
+ StringCchCopyExA( p, additional, header, &p, &additional, 0 );
+ StringCchCatExA( p, additional, ": ", &p, &additional, 0 );
+ StringCchCatExA( p, additional, value, &p, &additional, 0 );
+ StringCchCatExA( p, additional, "\r\n", &p, &additional, 0 );
+ }
+ }
+ else
+ {
+ size_t alloc_len = strlen( m_sendheaders ) + additional;
+ char *t = (char *)malloc( alloc_len );
+ if ( t )
+ {
+ char *p = t;
+ StringCchCopyExA( p, alloc_len, m_sendheaders, &p, &alloc_len, 0 );
+ StringCchCatExA( p, alloc_len, header, &p, &alloc_len, 0 );
+ StringCchCatExA( p, alloc_len, ": ", &p, &alloc_len, 0 );
+ StringCchCatExA( p, alloc_len, value, &p, &alloc_len, 0 );
+ StringCchCatExA( p, alloc_len, "\r\n", &p, &alloc_len, 0 );
+
+ free( m_sendheaders );
+
+ m_sendheaders = t;
+ }
+ }
+}
+
+void JNL_HTTPGet::do_encode_mimestr( char *in, char *out )
+{
+ char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ int shift = 0;
+ int accum = 0;
+
+ while ( in && *in )
+ {
+ if ( *in )
+ {
+ accum <<= 8;
+ shift += 8;
+ accum |= *in++;
+ }
+
+ while ( shift >= 6 )
+ {
+ shift -= 6;
+ *out++ = alphabet[ ( accum >> shift ) & 0x3F ];
+ }
+ }
+
+ if ( shift == 4 )
+ {
+ *out++ = alphabet[ ( accum & 0xF ) << 2 ];
+ *out++ = '=';
+ }
+ else if ( shift == 2 )
+ {
+ *out++ = alphabet[ ( accum & 0x3 ) << 4 ];
+ *out++ = '=';
+ *out++ = '=';
+ }
+
+ *out++ = 0;
+}
+
+
+void JNL_HTTPGet::connect( const char *url, int ver, const char *requestmethod )
+{
+ deinit( false );
+
+ m_http_url = _strdup( url );
+ do_parse_url( m_http_url, &m_http_host, &m_http_port, &m_http_request, &m_http_lpinfo );
+
+ if ( !m_http_host || !m_http_host[ 0 ] || !m_http_port )
+ {
+ m_http_state = -1;
+ seterrstr( "invalid URL" );
+
+ return;
+ }
+
+ size_t sendbufferlen = 0;
+
+ if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
+ sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_request ) + 9 /* HTTP/1.0 */ + 2;
+ else
+ {
+ sendbufferlen += strlen( requestmethod ) + 1 /* GET */ + strlen( m_http_url ) + 9 /* HTTP/1.0 */ + 2;
+
+ if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
+ sendbufferlen += 58 + strlen( m_http_proxylpinfo ) * 2; // being safe here
+ }
+
+ sendbufferlen += 5 /* Host: */ + strlen( m_http_host ) + 2;
+ if ( m_http_port != 80 )
+ sendbufferlen += 6;
+
+ if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
+ sendbufferlen += 46 + strlen( m_http_lpinfo ) * 2; // being safe here
+
+ if ( m_sendheaders )
+ sendbufferlen += strlen( m_sendheaders );
+
+ size_t strLen = sendbufferlen + 1024;
+ char *str = (char *)calloc( strLen, sizeof( char ) );
+ char *connectString = str;
+
+ if ( !str )
+ {
+ seterrstr( "error allocating memory" );
+ m_http_state = -1;
+ }
+
+ if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
+ {
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_request, ver % 10 );
+ }
+ else
+ {
+ char *myp = NULL;
+ if ( strncasecmp( m_http_url, "uvox://", 7 ) == 0 )
+ {
+ myp = m_http_url + 7;
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
+ }
+ else if ( strncasecmp( m_http_url, "unsv://", 7 ) == 0 )
+ {
+ myp = m_http_url + 7;
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
+ }
+ else if ( strncasecmp( m_http_url, "uasf://", 7 ) == 0 )
+ {
+ myp = m_http_url + 7;
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s http://%s HTTP/1.%d\r\n", requestmethod, myp, ver % 10 );
+ }
+ else
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "%s %s HTTP/1.%d\r\n", requestmethod, m_http_url, ver % 10 );
+ }
+
+ if ( m_http_port == 80 )
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s\r\n", m_http_host );
+ else
+ StringCchPrintfExA( str, strLen, &str, &strLen, 0, "Host: %s:%d\r\n", m_http_host, m_http_port );
+
+ if ( m_http_lpinfo && m_http_lpinfo[ 0 ] )
+ {
+ StringCchCatExA( str, strLen, "Authorization: Basic ", &str, &strLen, 0 );
+ do_encode_mimestr( m_http_lpinfo, str );
+ StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
+ }
+
+ if ( m_http_proxylpinfo && m_http_proxylpinfo[ 0 ] )
+ {
+ StringCchCatExA( str, strLen, "Proxy-Authorization: Basic ", &str, &strLen, 0 );
+ do_encode_mimestr( m_http_proxylpinfo, str );
+ StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
+ }
+
+ if ( allowCompression )
+ StringCchCatExA( str, strLen, "Accept-Encoding: gzip\r\n", &str, &strLen, 0 );
+
+ if ( m_sendheaders )
+ StringCchCatExA( str, strLen, m_sendheaders, &str, &strLen, 0 );
+
+ StringCchCatExA( str, strLen, "\r\n", &str, &strLen, 0 );
+
+ int a = (int)m_recvbufsize;
+ if ( a < 4096 )
+ a = 4096;
+
+ if ( !m_con )
+ {
+ //m_con=new JNL_Connection(m_dns,strlen(str)+4,a);
+ /*
+ ** Joshua Teitelbaum delta 1/15/2006
+ */
+
+#ifdef USE_SSL
+ /*
+ ** Joshua Teitelbaum 1/27/2006
+ ** Check for secure
+ */
+ if ( !_strnicmp( m_http_url, "https:", strlen( "https:" ) ) )
+ {
+ size_t send_buffer_size = strlen( connectString ) + 4;
+ if ( send_buffer_size < 8192 )
+ send_buffer_size = 8192;
+
+ send_buffer_size += m_sendbufsize;
+
+ if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
+ send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
+
+ m_con = new JNL_SSL_Connection( NULL, m_dns, send_buffer_size, a );
+ }
+ else
+ {
+#endif
+
+ size_t send_buffer_size = strlen( connectString ) + 4 + m_sendbufsize;
+ if ( m_sendbufsize == 0 && !strcmp( requestmethod, "POST" ) )
+ send_buffer_size += 8192; // some extra room for posting data if it wasn't explicitly defined
+
+ m_con = new JNL_Connection( m_dns, send_buffer_size, a );
+
+#ifdef USE_SSL
+ }
+#endif
+
+ if ( m_con )
+ {
+ if ( !m_http_proxyhost || !m_http_proxyhost[ 0 ] )
+ m_con->connect( m_http_host, m_http_port );
+ else
+ m_con->connect( m_http_proxyhost, m_http_proxyport );
+
+ m_con->send_string( connectString );
+ }
+ else
+ {
+ m_http_state = -1;
+ seterrstr( "could not create connection object" );
+ }
+ }
+ else
+ {
+ m_con->reuse();
+ m_con->send_string( connectString );
+ }
+
+ free(connectString);
+}
+
+void JNL_HTTPGet::do_parse_url( const char *url, char **host, unsigned short *port, char **req, char **lp )
+{
+ char *l_port = 0;
+
+ JNL::parse_url( url, &l_port, host, port, req, lp );
+
+ if ( !*port )
+ {
+ if ( l_port )
+ {
+ addrinfo *res;
+
+ addrinfo hints;
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = 0;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if ( getaddrinfo( 0, l_port, &hints, &res ) == 0 )
+ {
+ if ( res->ai_family == AF_INET )
+ *port = htons( ( (sockaddr_in *)res->ai_addr )->sin_port );
+ else if ( res->ai_family == AF_INET6 )
+ *port = htons( ( (sockaddr_in6 *)res->ai_addr )->sin6_port );
+ else // wtf?
+ *port = 80;
+ }
+ else
+ *port = 80;
+ }
+ else
+ *port = 80;
+ }
+
+ if ( l_port )
+ free( l_port );
+
+ if ( !*req )
+ *req = _strdup( "/" );
+}
+
+const char *JNL_HTTPGet::getallheaders()
+{
+ // double null terminated, null delimited list
+ if (m_recvheaders)
+ return m_recvheaders;
+ else
+ return "\0\0";
+}
+
+const char *JNL_HTTPGet::getheader( const char *headername )
+{
+ char *ret = NULL;
+ if ( headername[ 0 ] == 0 || !m_recvheaders )
+ return NULL;
+
+ size_t headername_size = strlen( headername );
+ char *buf = (char *)malloc( headername_size + 2 );
+
+#ifdef _WIN32
+ StringCchCopyA( buf, headername_size + 2, headername );
+#elif defined(__APPLE__)
+ strlcpy( buf, headername, headername_size + 2 );
+#else
+ strncpy( buf, headername, headername_size + 1 );
+ buf[ headername_size + 1 ] = 0;
+#endif
+
+ if ( buf[ headername_size - 1 ] != ':' )
+ {
+ buf[ headername_size++ ] = ':';
+ buf[ headername_size ] = 0;
+ }
+
+ char *p = m_recvheaders;
+ while ( p && *p )
+ {
+ if ( !strncasecmp( buf, p, headername_size ) )
+ {
+ ret = p + headername_size;
+ while ( ret && *ret && *ret == ' ' )
+ ret++;
+
+ break;
+ }
+
+ p += strlen( p ) + 1;
+ }
+
+ free( buf );
+
+ return ret;
+}
+
+int JNL_HTTPGet::run()
+{
+ int cnt = 0;
+ if ( m_http_state == -1 || !m_con )
+ return HTTPGET_RUN_ERROR; // error
+
+
+run_again:
+ m_con->run();
+
+ if ( m_con->get_state() == JNL_Connection::STATE_ERROR )
+ {
+ seterrstr( m_con->get_errstr() );
+
+ return HTTPGET_RUN_ERROR;
+ }
+
+ if ( m_con->get_state() == JNL_Connection::STATE_CLOSED )
+ return HTTPGET_RUN_CONNECTION_CLOSED;
+
+ if ( m_http_state == 0 ) // connected, waiting for reply
+ {
+ if ( m_con->recv_lines_available() > 0 )
+ {
+ char buf[ 4096 ] = { 0 };
+ m_con->recv_line( buf, 4096 );
+ buf[ 4095 ] = 0;
+
+ if ( m_reply && getreplycode() == 100 )
+ {
+ free( m_reply );
+ m_reply = 0;
+ goto run_again;
+ }
+
+ m_reply = _strdup( buf );
+ int code = getreplycode();
+ if ( code >= 200 && code <= 206 )
+ m_http_state = 2; // proceed to read headers normally
+ else if ( code == 301 || code == 302 || code == 303 || code == 307 )
+ {
+ m_http_state = 1; // redirect city
+ }
+ else if ( code != 100 ) // in case of HTTP 100 Continue code, we'll keep looping
+ {
+ if ( accept_all_reply_codes )
+ {
+ m_http_state = 2; // proceed to read headers normally
+ }
+ else
+ {
+ seterrstr( buf );
+ m_http_state = -1;
+
+ return HTTPGET_RUN_ERROR;
+ }
+ }
+
+ cnt = 0;
+ }
+ else if ( !cnt++ )
+ goto run_again;
+ }
+
+ if ( m_http_state == 1 ) // redirect
+ {
+ char *loc = 0;
+ while ( m_con->recv_lines_available() > 0 )
+ {
+ char buf[ 4096 ] = { 0 };
+ m_con->recv_line( buf, 4096 );
+ buf[ 4095 ] = 0;
+
+ if ( !buf[ 0 ] )
+ {
+ if ( !loc )
+ {
+ m_http_state = -1;
+ return HTTPGET_RUN_ERROR;
+ }
+ else
+ break;
+ }
+
+ if ( !strncasecmp( buf, "Location:", 9 ) )
+ {
+ char *p = buf + 9;
+ while ( p && *p && *p == ' ' ) p++;
+ if ( p && *p )
+ {
+ // TODO need to make this match the request type
+ loc = _strdup( p );
+ }
+ }
+ }
+
+ if ( loc )
+ {
+ connect( loc );
+ free( loc );
+
+ return HTTPGET_RUN_OK;
+ }
+ }
+
+ /* ----- read headers ----- */
+ if ( m_http_state == 2 )
+ {
+ if ( !cnt++ && m_con->recv_lines_available() < 1 )
+ goto run_again;
+
+ while ( m_con->recv_lines_available() > 0 )
+ {
+ char buf[ 8192 ] = { 0 };
+ m_con->recv_line( buf, 8192 );
+ buf[ 8191 ] = 0;
+
+ if ( !buf[ 0 ] )
+ {
+ const char *compression = getheader( "Content-Encoding" );
+ if ( compression && !strcmp( compression, "gzip" ) )
+ {
+ zlibStream = (z_stream *)malloc( sizeof( z_stream ) );
+ zlibStream->next_in = Z_NULL;
+ zlibStream->avail_in = Z_NULL;
+ zlibStream->next_out = Z_NULL;
+ zlibStream->avail_out = Z_NULL;
+ zlibStream->zalloc = (alloc_func)0;
+ zlibStream->zfree = (free_func)0;
+ zlibStream->opaque = 0;
+
+ int z_err = inflateInit2( zlibStream, 15 + 16 /* +16 for gzip */ );
+ if ( z_err != Z_OK )
+ {
+ free( zlibStream );
+ zlibStream = 0;
+ }
+ }
+ else
+ {
+ if ( zlibStream )
+ {
+ free( zlibStream );
+ zlibStream = 0;
+ }
+ }
+ m_http_state = 3;
+ break;
+ }
+ if ( !m_recvheaders )
+ {
+ m_recvheaders_size = strlen( buf ) + 1;
+ if ( m_recvheaders_size == 0 || m_recvheaders_size == (size_t)-1 ) // check for overflow
+ {
+ m_http_state = -1;
+ return HTTPGET_RUN_ERROR;
+ }
+
+ m_recvheaders = (char *)malloc( m_recvheaders_size + 1 );
+ if ( m_recvheaders )
+ {
+ strcpy( m_recvheaders, buf ); // safe because we malloc'd specifically above
+ m_recvheaders[ m_recvheaders_size ] = 0;
+ }
+ else
+ {
+ m_http_state = -1;
+ return HTTPGET_RUN_ERROR;
+ }
+ }
+ else
+ {
+ size_t oldsize = m_recvheaders_size;
+ m_recvheaders_size += strlen( buf ) + 1;
+ if ( m_recvheaders_size + 1 < oldsize ) // check for overflow
+ {
+ m_http_state = -1;
+ return HTTPGET_RUN_ERROR;
+ }
+
+ char *n = (char *)realloc( m_recvheaders, m_recvheaders_size + 1 );
+ if ( !n )
+ {
+ m_http_state = -1;
+ return HTTPGET_RUN_ERROR;
+ }
+
+ strcpy( n + oldsize, buf ); // safe because we malloc specifially for the size
+ n[ m_recvheaders_size ] = 0; // double null terminate
+ m_recvheaders = n;
+ }
+ }
+ }
+
+ return HTTPGET_RUN_OK;
+}
+
+int JNL_HTTPGet::get_status() // returns 0 if connecting, 1 if reading headers, 2 if reading content, -1 if error.
+{
+ if ( m_http_state < 0 )
+ return HTTPGET_STATUS_ERROR;
+
+ if ( m_http_state < 2 )
+ return HTTPGET_STATUS_CONNECTING;
+
+ if ( m_http_state == 2 )
+ return HTTPGET_STATUS_READING_HEADERS;
+
+ if ( m_http_state == 3 )
+ return HTTPGET_STATUS_READING_CONTENT;
+
+ return HTTPGET_STATUS_ERROR;
+}
+
+int JNL_HTTPGet::getreplycode() // returns 0 if none yet, otherwise returns http reply code.
+{
+ if ( !m_reply )
+ return 0;
+
+ char *p = m_reply;
+
+ while ( p && *p && *p != ' ' )
+ p++; // skip over HTTP/x.x
+
+ if ( !p || !*p )
+ return 0;
+
+ return atoi( ++p );
+}
+
+size_t JNL_HTTPGet::bytes_available()
+{
+ if ( m_con && m_http_state == 3 )
+ return m_con->recv_bytes_available();
+
+ return 0;
+}
+
+size_t JNL_HTTPGet::get_bytes( char *buf, size_t len )
+{
+ if ( m_con && m_http_state == 3 )
+ {
+ if ( zlibStream )
+ {
+ // TODO: benski> we need to pick a better buffer size
+ // either alloca() and use the passed in length
+ // or malloc a buffer based on the constructor-initted buffer size
+ char temp[ 8192 ] = { 0 };
+
+ int size = (int)m_con->peek_bytes( temp, 8192 );
+ if ( size )
+ {
+ zlibStream->next_in = reinterpret_cast<Bytef *>( temp );
+ zlibStream->avail_in = (uInt)size;
+ zlibStream->next_out = reinterpret_cast<Bytef *>( buf );
+ zlibStream->avail_out = (uInt)len;
+
+ int zlib_err = inflate( zlibStream, Z_SYNC_FLUSH );
+
+ if ( zlib_err == Z_OK || zlib_err == Z_STREAM_END )
+ {
+ m_con->recv_bytes( 0, size - zlibStream->avail_in ); // since we only peeked above
+ return len - zlibStream->avail_out;
+ }
+ else
+ return 0; // TODO: should we do something else here?
+ }
+ }
+ else
+ return m_con->recv_bytes( buf, len );
+ }
+
+ return 0;
+}
+
+size_t JNL_HTTPGet::peek_bytes( char *buf, size_t len )
+{
+ if ( m_con && m_http_state == 3 )
+ {
+ if ( zlibStream )
+ return 0; // TODO: benski> how are we going to do peek_bytes, since the inflater saves state?
+ else
+ return m_con->peek_bytes( buf, len );
+ }
+
+ return 0;
+}
+
+uint64_t JNL_HTTPGet::content_length()
+{
+ const char *p = getheader( "content-length" );
+ if ( p && *p )
+ return strtoull( p, 0, 10 );
+ else
+ {
+ // TODO need to check this further for reliability!
+ // Helps to handle responses without content-length
+ if ( m_recvheaders_size > 0 && bytes_available() > 0 )
+ return bytes_available() - m_recvheaders_size;
+ }
+ return 0;
+}
+
+void JNL_HTTPGet::seterrstr( const char *str )
+{
+ if ( m_errstr )
+ free( m_errstr );
+
+ m_errstr = _strdup( str );
+}
+
+void JNL_HTTPGet::AllowCompression()
+{
+ allowCompression = true;
+}
+
+void JNL_HTTPGet::reset_headers()
+{
+ if ( m_sendheaders )
+ {
+ free( m_sendheaders );
+ m_sendheaders = 0;
+ }
+}
+
+void JNL_HTTPGet::set_accept_all_reply_codes()
+{
+ accept_all_reply_codes = true;
+}
+
+void JNL_HTTPGet::set_persistent()
+{
+ persistent = true;
+}
diff --git a/Src/replicant/jnetlib/httpget.h b/Src/replicant/jnetlib/httpget.h
new file mode 100644
index 00000000..b29a17ce
--- /dev/null
+++ b/Src/replicant/jnetlib/httpget.h
@@ -0,0 +1,139 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: httpget.h - JNL interface for doing HTTP GETs.
+** License: see jnetlib.h
+**
+** Usage:
+** 1. Create a JNL_HTTPGet object, optionally specifying a JNL_AsyncDNS
+** object to use (or NULL for none, or WAC_NETWORK_CONNECTION_AUTODNS for auto),
+** and the receive buffer size, and a string specifying proxy (or NULL
+** for none). See note on proxy string below.
+** 2. call addheader() to add whatever headers you want. It is recommended to
+** add at least the following two:
+** addheader("User-Agent:MyApp (Mozilla)");
+*/// addheader("Accept:*/*");
+/* ( the comment weirdness is there so I Can do the star-slash :)
+** 3. Call connect() with the URL you wish to GET (see URL string note below)
+** 4. Call run() once in a while, checking to see if it returns -1
+** (if it does return -1, call geterrorstr() to see what the error is).
+** (if it returns 1, no big deal, the connection has closed).
+** 5. While you're at it, you can call bytes_available() to see if any data
+** from the http stream is available, or getheader() to see if any headers
+** are available, or getreply() to see the HTTP reply, or getallheaders()
+** to get a double null terminated, null delimited list of headers returned.
+** 6. If you want to read from the stream, call get_bytes (which returns how much
+** was actually read).
+** 7. content_length() is a helper function that uses getheader() to check the
+** content-length header.
+** 8. Delete ye' ol' object when done.
+**
+** Proxy String:
+** should be in the format of host:port, or user@host:port, or
+** user:password@host:port. if port is not specified, 80 is assumed.
+** URL String:
+** should be in the format of http://user:pass@host:port/requestwhatever
+** note that user, pass, port, and /requestwhatever are all optional :)
+** note that also, http:// is really not important. if you do poo://
+** or even leave out the http:// altogether, it will still work.
+*/
+
+#ifndef _HTTPGET_H_
+#define _HTTPGET_H_
+
+#include "connection.h"
+#include "asyncdns.h"
+#include "jnetlib_defines.h"
+#ifdef _WIN32
+#include "minizip/unzip.h"
+#else
+#include <zlib.h>
+#endif
+#include "nswasabi/ReferenceCounted.h"
+
+class JNL_HTTPGet : public ReferenceCountedBase<JNL_HTTPGet>
+{
+public:
+ JNL_HTTPGet(size_t recvbufsize=PACKET_SIZE, size_t sendbufsize=0);
+ ~JNL_HTTPGet();
+
+ void set_sendbufsize( size_t sendbufsize = PACKET_SIZE ); // call if you're going to POST or do any kind of bidirectional communications
+ int set_recv_buffer_size(size_t new_buffer_size);
+ void addheader(const char *header);
+ void addheadervalue(const char *header, const char *value);
+
+ void connect(const char *url, int ver=0, const char *requestmethod="GET");
+
+ int run(); // returns: 0 if all is OK. -1 if error (call geterrorstr()). 1 if connection closed.
+
+ int get_status(); // returns 0 if connecting, 1 if reading headers,
+ // 2 if reading content, -1 if error.
+
+ const char *getallheaders(); // double null terminated, null delimited list
+ const char *getheader(const char *headername);
+ const char *getreply() { return m_reply; }
+ int getreplycode(); // returns 0 if none yet, otherwise returns http reply code.
+
+ const char *geterrorstr() { return m_errstr;}
+
+ size_t bytes_available();
+ size_t get_bytes(char *buf, size_t len);
+ size_t peek_bytes(char *buf, size_t len);
+
+ uint64_t content_length();
+
+ JNL_Connection *get_con() { return m_con; }
+ void AllowCompression();
+ void reset_headers();
+
+ void set_dns(JNL_AsyncDNS *dns);
+ const char *get_url() { return m_http_url; }
+ void set_accept_all_reply_codes(); // call this if you want to retrieve content even though a 404 (etc) was returned
+ void set_persistent();
+ static void set_proxy(const char *proxy);
+
+protected:
+ static char *get_proxy();
+ void reinit();
+ void deinit(bool full=true);
+ void seterrstr(const char *str);
+
+ void do_parse_url(const char *url, char **host, unsigned short*port, char **req, char **lp);
+ void do_encode_mimestr(char *in, char *out);
+
+ JNL_AsyncDNS *m_dns;
+ JNL_Connection *m_con;
+ size_t m_recvbufsize;
+
+ int m_http_state;
+
+ unsigned short m_http_port;
+ char *m_http_url;
+ char *m_http_host;
+ char *m_http_lpinfo;
+ char *m_http_request;
+
+ char *m_http_proxylpinfo;
+ char *m_http_proxyhost;
+ unsigned short m_http_proxyport;
+
+ char *m_sendheaders;
+ char *m_recvheaders;
+ size_t m_recvheaders_size;
+ char *m_reply;
+
+ char *m_errstr;
+ bool allowCompression;
+
+ size_t m_sendbufsize;
+ /* gzip stuff */
+ z_stream *zlibStream;
+
+ bool accept_all_reply_codes;
+ bool persistent;
+
+ static char *g_proxy;
+};
+
+#endif // _HTTPGET_H_
diff --git a/Src/replicant/jnetlib/httpserv.cpp b/Src/replicant/jnetlib/httpserv.cpp
new file mode 100644
index 00000000..4a129e9b
--- /dev/null
+++ b/Src/replicant/jnetlib/httpserv.cpp
@@ -0,0 +1,234 @@
+/*
+** JNetLib
+** Copyright (C) 2001 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: httpserv.cpp - JNL HTTP GET/POST serving implementation
+** License: see jnetlib.h
+**
+** This class just manages the http reply/sending, not where the data
+** comes from, etc.
+*/
+
+#include "netinc.h"
+#include "util.h"
+
+#include "httpserv.h"
+
+/*
+ States for m_state:
+ -1 error (connection closed, etc)
+ 0 not read request yet.
+ 1 reading headers
+ 2 headers read, have not sent reply
+ 3 sent reply
+ 4 closed
+*/
+
+JNL_HTTPServ::JNL_HTTPServ(JNL_Connection *con)
+{
+ m_con=con;
+ m_state=0;
+ m_reply_headers=0;
+ m_reply_string=0;
+ m_recv_request=0;
+ m_errstr=0;
+ m_reply_ready=0;
+ m_method = 0;
+ http_ver = 0;
+ keep_alive = 0;
+}
+
+JNL_HTTPServ::~JNL_HTTPServ()
+{
+ free(m_recv_request);
+ free(m_reply_string);
+ free(m_reply_headers);
+ free(m_errstr);
+ free(m_method);
+ m_con->Release();
+}
+
+static size_t strlen_whitespace(const char *str)
+{
+ size_t size=0;
+ while (str && *str && *str != ' ' && *str != '\r' && *str!='\n')
+ {
+ str++;
+ size++;
+ }
+ return size;
+}
+
+int JNL_HTTPServ::run()
+{ // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
+ int cnt=0;
+run_again:
+ m_con->run();
+ if (m_con->get_state()==JNL_Connection::STATE_ERROR)
+ {
+ seterrstr(m_con->get_errstr());
+ return -1;
+ }
+
+ if (m_con->get_state()==JNL_Connection::STATE_CLOSED)
+ return 4;
+
+ if (m_state == 0)
+ {
+ if (m_con->recv_lines_available()>0)
+ {
+ char *buf=(char*)malloc(m_con->recv_bytes_available()-1);
+ m_con->recv_line(buf,m_con->recv_bytes_available()-1);
+ free(m_recv_request);
+ m_recv_request=(char*)malloc(strlen(buf)+2);
+ strcpy(m_recv_request,buf);
+ m_recv_request[strlen(m_recv_request)+1]=0;
+ free(buf);
+ buf=m_recv_request;
+ while (buf && *buf) buf++;
+ while (buf >= m_recv_request && *buf != ' ') buf--;
+ if (strncmp(buf+1,"HTTP",4))// || strncmp(m_recv_request,"GET ",3))
+ {
+ seterrstr("malformed HTTP request");
+ m_state=-1;
+ }
+ else
+ {
+ http_ver = atoi(buf+8);
+
+ size_t method_len = strlen_whitespace(m_recv_request);
+ m_method = (char *)malloc(method_len + 1);
+ memcpy(m_method, m_recv_request, method_len);
+ m_method[method_len]=0;
+
+ m_state=1;
+ cnt=0;
+ if (buf >= m_recv_request) buf[0]=buf[1]=0;
+
+ buf=strstr(m_recv_request,"?");
+ if (buf)
+ {
+ *buf++=0; // change &'s into 0s now.
+ char *t=buf;
+ int stat=1;
+ while (t && *t)
+ {
+ if (*t == '&' && !stat) { stat=1; *t=0; }
+ else stat=0;
+ t++;
+ }
+ }
+ }
+ }
+ else if (!cnt++) goto run_again;
+ }
+ if (m_state == 1)
+ {
+ if (!cnt++ && m_con->recv_lines_available()<1) goto run_again;
+ while (m_con->recv_lines_available()>0)
+ {
+ char buf[4096] = {0};
+ m_con->recv_line(buf,4096);
+ if (!buf[0])
+ {
+ m_state=2;
+ break;
+ }
+ recvheaders.Add(buf);
+ }
+ }
+ if (m_state == 2)
+ {
+ if (m_reply_ready)
+ {
+ // send reply
+ m_con->send_string((char*)(m_reply_string?m_reply_string:"HTTP/1.1 200 OK"));
+ m_con->send_string("\r\n");
+ if (m_reply_headers) m_con->send_string(m_reply_headers);
+ m_con->send_string("\r\n");
+ m_state=3;
+ }
+ }
+ if (m_state == 3)
+ {
+ // nothing.
+ }
+
+ return m_state;
+}
+
+const char *JNL_HTTPServ::get_request_file()
+{
+ // file portion of http request
+ if (!m_recv_request) return NULL;
+ char *t=m_recv_request;
+ while (t && *t && *t != ' ') t++;
+ if (!t || !*t) return NULL;
+ while (t && *t && *t == ' ') t++;
+ return t;
+}
+
+const char *JNL_HTTPServ::get_request_parm(const char *parmname) // parameter portion (after ?)
+{
+ const char *t=m_recv_request;
+ while (t && *t) t++;
+ if (t) t++;
+ while (t && *t)
+ {
+ while (t && *t && *t == '&') t++;
+ if (!_strnicmp(t,parmname,strlen(parmname)) && t[strlen(parmname)] == '=')
+ {
+ return t+strlen(parmname)+1;
+ }
+ t+=strlen(t)+1;
+ }
+ return NULL;
+}
+
+const char *JNL_HTTPServ::getheader(const char *headername)
+{
+ return recvheaders.GetHeader(headername);
+}
+
+void JNL_HTTPServ::set_reply_string(const char *reply_string) // should be HTTP/1.1 OK or the like
+{
+ free(m_reply_string);
+ m_reply_string=(char*)malloc(strlen(reply_string)+1);
+ strcpy(m_reply_string,reply_string);
+}
+
+void JNL_HTTPServ::add_reply_header(const char *header) // "Connection: close" for example
+{
+ // if they've specified a content-length, then we can keep alive an HTTP/1.1 connection
+ if (!keep_alive && http_ver == 1 && !_strnicmp(header, "Content-Length", 14))
+ keep_alive = 1;
+
+ if (m_reply_headers)
+ {
+ char *tmp=(char*)malloc(strlen(m_reply_headers)+strlen(header)+3);
+ strcpy(tmp,m_reply_headers);
+ strcat(tmp,header);
+ strcat(tmp,"\r\n");
+ free(m_reply_headers);
+ m_reply_headers=tmp;
+ }
+ else
+ {
+ m_reply_headers=(char*)malloc(strlen(header)+3);
+ strcpy(m_reply_headers,header);
+ strcat(m_reply_headers,"\r\n");
+ }
+}
+
+void JNL_HTTPServ::reset()
+{
+ free(m_recv_request); m_recv_request = 0;
+ free(m_reply_string); m_reply_string = 0;
+ free(m_reply_headers); m_reply_headers = 0;
+ free(m_errstr); m_errstr = 0;
+ free(m_method); m_method =0;
+ m_reply_ready=0;
+ m_state = 0;
+ keep_alive = 0;
+}
+
diff --git a/Src/replicant/jnetlib/httpserv.h b/Src/replicant/jnetlib/httpserv.h
new file mode 100644
index 00000000..3b8e8cb5
--- /dev/null
+++ b/Src/replicant/jnetlib/httpserv.h
@@ -0,0 +1,71 @@
+/*
+** JNetLib
+** Copyright (C) 2001 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: httpserv.h - JNL interface for doing HTTP GET/POST serving.
+** License: see jnetlib.h
+** This class just manages the http reply/sending, not where the data
+** comes from, etc.
+** for a mini-web server see webserver.h
+*/
+
+#ifndef _HTTPSERV_H_
+#define _HTTPSERV_H_
+
+#include "connection.h"
+#include "headers.h"
+#include "nswasabi/ReferenceCounted.h"
+
+class JNL_HTTPServ : public ReferenceCountedBase<JNL_HTTPServ>
+{
+ public:
+ JNL_HTTPServ(JNL_Connection *con=NULL);
+ ~JNL_HTTPServ();
+
+ int run(); // returns: < 0 on error, 0 on request not read yet, 1 if reading headers, 2 if reply not sent, 3 if reply sent, sending data. 4 on connection closed.
+
+ const char *geterrorstr() { return m_errstr;}
+
+ // use these when state returned by run() is 2
+ const char *get_request_file(); // file portion of http request
+ const char *get_request_parm(const char *parmname); // parameter portion (after ?)
+ const char *getallheaders() { return recvheaders.GetAllHeaders(); } // double null terminated, null delimited list
+ const char *getheader(const char *headername);
+ const char *get_method() { return m_method; };
+ void set_reply_string(const char *reply_string); // should be HTTP/1.1 OK or the like
+ void add_reply_header(const char *header); // i.e. "content-size: 12345"
+
+ void send_reply() { m_reply_ready=1; } // send reply, state will advance to 3.
+
+ ////////// sending data ///////////////
+ int bytes_inqueue() { if (m_state == 3 || m_state == -1 || m_state ==4) return (int)m_con->send_bytes_in_queue(); else return 0; }
+ int bytes_cansend() { if (m_state == 3) return (int)m_con->send_bytes_available(); else return 0; }
+ void write_bytes(char *bytes, int length) { m_con->send(bytes,length); }
+
+ void close(int quick) { m_con->close(quick); m_state=4; }
+
+ JNL_Connection *get_con() { return m_con; }
+
+ void reset(); // prepare for another request on the same connection (HTTP/1.1)
+ int get_http_version() { return http_ver; }
+ int get_keep_alive() { return keep_alive; }
+
+ protected:
+ void seterrstr(const char *str) { if (m_errstr) free(m_errstr); m_errstr=_strdup(str); }
+
+ int m_reply_ready;
+ int m_state;
+ int http_ver;
+ int keep_alive;
+
+ char *m_errstr;
+ char *m_reply_headers;
+ char *m_reply_string;
+ JNL_Headers recvheaders;
+ char *m_recv_request; // either double-null terminated, or may contain parameters after first null.
+ char *m_method;
+
+ JNL_Connection *m_con;
+};
+
+#endif // _HTTPSERV_H_
diff --git a/Src/replicant/jnetlib/httpuserv.cpp b/Src/replicant/jnetlib/httpuserv.cpp
new file mode 100644
index 00000000..de14219a
--- /dev/null
+++ b/Src/replicant/jnetlib/httpuserv.cpp
@@ -0,0 +1,216 @@
+/*
+** JNetLib
+** Copyright (C) 2012 Nullsoft, Inc.
+** Author: Ben Allison
+** File: httpuserv.cpp - JNL HTTPU (HTTP over UDP) serving implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "httpuserv.h"
+
+#include "foundation/error.h"
+
+/*
+States for m_state:
+-1 error (connection closed, etc)
+0 not read request yet.
+1 reading headers
+2 headers read, have not sent reply
+3 sent reply
+4 closed
+*/
+
+JNL_HTTPUServ::JNL_HTTPUServ()
+{
+ m_reply_headers=0;
+ m_reply_string=0;
+ m_recv_request=0;
+ m_errstr=0;
+ m_reply_ready=0;
+ m_method = 0;
+ http_ver = 0;
+}
+
+JNL_HTTPUServ::~JNL_HTTPUServ()
+{
+ free(m_recv_request);
+ free(m_reply_string);
+ free(m_reply_headers);
+ free(m_errstr);
+ free(m_method);
+}
+
+static size_t strlen_whitespace(const char *str)
+{
+ size_t size=0;
+ while (str && *str && *str != ' ' && *str != '\r' && *str!='\n')
+ {
+ str++;
+ size++;
+ }
+ return size;
+}
+
+int JNL_HTTPUServ::process(JNL_UDPConnection *m_con)
+{ // returns: < 0 on error, 0 on connection close, 1 if reading request, 2 if reply not sent, 3 if reply sent, sending data.
+
+ reset();
+ if (m_con->get_state()==JNL_CONNECTION_STATE_ERROR)
+ {
+ seterrstr(m_con->get_errstr());
+ return -1;
+ }
+
+ if (m_con->get_state()==JNL_CONNECTION_STATE_CLOSED)
+ return 4;
+
+ if (m_con->recv_lines_available()>0)
+ {
+ char *buf=(char*)malloc(m_con->recv_bytes_available()-1);
+ m_con->recv_line(buf,m_con->recv_bytes_available()-1);
+ free(m_recv_request);
+ m_recv_request=(char*)malloc(strlen(buf)+2);
+ strcpy(m_recv_request,buf);
+ m_recv_request[strlen(m_recv_request)+1]=0;
+ free(buf);
+ buf=m_recv_request;
+ while (buf && *buf) buf++;
+ while (buf >= m_recv_request && *buf != ' ') buf--;
+ if (strncmp(buf+1,"HTTP",4))// || strncmp(m_recv_request,"GET ",3))
+ {
+ seterrstr("malformed HTTP request");
+ }
+ else
+ {
+ http_ver = atoi(buf+8);
+
+ size_t method_len = strlen_whitespace(m_recv_request);
+ m_method = (char *)malloc(method_len + 1);
+ if (m_method)
+ {
+ memcpy(m_method, m_recv_request, method_len);
+ m_method[method_len]=0;
+ }
+ else
+ {
+ seterrstr("malformed HTTP request");
+ return -1;
+ }
+
+ if (buf >= m_recv_request) buf[0]=buf[1]=0;
+
+ buf=strstr(m_recv_request,"?");
+ if (buf)
+ {
+ *buf++=0; // change &'s into 0s now.
+ char *t=buf;
+ int stat=1;
+ while (t && *t)
+ {
+ if (*t == '&' && !stat) { stat=1; *t=0; }
+ else stat=0;
+ t++;
+ }
+ }
+ }
+ }
+ else
+ {
+ seterrstr("malformed HTTP request");
+ return -1;
+ }
+
+ while (m_con->recv_lines_available()>0)
+ {
+ char buf[8192] = {0};
+ m_con->recv_line(buf, 8192);
+ if (!buf[0])
+ break;
+
+ recvheaders.Add(buf);
+ }
+
+
+ return NErr_Success;
+}
+
+void JNL_HTTPUServ::send_reply(JNL_UDPConnection *m_con)
+{
+ m_con->send_string((char*)(m_reply_string?m_reply_string:"HTTP/1.1 200 OK"));
+ m_con->send_string("\r\n");
+ if (m_reply_headers) m_con->send_string(m_reply_headers);
+ m_con->send_string("\r\n");
+
+}
+
+const char *JNL_HTTPUServ::get_request_uri()
+{
+ // file portion of http request
+ if (!m_recv_request) return NULL;
+ char *t=m_recv_request;
+ while (t && *t && *t != ' ') t++;
+ if (!t || !*t) return NULL;
+ while (t && *t && *t == ' ') t++;
+ return t;
+}
+
+const char *JNL_HTTPUServ::get_request_parm(const char *parmname) // parameter portion (after ?)
+{
+ const char *t=m_recv_request;
+ while (*t) t++;
+ t++;
+ while (t && *t)
+ {
+ while (t && *t && *t == '&') t++;
+ if (!strncasecmp(t,parmname,strlen(parmname)) && t[strlen(parmname)] == '=')
+ {
+ return t+strlen(parmname)+1;
+ }
+ t+=strlen(t)+1;
+ }
+ return NULL;
+}
+
+const char *JNL_HTTPUServ::getheader(const char *headername)
+{
+ return recvheaders.GetHeader(headername);
+}
+
+void JNL_HTTPUServ::set_reply_string(const char *reply_string) // should be HTTP/1.1 OK or the like
+{
+ free(m_reply_string);
+ m_reply_string=(char*)malloc(strlen(reply_string)+1);
+ strcpy(m_reply_string,reply_string);
+}
+
+void JNL_HTTPUServ::set_reply_header(const char *header) // "Connection: close" for example
+{
+ if (m_reply_headers)
+ {
+ char *tmp=(char*)malloc(strlen(m_reply_headers)+strlen(header)+3);
+ strcpy(tmp,m_reply_headers);
+ strcat(tmp,header);
+ strcat(tmp,"\r\n");
+ free(m_reply_headers);
+ m_reply_headers=tmp;
+ }
+ else
+ {
+ m_reply_headers=(char*)malloc(strlen(header)+3);
+ strcpy(m_reply_headers,header);
+ strcat(m_reply_headers,"\r\n");
+ }
+}
+
+void JNL_HTTPUServ::reset()
+{
+ free(m_recv_request); m_recv_request = 0;
+ free(m_reply_string); m_reply_string = 0;
+ free(m_reply_headers); m_reply_headers = 0;
+ free(m_errstr); m_errstr = 0;
+ free(m_method); m_method =0;
+ recvheaders.Reset();
+ m_reply_ready=0;
+}
diff --git a/Src/replicant/jnetlib/httpuserv.h b/Src/replicant/jnetlib/httpuserv.h
new file mode 100644
index 00000000..d6015067
--- /dev/null
+++ b/Src/replicant/jnetlib/httpuserv.h
@@ -0,0 +1,55 @@
+/*
+** JNetLib
+** Copyright (C) 2012 Nullsoft, Inc.
+** Author: Ben Allison
+** File: httpuserv.h - JNL interface for doing HTTPU (HTTP over UDP)
+** This is half-baked so far. Need to think things through a touch more
+*/
+
+#pragma once
+
+#include "udpconnection.h"
+#include "headers.h"
+
+class JNL_HTTPUServ
+{
+public:
+ JNL_HTTPUServ();
+ ~JNL_HTTPUServ();
+
+ // pass this a connection that has just received a packet
+ int process( JNL_UDPConnection *m_con );
+
+ const char *geterrorstr() { return m_errstr; }
+
+ // use these when state returned by run() is 2
+ const char *get_request_uri(); // file portion of http request
+ const char *get_request_parm( const char *parmname ); // parameter portion (after ?)
+ const char *getallheaders() { return recvheaders.GetAllHeaders(); } // double null terminated, null delimited list
+ const char *getheader( const char *headername );
+ const char *get_method() { return m_method; }
+
+ void set_reply_string( const char *reply_string ); // should be HTTP/1.1 OK or the like
+ void set_reply_header( const char *header ); // i.e. "content-size: 12345"
+
+ void send_reply( JNL_UDPConnection *m_con ); // sends a reply to the given UDP socket. it must have been setup beforehand with the appropriate peer
+
+ void reset(); // prepare for another request
+
+ int get_http_version() { return http_ver; }
+
+protected:
+ void seterrstr( const char *str ) { if ( m_errstr ) free( m_errstr ); m_errstr = _strdup( str ); }
+
+ int m_reply_ready;
+ int http_ver;
+
+ char *m_errstr;
+ char *m_reply_headers;
+ char *m_reply_string;
+ JNL_Headers recvheaders;
+ char *m_recv_request; // either double-null terminated, or may contain parameters after first null.
+ char *m_method;
+};
+
+
diff --git a/Src/replicant/jnetlib/jnetlib-replicant.rc b/Src/replicant/jnetlib/jnetlib-replicant.rc
new file mode 100644
index 00000000..fcff7711
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib-replicant.rc
@@ -0,0 +1,76 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.K.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "#include ""version.rc2""\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.K.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+#include "version.rc2"
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Src/replicant/jnetlib/jnetlib-replicant.vcproj b/Src/replicant/jnetlib/jnetlib-replicant.vcproj
new file mode 100644
index 00000000..a514c3c0
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib-replicant.vcproj
@@ -0,0 +1,491 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="jnetlib-replicant"
+ ProjectGUID="{AAE8BF3C-AD6B-405C-A216-BF62E2D49E95}"
+ RootNamespace="jnetlib"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../../openssl/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ DisableSpecificWarnings="4995;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
+ OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ IgnoreDefaultLibraryNames="msvcprt.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
+ SubSystem="2"
+ ImportLibrary="$(IntDir)\$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="..;../../openssl/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL;WIN32_LEAN_AND_MEAN"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4995;4996;4244"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
+ OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
+ LinkIncremental="1"
+ GenerateManifest="false"
+ IgnoreDefaultLibraryNames="msvcprt.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/$(TargetName).pdb"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(IntDir)\$(TargetName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..;../../openssl/include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4995;4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
+ OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
+ LinkIncremental="2"
+ GenerateManifest="false"
+ IgnoreDefaultLibraryNames="msvcprt.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)\$(TargetName).pdb"
+ SubSystem="2"
+ ImportLibrary="$(IntDir)\$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="..;../../openssl/include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;USE_SSL;WIN32_LEAN_AND_MEAN"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4995;4996;4244"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="ws2_32.lib"
+ OutputFile="$(ProgramFiles)\Winamp\Shared\jnetlib.dll"
+ LinkIncremental="1"
+ GenerateManifest="false"
+ IgnoreDefaultLibraryNames="msvcprt.lib"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/$(TargetName).pdb"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ImportLibrary="$(IntDir)\$(TargetName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ <ProjectReference
+ ReferencedProjectIdentifier="{EFC75A79-269F-44FC-BAC5-D7D4FD4EC92C}"
+ RelativePathToProject="..\replicant\nu\nu.vcproj"
+ />
+ <ProjectReference
+ ReferencedProjectIdentifier="{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
+ RelativePathToProject="..\replicant\zlib\zlib.vcproj"
+ />
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\asyncdns.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\connection.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\headers.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\httpget.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\httpserv.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\httpuserv.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\jnetlib.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\listen.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\multicastlisten.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\sslconnection.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\udpconnection.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\util.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\asyncdns.h"
+ >
+ </File>
+ <File
+ RelativePath=".\connection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\headers.h"
+ >
+ </File>
+ <File
+ RelativePath=".\httpget.h"
+ >
+ </File>
+ <File
+ RelativePath=".\httpserv.h"
+ >
+ </File>
+ <File
+ RelativePath=".\httpuserv.h"
+ >
+ </File>
+ <File
+ RelativePath=".\jnetlib.h"
+ >
+ </File>
+ <File
+ RelativePath=".\listen.h"
+ >
+ </File>
+ <File
+ RelativePath=".\multicastlisten.h"
+ >
+ </File>
+ <File
+ RelativePath=".\netinc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\precomp.h"
+ >
+ </File>
+ <File
+ RelativePath=".\sslconnection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\udpconnection.h"
+ >
+ </File>
+ <File
+ RelativePath=".\util.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ >
+ <File
+ RelativePath=".\jnetlib-replicant.rc"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Src/replicant/jnetlib/jnetlib.cpp b/Src/replicant/jnetlib/jnetlib.cpp
new file mode 100644
index 00000000..00fcfbdb
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib.cpp
@@ -0,0 +1,630 @@
+#include "jnetlib.h"
+#include "httpget.h"
+#include "sslconnection.h"
+#include "asyncdns.h"
+#include "util.h"
+#include "httpserv.h"
+#include "httpuserv.h"
+#include "listen.h"
+#include "multicastlisten.h"
+
+#include "foundation/error.h"
+
+#include <new>
+
+int jnl_init()
+{
+ return JNL::open_socketlib();
+}
+
+void jnl_quit()
+{
+ JNL::close_socketlib();
+}
+
+/* --- Connection --- */
+jnl_connection_t jnl_connection_create(jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize)
+{
+ JNL_Connection *connection = new (std::nothrow) JNL_Connection((JNL_AsyncDNS *)dns, sendbufsize, recvbufsize);
+ return (jnl_connection_t)connection;
+}
+
+jnl_connection_t jnl_sslconnection_create(jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize)
+{
+ JNL_SSL_Connection *connection = new (std::nothrow) JNL_SSL_Connection(NULL, (JNL_AsyncDNS *)dns, sendbufsize, recvbufsize);
+ return (jnl_connection_t)connection;
+}
+
+void jnl_connection_run(jnl_connection_t _connection, size_t max_send_bytes, size_t max_receive_bytes, size_t *bytes_sent, size_t *bytes_received)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ connection->run(max_send_bytes, max_receive_bytes, bytes_sent, bytes_received);
+}
+
+int jnl_connection_get_state(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->get_state();
+}
+
+size_t jnl_connection_send_bytes_available(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->send_bytes_available();
+}
+
+size_t jnl_connection_receive_bytes_available(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->recv_bytes_available();
+}
+
+int jnl_connection_send(jnl_connection_t _connection, const void *bytes, size_t size)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->send(bytes, size);
+}
+
+JNL_API int jnl_connection_send_string(jnl_connection_t _connection, const char *str)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->send_string(str);
+}
+
+size_t jnl_connection_send_bytes_in_queue(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->send_bytes_in_queue();
+}
+
+size_t jnl_connection_receive(jnl_connection_t _connection, void *bytes, size_t size)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->recv_bytes(bytes, size);
+}
+
+size_t jnl_connection_peek(jnl_connection_t _connection, void *bytes, size_t size)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->peek_bytes(bytes, size);
+}
+
+void jnl_connection_release(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ if (connection)
+ connection->Release();
+}
+
+int jnl_connection_receive_line(jnl_connection_t _connection, void *bytes, size_t size)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->recv_line((char *)bytes, size);
+}
+
+size_t jnl_connection_receive_lines_available(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->recv_lines_available();
+}
+
+void jnl_connection_close(jnl_connection_t _connection, int fast)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ connection->close(fast);
+}
+
+void jnl_connection_connect(jnl_connection_t _connection, const char *hostname, int port)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ connection->connect(hostname, port);
+}
+
+const char *jnl_connection_get_error(jnl_connection_t _connection)
+{
+ JNL_Connection *connection = (JNL_Connection *)_connection;
+ return connection->get_errstr();
+}
+
+/* ---- UDP ----- */
+int jnl_udp_create_multicast_listener(jnl_udp_t *connection, const char *mcast_ip, unsigned short port)
+{
+ JNL_UDPConnection *udp = 0;
+ JNL::open_socketlib(); // TODO: cut
+
+ int ret = CreateMulticastListener(&udp, mcast_ip, port);
+ if (ret != NErr_Success)
+ {
+ JNL::close_socketlib(); // TODO: cut
+
+ return ret;
+ }
+ *connection = (jnl_udp_t)udp;
+ return NErr_Success;
+}
+
+void jnl_udp_release(jnl_udp_t _connection)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ delete connection; // TODO: reference count
+ JNL::close_socketlib(); // TODO: cut
+}
+
+void jnl_udp_run(jnl_udp_t _connection, size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ if (connection)
+ {
+ connection->run(max_send_bytes, max_recv_bytes, bytes_sent, bytes_rcvd);
+ }
+}
+
+size_t jnl_udp_recv_bytes(jnl_udp_t _connection, void *buf, size_t len)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ if (connection)
+ {
+ return connection->recv_bytes(buf, len);
+ }
+ else
+ return 0;
+}
+
+int jnl_udp_send(jnl_udp_t _connection, const void *bytes, size_t size)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ return connection->send(bytes, size);
+}
+
+void jnl_udp_set_peer(jnl_udp_t _connection, const char *hostname, unsigned short port)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ connection->setpeer(hostname, port);
+}
+
+void jnl_udp_set_peer_address(jnl_udp_t _connection, sockaddr *addr, socklen_t length)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ connection->setpeer(addr, length);
+}
+
+int jnl_udp_get_address(jnl_udp_t _connection, sockaddr **addr, socklen_t *length)
+{
+ JNL_UDPConnection *connection = (JNL_UDPConnection *)_connection;
+ connection->get_last_recv_msg_addr(addr, length);
+ return NErr_Success;
+}
+
+/* ---- HTTP ---- */
+jnl_http_t jnl_http_create(int recvbufsize, int sendbufsize)
+{
+ JNL_HTTPGet *http = new (std::nothrow) JNL_HTTPGet(recvbufsize, sendbufsize);
+ return (jnl_http_t)http;
+}
+
+int jnl_http_set_recv_buffer_size(jnl_http_t _http, size_t new_size)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->set_recv_buffer_size(new_size);
+}
+
+int jnl_http_run(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->run();
+}
+
+size_t jnl_http_get_bytes(jnl_http_t _http, void *buf, size_t len)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->get_bytes(static_cast<char *>(buf), len);
+}
+
+size_t jnl_http_peek_bytes(jnl_http_t _http, void *buf, size_t len)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->peek_bytes(static_cast<char *>(buf), len);
+}
+
+size_t jnl_http_bytes_available(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->bytes_available();
+}
+
+uint64_t jnl_http_content_length(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->content_length();
+}
+
+int jnl_http_get_status(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->get_status();
+}
+
+int jnl_http_getreplycode(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->getreplycode();
+}
+
+const char *jnl_http_getreply(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->getreply();
+}
+
+const char *jnl_http_getheader(jnl_http_t _http, const char *header)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->getheader(header);
+}
+
+const char *jnl_http_get_all_headers(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->getallheaders();
+}
+
+void jnl_http_addheader(jnl_http_t _http, const char *header)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->addheader(header);
+}
+
+void jnl_http_addheadervalue(jnl_http_t _http, const char *header, const char *value)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->addheadervalue(header, value);
+}
+
+void jnl_http_connect(jnl_http_t _http, const char *url, int http_version, const char *method)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->connect(url, http_version, method);
+}
+
+void jnl_http_release(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+
+ if (http)
+ http->Release();
+}
+
+jnl_http_t jnl_http_retain(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ if (http)
+ http->Retain();
+ return _http;
+}
+
+const char *jnl_http_get_url(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return http->get_url();
+}
+
+void jnl_http_reset_headers(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->reset_headers();
+}
+
+void jnl_http_set_persistent(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->set_persistent();
+}
+
+void jnl_http_allow_compression(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->AllowCompression();
+}
+
+void jnl_http_allow_accept_all_reply_codes(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ http->set_accept_all_reply_codes();
+}
+
+jnl_connection_t jnl_http_get_connection(jnl_http_t _http)
+{
+ JNL_HTTPGet *http = (JNL_HTTPGet *)_http;
+ return (jnl_connection_t)http->get_con();
+}
+
+void jnl_http_set_proxy(const char *proxy)
+{
+ JNL_HTTPGet::set_proxy(proxy);
+}
+
+/* ------- HTTP Request Parser ------- */
+int jnl_http_request_create(jnl_http_request_t *_http, jnl_connection_t _connection)
+{
+ JNL_HTTPServ *http = new (std::nothrow) JNL_HTTPServ((JNL_Connection *)_connection);;
+ if (!http)
+ return NErr_OutOfMemory;
+
+ *_http = (jnl_http_request_t) http;
+ return NErr_Success;
+}
+
+void jnl_http_request_release(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ if (http)
+ http->Release();
+}
+
+int jnl_http_request_run(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->run();
+}
+
+int jnl_htt_request_get_keep_alive(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->get_keep_alive();
+}
+
+const char *jnl_http_request_get_header(jnl_http_request_t _http, const char *header)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->getheader(header);
+}
+
+void jnl_http_request_reset(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ http->reset();
+}
+
+void jnl_http_request_addheader(jnl_http_request_t _http, const char *header)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ http->add_reply_header(header);
+}
+
+void jnl_http_request_set_reply_string(jnl_http_request_t _http, const char *reply)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ http->set_reply_string(reply);
+}
+
+void jnl_http_request_send_reply(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ http->send_reply();
+}
+
+const char *jnl_http_request_get_uri(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->get_request_file();
+}
+
+const char *jnl_http_request_get_parameter(jnl_http_request_t _http, const char *parameter)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->get_request_parm(parameter);
+}
+
+jnl_connection_t jnl_http_request_get_connection(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ JNL_Connection *connection = http->get_con();
+ if (connection)
+ {
+ connection->Retain();
+ return (jnl_connection_t)connection;
+ }
+ else
+ return 0;
+}
+
+const char *jnl_http_request_get_method(jnl_http_request_t _http)
+{
+ JNL_HTTPServ *http = (JNL_HTTPServ *)_http;
+ return http->get_method();
+}
+
+/* ------- HTTPU Request Parser ------- */
+int jnl_httpu_request_create(jnl_httpu_request_t *_httpu)
+{
+ JNL_HTTPUServ *httpu = new (std::nothrow) JNL_HTTPUServ;
+ if (!httpu)
+ return NErr_OutOfMemory;
+
+ *_httpu = (jnl_httpu_request_t) httpu;
+ return NErr_Success;
+}
+
+void jnl_httpu_request_release(jnl_httpu_request_t _httpu)
+{
+ JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
+ delete httpu; // TODO: reference count
+}
+
+int jnl_httpu_request_process(jnl_httpu_request_t _httpu, jnl_udp_t _udp)
+{
+ JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
+ return httpu->process((JNL_UDPConnection *)_udp);
+}
+
+const char *jnl_httpu_request_get_method(jnl_httpu_request_t _httpu)
+{
+ JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
+ return httpu->get_method();
+}
+
+
+const char *jnl_httpu_request_get_uri(jnl_httpu_request_t _httpu)
+{
+ JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
+ return httpu->get_request_uri();
+}
+
+const char *jnl_httpu_request_get_header(jnl_httpu_request_t _httpu, const char *header)
+{
+ JNL_HTTPUServ *httpu = (JNL_HTTPUServ *)_httpu;
+ return httpu->getheader(header);
+}
+
+/* ----- DNS ----- */
+int jnl_dns_create(jnl_dns_t *out_dns)
+{
+ JNL_AsyncDNS *dns = new (std::nothrow)JNL_AsyncDNS;
+ if (!dns)
+ return NErr_OutOfMemory;
+
+ *out_dns = (jnl_dns_t)dns;
+ return NErr_Success;
+}
+
+void jnl_dns_release(jnl_dns_t _dns)
+{
+ JNL_AsyncDNS *dns = (JNL_AsyncDNS *)_dns;
+ delete dns; // TODO: reference counting
+}
+
+int jnl_dns_resolve(jnl_dns_t _dns, const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ JNL_AsyncDNS *dns = (JNL_AsyncDNS *)_dns;
+ int ret = dns->resolve(hostname, port, addr, sockettype);
+ if (ret == 0)
+ return NErr_Success;
+ else if (ret == -1)
+ return NErr_TryAgain;
+ else
+ return NErr_Unknown;
+}
+
+int jnl_dns_resolve_now(const char *hostname, unsigned short port, addrinfo **addr, int sockettype)
+{
+ int ret = JNL_AsyncDNS::resolvenow(hostname, port, addr, sockettype);
+ if (ret == 0)
+ return NErr_Success;
+ else
+ return NErr_Unknown;
+}
+
+
+void jnl_dns_freeaddrinfo(addrinfo *addr)
+{
+ freeaddrinfo(addr);
+}
+
+void jnl_dns_gethostname(char *name, size_t cch)
+{
+ gethostname(name, (int)cch);
+}
+
+#ifdef _WIN32
+PCSTR WSAAPI inet_ntop_xp(INT af, PVOID src, PSTR dst, size_t cnt)
+{
+ struct sockaddr_in srcaddr;
+
+ memset(&srcaddr, 0, sizeof(struct sockaddr_in));
+ memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
+
+ srcaddr.sin_family = af;
+ if (WSAAddressToStringA((struct sockaddr*) &srcaddr, sizeof(struct sockaddr_in), 0, dst, (LPDWORD) &cnt) != 0) {
+ return NULL;
+ }
+ return dst;
+}
+
+PCSTR WSAAPI inet_ntop_win32(INT Family, PVOID pAddr, PSTR pStringBuf, size_t StringBufSize) {
+ typedef PCSTR (WSAAPI * win32_inet_ntop)(INT, PVOID, PSTR, size_t);
+ static win32_inet_ntop pwin32_inet_ntop = NULL;
+
+ if (!pwin32_inet_ntop){
+ HMODULE hlib = LoadLibrary(L"WS2_32.DLL");
+ pwin32_inet_ntop = (win32_inet_ntop)GetProcAddress(hlib, "inet_ntop");
+ if (!pwin32_inet_ntop) {
+ pwin32_inet_ntop = inet_ntop_xp;
+ }
+ }
+
+ return (*pwin32_inet_ntop)(Family, pAddr, pStringBuf, StringBufSize);
+}
+
+#endif
+
+void jnl_dns_ntop(int af, const void *src, char *dst, socklen_t size)
+{
+#ifdef _WIN32
+ // TODO need to revist this at a later date
+ // [22:01:08] audiodsp: i will make a tweak for IPv6 compatability at some point
+ // [22:01:49] audiodsp: just change references from sockaddr_in to sockaddr_storage
+ // [22:02:24] audiodsp: keep it as is
+ // [22:02:32] audiodsp: we're only using it in IPv4 mode at the moment
+ // [22:02:40] audiodsp: i will fix when we need IPv6 server support
+ // [22:03:58] audiodsp: the memcpy is what makes it non-trivial
+ // [22:04:05] audiodsp: i have to switch on family and do different memcpy's accordingly
+ // [22:04:16] audiodsp: or change the method to require a length
+ // [22:04:19] audiodsp: which makes more sense
+ // [22:04:29] audiodsp: and just not pass it to the linux function
+ // [22:05:08] audiodsp: anyway not important.
+ inet_ntop_win32(af, (PVOID)src, dst, size);
+#else
+ inet_ntop(af, src, dst, size);
+#endif
+}
+/* Listen */
+
+int jnl_listen_create(jnl_listen_t *_listen, unsigned short port)
+{
+ JNL_Listen *l = new (std::nothrow) JNL_Listen();
+ if (!l)
+ return NErr_OutOfMemory;
+ int ret = l->Initialize(port);
+ if (ret != NErr_Success)
+ {
+ delete l;
+ return ret;
+ }
+ *_listen = (jnl_listen_t)l;
+ return NErr_Success;
+}
+
+int jnl_listen_create_from_address(jnl_listen_t *_listen, struct addrinfo *addr, size_t index)
+{
+ JNL_Listen *l = new (std::nothrow) JNL_Listen();
+ if (!l)
+ return NErr_OutOfMemory;
+ int ret = l->Initialize(addr, index);
+ if (ret != NErr_Success)
+ {
+ delete l;
+ return ret;
+ }
+ *_listen = (jnl_listen_t)l;
+ return NErr_Success;
+}
+
+jnl_connection_t jnl_listen_get_connection(jnl_listen_t _listen)
+{
+ JNL_Listen *listen = (JNL_Listen *)_listen;
+ JNL_Connection *connection = listen->get_connect();
+ return (jnl_connection_t)connection;
+}
+
+unsigned short jnl_listen_get_port(jnl_listen_t _listen)
+{
+ JNL_Listen *listen = (JNL_Listen *)_listen;
+ return listen->get_port();
+}
+
+void jnl_listen_release(jnl_listen_t _listen)
+{
+ JNL_Listen *listen = (JNL_Listen *)_listen;
+ if (listen)
+ listen->Release();
+} \ No newline at end of file
diff --git a/Src/replicant/jnetlib/jnetlib.h b/Src/replicant/jnetlib/jnetlib.h
new file mode 100644
index 00000000..2dcf08ca
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib.h
@@ -0,0 +1,177 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2006 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: jnetlib.h - JNL main include file (not really necessary).
+**
+** For documentation, look at the following files:
+** Generic network initialization: netinc.h
+** DNS: asyncdns.h
+** TCP connections: connection.h
+** HTTP GET connections: httpget.h
+** TCP listen: listen.h
+**
+** license:
+**
+** This software is provided 'as-is', without any express or implied
+** warranty. In no event will the authors be held liable for any damages
+** arising from the use of this software.
+**
+** Permission is granted to anyone to use this software for any purpose,
+** including commercial applications, and to alter it and redistribute it
+** freely, subject to the following restrictions:
+**
+** 1. The origin of this software must not be misrepresented; you must not
+** claim that you wrote the original software. If you use this software
+** in a product, an acknowledgment in the product documentation would be
+** appreciated but is not required.
+** 2. Altered source versions must be plainly marked as such, and must not be
+** misrepresented as being the original software.
+** 3. This notice may not be removed or altered from any source distribution.
+**
+*/
+
+#ifndef _JNETLIB_H_
+#define _JNETLIB_H_
+
+#include "netinc.h"
+#include "../foundation/types.h"
+#include "jnetlib_defines.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _MSC_VER
+#ifdef JNETLIB_EXPORTS
+#define JNL_API __declspec(dllexport)
+#else
+#define JNL_API __declspec(dllimport)
+#endif
+#elif defined(__ANDROID__) || defined(__APPLE__)
+#define JNL_API __attribute__ ((visibility("default")))
+#elif defined(__linux__)
+#if __GNUC__ >= 4
+#define JNL_API __attribute__ ((visibility ("default")))
+#else
+#define JNL_API
+#endif
+#else
+#error port me
+#endif
+
+/* these are reference counted. so make sure to match init/quit calls. */
+JNL_API int jnl_init();
+JNL_API void jnl_quit();
+
+/* ----- Connection ----- */
+JNL_API jnl_connection_t jnl_connection_create( jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize );
+JNL_API jnl_connection_t jnl_sslconnection_create( jnl_dns_t dns, size_t sendbufsize, size_t recvbufsize );
+JNL_API void jnl_connection_run( jnl_connection_t connection, size_t max_send_bytes, size_t max_receive_bytes, size_t *bytes_sent, size_t *bytes_received );
+JNL_API int jnl_connection_get_state( jnl_connection_t connection );
+JNL_API size_t jnl_connection_send_bytes_available( jnl_connection_t connection );
+JNL_API size_t jnl_connection_receive_bytes_available( jnl_connection_t connection );
+JNL_API int jnl_connection_receive_line( jnl_connection_t _connection, void *bytes, size_t size );
+JNL_API int jnl_connection_send( jnl_connection_t connection, const void *bytes, size_t size );
+JNL_API int jnl_connection_send_string( jnl_connection_t connection, const char *str );
+JNL_API size_t jnl_connection_receive( jnl_connection_t connection, void *bytes, size_t size );
+JNL_API size_t jnl_connection_send_bytes_in_queue( jnl_connection_t connection );
+JNL_API void jnl_connection_release( jnl_connection_t connection );
+JNL_API size_t jnl_connection_receive_lines_available( jnl_connection_t connection );
+JNL_API void jnl_connection_close( jnl_connection_t _connection, int fast );
+JNL_API void jnl_connection_connect( jnl_connection_t connection, const char *hostname, int port );
+JNL_API const char *jnl_connection_get_error( jnl_connection_t connection );
+JNL_API size_t jnl_connection_peek( jnl_connection_t _connection, void *bytes, size_t size );
+
+/* ----- UDP ----- */
+JNL_API int jnl_udp_create_multicast_listener( jnl_udp_t *connection, const char *mcast_ip, unsigned short port );
+JNL_API void jnl_udp_release( jnl_udp_t connection );
+JNL_API void jnl_udp_run( jnl_udp_t connection, size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd );
+JNL_API size_t jnl_udp_recv_bytes( jnl_udp_t connection, void *buf, size_t len );
+JNL_API int jnl_udp_send( jnl_udp_t connection, const void *bytes, size_t size );
+JNL_API void jnl_udp_set_peer( jnl_udp_t connection, const char *hostname, unsigned short port );
+JNL_API void jnl_udp_set_peer_address( jnl_udp_t connection, struct sockaddr *addr, socklen_t length );
+// gets the address of whomever sent the last message
+JNL_API int jnl_udp_get_address( jnl_udp_t connection, struct sockaddr **addr, socklen_t *length );
+
+/* ----- HTTP ----- */
+
+/* creation/destruction */
+JNL_API jnl_http_t jnl_http_create( int recvbufsize, int sendbufsize );
+JNL_API int jnl_http_set_recv_buffer_size( jnl_http_t http, size_t new_size ); /* increases the receive buffer size */
+JNL_API jnl_http_t jnl_http_retain( jnl_http_t http );
+JNL_API void jnl_http_release( jnl_http_t http );
+JNL_API jnl_connection_t jnl_http_get_connection( jnl_http_t http );
+/* TODO: replace these with a jnl_http_configure(jnl_http_t http) function */
+JNL_API void jnl_http_set_persistent( jnl_http_t http );
+JNL_API void jnl_http_allow_compression( jnl_http_t http );
+JNL_API void jnl_http_allow_accept_all_reply_codes( jnl_http_t http );
+
+/* run & status stuff */
+JNL_API void jnl_http_connect( jnl_http_t http, const char *url, int http_version, const char *method );
+JNL_API int jnl_http_run( jnl_http_t http );
+JNL_API int jnl_http_get_status( jnl_http_t http );
+JNL_API int jnl_http_getreplycode( jnl_http_t http );
+JNL_API const char *jnl_http_getreply( jnl_http_t http );
+
+/* reading data */
+JNL_API size_t jnl_http_get_bytes( jnl_http_t http, void *buf, size_t len );
+JNL_API size_t jnl_http_peek_bytes( jnl_http_t http, void *buf, size_t len );
+JNL_API size_t jnl_http_bytes_available( jnl_http_t http );
+JNL_API uint64_t jnl_http_content_length( jnl_http_t http );
+
+/* HTTP headers */
+JNL_API const char *jnl_http_getheader( jnl_http_t http, const char *header );
+JNL_API void jnl_http_addheader( jnl_http_t http, const char *header );
+JNL_API void jnl_http_addheadervalue( jnl_http_t http, const char *header, const char *value );
+JNL_API void jnl_http_reset_headers( jnl_http_t http );
+JNL_API const char *jnl_http_get_all_headers( jnl_http_t http );
+
+/* other information */
+JNL_API const char *jnl_http_get_url( jnl_http_t http );
+JNL_API void jnl_http_set_proxy( const char *proxy );
+
+/* ----- HTTP Request Parsing ----- */
+JNL_API int jnl_http_request_create( jnl_http_request_t *http, jnl_connection_t connection );
+JNL_API void jnl_http_request_release( jnl_http_request_t http );
+JNL_API int jnl_http_request_run( jnl_http_request_t http );
+JNL_API int jnl_htt_request_get_keep_alive( jnl_http_request_t http );
+JNL_API const char *jnl_http_request_get_header( jnl_http_request_t http, const char *header );
+JNL_API void jnl_http_request_reset( jnl_http_request_t http );
+JNL_API void jnl_http_request_addheader( jnl_http_request_t http, const char *header );
+JNL_API void jnl_http_request_set_reply_string( jnl_http_request_t http, const char *reply );
+JNL_API void jnl_http_request_send_reply( jnl_http_request_t http );
+JNL_API const char *jnl_http_request_get_uri( jnl_http_request_t http );
+JNL_API const char *jnl_http_request_get_parameter( jnl_http_request_t _http, const char *parameter );
+JNL_API jnl_connection_t jnl_http_request_get_connection( jnl_http_request_t http );
+JNL_API const char *jnl_http_request_get_method( jnl_http_request_t http );
+
+/* ----- HTTPU Request Parsing ----- */
+JNL_API int jnl_httpu_request_create( jnl_httpu_request_t *httpu );
+JNL_API void jnl_httpu_request_release( jnl_httpu_request_t httpu );
+JNL_API int jnl_httpu_request_process( jnl_httpu_request_t httpu, jnl_udp_t udp );
+JNL_API const char *jnl_httpu_request_get_method( jnl_httpu_request_t httpu );
+JNL_API const char *jnl_httpu_request_get_uri( jnl_httpu_request_t httpu );
+JNL_API const char *jnl_httpu_request_get_header( jnl_httpu_request_t httpu, const char *header );
+
+/* ----- DNS ------ */
+JNL_API int jnl_dns_create( jnl_dns_t *dns );
+JNL_API void jnl_dns_release( jnl_dns_t dns );
+JNL_API int jnl_dns_resolve( jnl_dns_t dns, const char *hostname, unsigned short port, struct addrinfo **addr, int sockettype );
+// when you call jnl_dns_resolve_now, you need to call jnl_dns_freeaddrinfo
+JNL_API int jnl_dns_resolve_now( const char *hostname, unsigned short port, struct addrinfo **addr, int sockettype );
+JNL_API void jnl_dns_freeaddrinfo( struct addrinfo *addr );
+JNL_API void jnl_dns_gethostname( char *name, size_t cch );
+JNL_API void jnl_dns_ntop( int af, const void *src, char *dst, socklen_t size );
+/* listen */
+JNL_API int jnl_listen_create( jnl_listen_t *listen, unsigned short port );
+JNL_API int jnl_listen_create_from_address( jnl_listen_t *listen, struct addrinfo *addr, size_t index );
+JNL_API void jnl_listen_release( jnl_listen_t listen );
+JNL_API jnl_connection_t jnl_listen_get_connection( jnl_listen_t listen );
+JNL_API unsigned short jnl_listen_get_port( jnl_listen_t listen );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif//_JNETLIB_H_
diff --git a/Src/replicant/jnetlib/jnetlib.sln b/Src/replicant/jnetlib/jnetlib.sln
new file mode 100644
index 00000000..a8e81332
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib.sln
@@ -0,0 +1,54 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29509.3
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
+ {E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
+ {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
+ {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
+ EndGlobalSection
+EndGlobal
diff --git a/Src/replicant/jnetlib/jnetlib.vcxproj b/Src/replicant/jnetlib/jnetlib.vcxproj
new file mode 100644
index 00000000..c0913b22
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib.vcxproj
@@ -0,0 +1,281 @@
+<?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="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{E105A0A2-7391-47C5-86AC-718003524C3D}</ProjectGuid>
+ <RootNamespace>jnetlib</RootNamespace>
+ <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ <PlatformToolset>v142</PlatformToolset>
+ </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)'=='Debug|x64'">
+ <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>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <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>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ <IncludePath>$(IncludePath)</IncludePath>
+ <LibraryPath>$(LibraryPath)</LibraryPath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
+ <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg">
+ <VcpkgEnableManifest>false</VcpkgEnableManifest>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ <VcpkgConfiguration>Debug</VcpkgConfiguration>
+ </PropertyGroup>
+ <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <VcpkgInstalledDir>
+ </VcpkgInstalledDir>
+ <VcpkgUseStatic>false</VcpkgUseStatic>
+ <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>false</MinimalRebuild>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ <AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\
+xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <TargetMachine>MachineX86</TargetMachine>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;JNETLIB_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <StringPooling>true</StringPooling>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>None</DebugInformationFormat>
+ <DisableSpecificWarnings>4244;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>ws2_32.lib;Crypt32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+ </Link>
+ <PostBuildEvent>
+ <Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\ </Command>
+ <Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Shared\'</Message>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="asyncdns.cpp" />
+ <ClCompile Include="connection.cpp" />
+ <ClCompile Include="Headers.cpp" />
+ <ClCompile Include="httpget.cpp" />
+ <ClCompile Include="httpserv.cpp" />
+ <ClCompile Include="httpuserv.cpp" />
+ <ClCompile Include="jnetlib.cpp" />
+ <ClCompile Include="listen.cpp" />
+ <ClCompile Include="multicastlisten.cpp" />
+ <ClCompile Include="sslconnection.cpp" />
+ <ClCompile Include="udpconnection.cpp" />
+ <ClCompile Include="util.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="asyncdns.h" />
+ <ClInclude Include="connection.h" />
+ <ClInclude Include="Headers.h" />
+ <ClInclude Include="httpget.h" />
+ <ClInclude Include="httpserv.h" />
+ <ClInclude Include="httpuserv.h" />
+ <ClInclude Include="jnetlib.h" />
+ <ClInclude Include="jnetlib_defines.h" />
+ <ClInclude Include="listen.h" />
+ <ClInclude Include="multicastlisten.h" />
+ <ClInclude Include="netinc.h" />
+ <ClInclude Include="sslconnection.h" />
+ <ClInclude Include="udpconnection.h" />
+ <ClInclude Include="util.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="jnetlib-replicant.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\nu\nu.vcxproj">
+ <Project>{f1f5cd60-0d5b-4cea-9eeb-2f87ff9aa915}</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/Src/replicant/jnetlib/jnetlib.vcxproj.filters b/Src/replicant/jnetlib/jnetlib.vcxproj.filters
new file mode 100644
index 00000000..09c9c057
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib.vcxproj.filters
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="Headers.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="jnetlib.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="multicastlisten.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="connection.cpp">
+ <Filter>Source Files\Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="asyncdns.cpp">
+ <Filter>Source Files\DNS</Filter>
+ </ClCompile>
+ <ClCompile Include="sslconnection.cpp">
+ <Filter>Source Files\Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="httpget.cpp">
+ <Filter>Source Files\HTTP Receiver</Filter>
+ </ClCompile>
+ <ClCompile Include="httpserv.cpp">
+ <Filter>Source Files\HTTP Server</Filter>
+ </ClCompile>
+ <ClCompile Include="udpconnection.cpp">
+ <Filter>Source Files\UDP Connection</Filter>
+ </ClCompile>
+ <ClCompile Include="listen.cpp">
+ <Filter>Source Files\Web Server</Filter>
+ </ClCompile>
+ <ClCompile Include="httpuserv.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="Headers.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="httpuserv.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="jnetlib.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="jnetlib_defines.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="netinc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="connection.h">
+ <Filter>Header Files\Connection</Filter>
+ </ClInclude>
+ <ClInclude Include="asyncdns.h">
+ <Filter>Header Files\DNS</Filter>
+ </ClInclude>
+ <ClInclude Include="sslconnection.h">
+ <Filter>Header Files\Connection</Filter>
+ </ClInclude>
+ <ClInclude Include="httpget.h">
+ <Filter>Header Files\HTTP Receiver</Filter>
+ </ClInclude>
+ <ClInclude Include="httpserv.h">
+ <Filter>Header Files\HTTP Server</Filter>
+ </ClInclude>
+ <ClInclude Include="listen.h">
+ <Filter>Header Files\Web Server</Filter>
+ </ClInclude>
+ <ClInclude Include="udpconnection.h">
+ <Filter>Header Files\UDP Connection</Filter>
+ </ClInclude>
+ <ClInclude Include="multicastlisten.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{bcdc816d-5cef-49ce-bcae-e765d84d9d0d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Ressource Files">
+ <UniqueIdentifier>{22cf6f69-c499-4eb0-851c-e405c0343744}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{ebc9b8af-fa9f-4cb3-bd28-a6f2fa43f47a}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Connection">
+ <UniqueIdentifier>{08aa3960-7673-4eee-a554-f75b30f6ca9d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\DNS">
+ <UniqueIdentifier>{2194f281-7614-4fce-ae5b-14ebe64c75df}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\HTTP Receiver">
+ <UniqueIdentifier>{2a2b5cdf-93f4-4228-ab77-50138a1df782}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\HTTP Server">
+ <UniqueIdentifier>{c3f9a1b8-ab75-4d41-b614-df702b4a9113}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\UDP Connection">
+ <UniqueIdentifier>{080bb148-d8bc-41d5-b2a2-405b3068b15f}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Web Server">
+ <UniqueIdentifier>{2208b2ff-bd0e-42a9-b60b-fb6c1be6bad8}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Connection">
+ <UniqueIdentifier>{ab26ced4-713d-4b15-bea7-49219fe68955}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\DNS">
+ <UniqueIdentifier>{336ee3a1-044b-42c0-9f39-f03f381c73ee}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\HTTP Receiver">
+ <UniqueIdentifier>{b7051bc5-90cf-4673-8274-02c12e3da56c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\HTTP Server">
+ <UniqueIdentifier>{48e64e69-bc76-467b-8fd3-3430694896ee}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Web Server">
+ <UniqueIdentifier>{ad8b2861-d8e2-4737-b293-124ad361f20c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\UDP Connection">
+ <UniqueIdentifier>{60bab4c5-d369-4284-b314-dd8c3c4dcd37}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="jnetlib-replicant.rc">
+ <Filter>Ressource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/Src/replicant/jnetlib/jnetlib_defines.h b/Src/replicant/jnetlib/jnetlib_defines.h
new file mode 100644
index 00000000..76647604
--- /dev/null
+++ b/Src/replicant/jnetlib/jnetlib_defines.h
@@ -0,0 +1,66 @@
+#pragma once
+#include "../foundation/types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Connection */
+typedef struct jnl_connection_struct jnl_connection_struct;
+typedef jnl_connection_struct *jnl_connection_t;
+
+enum
+{
+ JNL_CONNECTION_STATE_ERROR = 0,
+ JNL_CONNECTION_STATE_NOCONNECTION = 1,
+ JNL_CONNECTION_STATE_RESOLVING = 2,
+ JNL_CONNECTION_STATE_CONNECTING = 3,
+ JNL_CONNECTION_STATE_CONNECTED = 4,
+ JNL_CONNECTION_STATE_CLOSING = 5,
+ JNL_CONNECTION_STATE_CLOSED = 6,
+ JNL_CONNECTION_STATE_RESOLVED = 7, // happens after RESOLVING, but going here for compatability
+};
+
+/* UDP */
+typedef struct jnl_udp_struct jnl_udp_struct;
+typedef jnl_udp_struct *jnl_udp_t;
+
+/* HTTP */
+typedef struct jnl_http_struct jnl_http_struct;
+typedef jnl_http_struct *jnl_http_t;
+
+enum
+{
+ HTTPGET_STATUS_ERROR = -1,
+ JNL_HTTP_STATUS_ERROR = HTTPGET_STATUS_ERROR,
+ HTTPGET_STATUS_CONNECTING = 0,
+ JNL_HTTP_STATUS_CONNECTING = HTTPGET_STATUS_CONNECTING,
+ HTTPGET_STATUS_READING_HEADERS = 1,
+ JNL_HTTP_STATUS_READING_HEADERS = HTTPGET_STATUS_READING_HEADERS,
+ HTTPGET_STATUS_READING_CONTENT = 2,
+ JNL_HTTP_STATUS_READING_CONTENT = HTTPGET_STATUS_READING_CONTENT,
+};
+
+enum
+{
+ HTTPGET_RUN_ERROR = -1,
+ HTTPGET_RUN_OK = 0,
+ JNL_HTTP_RUN_OK = HTTPGET_RUN_OK,
+ HTTPGET_RUN_CONNECTION_CLOSED = 1,
+};
+
+/* DNS */
+typedef struct jnl_dns_struct jnl_dns_struct;
+typedef jnl_dns_struct *jnl_dns_t;
+
+typedef struct jnl_httpu_request_struct jnl_httpu_request_struct;
+typedef jnl_httpu_request_struct *jnl_httpu_request_t;
+
+typedef struct jnl_http_request_struct jnl_http_request_struct;
+typedef jnl_http_request_struct *jnl_http_request_t;
+
+typedef struct jnl_listen_struct jnl_listen_struct;
+typedef jnl_listen_struct *jnl_listen_t;
+
+#ifdef __cplusplus
+}
+#endif \ No newline at end of file
diff --git a/Src/replicant/jnetlib/listen.cpp b/Src/replicant/jnetlib/listen.cpp
new file mode 100644
index 00000000..20d34d06
--- /dev/null
+++ b/Src/replicant/jnetlib/listen.cpp
@@ -0,0 +1,131 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2013 Nullsoft, Inc.
+** Author: Justin Frankel, Ben Allison
+** File: listen.cpp - JNL TCP listen implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "listen.h"
+#include "foundation/error.h"
+
+JNL_Listen::JNL_Listen()
+{
+ m_port=0;
+ m_socket=-1;
+}
+
+int JNL_Listen::Initialize(unsigned short port, sockaddr *which_interface, int family)
+{
+ m_port = port;
+
+ char portString[32] = {0};
+ sprintf(portString, "%d", (int)port);
+
+ addrinfo *res;
+
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ hints.ai_addr = which_interface?which_interface:INADDR_ANY;
+
+ if (getaddrinfo(NULL, portString, &hints, &res) == 0)
+ {
+ int ret = Initialize(res, 0);
+ freeaddrinfo(res);
+ return ret;
+ }
+ else
+ {
+ return NErr_Error;
+ }
+}
+
+int JNL_Listen::Initialize(addrinfo *address, size_t index)
+{
+ addrinfo *res = address;
+
+ while (index--)
+ {
+ res = res->ai_next;
+ if (!res)
+ return NErr_EndOfEnumeration;
+ }
+
+ m_socket = ::socket(res->ai_family,res->ai_socktype, res->ai_protocol);
+ if (m_socket < 0)
+ {
+ freeaddrinfo(res);
+ return NErr_Error;
+ }
+ else
+ {
+ SET_SOCK_BLOCK(m_socket,0);
+#ifndef _WIN32
+ int bflag = 1;
+ setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &bflag, sizeof(bflag));
+#endif
+ if (::bind(m_socket, res->ai_addr, (int)res->ai_addrlen))
+ {
+ closesocket(m_socket);
+ m_socket=-1;
+ return NErr_Error;
+ }
+ else if (::listen(m_socket,8)==-1)
+ {
+ closesocket(m_socket);
+ m_socket=-1;
+ return NErr_Error;
+ }
+ }
+ return NErr_Success;
+}
+
+JNL_Listen::~JNL_Listen()
+{
+ if (m_socket>=0)
+ {
+ closesocket(m_socket);
+ }
+}
+
+JNL_Connection *JNL_Listen::get_connect(size_t sendbufsize, size_t recvbufsize)
+{
+ if (m_socket < 0)
+ {
+ return NULL;
+ }
+ sockaddr_storage saddr;
+ socklen_t length = sizeof(saddr);
+ SOCKET s = accept(m_socket, (sockaddr *)&saddr, &length);
+ if (s != -1)
+ {
+ JNL_Connection *c=new JNL_Connection(NULL,sendbufsize, recvbufsize);
+ c->connect(s, (sockaddr *)&saddr, length);
+ return c;
+ }
+
+ return NULL;
+}
+
+socklen_t JNL_Listen::get_address(sockaddr* address, socklen_t *address_len)
+{
+ return getsockname(m_socket, address, address_len);
+}
+
+unsigned short JNL_Listen::get_port()
+{
+ if (!m_port)
+ {
+ sockaddr_in address;
+ socklen_t namelen = sizeof(address);
+ if (getsockname(m_socket, (sockaddr *)&address, &namelen) == 0)
+ m_port = ntohs(address.sin_port);
+ }
+
+ return m_port;
+} \ No newline at end of file
diff --git a/Src/replicant/jnetlib/listen.h b/Src/replicant/jnetlib/listen.h
new file mode 100644
index 00000000..dc8cfc18
--- /dev/null
+++ b/Src/replicant/jnetlib/listen.h
@@ -0,0 +1,44 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2013 Nullsoft, Inc.
+** Author: Justin Frankel, Ben Allison
+** File: listen.h - JNL interface for opening a TCP listen
+** License: see jnetlib.h
+**
+** Usage:
+** 1. create a JNL_Listen object with the port and (optionally) the interface
+** to listen on.
+** 2. call get_connect() to get any new connections (optionally specifying what
+** buffer sizes the connection should be created with)
+** 3. check is_error() to see if an error has occured
+** 4. call port() if you forget what port the listener is on.
+**
+*/
+
+#ifndef _LISTEN_H_
+#define _LISTEN_H_
+
+#include "connection.h"
+#include "nswasabi/ReferenceCounted.h"
+
+class JNL_Listen : public ReferenceCountedBase<JNL_Listen>
+{
+public:
+ JNL_Listen();
+ ~JNL_Listen();
+
+ int Initialize( unsigned short port, sockaddr *which_interface = 0, int family = PF_UNSPEC );
+ int Initialize( struct addrinfo *address, size_t index );
+
+ JNL_Connection *get_connect( size_t sendbufsize = 8192, size_t recvbufsize = 8192 );
+ unsigned short get_port();
+ int is_error( void ) { return ( m_socket < 0 ); }
+
+ socklen_t get_address( sockaddr *address, socklen_t *address_len );
+
+protected:
+ SOCKET m_socket;
+ unsigned short m_port;
+};
+
+#endif //_LISTEN_H_
diff --git a/Src/replicant/jnetlib/multicastlisten.cpp b/Src/replicant/jnetlib/multicastlisten.cpp
new file mode 100644
index 00000000..21eea33c
--- /dev/null
+++ b/Src/replicant/jnetlib/multicastlisten.cpp
@@ -0,0 +1,123 @@
+/*
+** JNetLib
+** Copyright (C) 2008 Nullsoft, Inc.
+** Author: Ben Allison
+** File: multicastlisten.cpp - JNL Multicast UDP listen implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "multicastlisten.h"
+#include "foundation/error.h"
+#include <new>
+
+int CreateMulticastListener(JNL_UDPConnection **connection, const char *mcast_ip, unsigned short port, size_t sendbufsize, size_t recvbufsize)
+{
+ char portString[32] = {0};
+
+ if (port)
+ sprintf(portString, "%d", (int)port);
+
+ addrinfo *res=0;
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET; /* IPv4 only for now until we get IPv6 multicast registration working */
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ hints.ai_protocol = IPPROTO_UDP;
+
+ if (getaddrinfo(NULL, port?portString:0, &hints, &res) == 0)
+ {
+ SOCKET m_socket = ::socket(res->ai_family,res->ai_socktype, res->ai_protocol);
+ if (m_socket < 0)
+ {
+ freeaddrinfo(res);
+ return NErr_Error;
+ }
+ else
+ {
+ SET_SOCK_BLOCK(m_socket,0);
+
+ int bflag = 1;
+ if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bflag, sizeof(bflag)))
+ {
+ /*int err = ERRNO;
+ err=err;
+ printf("SO_REUSEADDR error: %d\n", err);*/
+ }
+#if defined(__FreeBSD__) || defined(__APPLE__)
+ bflag=1; // in case it magically got unset above
+ setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (const char *)&bflag, sizeof(bflag));
+#endif
+ if (::bind(m_socket, res->ai_addr, (int)res->ai_addrlen))
+ {
+ closesocket(m_socket);
+ return NErr_Error;
+ }
+ else
+ {
+ // TODO: ipv6 with IPV6_ADD_MEMBERSHIP and ipv6_mreq
+
+ sockaddr_in *ipv4 = (sockaddr_in *)res->ai_addr;
+
+ /* join multicast group */
+ ip_mreq ssdpMcastAddr;
+ memset(&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr));
+ ssdpMcastAddr.imr_interface = ipv4->sin_addr;
+ ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr(mcast_ip);
+ if (setsockopt(m_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr)))
+ {
+ closesocket(m_socket);
+ freeaddrinfo(res);
+ return NErr_Error;
+ }
+
+ /* Set multicast interface. */
+ in_addr addr;
+ memset(&addr, 0, sizeof(addr));
+ addr = ipv4->sin_addr;
+ if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&addr, sizeof(addr)))
+ {
+ /*int err = ERRNO;
+ err=err;
+ printf("IP_MULTICAST_IF error: %d\n", err);*/
+ /* This is probably not a critical error, so let's continue. */
+ }
+
+ /* set TTL to 4 */
+ uint8_t ttl=4;
+ if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl)))
+ {
+ /*int err = ERRNO;
+ err=err;
+ printf("IP_MULTICAST_TTL error: %d\n", err);*/
+ /* This is probably not a critical error, so let's continue. */
+ }
+
+ int option = 1;
+ if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (const char *)&option, sizeof(option)) != 0)
+ {
+ closesocket(m_socket);
+ freeaddrinfo(res);
+ return NErr_Error;
+ }
+ }
+ }
+ freeaddrinfo(res);
+ JNL_UDPConnection *c=new (std::nothrow) JNL_UDPConnection();
+ if (!c)
+ {
+ closesocket(m_socket);
+ return NErr_OutOfMemory;
+ }
+ c->open((int)m_socket, NULL, sendbufsize, recvbufsize);
+ *connection = c;
+ return NErr_Success;
+ }
+ else
+ {
+ return NErr_Error;
+ }
+}
+
diff --git a/Src/replicant/jnetlib/multicastlisten.h b/Src/replicant/jnetlib/multicastlisten.h
new file mode 100644
index 00000000..eaa918a1
--- /dev/null
+++ b/Src/replicant/jnetlib/multicastlisten.h
@@ -0,0 +1,26 @@
+/*
+** JNetLib
+** Copyright (C) 2008 Nullsoft, Inc.
+** Author: Ben Allison
+** File: multicastlisten.h - JNL interface for opening a Multicast UDP listen
+** License: see jnetlib.h
+**
+** Usage:
+** 1. create a JNL_MulticastUDPListen object with the port and (optionally) the interface
+** to listen on.
+** 2. call get_connect() to get the associated UDP connection (optionally specifying what
+** buffer sizes the connection should be created with). Unlike TCP listen, there is only one listen object.
+** 3. check is_error() to see if an error has occured
+** 4. call port() if you forget what port the listener is on.
+**
+*/
+
+#ifndef _MULTICASTLISTEN_H_
+#define _MULTICASTLISTEN_H_
+
+#include "udpconnection.h"
+
+
+int CreateMulticastListener( JNL_UDPConnection **connection, const char *mcast_ip, unsigned short port, size_t sendbufsize = 8192, size_t recvbufsize = 8192 );
+
+#endif //_LISTEN_H_
diff --git a/Src/replicant/jnetlib/netinc.h b/Src/replicant/jnetlib/netinc.h
new file mode 100644
index 00000000..1952d3d7
--- /dev/null
+++ b/Src/replicant/jnetlib/netinc.h
@@ -0,0 +1,84 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2006 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: netinc.h - network includes and portability defines (used internally)
+** License: see jnetlib.h
+*/
+
+#ifndef _NETINC_H_
+#define _NETINC_H_
+
+#ifdef _WIN32
+
+//#include <time.h>
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <winsock2.h>
+#include <Ws2tcpip.h>
+#include <wspiapi.h>
+#include "../foundation/types.h"
+
+#define strtoull(x,y,z) _strtoui64(x,y,z)
+#define strcasecmp(x,y) _stricmp(x,y)
+#define strcasecmpn(x,y, count) _strnicmp(x,y,count)
+#define strncasecmp(x,y, count) _strnicmp(x,y,count)
+#define HTONS(val) ((((unsigned short) (val) & (unsigned short) 0x00ffU) << 8) | (((unsigned short) (val) & (unsigned short) 0xff00U) >> 8))
+#define ERRNO (WSAGetLastError())
+#define SET_SOCK_BLOCK(s,block) { unsigned long __i=block?0:1; ioctlsocket(s,FIONBIO,&__i); }
+#define JNL_EWOULDBLOCK WSAEWOULDBLOCK
+#define JNL_EINPROGRESS WSAEWOULDBLOCK
+
+#else
+#define JNL_EWOULDBLOCK EWOULDBLOCK
+#define JNL_EINPROGRESS EINPROGRESS
+#ifndef THREAD_SAFE
+#define THREAD_SAFE
+#endif
+#ifndef _REENTRANT
+#define _REENTRANT
+#endif
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#define ERRNO errno
+#define closesocket(s) close(s)
+#define SET_SOCK_BLOCK(s,block) { int __flags; if ((__flags = fcntl(s, F_GETFL, 0)) != -1) { if (!block) __flags |= O_NONBLOCK; else __flags &= ~O_NONBLOCK; fcntl(s, F_SETFL, __flags); } }
+
+#define _stricmp(x,y) strcasecmp(x,y)
+#define _strnicmp(x,y,z) strncasecmp(x,y,z)
+#define wsprintf sprintf
+typedef int SOCKET;
+
+#endif // !_WIN32
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#ifndef INADDR_ANY
+#define INADDR_ANY 0
+#endif
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+#endif //_NETINC_H_
diff --git a/Src/replicant/jnetlib/resource.h b/Src/replicant/jnetlib/resource.h
new file mode 100644
index 00000000..b6cf148a
--- /dev/null
+++ b/Src/replicant/jnetlib/resource.h
@@ -0,0 +1,14 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by jnetlib-replicant.rc
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/Src/replicant/jnetlib/sslconnection.cpp b/Src/replicant/jnetlib/sslconnection.cpp
new file mode 100644
index 00000000..5362c445
--- /dev/null
+++ b/Src/replicant/jnetlib/sslconnection.cpp
@@ -0,0 +1,329 @@
+//#ifdef USE_SSL
+//#include "netinc.h"
+//#include "util.h"
+//#include "connection.h"
+#include "sslconnection.h"
+
+SSL_CTX *sslContext = 0;
+
+#ifdef _DEBUG
+
+extern "C" void apps_ssl_info_callback (const SSL * s, int where, int ret)
+{
+ /*
+ ** DEBUG INFO HERE
+ */
+}
+#endif
+
+/*
+** Well, you should probably change this based on like...
+** well, you're level of trust heh
+** For now, this basically trusts all certs :)
+**
+*/
+#if 0
+extern "C" int verify_callback(int ok, X509_STORE_CTX * ctx)
+{
+ /* For certificate verification */
+ int verify_depth = 0;
+ int verify_error = X509_V_OK;
+
+ char buf[1024] = {0};
+ X509 * err_cert = X509_STORE_CTX_get_current_cert(ctx);
+ int err = X509_STORE_CTX_get_error(ctx);
+ int depth = X509_STORE_CTX_get_error_depth(ctx);
+ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
+
+ if (!ok)
+ {
+ if (verify_depth >= depth)
+ {
+ ok = 1;
+ verify_error = X509_V_OK;
+ }
+ else
+ {
+ ok = 0;
+ verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+ }
+ }
+ switch (ctx->error)
+ {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, sizeof(buf));
+ break;
+
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ break;
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ break;
+ }
+ return ok;
+}
+#endif
+
+JNL_SSL_Connection::JNL_SSL_Connection() : forceConnect(false), m_ssl(0), m_bsslinit(false), m_bcontextowned(true)
+{
+ m_bsslinit = true;
+}
+
+
+JNL_SSL_Connection::JNL_SSL_Connection(SSL* pssl, JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize) : JNL_Connection(dns, sendbufsize, recvbufsize),
+ forceConnect(false)
+{
+ m_ssl = pssl;
+ m_bsslinit = false;
+
+ if (m_ssl)
+ {
+ m_bcontextowned = false;
+ }
+ else
+ {
+ m_bcontextowned = true;
+ }
+
+ if (m_bcontextowned == false)
+ {
+ return ;
+ }
+
+ m_bsslinit = true;
+
+
+ /* See the SSL states in our own callback */
+#ifdef _DEBUG
+ // SSL_CTX_set_info_callback(m_app_ctx, apps_ssl_info_callback);
+#endif
+
+ /* Set the certificate verification callback */
+ //SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, verify_callback);
+
+ /* Not sure what this does */
+ //SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_CLIENT);
+
+ return ;
+}
+
+int JNL_SSL_Connection::socket_connect()
+{
+ int retval;
+
+ if (m_bcontextowned == false)
+ {
+ /*
+ ** WTF?
+ */
+ return -1;
+ }
+ if (m_ssl != NULL)
+ {
+ return -1;
+ }
+
+ retval = JNL_Connection::socket_connect();
+
+ if (retval != 0)
+ {
+ if (ERRNO != JNL_EINPROGRESS)
+ {
+ return retval; // benski> if the underlying socket hasn't connected yet, then we can't start the SSL connection
+ /*
+ ** Joshua Teitelbaum 3/2/2006
+ ** Fatal error here
+ */
+ }
+ }
+
+ // moved from InitSSL() as no need to create this unless
+ // we're actually going to use it which helps slow loads
+ if (!sslContext)
+ {
+ sslContext = SSL_CTX_new(SSLv23_client_method());
+ if (sslContext)
+ {
+ SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ m_ssl = SSL_new(sslContext);
+
+ if (m_ssl == NULL)
+ {
+ return -1;
+ }
+
+ /* Tell that we are in connect mode */
+ SSL_set_connect_state(m_ssl);
+
+ /* Set socket descriptor with the socket we already have open */
+ if(SSL_set_fd(m_ssl, m_socket) != 0)
+ {
+ return -1;
+ }
+
+ return retval;
+}
+
+void JNL_SSL_Connection::socket_shutdown()
+{
+ if (m_ssl)
+ SSL_shutdown(m_ssl);
+ JNL_Connection::socket_shutdown();
+
+ if (m_ssl)
+ {
+ SSL_free(m_ssl);
+ m_ssl = NULL;
+ }
+ return ;
+}
+
+void JNL_SSL_Connection::run(size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
+{
+ if (!m_bsslinit)
+ {
+ int rval = SSL_accept(m_ssl);
+ if (rval == -1)
+ {
+ int e = SSL_get_error(m_ssl, rval);
+
+ if (!((e == SSL_ERROR_WANT_READ) || (e == SSL_ERROR_WANT_WRITE)))
+ {
+ m_state = STATE_ERROR;
+ }
+
+ return ;
+ }
+ else
+ {
+ m_bsslinit = true;
+ }
+ }
+
+ /**
+ ** benski - march 2, 2006
+ **if the underlying socket didn't connected yet, we need to try the SSL connection again
+ */
+ if (forceConnect)
+ {
+ if(init_ssl_connection() == false)
+ {
+ return;
+ }
+ }
+ JNL_Connection::run(max_send_bytes, max_recv_bytes, bytes_sent, bytes_rcvd);
+}
+
+/*
+** init_ssl_connection:
+** Returns true, meaning can continue
+** Else, cannot continue with underlying run
+** side effects:
+** sets forceConnect
+*/
+bool JNL_SSL_Connection::init_ssl_connection()
+{
+ if(m_ssl == NULL)
+ {
+ /*
+ ** WTF?
+ ** cascade up.
+ */
+ return true;
+ }
+
+ int retval = SSL_connect(m_ssl);
+
+ if (retval < 0)
+ {
+ int err = SSL_get_error(m_ssl, retval);
+
+ switch (err)
+ {
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ forceConnect = true;
+ break;
+ // fall through
+ default: // TODO: benski> MOST other errors are OK, (especially "want read" and "want write", but we need to think through all the scenarios here
+ forceConnect=false;
+ }
+ }
+ else if(retval)
+ {
+ /*
+ ** success
+ */
+ forceConnect = false;
+ }
+
+ /*
+ ** If retval == 0
+ ** socket is closed, or serious error occurred.
+ ** cascade up.
+ */
+
+ return forceConnect==false;
+}
+
+void JNL_SSL_Connection::on_socket_connected(void)
+{
+ init_ssl_connection();
+}
+
+void JNL_SSL_Connection::connect(SOCKET s, sockaddr *addr, socklen_t length)
+{
+ /*
+ ** Joshua Teitelbaum 2/01/2006
+ ** No need to close
+ ** This is the reason for divergence as well as setting
+ ** the connect state
+ */
+
+ m_socket = s;
+ address=(sockaddr *)malloc(length);
+ memcpy(address, addr, length);
+
+ m_remote_port = 0;
+ if (m_socket != -1)
+ {
+ SET_SOCK_BLOCK(m_socket, 0);
+ m_state = STATE_CONNECTED;
+ SSL_set_fd(m_ssl, m_socket);
+ }
+ else
+ {
+ m_errorstr = "invalid socket passed to connect";
+ m_state = STATE_ERROR;
+ }
+}
+
+ssize_t JNL_SSL_Connection::socket_recv(char *buf, size_t len, int options)
+{
+ return SSL_read(m_ssl, buf, (int)len);
+}
+
+ssize_t JNL_SSL_Connection::socket_send(const char *buf, size_t len, int options)
+{
+ return SSL_write(m_ssl, buf, (int)len);
+}
+
+JNL_SSL_Connection::~JNL_SSL_Connection()
+{
+ if (m_ssl)
+ {
+ SSL_free(m_ssl);
+ m_ssl = NULL;
+ }
+}
+//#endif \ No newline at end of file
diff --git a/Src/replicant/jnetlib/sslconnection.h b/Src/replicant/jnetlib/sslconnection.h
new file mode 100644
index 00000000..f6e54d05
--- /dev/null
+++ b/Src/replicant/jnetlib/sslconnection.h
@@ -0,0 +1,61 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2006 CockOS, Inc.
+** Author: Justin Frankel, Joshua Teitelbaum
+** File: sslconnection.h - JNL SSL TCP connection interface
+** License: see jnetlib.h
+*/
+
+#ifndef _JNETLIB_SSL_H_
+#define _JNETLIB_SSL_H_
+
+#include "netinc.h"
+#include "util.h"
+#include "connection.h"
+
+/*
+** AUTOLINK WITH THESE GUYS NOT IN PROJECT HEH HEH :)
+** Build and go, for you :)
+*/
+
+#include <openssl/ssl.h>
+
+class JNL_SSL_Connection : public JNL_Connection
+{
+protected:
+ SSL *m_ssl;
+ bool m_bcontextowned;
+ bool m_bsslinit;
+
+public:
+ JNL_SSL_Connection();
+ JNL_SSL_Connection( SSL *pssl, JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize );
+ virtual ~JNL_SSL_Connection();
+
+ virtual void connect( SOCKET sock, sockaddr *addr, socklen_t length /* of addr */ ); // used by the listen object, usually not needed by users.
+ virtual void run( size_t max_send_bytes = -1, size_t max_recv_bytes = -1, size_t *bytes_sent = NULL, size_t *bytes_rcvd = NULL );
+
+ /*
+ ** Joshua Teitelbaum 1/27/2006 Adding new BSD socket analogues for SSL compatibility
+ */
+protected:
+ virtual void socket_shutdown();
+ virtual ssize_t socket_recv( char *buf, size_t len, int options );
+ virtual ssize_t socket_send( const char *buf, size_t len, int options );
+ virtual int socket_connect();
+ virtual void on_socket_connected();
+ /*
+ ** init_ssl_connection:
+ ** returns true if can continue onwards (could be error, in which case
+ ** we want the error to cascade through).
+ ** Else, false if connection was not made, and we have to call this
+ ** again.
+ */
+ bool init_ssl_connection();
+
+ bool forceConnect;
+};
+
+extern SSL_CTX *sslContext;
+
+#endif
diff --git a/Src/replicant/jnetlib/udpconnection.cpp b/Src/replicant/jnetlib/udpconnection.cpp
new file mode 100644
index 00000000..fbb36eca
--- /dev/null
+++ b/Src/replicant/jnetlib/udpconnection.cpp
@@ -0,0 +1,384 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2001 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: udpconnection.cpp - JNL UDP connection implementation
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "udpconnection.h"
+
+JNL_UDPConnection::JNL_UDPConnection(unsigned short incoming_port, JNL_AsyncDNS *dns, int sendbufsize, int recvbufsize)
+{
+ init();
+ open(dns, sendbufsize, recvbufsize);
+
+ m_socket=::socket(PF_INET,SOCK_DGRAM,0);
+ if (m_socket==-1)
+ {
+ m_errorstr="creating socket";
+ m_state=STATE_ERROR;
+ }
+ SET_SOCK_BLOCK(m_socket,0);
+ sockaddr_in m_iaddr;
+ memset(&m_iaddr,0,sizeof(struct sockaddr_in));
+ m_iaddr.sin_family=AF_INET;
+ m_iaddr.sin_port=htons(incoming_port);
+ m_iaddr.sin_addr.s_addr = htonl( INADDR_ANY );
+ if(::bind(m_socket,(struct sockaddr *)&m_iaddr,sizeof(m_iaddr))==-1)
+ {
+ m_errorstr="binding socket";
+ m_state=STATE_ERROR;
+ }
+ m_state=STATE_CONNECTED;
+}
+
+JNL_UDPConnection::JNL_UDPConnection()
+{
+ init();
+}
+
+void JNL_UDPConnection::init()
+{
+ m_errorstr="";
+ address=0;
+ address_len=0;
+ m_dns=0;
+ m_dns_owned=false;
+ m_socket=-1;
+ m_remote_port=0;
+ m_state=STATE_NOCONNECTION;
+ m_host=0;
+ saddr=0;
+ m_last_addr_len=0;
+ ttl=0;
+}
+
+void JNL_UDPConnection::set_ttl(uint8_t new_ttl)
+{
+ ttl=new_ttl;
+ setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&ttl, sizeof(ttl));
+}
+
+void JNL_UDPConnection::open(int incoming_socket, JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
+{
+ if (dns != JNL_AUTODNS && dns)
+ {
+ m_dns=dns;
+ m_dns_owned=false;
+ }
+ else if (!m_dns)
+ {
+ m_dns=new JNL_AsyncDNS;
+ m_dns_owned=true;
+ }
+ recv_buffer.reserve(recvbufsize);
+ send_buffer.reserve(sendbufsize);
+
+ m_socket=incoming_socket;
+ m_state=STATE_CONNECTED;
+
+}
+
+void JNL_UDPConnection::open(JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize)
+{
+ if (dns != JNL_AUTODNS && dns)
+ {
+ m_dns=dns;
+ m_dns_owned=false;
+ }
+ else if (!m_dns)
+ {
+ m_dns=new JNL_AsyncDNS;
+ m_dns_owned=true;
+ }
+ recv_buffer.reserve(recvbufsize);
+ send_buffer.reserve(sendbufsize);
+}
+
+void JNL_UDPConnection::setpeer(const char *hostname, int port)
+{
+ m_remote_port=(unsigned short)port;
+ m_host = _strdup(hostname);
+
+ if (!m_host || !m_host[0])
+ {
+ m_errorstr="empty hostname";
+ m_state=STATE_ERROR;
+ }
+ else
+ {
+ m_state=STATE_RESOLVING;
+ }
+}
+
+void JNL_UDPConnection::setpeer(sockaddr *addr, socklen_t length /* of addr */)
+{
+ //memcpy(&m_saddr, addr, sizeof(sockaddr));
+ free(address);
+ address_len=length;
+ address=(sockaddr *)malloc(length);
+ memcpy(address, addr, length);
+}
+
+JNL_UDPConnection::~JNL_UDPConnection()
+{
+ if (m_socket >= 0)
+ {
+ ::closesocket(m_socket);
+ m_socket=-1;
+ }
+ if (!saddr) // free it if it was passed to us (by JNL_Listen, presumably)
+ free(address); // TODO: change this if we ever do round-robin DNS connecting or in any way change how we handle 'address'
+
+ if (m_dns_owned)
+ {
+ delete static_cast<JNL_AsyncDNS *>(m_dns);
+ }
+ free(m_host);
+}
+
+void JNL_UDPConnection::run(size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd)
+{
+ size_t bytes_allowed_to_send=(max_send_bytes<0)?send_buffer.size():max_send_bytes;
+ size_t bytes_allowed_to_recv=(max_recv_bytes<0)?recv_buffer.avail():max_recv_bytes;
+
+ if (bytes_sent) *bytes_sent=0;
+ if (bytes_rcvd) *bytes_rcvd=0;
+
+ switch (m_state)
+ {
+ case STATE_RESOLVING:
+ if (saddr == 0)
+ {
+ int a=m_dns->resolve(m_host, m_remote_port, &saddr, SOCK_DGRAM);
+ if (!a)
+ {
+ address=saddr->ai_addr;
+ address_len=(socklen_t)saddr->ai_addrlen;
+ m_state=STATE_CONNECTED;
+ }
+ else if (a == 1)
+ {
+ m_state=STATE_RESOLVING;
+ break;
+ }
+ else
+ {
+ m_errorstr="resolving hostname";
+ m_state=STATE_ERROR;
+ return;
+ }
+ }
+ break;
+ case STATE_CONNECTED:
+ case STATE_CLOSING:
+ if (!send_buffer.empty() && bytes_allowed_to_send>0)
+ {
+ size_t sent = send_buffer.drain(this, bytes_allowed_to_send);
+ if (bytes_sent)
+ *bytes_sent+=sent;
+ }
+ /* only read from socket when buffer is empty
+ * otherwise we risk data loss
+ * see "man 2 recvfrom" for details
+ */
+ if (recv_buffer.empty() && bytes_allowed_to_recv)
+ {
+ /*
+ * use LockBuffer()/UnlockBuffer() because
+ * "wrap-around" reads can't be done
+ * we might read data from two separate packets
+ */
+ size_t len = recv_buffer.avail();
+ if (bytes_allowed_to_recv < len)
+ len = bytes_allowed_to_recv;
+
+ recv_buffer.clear();
+ void *buffer = recv_buffer.LockBuffer();
+ m_last_addr_len = (int)sizeof(m_last_addr);
+ int res=::recvfrom(m_socket,(char *)buffer,(int)len,0,(sockaddr *)&m_last_addr,&m_last_addr_len);
+ if (res == 0 || (res < 0 && ERRNO != JNL_EWOULDBLOCK))
+ {
+ recv_buffer.UnlockBuffer(0);
+ m_state=STATE_CLOSED;
+ break;
+ }
+ if (res > 0)
+ {
+ if (bytes_rcvd)
+ *bytes_rcvd+=res;
+ recv_buffer.UnlockBuffer(res);
+ }
+ else
+ recv_buffer.UnlockBuffer(0);
+
+ }
+ if (m_state == STATE_CLOSING)
+ {
+ if (send_buffer.empty()) m_state = STATE_CLOSED;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* RingBuffer client function */
+size_t JNL_UDPConnection::Read(void *dest, size_t len)
+{
+ if (!len)
+ return 0;
+
+ m_last_addr_len = (int)sizeof(m_last_addr);
+ int res=::recvfrom(m_socket, (char *)dest, (int)len, 0, (sockaddr *)&m_last_addr,&m_last_addr_len);
+ if (res == 0 || (res < 0 && ERRNO != JNL_EWOULDBLOCK))
+ {
+ m_state=STATE_CLOSED;
+ return 0;
+ }
+ if (res > 0)
+ return res;
+ else
+ return 0;
+}
+
+/* RingBuffer client function */
+size_t JNL_UDPConnection::Write(const void *dest, size_t len)
+{
+ if (!len)
+ return 0;
+ int res=::sendto(m_socket, (const char *)dest, (int)len, 0, address, address_len);
+ if (res==-1 && ERRNO != JNL_EWOULDBLOCK)
+ {
+ return 0;
+ // m_state=STATE_CLOSED;
+ }
+ if (res > 0)
+ return res;
+ else
+ return 0;
+}
+
+void JNL_UDPConnection::close(int quick)
+{
+ if (quick || m_state == STATE_RESOLVING)
+ {
+ m_state=STATE_CLOSED;
+ if (m_socket >= 0)
+ {
+ ::closesocket(m_socket);
+ }
+ m_socket=-1;
+ recv_buffer.clear();
+ send_buffer.clear();
+ m_remote_port=0;
+ free(m_host);
+ m_host=0;
+ //memset(&m_saddr,0,sizeof(m_saddr));
+ }
+ else
+ {
+ if (m_state == STATE_CONNECTED) m_state=STATE_CLOSING;
+ }
+}
+
+size_t JNL_UDPConnection::send_bytes_in_queue(void)
+{
+ return send_buffer.size();
+}
+
+size_t JNL_UDPConnection::send_bytes_available(void)
+{
+ return send_buffer.avail();
+}
+
+int JNL_UDPConnection::send(const void *data, size_t length)
+{
+ if (length > send_bytes_available())
+ {
+ return -1;
+ }
+
+ send_buffer.write(data, length);
+ return 0;
+}
+
+int JNL_UDPConnection::send_string(const char *line)
+{
+ return send(line,strlen(line));
+}
+
+size_t JNL_UDPConnection::recv_bytes_available(void)
+{
+ return recv_buffer.size();
+}
+
+size_t JNL_UDPConnection::peek_bytes(void *data, size_t maxlength)
+{
+ return recv_buffer.peek(data, maxlength);
+}
+
+size_t JNL_UDPConnection::recv_bytes(void *data, size_t maxlength)
+{
+ return recv_buffer.read(data, maxlength);
+}
+
+int JNL_UDPConnection::recv_lines_available(void)
+{
+ int l=(int)recv_bytes_available();
+ int lcount=0;
+ int lastch=0;
+ int pos;
+ for (pos=0; pos < l; pos ++)
+ {
+ char t;
+ if (recv_buffer.at(pos, &t, 1) != 1)
+ return lcount;
+ if ((t=='\r' || t=='\n') &&(
+ (lastch != '\r' && lastch != '\n') || lastch==t
+ )) lcount++;
+ lastch=t;
+ }
+ return lcount;
+}
+
+int JNL_UDPConnection::recv_line(char *line, size_t maxlength)
+{
+ if (maxlength > recv_buffer.size()) maxlength=recv_buffer.size();
+ while (maxlength--)
+ {
+ char t;
+ if (recv_buffer.read(&t, 1) == 0)
+ {
+ *line=0;
+ return 0;
+ }
+ if (t == '\r' || t == '\n')
+ {
+ char r;
+ if (recv_buffer.peek(&r, 1) != 0)
+ {
+ if ((r == '\r' || r == '\n') && r != t)
+ recv_buffer.advance(1);
+ }
+ *line=0;
+ return 0;
+ }
+ *line++=t;
+ }
+ return 1;
+}
+
+int JNL_UDPConnection::get_interface(sockaddr *sin, socklen_t *sin_length)
+{
+ if (m_socket==-1) return 1;
+ /*memset(sin,0,sizeof(sockaddr_storage));
+ *sin_length =sizeof(sockaddr_storage);*/
+ if (::getsockname(m_socket,(sockaddr *)sin,sin_length))
+ return 1;
+ return 0;
+}
+
diff --git a/Src/replicant/jnetlib/udpconnection.h b/Src/replicant/jnetlib/udpconnection.h
new file mode 100644
index 00000000..c91d8422
--- /dev/null
+++ b/Src/replicant/jnetlib/udpconnection.h
@@ -0,0 +1,151 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2001 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: udpconnection.h - JNL UDP connection interface
+** License: see jnetlib.h
+**
+** Usage:
+** 1. Create a JNL_Connection object, optionally specifying a JNL_AsyncDNS
+** object to use (or NULL for none, or WAC_NETWORK_CONNECTION_AUTODNS for auto),
+** and the send and receive buffer sizes.
+** 2. Call connect() to have it connect to a host/port (the hostname will be
+** resolved if possible).
+** 3. call run() with the maximum send/recv amounts, and optionally parameters
+** so you can tell how much has been send/received. You want to do this a lot, while:
+** 4. check get_state() to check the state of the connection. The states are:
+** JNL_Connection::STATE_ERROR
+** - an error has occured on the connection. the connection has closed,
+** and you can no longer write to the socket (there still might be
+** data in the receive buffer - use recv_bytes_available()).
+** JNL_Connection::STATE_NOCONNECTION
+** - no connection has been made yet. call connect() already! :)
+** JNL_Connection::STATE_RESOLVING
+** - the connection is still waiting for a JNL_AsycnDNS to resolve the
+** host.
+** JNL_Connection::STATE_CONNECTING
+** - the asynchronous call to connect() is still running.
+** JNL_Connection::STATE_CONNECTED
+** - the connection has connected, all is well.
+** JNL_Connection::STATE_CLOSING
+** - the connection is closing. This happens after a call to close,
+** without the quick parameter set. This means that the connection
+** will close once the data in the send buffer is sent (data could
+** still be being received when it would be closed). After it is
+** closed, the state will transition to:
+** JNL_Connection::STATE_CLOSED
+** - the connection has closed, generally without error. There still
+** might be data in the receieve buffer, use recv_bytes_available().
+** 5. Use send() and send_string() to send data. You can use
+** send_bytes_in_queue() to see how much has yet to go out, or
+** send_bytes_available() to see how much you can write. If you use send()
+** or send_string() and not enough room is available, both functions will
+** return error ( < 0)
+** 6. Use recv() and recv_line() to get data. If you want to see how much data
+** there is, use recv_bytes_available() and recv_lines_available(). If you
+** call recv() and not enough data is available, recv() will return how much
+** data was actually read. See comments at the function defs.
+**
+** 7. To close, call close(1) for a quick close, or close() for a close that will
+** make the socket close after sending all the data sent.
+**
+** 8. delete ye' ol' object.
+*/
+
+#ifndef _UDPCONNECTION_H_
+#define _UDPCONNECTION_H_
+
+#include "asyncdns.h"
+#include "nu/RingBuffer.h"
+#include "jnetlib_defines.h"
+
+#define JNL_DEFAULT_BUFFER_SIZE 8192
+
+class JNL_UDPConnection : private Drainer, private Filler
+{
+public:
+ typedef enum
+ {
+ STATE_ERROR = JNL_CONNECTION_STATE_ERROR,
+ STATE_NOCONNECTION = JNL_CONNECTION_STATE_NOCONNECTION,
+ STATE_RESOLVING = JNL_CONNECTION_STATE_RESOLVING,
+ STATE_CONNECTING = JNL_CONNECTION_STATE_CONNECTING,
+ STATE_CONNECTED = JNL_CONNECTION_STATE_CONNECTED,
+ STATE_CLOSING = JNL_CONNECTION_STATE_CLOSING,
+ STATE_CLOSED = JNL_CONNECTION_STATE_CLOSED,
+ STATE_RESOLVED = JNL_CONNECTION_STATE_RESOLVED,
+ } state;
+
+ JNL_UDPConnection();
+ JNL_UDPConnection( unsigned short port, JNL_AsyncDNS *dns, int sendbufsize = JNL_DEFAULT_BUFFER_SIZE, int recvbufsize = JNL_DEFAULT_BUFFER_SIZE );
+ ~JNL_UDPConnection();
+
+ void open( JNL_AsyncDNS *dns = JNL_AUTODNS, size_t sendbufsize = JNL_DEFAULT_BUFFER_SIZE, size_t recvbufsize = JNL_DEFAULT_BUFFER_SIZE );
+ void open( int incoming_socket, JNL_AsyncDNS *dns = JNL_AUTODNS, size_t sendbufsize = JNL_DEFAULT_BUFFER_SIZE, size_t recvbufsize = JNL_DEFAULT_BUFFER_SIZE );
+
+ void setpeer( const char *hostname, int port );
+ void setpeer( sockaddr *addr, socklen_t length /* of addr */ );
+
+ void run( size_t max_send_bytes = -1, size_t max_recv_bytes = -1, size_t *bytes_sent = NULL, size_t *bytes_rcvd = NULL );
+
+ int get_state() { return m_state; }
+ const char *get_errstr() { return m_errorstr; }
+
+ void close( int quick = 0 );
+ void flush_send( void ) { send_buffer.clear(); }
+
+ size_t send_bytes_in_queue( void );
+ size_t send_bytes_available( void );
+ int send( const void *data, size_t length ); // returns -1 if not enough room
+ int send_string( const char *line ); // returns -1 if not enough room
+
+
+ size_t recv_bytes_available( void );
+ size_t recv_bytes( void *data, size_t maxlength ); // returns actual bytes read
+ unsigned int recv_int( void );
+ int recv_lines_available( void );
+ int recv_line( char *line, size_t maxlength ); // returns 0 if the line was terminated with a \r or \n, 1 if not.
+ // (i.e. if you specify maxlength=10, and the line is 12 bytes long
+ // it will return 1. or if there is no \r or \n and that's all the data
+ // the connection has.)
+ size_t peek_bytes( void *data, size_t maxlength ); // returns bytes peeked
+
+ int get_interface( sockaddr *sin, socklen_t *sin_length ); // this returns the interface the connection is on
+ short get_remote_port( void ) { return m_remote_port; } // this returns the remote port of connection
+
+ void get_last_recv_msg_addr( sockaddr **addr, socklen_t *len ) { *addr = (sockaddr *)&m_last_addr; *len = m_last_addr_len; }
+
+ void set_ttl( uint8_t new_ttl );
+
+protected:
+ uint8_t ttl;
+ SOCKET m_socket;
+ unsigned short m_remote_port;
+ RingBuffer recv_buffer;
+ RingBuffer send_buffer;
+
+ sockaddr *address;
+ socklen_t address_len;
+
+ sockaddr_storage m_last_addr;
+ socklen_t m_last_addr_len;
+ addrinfo *saddr;
+
+ char *m_host;
+
+ JNL_AsyncDNS *m_dns;
+ int m_dns_owned;
+
+ state m_state;
+ const char *m_errorstr;
+
+private:
+ void init(); // constructor helper function
+
+ // functions for RingBuffer
+ size_t Read( void *dest, size_t len );
+ size_t Write( const void *dest, size_t len );
+
+};
+
+#endif // _UDPConnection_H_
diff --git a/Src/replicant/jnetlib/util.cpp b/Src/replicant/jnetlib/util.cpp
new file mode 100644
index 00000000..3b2b5a11
--- /dev/null
+++ b/Src/replicant/jnetlib/util.cpp
@@ -0,0 +1,185 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: util.cpp - JNL implementation of basic network utilities
+** License: see jnetlib.h
+*/
+
+#include "netinc.h"
+#include "util.h"
+#include "foundation/error.h"
+#ifdef USE_SSL
+#include "sslconnection.h"
+#ifdef _WIN32
+#include <wincrypt.h>
+#endif
+#include <openssl/rand.h>
+
+#ifdef _WIN32
+static HCRYPTPROV GetKeySet()
+{
+ HCRYPTPROV hCryptProv;
+ LPCWSTR UserName = L"WinampKeyContainer"; // name of the key container
+
+ if (CryptAcquireContext(
+ &hCryptProv, // handle to the CSP
+ UserName, // container name
+ NULL, // use the default provider
+ PROV_RSA_FULL, // provider type
+ 0)) // flag values
+ {
+ return hCryptProv;
+ }
+ else if (CryptAcquireContext(
+ &hCryptProv,
+ UserName,
+ NULL,
+ PROV_RSA_FULL,
+ CRYPT_NEWKEYSET))
+ {
+ return hCryptProv;
+ }
+ else
+ return 0;
+}
+#endif
+
+static void InitSSL()
+{
+ SSL_load_error_strings();
+ SSL_library_init();
+#ifdef _WIN32
+ HCRYPTPROV hCryptProv = GetKeySet();
+ if (hCryptProv)
+ {
+ BYTE pbData[8*sizeof(unsigned long)] = {0};
+ if (CryptGenRandom(hCryptProv, 8*sizeof(unsigned long), pbData))
+ {
+ RAND_seed(pbData, 16);
+ }
+ CryptReleaseContext(hCryptProv,0);
+ }
+#endif
+// sslContext = SSL_CTX_new(SSLv23_client_method());
+// SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
+
+// SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
+}
+static int open_ssl_initted = 0;
+#endif
+
+static int was_initted = 0;
+
+int JNL::open_socketlib()
+{
+#ifdef _WIN32
+ if (!was_initted)
+ {
+ WSADATA wsaData = {0};
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData))
+ {
+ return NErr_Error;
+ }
+ }
+#endif
+#ifdef USE_SSL
+ if (!open_ssl_initted)
+ {
+ InitSSL();
+ open_ssl_initted=1;
+ }
+#endif
+ return NErr_Success;
+}
+
+void JNL::close_socketlib()
+{
+#ifdef _WIN32
+ if (was_initted)
+ {
+ WSACleanup();
+ }
+#ifdef USE_SSL
+ // TODO need to do some reference counting to free this correctly
+ //SSL_CTX_free(sslContext);
+#endif
+#endif
+}
+
+static char *jnl_strndup(const char *str, size_t n)
+{
+ char *o = (char *)calloc(n+1, sizeof(char));
+ if (!o)
+ {
+ return 0;
+ }
+ strncpy(o, str, n);
+ o[n]=0;
+ return o;
+}
+
+int JNL::parse_url(const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp)
+{
+ free(*prot); *prot=0;
+ free(*host); *host = 0;
+ free(*req); *req = 0;
+ free(*lp); *lp = 0;
+ *port = 0;
+
+ const char *p;
+ const char *protocol = strstr(url, "://");
+ if (protocol)
+ {
+ *prot = jnl_strndup(url, protocol-url);
+ p = protocol + 3;
+ }
+ else
+ {
+ p = url;
+ }
+
+ while (p && *p && *p == '/') p++; // skip extra /
+
+ size_t end = strcspn(p, "@/");
+
+ // check for username
+ if (p[end] == '@')
+ {
+ *lp = jnl_strndup(p, end);
+ p = p+end+1;
+ end = strcspn(p, "[:/");
+ }
+
+ if (p[0] == '[') // IPv6 style address
+ {
+ p++;
+ const char *ipv6_end = strchr(p, ']');
+ if (!ipv6_end)
+ return NErr_Malformed;
+
+ *host = jnl_strndup(p, ipv6_end-p);
+ p = ipv6_end+1;
+ }
+ else
+ {
+ end = strcspn(p, ":/");
+ *host = jnl_strndup(p, end);
+ p += end;
+ }
+
+ // is there a port number?
+ if (p[0] == ':')
+ {
+ char *new_end;
+ *port = (unsigned short)strtoul(p+1, &new_end, 10);
+ p = new_end;
+ }
+
+ if (p[0])
+ {
+ *req = _strdup(p);
+ }
+
+ return NErr_Success;
+}
diff --git a/Src/replicant/jnetlib/util.h b/Src/replicant/jnetlib/util.h
new file mode 100644
index 00000000..fa1cd005
--- /dev/null
+++ b/Src/replicant/jnetlib/util.h
@@ -0,0 +1,40 @@
+/*
+** JNetLib
+** Copyright (C) 2000-2007 Nullsoft, Inc.
+** Author: Justin Frankel
+** File: util.h - JNL interface for basic network utilities
+** License: see jnetlib.h
+**
+** routines you may be interested in:
+** JNL::open_socketlib();
+** opens the socket library. Call this once before using any network
+** code. If you create a new thread, call this again. Only really an
+** issue for Win32 support, but use it anyway for portability/
+**
+** JNL::close_Socketlib();
+** closes the socketlib. Call this when you're done with the network,
+** after all your JNetLib objects have been destroyed.
+**
+** unsigned long JNL::ipstr_to_addr(const char *cp);
+** gives you the integer representation of a ip address in dotted
+** decimal form.
+**
+** JNL::addr_to_ipstr(unsigned long addr, char *host, int maxhostlen);
+** gives you the dotted decimal notation of an integer ip address.
+**
+*/
+
+#ifndef _UTIL_H_
+#define _UTIL_H_
+
+class JNL
+{
+public:
+ static int open_socketlib();
+ static void close_socketlib();
+ static unsigned long ipstr_to_addr( const char *cp );
+ static void addr_to_ipstr( unsigned long addr, char *host, int maxhostlen );
+ static int parse_url( const char *url, char **prot, char **host, unsigned short *port, char **req, char **lp );
+};
+
+#endif //_UTIL_H_
diff --git a/Src/replicant/jnetlib/version.rc2 b/Src/replicant/jnetlib/version.rc2
new file mode 100644
index 00000000..a5a7ce27
--- /dev/null
+++ b/Src/replicant/jnetlib/version.rc2
@@ -0,0 +1,39 @@
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+#include "../../Winamp/buildType.h"
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION WINAMP_PRODUCTVER
+ PRODUCTVERSION WINAMP_PRODUCTVER
+ FILEFLAGSMASK 0x17L
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x4L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "CompanyName", "Winamp SA"
+ VALUE "FileDescription", "Winamp Support Library"
+ VALUE "FileVersion", STR_WINAMP_PRODUCTVER
+ VALUE "InternalName", "jnetlib.dll"
+ VALUE "LegalCopyright", "Copyright © 2012-2014 Winamp SA"
+ VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
+ VALUE "OriginalFilename", "jnetlib.dll"
+ VALUE "ProductName", "Winamp Networking Service"
+ VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END