Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
1
Src/replicant/jnetlib/VERSION
Normal file
1
Src/replicant/jnetlib/VERSION
Normal file
|
@ -0,0 +1 @@
|
|||
1.2
|
314
Src/replicant/jnetlib/asyncdns.cpp
Normal file
314
Src/replicant/jnetlib/asyncdns.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
66
Src/replicant/jnetlib/asyncdns.h
Normal file
66
Src/replicant/jnetlib/asyncdns.h
Normal 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_
|
533
Src/replicant/jnetlib/connection.cpp
Normal file
533
Src/replicant/jnetlib/connection.cpp
Normal 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();
|
||||
}
|
||||
}
|
168
Src/replicant/jnetlib/connection.h
Normal file
168
Src/replicant/jnetlib/connection.h
Normal 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_
|
119
Src/replicant/jnetlib/headers.cpp
Normal file
119
Src/replicant/jnetlib/headers.cpp
Normal 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;
|
||||
}
|
20
Src/replicant/jnetlib/headers.h
Normal file
20
Src/replicant/jnetlib/headers.h
Normal 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;
|
||||
};
|
845
Src/replicant/jnetlib/httpget.cpp
Normal file
845
Src/replicant/jnetlib/httpget.cpp
Normal 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;
|
||||
}
|
139
Src/replicant/jnetlib/httpget.h
Normal file
139
Src/replicant/jnetlib/httpget.h
Normal 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_
|
234
Src/replicant/jnetlib/httpserv.cpp
Normal file
234
Src/replicant/jnetlib/httpserv.cpp
Normal 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;
|
||||
}
|
||||
|
71
Src/replicant/jnetlib/httpserv.h
Normal file
71
Src/replicant/jnetlib/httpserv.h
Normal 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_
|
216
Src/replicant/jnetlib/httpuserv.cpp
Normal file
216
Src/replicant/jnetlib/httpuserv.cpp
Normal 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;
|
||||
}
|
55
Src/replicant/jnetlib/httpuserv.h
Normal file
55
Src/replicant/jnetlib/httpuserv.h
Normal 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;
|
||||
};
|
||||
|
||||
|
76
Src/replicant/jnetlib/jnetlib-replicant.rc
Normal file
76
Src/replicant/jnetlib/jnetlib-replicant.rc
Normal 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
|
||||
|
491
Src/replicant/jnetlib/jnetlib-replicant.vcproj
Normal file
491
Src/replicant/jnetlib/jnetlib-replicant.vcproj
Normal 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>
|
630
Src/replicant/jnetlib/jnetlib.cpp
Normal file
630
Src/replicant/jnetlib/jnetlib.cpp
Normal 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();
|
||||
}
|
177
Src/replicant/jnetlib/jnetlib.h
Normal file
177
Src/replicant/jnetlib/jnetlib.h
Normal 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_
|
54
Src/replicant/jnetlib/jnetlib.sln
Normal file
54
Src/replicant/jnetlib/jnetlib.sln
Normal 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
|
281
Src/replicant/jnetlib/jnetlib.vcxproj
Normal file
281
Src/replicant/jnetlib/jnetlib.vcxproj
Normal 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>
|
137
Src/replicant/jnetlib/jnetlib.vcxproj.filters
Normal file
137
Src/replicant/jnetlib/jnetlib.vcxproj.filters
Normal 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>
|
66
Src/replicant/jnetlib/jnetlib_defines.h
Normal file
66
Src/replicant/jnetlib/jnetlib_defines.h
Normal 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
|
131
Src/replicant/jnetlib/listen.cpp
Normal file
131
Src/replicant/jnetlib/listen.cpp
Normal 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;
|
||||
}
|
44
Src/replicant/jnetlib/listen.h
Normal file
44
Src/replicant/jnetlib/listen.h
Normal 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_
|
123
Src/replicant/jnetlib/multicastlisten.cpp
Normal file
123
Src/replicant/jnetlib/multicastlisten.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
26
Src/replicant/jnetlib/multicastlisten.h
Normal file
26
Src/replicant/jnetlib/multicastlisten.h
Normal 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_
|
84
Src/replicant/jnetlib/netinc.h
Normal file
84
Src/replicant/jnetlib/netinc.h
Normal 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_
|
14
Src/replicant/jnetlib/resource.h
Normal file
14
Src/replicant/jnetlib/resource.h
Normal 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
|
329
Src/replicant/jnetlib/sslconnection.cpp
Normal file
329
Src/replicant/jnetlib/sslconnection.cpp
Normal 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
|
61
Src/replicant/jnetlib/sslconnection.h
Normal file
61
Src/replicant/jnetlib/sslconnection.h
Normal 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
|
384
Src/replicant/jnetlib/udpconnection.cpp
Normal file
384
Src/replicant/jnetlib/udpconnection.cpp
Normal 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;
|
||||
}
|
||||
|
151
Src/replicant/jnetlib/udpconnection.h
Normal file
151
Src/replicant/jnetlib/udpconnection.h
Normal 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_
|
185
Src/replicant/jnetlib/util.cpp
Normal file
185
Src/replicant/jnetlib/util.cpp
Normal 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;
|
||||
}
|
40
Src/replicant/jnetlib/util.h
Normal file
40
Src/replicant/jnetlib/util.h
Normal 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_
|
39
Src/replicant/jnetlib/version.rc2
Normal file
39
Src/replicant/jnetlib/version.rc2
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue