Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

View file

@ -0,0 +1 @@
1.2

View file

@ -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;
}
}
}

View file

@ -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_

View file

@ -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();
}
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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

View file

@ -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>

View file

@ -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();
}

View file

@ -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_

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}
}

View file

@ -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_

View file

@ -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_

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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_

View file

@ -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;
}

View file

@ -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_

View file

@ -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