add oversampler
This commit is contained in:
20
oversampling/WDL/jnetlib/Makefile
Normal file
20
oversampling/WDL/jnetlib/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# freebsd3 makefile
|
||||
default: jnl.a
|
||||
|
||||
LDFLAGS = -pthread
|
||||
CFLAGS = -s -O2 -Wall -DTHREAD_SAFE -D_THREAD_SAFE -D_REENTRANT
|
||||
CC = gcc
|
||||
CPP = g++
|
||||
CXX = g++
|
||||
|
||||
OBJS = asyncdns.o connection.o httpget.o httpserv.o listen.o util.o sercon.o
|
||||
|
||||
jnl.a: ${OBJS}
|
||||
-rm -f jnl.a
|
||||
ar rcs jnl.a ${OBJS}
|
||||
|
||||
test: ${OBJS} test.o
|
||||
$(CC) ${CFLAGS} -o test test.o ${OBJS} ${LDFLAGS}
|
||||
|
||||
clean:
|
||||
-rm -f ${OBJS} test jnl.a test.o
|
||||
257
oversampling/WDL/jnetlib/asyncdns.cpp
Normal file
257
oversampling/WDL/jnetlib/asyncdns.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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"
|
||||
#ifdef _WIN32
|
||||
#include <process.h>
|
||||
#endif
|
||||
#include "../wdlcstring.h"
|
||||
|
||||
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);
|
||||
if (m_cache) memset(m_cache,0,sizeof(cache_entry)*m_cache_size);
|
||||
else m_cache_size = 0;
|
||||
}
|
||||
|
||||
JNL_AsyncDNS::~JNL_AsyncDNS()
|
||||
{
|
||||
#ifndef NO_DNS_SUPPORT
|
||||
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
|
||||
#endif//NO_DNS_SUPPORT
|
||||
free(m_cache);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
unsigned WINAPI JNL_AsyncDNS::_threadfunc(void *_d)
|
||||
#else
|
||||
unsigned int JNL_AsyncDNS::_threadfunc(void *_d)
|
||||
#endif
|
||||
{
|
||||
#ifndef NO_DNS_SUPPORT
|
||||
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)
|
||||
{
|
||||
struct hostent *hostentry;
|
||||
hostentry=::gethostbyname(_this->m_cache[x].hostname);
|
||||
if (hostentry)
|
||||
{
|
||||
memcpy(&_this->m_cache[x].addr,hostentry->h_addr,sizeof(int));
|
||||
}
|
||||
else
|
||||
_this->m_cache[x].addr=INADDR_NONE;
|
||||
}
|
||||
else if (_this->m_cache[x].mode==1)
|
||||
{
|
||||
struct hostent *ent;
|
||||
ent=::gethostbyaddr((const char *)&_this->m_cache[x].addr,4,AF_INET);
|
||||
lstrcpyn_safe(_this->m_cache[x].hostname,ent ? ent->h_name : "",sizeof(_this->m_cache[x].hostname));
|
||||
}
|
||||
_this->m_cache[x].resolved=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_this->m_cache[x].mode==0)
|
||||
{
|
||||
_this->m_cache[x].addr=INADDR_NONE;
|
||||
_this->m_cache[x].resolved=1;
|
||||
}
|
||||
else if (_this->m_cache[x].mode==1)
|
||||
{
|
||||
_this->m_cache[x].hostname[0]=0;
|
||||
_this->m_cache[x].resolved=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!nowinsock) JNL::close_socketlib();
|
||||
_this->m_thread_kill=1;
|
||||
#endif // NO_DNS_SUPPORT
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int JNL_AsyncDNS::resolve(const char *hostname, unsigned int *addr)
|
||||
{
|
||||
// return 0 on success, 1 on wait, -1 on unresolvable
|
||||
int x;
|
||||
unsigned int ip=inet_addr(hostname);
|
||||
if (ip != INADDR_NONE)
|
||||
{
|
||||
*addr=ip;
|
||||
return 0;
|
||||
}
|
||||
#ifndef NO_DNS_SUPPORT
|
||||
|
||||
for (x = 0; x < m_cache_size; x ++)
|
||||
{
|
||||
if (!stricmp(m_cache[x].hostname,hostname) && m_cache[x].mode==0)
|
||||
{
|
||||
m_cache[x].last_used=time(NULL);
|
||||
if (m_cache[x].resolved)
|
||||
{
|
||||
if (m_cache[x].addr == INADDR_NONE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*addr=m_cache[x].addr;
|
||||
return 0;
|
||||
}
|
||||
makesurethreadisrunning();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// 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 -1;
|
||||
}
|
||||
strcpy(m_cache[oi].hostname,hostname);
|
||||
m_cache[oi].mode=0;
|
||||
m_cache[oi].addr=INADDR_NONE;
|
||||
m_cache[oi].resolved=0;
|
||||
m_cache[oi].last_used=time(NULL);
|
||||
|
||||
makesurethreadisrunning();
|
||||
return 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int JNL_AsyncDNS::reverse(unsigned int addr, char *hostname)
|
||||
{
|
||||
// return 0 on success, 1 on wait, -1 on unresolvable
|
||||
int x;
|
||||
if (addr == INADDR_NONE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#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(NULL);
|
||||
if (m_cache[x].resolved)
|
||||
{
|
||||
if (!m_cache[x].hostname[0])
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
lstrcpyn_safe(hostname,m_cache[x].hostname,256);
|
||||
return 0;
|
||||
}
|
||||
makesurethreadisrunning();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// 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 -1;
|
||||
}
|
||||
m_cache[oi].addr=addr;
|
||||
m_cache[oi].hostname[0]=0;
|
||||
m_cache[oi].resolved=0;
|
||||
m_cache[oi].mode=1;
|
||||
m_cache[oi].last_used=time(NULL);
|
||||
|
||||
makesurethreadisrunning();
|
||||
return 1;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void JNL_AsyncDNS::makesurethreadisrunning(void)
|
||||
{
|
||||
#ifndef NO_DNS_SUPPORT
|
||||
if (m_thread_kill)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (m_thread)
|
||||
{
|
||||
WaitForSingleObject(m_thread,INFINITE);
|
||||
CloseHandle(m_thread);
|
||||
}
|
||||
unsigned id;
|
||||
m_thread_kill=0;
|
||||
m_thread=(HANDLE)_beginthreadex(NULL,0,_threadfunc,(void *)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;
|
||||
}
|
||||
}
|
||||
#endif//NO_DNS_SUPPORT
|
||||
}
|
||||
76
oversampling/WDL/jnetlib/asyncdns.h
Normal file
76
oversampling/WDL/jnetlib/asyncdns.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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 <time.h>
|
||||
|
||||
#ifndef JNL_NO_DEFINE_INTERFACES
|
||||
class JNL_IAsyncDNS
|
||||
{
|
||||
public:
|
||||
virtual ~JNL_IAsyncDNS() { }
|
||||
virtual int resolve(const char *hostname, unsigned int *addr)=0; // return 0 on success, 1 on wait, -1 on unresolvable
|
||||
virtual int reverse(unsigned int addr, char *hostname)=0; // return 0 on success, 1 on wait, -1 on unresolvable. hostname must be at least 256 bytes.
|
||||
};
|
||||
#define JNL_AsyncDNS_PARENTDEF : public JNL_IAsyncDNS
|
||||
#else
|
||||
#define JNL_IAsyncDNS JNL_AsyncDNS
|
||||
#define JNL_AsyncDNS_PARENTDEF
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef JNL_NO_IMPLEMENTATION
|
||||
|
||||
class JNL_AsyncDNS JNL_AsyncDNS_PARENTDEF
|
||||
{
|
||||
public:
|
||||
JNL_AsyncDNS(int max_cache_entries=64);
|
||||
~JNL_AsyncDNS();
|
||||
|
||||
int resolve(const char *hostname, unsigned int *addr); // return 0 on success, 1 on wait, -1 on unresolvable
|
||||
int reverse(unsigned int addr, char *hostname); // return 0 on success, 1 on wait, -1 on unresolvable. hostname must be at least 256 bytes.
|
||||
|
||||
private:
|
||||
typedef struct
|
||||
{
|
||||
time_t last_used; // timestamp.
|
||||
char resolved;
|
||||
char mode; // 1=reverse
|
||||
char hostname[256];
|
||||
unsigned int addr;
|
||||
}
|
||||
cache_entry;
|
||||
|
||||
cache_entry *m_cache;
|
||||
int m_cache_size;
|
||||
volatile int m_thread_kill;
|
||||
#ifdef _WIN32
|
||||
HANDLE m_thread;
|
||||
static unsigned WINAPI _threadfunc(void *_d);
|
||||
#else
|
||||
pthread_t m_thread;
|
||||
static unsigned int _threadfunc(void *_d);
|
||||
#endif
|
||||
void makesurethreadisrunning(void);
|
||||
|
||||
};
|
||||
#endif // !JNL_NO_IMPLEMENTATION
|
||||
|
||||
#endif //_ASYNCDNS_H_
|
||||
505
oversampling/WDL/jnetlib/connection.cpp
Normal file
505
oversampling/WDL/jnetlib/connection.cpp
Normal file
@@ -0,0 +1,505 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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 "../wdlcstring.h"
|
||||
|
||||
|
||||
JNL_Connection::JNL_Connection(JNL_IAsyncDNS *dns, int sendbufsize, int recvbufsize)
|
||||
{
|
||||
m_errorstr="";
|
||||
if (dns == JNL_CONNECTION_AUTODNS)
|
||||
{
|
||||
m_dns=new JNL_AsyncDNS();
|
||||
m_dns_owned=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dns=dns;
|
||||
m_dns_owned=0;
|
||||
}
|
||||
m_recv_buffer.Resize(recvbufsize);
|
||||
m_send_buffer.Resize(sendbufsize);
|
||||
m_socket=INVALID_SOCKET;
|
||||
m_remote_port=0;
|
||||
m_state=STATE_NOCONNECTION;
|
||||
m_localinterfacereq=INADDR_ANY;
|
||||
m_recv_len=m_recv_pos=0;
|
||||
m_send_len=m_send_pos=0;
|
||||
m_host[0]=0;
|
||||
m_saddr = new struct sockaddr_in;
|
||||
memset(m_saddr,0,sizeof(struct sockaddr_in));
|
||||
}
|
||||
|
||||
void JNL_Connection::connect(SOCKET s, struct sockaddr_in *loc)
|
||||
{
|
||||
close(1);
|
||||
m_socket=s;
|
||||
m_remote_port=0;
|
||||
m_dns=NULL;
|
||||
if (loc) *m_saddr=*loc;
|
||||
else memset(m_saddr,0,sizeof(struct sockaddr_in));
|
||||
if (m_socket != INVALID_SOCKET)
|
||||
{
|
||||
SET_SOCK_DEFAULTS(m_socket);
|
||||
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=(short)port;
|
||||
m_socket=::socket(AF_INET,SOCK_STREAM,0);
|
||||
if (m_socket==INVALID_SOCKET)
|
||||
{
|
||||
m_errorstr="creating socket";
|
||||
m_state=STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_localinterfacereq != INADDR_ANY)
|
||||
{
|
||||
sockaddr_in sa={0,};
|
||||
sa.sin_family=AF_INET;
|
||||
sa.sin_addr.s_addr=m_localinterfacereq;
|
||||
bind(m_socket,(struct sockaddr *)&sa,16);
|
||||
}
|
||||
SET_SOCK_DEFAULTS(m_socket);
|
||||
SET_SOCK_BLOCK(m_socket,0);
|
||||
lstrcpyn_safe(m_host,hostname,sizeof(m_host));
|
||||
memset(m_saddr,0,sizeof(struct sockaddr_in));
|
||||
if (!m_host[0])
|
||||
{
|
||||
m_errorstr="empty hostname";
|
||||
m_state=STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state=STATE_RESOLVING;
|
||||
m_saddr->sin_family=AF_INET;
|
||||
m_saddr->sin_port=htons((unsigned short)port);
|
||||
m_saddr->sin_addr.s_addr=inet_addr(hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNL_Connection::~JNL_Connection()
|
||||
{
|
||||
if (m_socket != INVALID_SOCKET)
|
||||
{
|
||||
::shutdown(m_socket, SHUT_RDWR);
|
||||
::closesocket(m_socket);
|
||||
m_socket=INVALID_SOCKET;
|
||||
}
|
||||
if (m_dns_owned)
|
||||
{
|
||||
delete m_dns;
|
||||
}
|
||||
delete m_saddr;
|
||||
}
|
||||
|
||||
void JNL_Connection::run(int max_send_bytes, int max_recv_bytes, int *bytes_sent, int *bytes_rcvd)
|
||||
{
|
||||
int bytes_allowed_to_send=(max_send_bytes<0)?m_send_buffer.GetSize():max_send_bytes;
|
||||
int bytes_allowed_to_recv=(max_recv_bytes<0)?m_recv_buffer.GetSize():max_recv_bytes;
|
||||
|
||||
if (bytes_sent) *bytes_sent=0;
|
||||
if (bytes_rcvd) *bytes_rcvd=0;
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case STATE_RESOLVING:
|
||||
if (m_saddr->sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
int a=m_dns?m_dns->resolve(m_host,(unsigned int *)&m_saddr->sin_addr.s_addr):-1;
|
||||
if (!a) { m_state=STATE_CONNECTING; }
|
||||
else if (a == 1)
|
||||
{
|
||||
m_state=STATE_RESOLVING;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_errorstr="resolving hostname";
|
||||
m_state=STATE_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!::connect(m_socket,(struct sockaddr *)m_saddr,16))
|
||||
{
|
||||
m_state=STATE_CONNECTED;
|
||||
}
|
||||
else if (JNL_ERRNO!=JNL_EINPROGRESS)
|
||||
{
|
||||
m_errorstr="connecting to host";
|
||||
m_state=STATE_ERROR;
|
||||
}
|
||||
else { m_state=STATE_CONNECTING; }
|
||||
break;
|
||||
case STATE_CONNECTING:
|
||||
{
|
||||
#ifdef _WIN32
|
||||
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(0,&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;
|
||||
}
|
||||
else if (FD_ISSET(m_socket,&f[2]))
|
||||
{
|
||||
m_errorstr="connecting to host";
|
||||
m_state=STATE_ERROR;
|
||||
}
|
||||
#else
|
||||
struct pollfd pl = { m_socket, POLLERR|POLLHUP|POLLOUT, 0 };
|
||||
int res = poll(&pl,1,0);
|
||||
if (res < 0 || (pl.revents & (POLLERR|POLLHUP)))
|
||||
{
|
||||
m_errorstr="connecting to host";
|
||||
m_state=STATE_ERROR;
|
||||
}
|
||||
else if (res>0 || (pl.revents&POLLOUT))
|
||||
m_state=STATE_CONNECTED;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case STATE_CONNECTED:
|
||||
case STATE_CLOSING:
|
||||
if (m_send_len>0 && bytes_allowed_to_send>0)
|
||||
{
|
||||
int len=m_send_buffer.GetSize()-m_send_pos;
|
||||
if (len > m_send_len) len=m_send_len;
|
||||
if (len > bytes_allowed_to_send) len=bytes_allowed_to_send;
|
||||
if (len > 0)
|
||||
{
|
||||
int res=(int)::send(m_socket,(char*)m_send_buffer.Get()+m_send_pos,len,0);
|
||||
if (res==-1 && JNL_ERRNO != JNL_EWOULDBLOCK)
|
||||
{
|
||||
// m_state=STATE_CLOSED;
|
||||
// return;
|
||||
}
|
||||
if (res>0)
|
||||
{
|
||||
bytes_allowed_to_send-=res;
|
||||
if (bytes_sent) *bytes_sent+=res;
|
||||
m_send_pos+=res;
|
||||
m_send_len-=res;
|
||||
}
|
||||
}
|
||||
if (m_send_pos>=m_send_buffer.GetSize())
|
||||
{
|
||||
m_send_pos=0;
|
||||
if (m_send_len>0)
|
||||
{
|
||||
len=m_send_buffer.GetSize()-m_send_pos;
|
||||
if (len > m_send_len) len=m_send_len;
|
||||
if (len > bytes_allowed_to_send) len=bytes_allowed_to_send;
|
||||
int res=(int)::send(m_socket,(char*)m_send_buffer.Get()+m_send_pos,len,0);
|
||||
if (res==-1 && JNL_ERRNO != JNL_EWOULDBLOCK)
|
||||
{
|
||||
// m_state=STATE_CLOSED;
|
||||
}
|
||||
if (res>0)
|
||||
{
|
||||
bytes_allowed_to_send-=res;
|
||||
if (bytes_sent) *bytes_sent+=res;
|
||||
m_send_pos+=res;
|
||||
m_send_len-=res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_recv_len<m_recv_buffer.GetSize())
|
||||
{
|
||||
int len=m_recv_buffer.GetSize()-m_recv_pos;
|
||||
if (len > m_recv_buffer.GetSize()-m_recv_len) len=m_recv_buffer.GetSize()-m_recv_len;
|
||||
if (len > bytes_allowed_to_recv) len=bytes_allowed_to_recv;
|
||||
if (len>0)
|
||||
{
|
||||
int res=(int)::recv(m_socket,(char*)m_recv_buffer.Get()+m_recv_pos,len,0);
|
||||
if (res == 0 || (res < 0 && JNL_ERRNO != JNL_EWOULDBLOCK))
|
||||
{
|
||||
m_state=STATE_CLOSED;
|
||||
break;
|
||||
}
|
||||
if (res > 0)
|
||||
{
|
||||
bytes_allowed_to_recv-=res;
|
||||
if (bytes_rcvd) *bytes_rcvd+=res;
|
||||
m_recv_pos+=res;
|
||||
m_recv_len+=res;
|
||||
}
|
||||
}
|
||||
if (m_recv_pos >= m_recv_buffer.GetSize())
|
||||
{
|
||||
m_recv_pos=0;
|
||||
if (m_recv_len < m_recv_buffer.GetSize())
|
||||
{
|
||||
len=m_recv_buffer.GetSize()-m_recv_len;
|
||||
if (len > bytes_allowed_to_recv) len=bytes_allowed_to_recv;
|
||||
if (len > 0)
|
||||
{
|
||||
int res=(int)::recv(m_socket,(char*)m_recv_buffer.Get()+m_recv_pos,len,0);
|
||||
if (res == 0 || (res < 0 && JNL_ERRNO != JNL_EWOULDBLOCK))
|
||||
{
|
||||
m_state=STATE_CLOSED;
|
||||
break;
|
||||
}
|
||||
if (res > 0)
|
||||
{
|
||||
bytes_allowed_to_recv-=res;
|
||||
if (bytes_rcvd) *bytes_rcvd+=res;
|
||||
m_recv_pos+=res;
|
||||
m_recv_len+=res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_state == STATE_CLOSING)
|
||||
{
|
||||
if (m_send_len < 1) m_state = STATE_CLOSED;
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void JNL_Connection::close(int quick)
|
||||
{
|
||||
if (quick || m_state == STATE_RESOLVING || m_state == STATE_CONNECTING)
|
||||
{
|
||||
m_state=STATE_CLOSED;
|
||||
if (m_socket != INVALID_SOCKET)
|
||||
{
|
||||
::shutdown(m_socket, SHUT_RDWR);
|
||||
::closesocket(m_socket);
|
||||
}
|
||||
m_socket=INVALID_SOCKET;
|
||||
m_remote_port=0;
|
||||
m_recv_len=m_recv_pos=0;
|
||||
m_send_len=m_send_pos=0;
|
||||
m_host[0]=0;
|
||||
memset(m_saddr,0,sizeof(struct sockaddr_in));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_state == STATE_CONNECTED) m_state=STATE_CLOSING;
|
||||
}
|
||||
}
|
||||
|
||||
int JNL_Connection::send_bytes_in_queue(void)
|
||||
{
|
||||
return m_send_len;
|
||||
}
|
||||
|
||||
int JNL_Connection::send_bytes_available(void)
|
||||
{
|
||||
return m_send_buffer.GetSize()-m_send_len;
|
||||
}
|
||||
|
||||
int JNL_Connection::send(const void *_data, int length)
|
||||
{
|
||||
const char *data = static_cast<const char *>(_data);
|
||||
if (length > send_bytes_available())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int write_pos=m_send_pos+m_send_len;
|
||||
if (write_pos >= m_send_buffer.GetSize())
|
||||
{
|
||||
write_pos-=m_send_buffer.GetSize();
|
||||
}
|
||||
|
||||
int len=m_send_buffer.GetSize()-write_pos;
|
||||
if (len > length)
|
||||
{
|
||||
len=length;
|
||||
}
|
||||
|
||||
memcpy(m_send_buffer.Get()+write_pos,data,len);
|
||||
if (length > len)
|
||||
{
|
||||
memcpy(m_send_buffer.Get(),data+len,length-len);
|
||||
}
|
||||
m_send_len+=length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int JNL_Connection::send_string(const char *line)
|
||||
{
|
||||
return send(line,(int)strlen(line));
|
||||
}
|
||||
|
||||
int JNL_Connection::recv_bytes_available(void)
|
||||
{
|
||||
return m_recv_len;
|
||||
}
|
||||
|
||||
int JNL_Connection::peek_bytes(void *data, int maxlength)
|
||||
{
|
||||
if (maxlength > m_recv_len)
|
||||
{
|
||||
maxlength=m_recv_len;
|
||||
}
|
||||
int read_pos=m_recv_pos-m_recv_len;
|
||||
if (read_pos < 0)
|
||||
{
|
||||
read_pos += m_recv_buffer.GetSize();
|
||||
}
|
||||
int len=m_recv_buffer.GetSize()-read_pos;
|
||||
if (len > maxlength)
|
||||
{
|
||||
len=maxlength;
|
||||
}
|
||||
if (data != NULL) {
|
||||
memcpy(data,m_recv_buffer.Get()+read_pos,len);
|
||||
if (len < maxlength)
|
||||
{
|
||||
memcpy((char*)data+len,m_recv_buffer.Get(),maxlength-len);
|
||||
}
|
||||
}
|
||||
|
||||
return maxlength;
|
||||
}
|
||||
|
||||
int JNL_Connection::recv_bytes(void *_data, int maxlength)
|
||||
{
|
||||
char *data = static_cast<char *>(_data);
|
||||
|
||||
int ml=peek_bytes(data,maxlength);
|
||||
m_recv_len-=ml;
|
||||
return ml;
|
||||
}
|
||||
|
||||
int JNL_Connection::getbfromrecv(int pos, int remove)
|
||||
{
|
||||
int read_pos=m_recv_pos-m_recv_len + pos;
|
||||
if (pos < 0 || pos > m_recv_len) return -1;
|
||||
if (read_pos < 0)
|
||||
{
|
||||
read_pos += m_recv_buffer.GetSize();
|
||||
}
|
||||
if (read_pos >= m_recv_buffer.GetSize())
|
||||
{
|
||||
read_pos-=m_recv_buffer.GetSize();
|
||||
}
|
||||
if (remove) m_recv_len--;
|
||||
return m_recv_buffer.Get()[read_pos];
|
||||
}
|
||||
|
||||
int JNL_Connection::recv_lines_available(void)
|
||||
{
|
||||
int l=recv_bytes_available();
|
||||
int lcount=0;
|
||||
int lastch=0;
|
||||
int pos;
|
||||
for (pos=0; pos < l; pos ++)
|
||||
{
|
||||
int t=getbfromrecv(pos,0);
|
||||
if (t == -1) return lcount;
|
||||
if ((t=='\r' || t=='\n') &&(
|
||||
(lastch != '\r' && lastch != '\n') || lastch==t
|
||||
)) lcount++;
|
||||
lastch=t;
|
||||
}
|
||||
return lcount;
|
||||
}
|
||||
|
||||
int JNL_Connection::recv_get_linelen()
|
||||
{
|
||||
int l = 0;
|
||||
while (l < m_recv_len)
|
||||
{
|
||||
int t=getbfromrecv(l,0);
|
||||
if (t<0) return 0;
|
||||
|
||||
if (t == '\r' || t == '\n')
|
||||
{
|
||||
int r=getbfromrecv(++l,0);
|
||||
if ((r == '\r' || r == '\n') && r != t) l++;
|
||||
return l;
|
||||
}
|
||||
l++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int JNL_Connection::recv_line(char *line, int maxlength)
|
||||
{
|
||||
maxlength--; // room for trailing NUL
|
||||
if (maxlength > m_recv_len) maxlength=m_recv_len;
|
||||
while (maxlength-- > 0)
|
||||
{
|
||||
int t=getbfromrecv(0,1);
|
||||
if (t == -1)
|
||||
{
|
||||
*line=0;
|
||||
return 0;
|
||||
}
|
||||
if (t == '\r' || t == '\n')
|
||||
{
|
||||
int r=getbfromrecv(0,0);
|
||||
if ((r == '\r' || r == '\n') && r != t) getbfromrecv(0,1);
|
||||
*line=0;
|
||||
return 0;
|
||||
}
|
||||
*line++=(char)t;
|
||||
}
|
||||
*line=0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void JNL_Connection::set_interface(int useInterface) // call before connect if needed
|
||||
{
|
||||
m_localinterfacereq = useInterface;
|
||||
}
|
||||
|
||||
|
||||
unsigned int JNL_Connection::get_interface(void)
|
||||
{
|
||||
if (m_socket==INVALID_SOCKET) return 0;
|
||||
struct sockaddr_in sin;
|
||||
memset(&sin,0,sizeof(sin));
|
||||
socklen_t len=16;
|
||||
if (::getsockname(m_socket,(struct sockaddr *)&sin,&len)) return 0;
|
||||
return (unsigned int) sin.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
unsigned int JNL_Connection::get_remote()
|
||||
{
|
||||
return m_saddr->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
short JNL_Connection::get_remote_port()
|
||||
{
|
||||
return m_remote_port;
|
||||
}
|
||||
193
oversampling/WDL/jnetlib/connection.h
Normal file
193
oversampling/WDL/jnetlib/connection.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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_IAsyncDNS
|
||||
** object to use (or NULL for none, or JNL_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 "asyncdns.h"
|
||||
#include "netinc.h"
|
||||
#include "../heapbuf.h"
|
||||
|
||||
#define JNL_CONNECTION_AUTODNS ((JNL_IAsyncDNS*)-1)
|
||||
|
||||
struct sockaddr_in;
|
||||
|
||||
#ifndef JNL_NO_DEFINE_INTERFACES
|
||||
class JNL_IConnection
|
||||
{
|
||||
public:
|
||||
virtual ~JNL_IConnection() { }
|
||||
virtual void connect(const char *hostname, int port)=0;
|
||||
virtual void connect(SOCKET sock, struct sockaddr_in *loc=NULL)=0; // used by the listen object, usually not needed by users.
|
||||
|
||||
virtual void run(int max_send_bytes=-1, int max_recv_bytes=-1, int *bytes_sent=NULL, int *bytes_rcvd=NULL)=0;
|
||||
virtual int get_state()=0;
|
||||
virtual const char *get_errstr()=0;
|
||||
|
||||
virtual void close(int quick=0)=0;
|
||||
virtual void flush_send(void)=0;
|
||||
|
||||
virtual int send_bytes_in_queue(void)=0;
|
||||
virtual int send_bytes_available(void)=0;
|
||||
virtual int send(const void *data, int length)=0; // returns -1 if not enough room
|
||||
virtual int send_bytes(const void *data, int length)=0;
|
||||
virtual int send_string(const char *line)=0; // returns -1 if not enough room
|
||||
|
||||
virtual int recv_bytes_available(void)=0;
|
||||
virtual int recv_bytes(void *data, int maxlength)=0; // returns actual bytes read
|
||||
virtual int recv_lines_available(void)=0;
|
||||
virtual int recv_line(char *line, int maxlength)=0; // 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.)
|
||||
virtual int recv_get_linelen()=0; // length in bytes for current line (including \r and/or \n), or 0 if no newline in buffer
|
||||
virtual int peek_bytes(void *data, int maxlength)=0; // returns bytes peeked
|
||||
|
||||
virtual unsigned int get_interface(void)=0; // this returns the interface the connection is on
|
||||
virtual unsigned int get_remote(void)=0; // remote host ip.
|
||||
virtual short get_remote_port(void)=0; // this returns the remote port of connection
|
||||
|
||||
virtual void set_interface(int useInterface)=0; // call before connect if needed
|
||||
virtual SOCKET get_socket() const = 0;
|
||||
};
|
||||
|
||||
#define JNL_Connection_PARENTDEF : public JNL_IConnection
|
||||
#else
|
||||
#define JNL_IConnection JNL_Connection
|
||||
#define JNL_Connection_PARENTDEF
|
||||
#endif
|
||||
|
||||
#ifndef JNL_NO_IMPLEMENTATION
|
||||
|
||||
class JNL_Connection JNL_Connection_PARENTDEF
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
STATE_ERROR,
|
||||
STATE_NOCONNECTION,
|
||||
STATE_RESOLVING,
|
||||
STATE_CONNECTING,
|
||||
STATE_CONNECTED,
|
||||
STATE_CLOSING,
|
||||
STATE_CLOSED
|
||||
} state;
|
||||
|
||||
JNL_Connection(JNL_IAsyncDNS *dns=JNL_CONNECTION_AUTODNS, int sendbufsize=8192, int recvbufsize=8192);
|
||||
~JNL_Connection();
|
||||
|
||||
void connect(const char *hostname, int port);
|
||||
void connect(SOCKET sock, struct sockaddr_in *loc=NULL); // used by the listen object, usually not needed by users.
|
||||
|
||||
void run(int max_send_bytes=-1, int max_recv_bytes=-1, int *bytes_sent=NULL, int *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) { m_send_len=m_send_pos=0; }
|
||||
|
||||
int send_bytes_in_queue(void);
|
||||
int send_bytes_available(void);
|
||||
int send(const void *data, int length); // returns -1 if not enough room
|
||||
inline int send_bytes(const void *data, int length) { return send(data, length); }
|
||||
int send_string(const char *line); // returns -1 if not enough room
|
||||
|
||||
|
||||
int recv_bytes_available(void);
|
||||
int recv_bytes(void *data, int maxlength); // returns actual bytes read
|
||||
int recv_lines_available(void);
|
||||
int recv_line(char *line, int 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.)
|
||||
int recv_get_linelen(); // length in bytes for current line (including \r and/or \n), or 0 if no newline in buffer
|
||||
int peek_bytes(void *data, int maxlength); // returns bytes peeked
|
||||
|
||||
unsigned int get_interface(void); // this returns the interface the connection is on
|
||||
unsigned int get_remote(void); // remote host ip.
|
||||
short get_remote_port(void); // this returns the remote port of connection
|
||||
|
||||
void set_interface(int useInterface); // call before connect if needed
|
||||
|
||||
SOCKET get_socket() const { return m_socket; }
|
||||
|
||||
protected:
|
||||
SOCKET m_socket;
|
||||
short m_remote_port;
|
||||
WDL_TypedBuf<unsigned char> m_recv_buffer;
|
||||
WDL_TypedBuf<unsigned char> m_send_buffer;
|
||||
|
||||
int m_recv_pos;
|
||||
int m_recv_len;
|
||||
int m_send_pos;
|
||||
int m_send_len;
|
||||
|
||||
int m_localinterfacereq;
|
||||
struct sockaddr_in *m_saddr;
|
||||
char m_host[256];
|
||||
|
||||
JNL_IAsyncDNS *m_dns;
|
||||
int m_dns_owned;
|
||||
|
||||
state m_state;
|
||||
const char *m_errorstr;
|
||||
|
||||
int getbfromrecv(int pos, int remove); // used by recv_line*
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _Connection_H_
|
||||
446
oversampling/WDL/jnetlib/httpget.cpp
Normal file
446
oversampling/WDL/jnetlib/httpget.cpp
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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"
|
||||
|
||||
|
||||
JNL_HTTPGet::JNL_HTTPGet(JNL_IAsyncDNS *dns, int recvbufsize, char *proxy)
|
||||
{
|
||||
m_recvbufsize=recvbufsize;
|
||||
m_dns=dns;
|
||||
m_con=NULL;
|
||||
m_http_proxylpinfo=0;
|
||||
m_http_proxyhost=0;
|
||||
m_http_proxyport=0;
|
||||
if (proxy && *proxy)
|
||||
{
|
||||
char *p=(char*)malloc(strlen(proxy)+1);
|
||||
if (p)
|
||||
{
|
||||
char *r=NULL;
|
||||
strcpy(p,proxy);
|
||||
do_parse_url(p,&m_http_proxyhost,&m_http_proxyport,&r,&m_http_proxylpinfo);
|
||||
free(r);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
m_sendheaders=NULL;
|
||||
reinit();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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);
|
||||
reinit();
|
||||
}
|
||||
|
||||
JNL_HTTPGet::~JNL_HTTPGet()
|
||||
{
|
||||
deinit();
|
||||
free(m_sendheaders);
|
||||
free(m_http_proxylpinfo);
|
||||
free(m_http_proxyhost);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void JNL_HTTPGet::addheader(const char *header)
|
||||
{
|
||||
if (strstr(header,"\r") || strstr(header,"\n")) return;
|
||||
if (!m_sendheaders)
|
||||
{
|
||||
m_sendheaders=(char*)malloc(strlen(header)+3);
|
||||
if (m_sendheaders)
|
||||
{
|
||||
strcpy(m_sendheaders,header);
|
||||
strcat(m_sendheaders,"\r\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *t=(char*)malloc(strlen(header)+strlen(m_sendheaders)+1+2);
|
||||
if (t)
|
||||
{
|
||||
strcpy(t,m_sendheaders);
|
||||
strcat(t,header);
|
||||
strcat(t,"\r\n");
|
||||
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)
|
||||
{
|
||||
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();
|
||||
m_http_url=(char*)malloc(strlen(url)+1);
|
||||
strcpy(m_http_url,url);
|
||||
do_parse_url(m_http_url,&m_http_host,&m_http_port,&m_http_request, &m_http_lpinfo);
|
||||
strcpy(m_http_url,url);
|
||||
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_lpinfo&&m_http_lpinfo[0])
|
||||
{
|
||||
sendbufferlen+=46+strlen(m_http_lpinfo)*2; // being safe here
|
||||
}
|
||||
|
||||
if (m_sendheaders) sendbufferlen+=strlen(m_sendheaders);
|
||||
|
||||
char *str=(char*)malloc(sendbufferlen+1024);
|
||||
if (!str)
|
||||
{
|
||||
seterrstr("error allocating memory");
|
||||
m_http_state=-1;
|
||||
}
|
||||
|
||||
if (!m_http_proxyhost || !m_http_proxyhost[0])
|
||||
{
|
||||
sprintf(str,"%s %s HTTP/1.%d\r\n",requestmethod,m_http_request,ver%10);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(str,"%s %s HTTP/1.%d\r\n",requestmethod, m_http_url,ver%10);
|
||||
}
|
||||
|
||||
sprintf(str+strlen(str),"Host:%s\r\n",m_http_host);
|
||||
|
||||
if (m_http_lpinfo&&m_http_lpinfo[0])
|
||||
{
|
||||
strcat(str,"Authorization: Basic ");
|
||||
do_encode_mimestr(m_http_lpinfo,str+strlen(str));
|
||||
strcat(str,"\r\n");
|
||||
}
|
||||
if (m_http_proxylpinfo&&m_http_proxylpinfo[0])
|
||||
{
|
||||
strcat(str,"Proxy-Authorization: Basic ");
|
||||
do_encode_mimestr(m_http_proxylpinfo,str+strlen(str));
|
||||
strcat(str,"\r\n");
|
||||
}
|
||||
|
||||
if (m_sendheaders) strcat(str,m_sendheaders);
|
||||
strcat(str,"\r\n");
|
||||
|
||||
int a=m_recvbufsize;
|
||||
if (a < 4096) a=4096;
|
||||
m_con=new JNL_Connection(m_dns,(int)strlen(str)+4,a);
|
||||
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(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_http_state=-1;
|
||||
seterrstr("could not create connection object");
|
||||
}
|
||||
free(str);
|
||||
|
||||
}
|
||||
|
||||
void JNL_HTTPGet::do_parse_url(char *url, char **host, int *port, char **req, char **lp)
|
||||
{
|
||||
char *p,*np;
|
||||
free(*host); *host=0;
|
||||
free(*req); *req=0;
|
||||
free(*lp); *lp=0;
|
||||
|
||||
if (strstr(url,"://")) np=p=strstr(url,"://")+3;
|
||||
else np=p=url;
|
||||
while (*np != '/' && *np) np++;
|
||||
if (*np)
|
||||
{
|
||||
*req=(char*)malloc(strlen(np)+1);
|
||||
if (*req) strcpy(*req,np);
|
||||
*np++=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*req=(char*)malloc(2);
|
||||
if (*req) strcpy(*req,"/");
|
||||
}
|
||||
|
||||
np=p;
|
||||
while (*np != '@' && *np) np++;
|
||||
if (*np)
|
||||
{
|
||||
*np++=0;
|
||||
*lp=(char*)malloc(strlen(p)+1);
|
||||
if (*lp) strcpy(*lp,p);
|
||||
p=np;
|
||||
}
|
||||
else
|
||||
{
|
||||
*lp=(char*)malloc(1);
|
||||
if (*lp) strcpy(*lp,"");
|
||||
}
|
||||
np=p;
|
||||
while (*np != ':' && *np) np++;
|
||||
if (*np)
|
||||
{
|
||||
*np++=0;
|
||||
*port=atoi(np);
|
||||
} else *port=80;
|
||||
*host=(char*)malloc(strlen(p)+1);
|
||||
if (*host) strcpy(*host,p);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
if (!headername || !m_recvheaders) return NULL;
|
||||
|
||||
size_t headername_len = strlen(headername);
|
||||
if (headername_len<1) return NULL;
|
||||
|
||||
if (headername[headername_len - 1] == ':') headername_len--;
|
||||
|
||||
const char *p=m_recvheaders;
|
||||
while (*p)
|
||||
{
|
||||
if (!strnicmp(headername,p,headername_len) && p[headername_len] == ':')
|
||||
{
|
||||
p += headername_len + 1;
|
||||
while (*p == ' ') p++;
|
||||
return p;
|
||||
}
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int JNL_HTTPGet::run()
|
||||
{
|
||||
int cnt=0;
|
||||
if (m_http_state==-1||!m_con) return -1; // error
|
||||
|
||||
|
||||
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 1;
|
||||
|
||||
if (m_http_state==0) // connected, waiting for reply
|
||||
{
|
||||
if (m_con->recv_lines_available()>0)
|
||||
{
|
||||
char buf[4096];
|
||||
m_con->recv_line(buf,4095);
|
||||
buf[4095]=0;
|
||||
m_reply=(char*)malloc(strlen(buf)+1);
|
||||
strcpy(m_reply,buf);
|
||||
|
||||
int code=getreplycode();
|
||||
if (code == 200 || code==206) m_http_state=2; // proceed to read headers normally
|
||||
else if (code == 301 || code==302)
|
||||
{
|
||||
m_http_state=1; // redirect city
|
||||
}
|
||||
else
|
||||
{
|
||||
seterrstr(buf);
|
||||
m_http_state=-1;
|
||||
return -1;
|
||||
}
|
||||
cnt=0;
|
||||
}
|
||||
else if (!cnt++) goto run_again;
|
||||
}
|
||||
if (m_http_state == 1) // redirect
|
||||
{
|
||||
while (m_con->recv_lines_available() > 0)
|
||||
{
|
||||
char buf[4096];
|
||||
m_con->recv_line(buf,4096);
|
||||
if (!buf[0])
|
||||
{
|
||||
m_http_state=-1;
|
||||
return -1;
|
||||
}
|
||||
if (!strnicmp(buf,"Location:",9))
|
||||
{
|
||||
const char *p=buf+9; while (*p== ' ') p++;
|
||||
if (*p)
|
||||
{
|
||||
connect(p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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[4096];
|
||||
m_con->recv_line(buf,4096);
|
||||
if (!buf[0]) { m_http_state=3; break; }
|
||||
if (!m_recvheaders)
|
||||
{
|
||||
m_recvheaders_size=(int)strlen(buf)+1;
|
||||
m_recvheaders=(char*)malloc(m_recvheaders_size+1);
|
||||
if (m_recvheaders)
|
||||
{
|
||||
strcpy(m_recvheaders,buf);
|
||||
m_recvheaders[m_recvheaders_size]=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int oldsize=m_recvheaders_size;
|
||||
m_recvheaders_size+=(int)strlen(buf)+1;
|
||||
char *n=(char*)malloc(m_recvheaders_size+1);
|
||||
if (n)
|
||||
{
|
||||
memcpy(n,m_recvheaders,oldsize);
|
||||
strcpy(n+oldsize,buf);
|
||||
n[m_recvheaders_size]=0;
|
||||
free(m_recvheaders);
|
||||
m_recvheaders=n;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_http_state==3)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 -1;
|
||||
if (m_http_state < 2) return 0;
|
||||
if (m_http_state == 2) return 1;
|
||||
if (m_http_state == 3) return 2;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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++; // skip over HTTP/x.x
|
||||
if (!*p) return 0;
|
||||
return atoi(++p);
|
||||
}
|
||||
|
||||
int JNL_HTTPGet::bytes_available()
|
||||
{
|
||||
if (m_con && m_http_state==3) return m_con->recv_bytes_available();
|
||||
return 0;
|
||||
}
|
||||
int JNL_HTTPGet::get_bytes(char *buf, int len)
|
||||
{
|
||||
if (m_con && m_http_state==3) return m_con->recv_bytes(buf,len);
|
||||
return 0;
|
||||
}
|
||||
int JNL_HTTPGet::peek_bytes(char *buf, int len)
|
||||
{
|
||||
if (m_con && m_http_state==3) return m_con->peek_bytes(buf,len);
|
||||
return 0;
|
||||
}
|
||||
152
oversampling/WDL/jnetlib/httpget.h
Normal file
152
oversampling/WDL/jnetlib/httpget.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 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 JNL_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"
|
||||
|
||||
#ifndef JNL_NO_DEFINE_INTERFACES
|
||||
class JNL_IHTTPGet
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~JNL_IHTTPGet() { }
|
||||
|
||||
virtual void addheader(const char *header)=0;
|
||||
|
||||
virtual void connect(const char *url, int ver=0, const char *requestmethod="GET")=0;
|
||||
|
||||
virtual int run()=0; // returns: 0 if all is OK. -1 if error (call geterrorstr()). 1 if connection closed.
|
||||
|
||||
virtual int get_status()=0; // returns 0 if connecting, 1 if reading headers,
|
||||
// 2 if reading content, -1 if error.
|
||||
|
||||
virtual const char *getallheaders()=0; // double null terminated, null delimited list
|
||||
virtual const char *getheader(const char *headername)=0;
|
||||
virtual const char *getreply()=0;
|
||||
virtual int getreplycode()=0; // returns 0 if none yet, otherwise returns http reply code.
|
||||
|
||||
virtual const char *geterrorstr()=0;
|
||||
|
||||
virtual int bytes_available()=0;
|
||||
virtual int get_bytes(char *buf, int len)=0;
|
||||
virtual int peek_bytes(char *buf, int len)=0;
|
||||
|
||||
virtual int content_length()=0;
|
||||
|
||||
virtual JNL_IConnection *get_con()=0;
|
||||
};
|
||||
#define JNL_HTTPGet_PARENTDEF : public JNL_IHTTPGet
|
||||
#else
|
||||
#define JNL_IHTTPGet JNL_HTTPGet
|
||||
#define JNL_HTTPGet_PARENTDEF
|
||||
#endif
|
||||
|
||||
#ifndef JNL_NO_IMPLEMENTATION
|
||||
|
||||
class JNL_HTTPGet JNL_HTTPGet_PARENTDEF
|
||||
{
|
||||
public:
|
||||
JNL_HTTPGet(JNL_IAsyncDNS *dns=JNL_CONNECTION_AUTODNS, int recvbufsize=16384, char *proxy=NULL);
|
||||
~JNL_HTTPGet();
|
||||
|
||||
void addheader(const char *header);
|
||||
|
||||
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;}
|
||||
|
||||
int bytes_available();
|
||||
int get_bytes(char *buf, int len);
|
||||
int peek_bytes(char *buf, int len);
|
||||
|
||||
int content_length() { const char *p=getheader("content-length"); if (p) return atoi(p); return 0; }
|
||||
|
||||
JNL_IConnection *get_con() { return m_con; }
|
||||
|
||||
|
||||
|
||||
static void do_parse_url(char *url, char **host, int *port, char **req, char **lp); // url gets thrashed, and host/req/lp are freed/allocated
|
||||
static void do_encode_mimestr(char *in, char *out);
|
||||
|
||||
protected:
|
||||
void reinit();
|
||||
void deinit();
|
||||
void seterrstr(const char *str) { if (m_errstr) free(m_errstr); m_errstr=(char*)malloc(strlen(str)+1); strcpy(m_errstr,str); }
|
||||
|
||||
JNL_IAsyncDNS *m_dns;
|
||||
JNL_IConnection *m_con;
|
||||
int m_recvbufsize;
|
||||
|
||||
int m_http_state;
|
||||
|
||||
int 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;
|
||||
int m_http_proxyport;
|
||||
|
||||
char *m_sendheaders;
|
||||
char *m_recvheaders;
|
||||
int m_recvheaders_size;
|
||||
char *m_reply;
|
||||
|
||||
char *m_errstr;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // _HTTPGET_H_
|
||||
262
oversampling/WDL/jnetlib/httpserv.cpp
Normal file
262
oversampling/WDL/jnetlib/httpserv.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** 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_IConnection *con)
|
||||
{
|
||||
m_usechunk = false;
|
||||
m_keepalive = true;
|
||||
m_con=con;
|
||||
m_state=0;
|
||||
m_reply_ready=0;
|
||||
}
|
||||
|
||||
JNL_HTTPServ::~JNL_HTTPServ()
|
||||
{
|
||||
delete m_con;
|
||||
}
|
||||
|
||||
void JNL_HTTPServ::write_bytes(const char *bytes, int length)
|
||||
{
|
||||
if (m_usechunk)
|
||||
{
|
||||
char buf[32];
|
||||
sprintf(buf,"%x\r\n",length);
|
||||
m_con->send_string(buf);
|
||||
}
|
||||
m_con->send(bytes,length);
|
||||
if (m_usechunk) m_con->send_string("\r\n");
|
||||
}
|
||||
|
||||
bool JNL_HTTPServ::want_keepalive_reset()
|
||||
{
|
||||
if (m_state >= 2 && m_con && m_con->get_state() == JNL_Connection::STATE_CONNECTED)
|
||||
{
|
||||
m_usechunk = false;
|
||||
m_state = 0;
|
||||
m_reply_ready = 0;
|
||||
m_errstr.Set("");
|
||||
m_reply_headers.Set("");
|
||||
m_reply_string.Set("");
|
||||
m_recvheaders.Clear();
|
||||
m_recv_request.Resize(0,false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int reqlen = m_con->recv_get_linelen();
|
||||
if (reqlen>0)
|
||||
{
|
||||
if (!m_recv_request.ResizeOK(reqlen+2,false))
|
||||
{
|
||||
seterrstr("malloc fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
reqlen = m_con->recv_bytes(m_recv_request.Get(),reqlen);
|
||||
char *buf = m_recv_request.Get() + reqlen;
|
||||
*buf=0;
|
||||
while (buf > m_recv_request.Get() && (buf[-1] == '\r' || buf[-1]=='\n')) *--buf=0;
|
||||
const char *endptr = buf;
|
||||
while (buf >= m_recv_request.Get() && *buf != ' ') buf--;
|
||||
|
||||
if (buf < m_recv_request.Get() || strncmp(buf+1,"HTTP",4) || strncmp(m_recv_request.Get(),"GET ",4))
|
||||
{
|
||||
seterrstr("malformed HTTP request");
|
||||
m_state=-1;
|
||||
buf=m_recv_request.Get();
|
||||
buf[0]=buf[1]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (endptr[-1]=='0') m_keepalive = false; // old http 1.0
|
||||
m_state=1;
|
||||
cnt=0;
|
||||
buf[0]=buf[1]=0;
|
||||
|
||||
buf=strstr(m_recv_request.Get(),"?");
|
||||
if (buf)
|
||||
{
|
||||
*buf++=0; // change &'s into 0s now.
|
||||
char *t=buf;
|
||||
int stat=1;
|
||||
while (*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_get_linelen()>0)
|
||||
{
|
||||
char buf[4096];
|
||||
buf[0]=0;
|
||||
m_con->recv_line(buf,4096);
|
||||
if (!buf[0]) { m_state=2; break; }
|
||||
|
||||
if (!strnicmp(buf,"Connection:",11))
|
||||
{
|
||||
const char *p=buf+11;
|
||||
while (*p && strnicmp(p,"close",5)) p++;
|
||||
if (*p) m_keepalive = false;
|
||||
}
|
||||
|
||||
if (m_recvheaders.GetSize()) m_recvheaders.Add(NULL,-1); // remove doublenull
|
||||
m_recvheaders.Add(buf,strlen(buf)+1);
|
||||
m_recvheaders.Add("",1);
|
||||
}
|
||||
}
|
||||
if (m_state == 2)
|
||||
{
|
||||
if (m_reply_ready)
|
||||
{
|
||||
// send reply
|
||||
m_con->send_string((char*)(m_reply_string.GetLength()?m_reply_string.Get():"HTTP/1.1 200 OK"));
|
||||
m_con->send_string("\r\n");
|
||||
if (m_reply_headers.GetLength()) m_con->send_string(m_reply_headers.Get());
|
||||
if (m_keepalive)
|
||||
{
|
||||
const char *p = m_reply_headers.Get();
|
||||
bool had_cl=false,had_con=false;
|
||||
while (*p && (!had_cl || !had_con))
|
||||
{
|
||||
if (!strnicmp(p,"Content-Length:",15)) had_cl=true;
|
||||
else if (!strnicmp(p,"Connection:",11)) had_con=true;
|
||||
|
||||
while (*p && *p != '\r' && *p != '\n') p++;
|
||||
while (*p == '\r' || *p == '\n') p++;
|
||||
}
|
||||
if (!had_con) m_con->send_string("Connection: keep-alive\r\n");
|
||||
if (!had_cl)
|
||||
{
|
||||
m_usechunk = true;
|
||||
m_con->send_string("Transfer-Encoding: chunked\r\n");
|
||||
}
|
||||
}
|
||||
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
|
||||
char *t=m_recv_request.Get();
|
||||
if (!t) return NULL;
|
||||
|
||||
while (*t != ' ' && *t) t++;
|
||||
if (!*t) return NULL;
|
||||
while (*t == ' ') t++;
|
||||
return t;
|
||||
}
|
||||
|
||||
const char *JNL_HTTPServ::get_request_parm(const char *parmname) // parameter portion (after ?)
|
||||
{
|
||||
const char *t=m_recv_request.Get();
|
||||
if (!t) return NULL;
|
||||
|
||||
while (*t) t++;
|
||||
t++;
|
||||
while (*t)
|
||||
{
|
||||
while (*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)
|
||||
{
|
||||
const char *ret=NULL;
|
||||
if (strlen(headername)<1||!m_recvheaders.Available()) return NULL;
|
||||
const char *p=m_recvheaders.Get();
|
||||
const int hdrlen = (int) strlen(headername);
|
||||
while (*p)
|
||||
{
|
||||
if (!strnicmp(headername,p,hdrlen) && p[hdrlen] == ':')
|
||||
{
|
||||
ret=p+hdrlen+1;
|
||||
while (*ret == ' ') ret++;
|
||||
break;
|
||||
}
|
||||
while (*p) p++;
|
||||
p++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JNL_HTTPServ::set_reply_string(const char *reply_string) // should be HTTP/1.1 OK or the like
|
||||
{
|
||||
m_reply_string.Set(reply_string);
|
||||
}
|
||||
|
||||
void JNL_HTTPServ::set_reply_size(int sz) // if set, size will also add keep-alive etc
|
||||
{
|
||||
if (sz>=0)
|
||||
{
|
||||
char buf[512];
|
||||
sprintf(buf,"Content-length: %d",sz);
|
||||
set_reply_header(buf);
|
||||
}
|
||||
}
|
||||
void JNL_HTTPServ::set_reply_header(const char *header) // "Connection: close" for example
|
||||
{
|
||||
m_reply_headers.Append(header);
|
||||
m_reply_headers.Append("\r\n");
|
||||
}
|
||||
118
oversampling/WDL/jnetlib/httpserv.h
Normal file
118
oversampling/WDL/jnetlib/httpserv.h
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** 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 "../wdlstring.h"
|
||||
#include "../queue.h"
|
||||
|
||||
#ifndef JNL_NO_DEFINE_INTERFACES
|
||||
class JNL_IHTTPServ
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~JNL_IHTTPServ() { }
|
||||
|
||||
virtual int run()=0; // 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.
|
||||
|
||||
virtual const char *geterrorstr()=0;
|
||||
|
||||
// use these when state returned by run() is 2
|
||||
virtual const char *get_request_file()=0; // file portion of http request
|
||||
virtual const char *get_request_parm(const char *parmname)=0; // parameter portion (after ?)
|
||||
virtual const char *getallheaders()=0;
|
||||
virtual const char *getheader(const char *headername)=0;
|
||||
|
||||
virtual void set_reply_string(const char *reply_string)=0; // should be HTTP/1.1 OK or the like
|
||||
virtual void set_reply_header(const char *header)=0; // i.e. "content-size: 12345"
|
||||
virtual void set_reply_size(int sz)=0; // if set, size will also add keep-alive etc
|
||||
|
||||
virtual void send_reply()=0;
|
||||
|
||||
////////// sending data ///////////////
|
||||
virtual int bytes_inqueue()=0;
|
||||
virtual int bytes_cansend()=0;
|
||||
virtual void write_bytes(const char *bytes, int length)=0;
|
||||
|
||||
virtual void close(int quick)=0;
|
||||
|
||||
virtual JNL_IConnection *get_con()=0;
|
||||
virtual JNL_IConnection *steal_con()=0;
|
||||
virtual bool want_keepalive_reset()=0;
|
||||
|
||||
virtual bool canKeepAlive()=0;
|
||||
};
|
||||
#define JNL_HTTPServ_PARENTDEF : public JNL_IHTTPServ
|
||||
#else
|
||||
#define JNL_IHTTPServ JNL_HTTPServ
|
||||
#define JNL_HTTPServ_PARENTDEF
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef JNL_NO_IMPLEMENTATION
|
||||
|
||||
class JNL_HTTPServ JNL_HTTPServ_PARENTDEF
|
||||
{
|
||||
public:
|
||||
JNL_HTTPServ(JNL_IConnection *con);
|
||||
~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.Get()[0] ? m_errstr.Get() : NULL; }
|
||||
|
||||
// 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 m_recvheaders.Get(); } // double null terminated, null delimited list
|
||||
const char *getheader(const char *headername);
|
||||
|
||||
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 set_reply_size(int sz); // if set, size will also add keep-alive etc
|
||||
|
||||
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 m_con->send_bytes_in_queue(); else return 0; }
|
||||
int bytes_cansend() { if (m_state == 3) return m_con->send_bytes_available() - (m_usechunk?16:0); else return 0; }
|
||||
void write_bytes(const char *bytes, int length);
|
||||
|
||||
void close(int quick) { m_con->close(quick); m_state=4; }
|
||||
|
||||
JNL_IConnection *get_con() { return m_con; }
|
||||
JNL_IConnection *steal_con() { JNL_IConnection *ret= m_con; m_con=0; return ret; }
|
||||
bool want_keepalive_reset();
|
||||
|
||||
bool canKeepAlive() { return m_keepalive; }
|
||||
|
||||
protected:
|
||||
void seterrstr(const char *str) { m_errstr.Set(str); }
|
||||
|
||||
int m_reply_ready;
|
||||
int m_state;
|
||||
bool m_keepalive, m_usechunk;
|
||||
|
||||
WDL_FastString m_errstr;
|
||||
WDL_FastString m_reply_headers;
|
||||
WDL_FastString m_reply_string;
|
||||
WDL_TypedQueue<char> m_recvheaders;
|
||||
WDL_TypedBuf<char> m_recv_request; // either double-null terminated, or may contain parameters after first null.
|
||||
JNL_IConnection *m_con;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // _HTTPSERV_H_
|
||||
59
oversampling/WDL/jnetlib/irc_util.h
Normal file
59
oversampling/WDL/jnetlib/irc_util.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef _WDL_JNL_IRC_UTIL_H_
|
||||
#define _WDL_JNL_IRC_UTIL_H_
|
||||
|
||||
#include "netinc.h"
|
||||
|
||||
static void FormatIRCMessage(char *bufout, const char *fmt, ...) // bufout should be 1024 bytes to be safe
|
||||
{
|
||||
va_list arglist;
|
||||
va_start(arglist, fmt);
|
||||
#ifdef _WIN32
|
||||
int written = _vsnprintf(bufout, 1024-16, fmt, arglist);
|
||||
#else
|
||||
int written = vsnprintf(bufout, 1024-16, fmt, arglist);
|
||||
#endif
|
||||
if (written < 0) written = 0;
|
||||
else if (written > 510) written=510;
|
||||
bufout[written]=0;
|
||||
va_end(arglist);
|
||||
|
||||
strcat(bufout,"\r\n");
|
||||
}
|
||||
|
||||
|
||||
static void ParseIRCMessage(char *buf, char **prefix, char *tokens[16], int *tokensvalid, bool *lastHadColon) // destroys buf
|
||||
{
|
||||
if (lastHadColon) *lastHadColon=false;
|
||||
*tokensvalid=0;
|
||||
if (prefix) *prefix=NULL;
|
||||
if (*buf==':')
|
||||
{
|
||||
if (prefix) *prefix=buf;
|
||||
while (*buf && *buf != ' ') buf++;
|
||||
if (*buf==' ')
|
||||
{
|
||||
*buf++=0;
|
||||
while (*buf== ' ') buf++;
|
||||
}
|
||||
}
|
||||
|
||||
while (*buf && *tokensvalid < 16)
|
||||
{
|
||||
tokens[(*tokensvalid)++] = buf[0] == ':' ? buf+1 : buf;
|
||||
if (buf[0] == ':' || *tokensvalid == 16)
|
||||
{
|
||||
if (buf[0] == ':' && lastHadColon) *lastHadColon=true;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip over parameter
|
||||
while (*buf && *buf != ' ') buf++;
|
||||
if (*buf == ' ')
|
||||
{
|
||||
*buf++=0;
|
||||
while (*buf== ' ') buf++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
47
oversampling/WDL/jnetlib/jnetlib.h
Normal file
47
oversampling/WDL/jnetlib/jnetlib.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2003 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 "util.h"
|
||||
|
||||
#include "asyncdns.h"
|
||||
#include "connection.h"
|
||||
#include "httpget.h"
|
||||
#include "httpserv.h"
|
||||
#include "listen.h"
|
||||
|
||||
#endif//_JNETLIB_H_
|
||||
75
oversampling/WDL/jnetlib/listen.cpp
Normal file
75
oversampling/WDL/jnetlib/listen.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** File: listen.cpp - JNL TCP listen implementation
|
||||
** License: see jnetlib.h
|
||||
*/
|
||||
|
||||
#include "netinc.h"
|
||||
#include "util.h"
|
||||
#include "listen.h"
|
||||
|
||||
JNL_Listen::JNL_Listen(short port, unsigned int which_interface)
|
||||
{
|
||||
m_port=port;
|
||||
m_socket = ::socket(AF_INET,SOCK_STREAM,0);
|
||||
if (m_socket == INVALID_SOCKET)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
SET_SOCK_DEFAULTS(m_socket);
|
||||
SET_SOCK_BLOCK(m_socket,0);
|
||||
int bflag = 1;
|
||||
setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&bflag, sizeof(bflag));
|
||||
memset((char *) &sin, 0,sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons( (short) port );
|
||||
sin.sin_addr.s_addr = which_interface?which_interface:INADDR_ANY;
|
||||
if (::bind(m_socket,(struct sockaddr *)&sin,sizeof(sin)))
|
||||
{
|
||||
shutdown(m_socket, SHUT_RDWR);
|
||||
closesocket(m_socket);
|
||||
m_socket=INVALID_SOCKET;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (::listen(m_socket,8)==-1)
|
||||
{
|
||||
shutdown(m_socket, SHUT_RDWR);
|
||||
closesocket(m_socket);
|
||||
m_socket=INVALID_SOCKET;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNL_Listen::~JNL_Listen()
|
||||
{
|
||||
if (m_socket!=INVALID_SOCKET)
|
||||
{
|
||||
shutdown(m_socket, SHUT_RDWR);
|
||||
closesocket(m_socket);
|
||||
}
|
||||
}
|
||||
|
||||
JNL_IConnection *JNL_Listen::get_connect(int sendbufsize, int recvbufsize)
|
||||
{
|
||||
if (m_socket == INVALID_SOCKET)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
struct sockaddr_in saddr;
|
||||
socklen_t length = sizeof(struct sockaddr_in);
|
||||
SOCKET s = accept(m_socket, (struct sockaddr *) &saddr, &length);
|
||||
if (s != INVALID_SOCKET)
|
||||
{
|
||||
JNL_IConnection *c=new JNL_Connection(NULL,sendbufsize, recvbufsize);
|
||||
c->connect(s,&saddr);
|
||||
return c;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
62
oversampling/WDL/jnetlib/listen.h
Normal file
62
oversampling/WDL/jnetlib/listen.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008 Cockos Inc
|
||||
** Copyright (C) 2000-2001 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** 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"
|
||||
|
||||
#ifndef JNL_NO_DEFINE_INTERFACES
|
||||
|
||||
class JNL_IListen
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~JNL_IListen() { }
|
||||
|
||||
virtual JNL_IConnection *get_connect(int sendbufsize=8192, int recvbufsize=8192)=0;
|
||||
virtual short port(void)=0;
|
||||
virtual int is_error(void)=0;
|
||||
};
|
||||
|
||||
#define JNL_Listen_PARENTDEF : public JNL_IListen
|
||||
#else
|
||||
#define JNL_IListen JNL_Listen
|
||||
#define JNL_Listen_PARENTDEF
|
||||
#endif
|
||||
|
||||
#ifndef JNL_NO_IMPLEMENTATION
|
||||
|
||||
|
||||
class JNL_Listen JNL_Listen_PARENTDEF
|
||||
{
|
||||
public:
|
||||
JNL_Listen(short port, unsigned int which_interface=0);
|
||||
~JNL_Listen();
|
||||
|
||||
JNL_IConnection *get_connect(int sendbufsize=8192, int recvbufsize=8192);
|
||||
short port(void) { return m_port; }
|
||||
int is_error(void) { return (m_socket == INVALID_SOCKET); }
|
||||
|
||||
protected:
|
||||
SOCKET m_socket;
|
||||
short m_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif //_LISTEN_H_
|
||||
90
oversampling/WDL/jnetlib/netinc.h
Normal file
90
oversampling/WDL/jnetlib/netinc.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2001 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 <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#define JNL_ERRNO (WSAGetLastError())
|
||||
#define SET_SOCK_BLOCK(s,block) { unsigned long __i=block?0:1; ioctlsocket(s,FIONBIO,&__i); }
|
||||
#define SET_SOCK_DEFAULTS(s) do { } while (0)
|
||||
#define JNL_EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define JNL_EINPROGRESS WSAEWOULDBLOCK
|
||||
#define JNL_ENOTCONN WSAENOTCONN
|
||||
|
||||
typedef int socklen_t;
|
||||
|
||||
#else
|
||||
|
||||
#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 <sys/poll.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 JNL_ERRNO ((errno)|0)
|
||||
#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); } }
|
||||
#ifdef __APPLE__
|
||||
#define SET_SOCK_DEFAULTS(s) do { int __flags = 1; setsockopt((s), SOL_SOCKET, SO_NOSIGPIPE, &__flags, sizeof(__flags)); } while (0)
|
||||
#else
|
||||
#define SET_SOCK_DEFAULTS(s) do { } while (0)
|
||||
#endif
|
||||
|
||||
typedef int SOCKET;
|
||||
#define INVALID_SOCKET (-1)
|
||||
|
||||
#define JNL_EWOULDBLOCK EWOULDBLOCK
|
||||
#define JNL_EINPROGRESS EINPROGRESS
|
||||
#define JNL_ENOTCONN ENOTCONN
|
||||
|
||||
#ifndef stricmp
|
||||
#define stricmp(x,y) strcasecmp(x,y)
|
||||
#endif
|
||||
#ifndef strnicmp
|
||||
#define strnicmp(x,y,z) strncasecmp(x,y,z)
|
||||
#endif
|
||||
|
||||
#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_
|
||||
555
oversampling/WDL/jnetlib/test.cpp
Normal file
555
oversampling/WDL/jnetlib/test.cpp
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2001 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** File: test.cpp - JNL test code
|
||||
** License: see jnetlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#define Sleep(x) usleep((x)*1000)
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include "jnetlib.h"
|
||||
|
||||
|
||||
#define TEST_ASYNCDNS 0
|
||||
#define TEST_CONNECTION 0
|
||||
#define TEST_LISTEN 0
|
||||
#define TEST_TELNET_GATEWAY 0
|
||||
#define TEST_HTTPGET 0
|
||||
#define TEST_WEBSERVER 1
|
||||
|
||||
#define TEST_UDP 0 //udp is not done yet tho :)
|
||||
|
||||
|
||||
|
||||
#if (TEST_WEBSERVER)
|
||||
#include "webserver.h"
|
||||
|
||||
|
||||
class MemPageGenerator : public IPageGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~MemPageGenerator() { free(m_buf); }
|
||||
MemPageGenerator(char *buf, int buf_len=-1) { m_buf=buf; if (buf_len >= 0) m_buf_size=buf_len; else m_buf_size=strlen(buf); m_buf_pos=0; }
|
||||
virtual int GetData(char *buf, int size) // return 0 when done
|
||||
{
|
||||
int a=m_buf_size-m_buf_pos;
|
||||
if (a < size) size=a;
|
||||
memcpy(buf,m_buf+m_buf_pos,size);
|
||||
m_buf_pos+=size;
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
char *m_buf;
|
||||
int m_buf_size;
|
||||
int m_buf_pos;
|
||||
};
|
||||
|
||||
class wwwServer : public WebServerBaseClass
|
||||
{
|
||||
public:
|
||||
wwwServer() { }
|
||||
virtual IPageGenerator *onConnection(JNL_HTTPServ *serv, int port)
|
||||
{
|
||||
serv->set_reply_header("Server:jnetlib_test/0.0");
|
||||
if (!strcmp(serv->get_request_file(),"/"))
|
||||
{
|
||||
serv->set_reply_string("HTTP/1.1 200 OK");
|
||||
serv->set_reply_header("Content-Type:text/html");
|
||||
serv->send_reply();
|
||||
|
||||
return new MemPageGenerator(strdup("Test Web Server v0.0"));
|
||||
}
|
||||
else
|
||||
{
|
||||
serv->set_reply_string("HTTP/1.1 404 NOT FOUND");
|
||||
serv->send_reply();
|
||||
return 0; // no data
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
JNL::open_socketlib();
|
||||
{
|
||||
wwwServer foo;
|
||||
foo.addListenPort(8080);
|
||||
while (1)
|
||||
{
|
||||
foo.run();
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (TEST_HTTPGET)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("usage: httpget <url> <outfile>\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
JNL_HTTPGet get;
|
||||
JNL::open_socketlib();
|
||||
|
||||
get.addheader("User-Agent:PooHead (Mozilla)");
|
||||
get.addheader("Accept:*/*");
|
||||
get.connect(argv[1]);
|
||||
|
||||
FILE *fp=fopen(argv[2],"wb");
|
||||
int headerstate=0;
|
||||
int has_printed_headers=0;
|
||||
int has_printed_reply=0;
|
||||
while (1)
|
||||
{
|
||||
int st=get.run();
|
||||
if (st<0)
|
||||
{
|
||||
printf("HTTPGet error: %s\n",get.geterrorstr());
|
||||
break;
|
||||
}
|
||||
if (get.get_status()>0)
|
||||
{
|
||||
if (!has_printed_reply)
|
||||
{
|
||||
has_printed_reply=1;
|
||||
printf("reply: %s (code:%d)\n",get.getreply(),get.getreplycode());
|
||||
}
|
||||
if (get.get_status()==2)
|
||||
{
|
||||
int len;
|
||||
if (!has_printed_headers)
|
||||
{
|
||||
has_printed_headers=1;
|
||||
printf("headers:\n");
|
||||
char *p=get.getallheaders();
|
||||
while (p&&*p)
|
||||
{
|
||||
printf("%s\n",p);
|
||||
p+=strlen(p)+1;
|
||||
}
|
||||
}
|
||||
while ((len=get.bytes_available()) > 0)
|
||||
{
|
||||
char buf[4096];
|
||||
if (len > 4096) len=4096;
|
||||
len=get.get_bytes(buf,len);
|
||||
if (len>0)fwrite(buf,len,1,fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (st==1) // 1 means connection closed
|
||||
{
|
||||
printf("HTTPGet done!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fp) fclose(fp);
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (TEST_TELNET_GATEWAY)
|
||||
|
||||
int main()
|
||||
{
|
||||
JNL_Connection *cons[32]={0,};
|
||||
JNL_Connection *outcons[32]={0,};
|
||||
char textpos[32][256];
|
||||
int n_cons=0;
|
||||
int states[32]={0,};
|
||||
|
||||
JNL::open_socketlib();
|
||||
JNL_AsyncDNS dns;
|
||||
JNL_Listen l(23);
|
||||
while (!l.is_error())
|
||||
{
|
||||
Sleep(30);
|
||||
if (n_cons<32)
|
||||
{
|
||||
JNL_Connection *con=l.get_connect();
|
||||
if (con)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (!cons[x])
|
||||
{
|
||||
cons[x]=con;
|
||||
outcons[x]=0;
|
||||
states[x]=0;
|
||||
n_cons++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (cons[x])
|
||||
{
|
||||
cons[x]->run();
|
||||
if (outcons[x]) outcons[x]->run();
|
||||
|
||||
if (cons[x]->get_state() == JNL_Connection::STATE_ERROR || cons[x]->get_state()==JNL_Connection::STATE_CLOSED ||
|
||||
(outcons[x] && (cons[x]->get_state() == JNL_Connection::STATE_ERROR || cons[x]->get_state()==JNL_Connection::STATE_CLOSED)))
|
||||
{
|
||||
delete cons[x];
|
||||
if (outcons[x]) delete outcons[x];
|
||||
outcons[x]=0;
|
||||
cons[x]=0;
|
||||
states[x]=0;
|
||||
n_cons--;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (states[x]==0)
|
||||
{
|
||||
cons[x]->send_string("\r\nwelcome ");
|
||||
states[x]++;
|
||||
}
|
||||
if (states[x]==1)
|
||||
{
|
||||
char hoststr[256];
|
||||
int ret=dns.reverse(cons[x]->get_remote(),hoststr);
|
||||
if (ret==0)
|
||||
{
|
||||
cons[x]->send_string(hoststr);
|
||||
cons[x]->send_string(". host: ");
|
||||
states[x]++;
|
||||
textpos[x][0]=0;
|
||||
}
|
||||
if (ret==-1)
|
||||
{
|
||||
JNL::addr_to_ipstr(cons[x]->get_remote(),hoststr,256);
|
||||
cons[x]->send_string(hoststr);
|
||||
cons[x]->send_string(". host: ");
|
||||
states[x]++;
|
||||
textpos[x][0]=0;
|
||||
}
|
||||
}
|
||||
if (states[x]==2)
|
||||
{
|
||||
char b;
|
||||
while (cons[x]->recv_bytes(&b,1) && states[x]==2)
|
||||
{
|
||||
if (b == '\r' || b == '\n')
|
||||
{
|
||||
if (strlen(textpos[x]))
|
||||
{
|
||||
char *p=strstr(textpos[x],":");
|
||||
int port=23;
|
||||
if (p)
|
||||
{
|
||||
*p++=0;
|
||||
if (atoi(p)) port=atoi(p);
|
||||
}
|
||||
outcons[x]=new JNL_Connection(&dns);
|
||||
outcons[x]->connect(textpos[x],port);
|
||||
|
||||
char str[512];
|
||||
sprintf(str,"\r\nconnecting to port %d of %s\r\n",port,textpos[x]);
|
||||
cons[x]->send_string(str);
|
||||
states[x]++;
|
||||
}
|
||||
else states[x]=0;
|
||||
}
|
||||
else if (b == '\b')
|
||||
{
|
||||
if (textpos[x][0])
|
||||
{
|
||||
textpos[x][strlen(textpos[x])-1]=0;
|
||||
cons[x]->send_string("\b \b");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textpos[x][strlen(textpos[x])+1]=0;
|
||||
textpos[x][strlen(textpos[x])]=b;
|
||||
cons[x]->send(&b,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (states[x]==3)
|
||||
{
|
||||
char buf[1024];
|
||||
outcons[x]->run();
|
||||
int l=cons[x]->recv_bytes(buf,1024);
|
||||
if (l) outcons[x]->send(buf,l);
|
||||
l=outcons[x]->recv_bytes(buf,1024);
|
||||
if (l) cons[x]->send(buf,l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#if (TEST_LISTEN)
|
||||
|
||||
int main()
|
||||
{
|
||||
JNL_HTTPServ *cons[32]={0,};
|
||||
char *contents[32]={0,};
|
||||
int n_cons=0;
|
||||
|
||||
JNL::open_socketlib();
|
||||
JNL_AsyncDNS dns;
|
||||
JNL_Listen l(8000);
|
||||
while (!l.is_error())
|
||||
{
|
||||
Sleep(100);
|
||||
if (n_cons<32)
|
||||
{
|
||||
JNL_Connection *con=l.get_connect();
|
||||
if (con)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (!cons[x])
|
||||
{
|
||||
cons[x]=new JNL_HTTPServ(con);
|
||||
n_cons++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (cons[x])
|
||||
{
|
||||
int r=cons[x]->run();
|
||||
if (r == -1 || r == 4)
|
||||
{
|
||||
if (r == -1) printf("error:%s\n",cons[x]->geterrorstr());
|
||||
delete cons[x];
|
||||
cons[x]=0;
|
||||
free(contents[x]);
|
||||
contents[x]=0;
|
||||
n_cons--;
|
||||
}
|
||||
if (r == 2)
|
||||
{
|
||||
cons[x]->set_reply_string("HTTP/1.1 200 OK");
|
||||
cons[x]->set_reply_header("Content-type:text/plain");
|
||||
cons[x]->set_reply_header("Server:JNLTest");
|
||||
contents[x]=(char*)malloc(32768);
|
||||
char *poop=cons[x]->get_request_parm("poop");
|
||||
sprintf(contents[x],"test, sucka\r\n%s\r\n\r\n",poop?poop:"no poop");
|
||||
cons[x]->send_reply();
|
||||
}
|
||||
if (r == 3)
|
||||
{
|
||||
if (contents[x] && cons[x]->bytes_cansend()>strlen(contents[x]))
|
||||
{
|
||||
cons[x]->write_bytes(contents[x],strlen(contents[x]));
|
||||
cons[x]->close(0);
|
||||
free(contents[x]);
|
||||
contents[x]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (TEST_CONNECTION)
|
||||
int main()
|
||||
{
|
||||
JNL::open_socketlib();
|
||||
{
|
||||
JNL_AsyncDNS dns;
|
||||
JNL_Connection con(&dns);
|
||||
con.connect("localhost",80);
|
||||
FILE *fp=fopen("c:\\hi.raw","wb");
|
||||
while (1)
|
||||
{
|
||||
con.run();
|
||||
if (con.get_state()==JNL_Connection::STATE_ERROR)
|
||||
{
|
||||
printf("error %s\n",con.get_errstr());
|
||||
}
|
||||
if (con.get_state()==JNL_Connection::STATE_CLOSED)
|
||||
{
|
||||
}
|
||||
while (con.recv_bytes_available()>0)
|
||||
{
|
||||
char buf[1024];
|
||||
int a=con.recv_bytes_available();
|
||||
if (a > 1024) a=1024;
|
||||
con.recv_bytes(buf,a);
|
||||
fwrite(buf,a,1,fp);
|
||||
}
|
||||
}
|
||||
if (fp) fclose(fp);
|
||||
}
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (TEST_ASYNCDNS)
|
||||
int main()
|
||||
{
|
||||
JNL_AsyncDNS dns;
|
||||
char *hosts[]=
|
||||
{
|
||||
"www.firehose.net",
|
||||
"gnutella.com",
|
||||
"207.48.52.200",
|
||||
"www.slashdot.org",
|
||||
"www.google.com",
|
||||
"www.winamp.com",
|
||||
"www.genekan.com",
|
||||
};
|
||||
char *reverses[]=
|
||||
{
|
||||
"64.0.160.98",
|
||||
"205.188.245.120",
|
||||
"207.48.52.222",
|
||||
"207.48.52.200",
|
||||
};
|
||||
int n=0;
|
||||
int pass=0;
|
||||
while (n<sizeof(hosts)/sizeof(hosts[0])+sizeof(reverses)/sizeof(reverses[0]))
|
||||
{
|
||||
int x;
|
||||
n=0;
|
||||
printf("pass %d\n",pass++);
|
||||
for (x = 0; x < sizeof(hosts)/sizeof(hosts[0]); x ++)
|
||||
{
|
||||
unsigned int addr;
|
||||
printf("%-30s",hosts[x]);
|
||||
switch (dns.resolve(hosts[x],&addr))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
char str[256];
|
||||
JNL::addr_to_ipstr(addr,str,256);
|
||||
printf("%s\n",str);
|
||||
n++;
|
||||
}
|
||||
break;
|
||||
case 1: printf("looking up\n"); break;
|
||||
case -1: printf("error\n"); n++; break;
|
||||
}
|
||||
}
|
||||
for (x = 0; x < sizeof(reverses)/sizeof(reverses[0]); x ++)
|
||||
{
|
||||
printf("reverse: %-21s",reverses[x]);
|
||||
char hn[512];
|
||||
switch (dns.reverse(JNL::ipstr_to_addr(reverses[x]),hn))
|
||||
{
|
||||
case 0: printf("%s\n",hn); n++; break;
|
||||
case 1: printf("looking up\n"); break;
|
||||
case -1: printf("error\n"); n++; break;
|
||||
}
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if (TEST_UDP)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("usage: udptest <mode>\n");
|
||||
printf("mode: 0 for client, 1 for server\n");
|
||||
exit(0);
|
||||
}
|
||||
int mode=atoi(argv[1]);
|
||||
|
||||
JNL::open_socketlib();
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case 0: // client mode
|
||||
{
|
||||
JNL_AsyncDNS dns;
|
||||
JNL_UDPConnection con(0,&dns); // 0 chooses a random port
|
||||
con.setpeer("localhost",80);
|
||||
printf("Sending message...\n");
|
||||
con.send("blah",5);
|
||||
while (1)
|
||||
{
|
||||
con.run();
|
||||
if (con.get_state()==JNL_UDPConnection::STATE_ERROR)
|
||||
{
|
||||
printf("error %s\n",con.get_errstr());
|
||||
}
|
||||
while (con.recv_bytes_available()>0)
|
||||
{
|
||||
char buf[1024];
|
||||
int s=min(con.recv_bytes_available(), sizeof(buf));
|
||||
con.recv_bytes(buf,s);
|
||||
printf("received message: %s\n", buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // server (listening) mode
|
||||
{
|
||||
JNL_UDPConnection con(80);
|
||||
printf("Waiting for messages...\n");
|
||||
while(1)
|
||||
{
|
||||
con.run();
|
||||
if (con.get_state()==JNL_UDPConnection::STATE_ERROR)
|
||||
{
|
||||
printf("error %s\n",con.get_errstr());
|
||||
}
|
||||
while (con.recv_bytes_available()>0)
|
||||
{
|
||||
char buf[1024];
|
||||
int s=min(con.recv_bytes_available(), sizeof(buf));
|
||||
con.recv_bytes(buf,s);
|
||||
printf("message received: %s. Replying...\n", buf);
|
||||
// reply on the addr:port from sender
|
||||
struct sockaddr from;
|
||||
con.get_last_recv_msg_addr(&from);
|
||||
con.setpeer(&from);
|
||||
con.send("blorp",6);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
102
oversampling/WDL/jnetlib/testbnc.cpp
Normal file
102
oversampling/WDL/jnetlib/testbnc.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2001 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** File: testbnc.cpp - JNL network bounce test code
|
||||
** License: see jnetlib.h
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#define Sleep(x) usleep((x)*1000)
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include "jnetlib.h"
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
JNL_Connection *cons[32]={0,};
|
||||
JNL_Connection *outcons[32]={0,};
|
||||
int n_cons=0;
|
||||
|
||||
if (argc != 4 || !atoi(argv[1]) || !atoi(argv[3]) || !argv[2][0])
|
||||
{
|
||||
printf("usage: redir localport host remoteport\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
JNL::open_socketlib();
|
||||
JNL_AsyncDNS dns;
|
||||
JNL_Listen l((short)atoi(argv[1]));
|
||||
printf("running...\n");
|
||||
while (!l.is_error())
|
||||
{
|
||||
Sleep(10);
|
||||
if (n_cons<32)
|
||||
{
|
||||
JNL_Connection *con=l.get_connect();
|
||||
if (con)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (!cons[x])
|
||||
{
|
||||
outcons[x]=new JNL_Connection();
|
||||
outcons[x]->connect(argv[2],atoi(argv[3]));
|
||||
cons[x]=con;
|
||||
char host[256];
|
||||
JNL::addr_to_ipstr(cons[x]->get_remote(),host,sizeof(host));
|
||||
n_cons++;
|
||||
printf("Connection %d (%s) opened (%d).\n",x,host,n_cons);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
int x;
|
||||
for (x = 0; x < 32; x ++)
|
||||
{
|
||||
if (cons[x])
|
||||
{
|
||||
cons[x]->run();
|
||||
outcons[x]->run();
|
||||
|
||||
int cerr=(cons[x]->get_state() == JNL_Connection::STATE_ERROR || cons[x]->get_state()==JNL_Connection::STATE_CLOSED);
|
||||
int oerr=(outcons[x]->get_state() == JNL_Connection::STATE_ERROR || outcons[x]->get_state()==JNL_Connection::STATE_CLOSED);
|
||||
|
||||
if ((!outcons[x]->send_bytes_in_queue() && !cons[x]->recv_bytes_available() && cerr) ||
|
||||
(!cons[x]->send_bytes_in_queue() && !outcons[x]->recv_bytes_available() && oerr) ||
|
||||
(cerr && oerr))
|
||||
{
|
||||
char host[256];
|
||||
JNL::addr_to_ipstr(cons[x]->get_remote(),host,sizeof(host));
|
||||
delete cons[x];
|
||||
delete outcons[x];
|
||||
outcons[x]=0;
|
||||
cons[x]=0;
|
||||
n_cons--;
|
||||
printf("Connection %d (%s) closed (%d)\n",x,host,n_cons);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[4096];
|
||||
int l;
|
||||
l=outcons[x]->send_bytes_available();
|
||||
if (l > 4096) l=4096;
|
||||
if (l) l=cons[x]->recv_bytes(buf,l);
|
||||
if (l) outcons[x]->send(buf,l);
|
||||
|
||||
l=cons[x]->send_bytes_available();
|
||||
if (l > 4096) l=4096;
|
||||
if (l) l=outcons[x]->recv_bytes(buf,l);
|
||||
if (l) cons[x]->send(buf,l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
JNL::close_socketlib();
|
||||
return 0;
|
||||
}
|
||||
38
oversampling/WDL/jnetlib/util.cpp
Normal file
38
oversampling/WDL/jnetlib/util.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2001 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 "../wdlcstring.h"
|
||||
|
||||
int JNL::open_socketlib()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(1, 1), &wsaData)) return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
void JNL::close_socketlib()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
unsigned int JNL::ipstr_to_addr(const char *cp)
|
||||
{
|
||||
return ::inet_addr(cp);
|
||||
}
|
||||
|
||||
void JNL::addr_to_ipstr(unsigned int addr, char *host, int maxhostlen)
|
||||
{
|
||||
struct in_addr a; a.s_addr=addr;
|
||||
char *p=::inet_ntoa(a);
|
||||
lstrcpyn_safe(host,p?p:"",maxhostlen);
|
||||
}
|
||||
39
oversampling/WDL/jnetlib/util.h
Normal file
39
oversampling/WDL/jnetlib/util.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2001 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 int 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 int 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 int ipstr_to_addr(const char *cp);
|
||||
static void addr_to_ipstr(unsigned int addr, char *host, int maxhostlen);
|
||||
};
|
||||
|
||||
#endif //_UTIL_H_
|
||||
318
oversampling/WDL/jnetlib/webserver.cpp
Normal file
318
oversampling/WDL/jnetlib/webserver.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2000-2003 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** File: webserver.cpp - Generic simple webserver baseclass
|
||||
** License: see jnetlib.h
|
||||
** see test.cpp for an example of how to use this class
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include "jnetlib.h"
|
||||
#include "webserver.h"
|
||||
|
||||
|
||||
WebServerBaseClass::~WebServerBaseClass()
|
||||
{
|
||||
m_connections.Empty(true);
|
||||
m_listeners.Empty(true);
|
||||
}
|
||||
|
||||
WebServerBaseClass::WebServerBaseClass()
|
||||
{
|
||||
m_listener_rot=0;
|
||||
m_timeout_s=30;
|
||||
m_max_con=100;
|
||||
}
|
||||
|
||||
|
||||
void WebServerBaseClass::setMaxConnections(int max_con)
|
||||
{
|
||||
m_max_con=max_con;
|
||||
}
|
||||
|
||||
void WebServerBaseClass::setRequestTimeout(int timeout_s)
|
||||
{
|
||||
m_timeout_s=timeout_s;
|
||||
}
|
||||
|
||||
int WebServerBaseClass::addListenPort(int port, unsigned int which_interface)
|
||||
{
|
||||
removeListenPort(port);
|
||||
|
||||
JNL_IListen *p=new JNL_Listen(port,which_interface);
|
||||
m_listeners.Add(p);
|
||||
if (p->is_error()) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebServerBaseClass::removeListenPort(int port)
|
||||
{
|
||||
int x;
|
||||
for (x = 0; x < m_listeners.GetSize(); x ++)
|
||||
{
|
||||
JNL_IListen *p=m_listeners.Get(x);
|
||||
if (p->port()==port)
|
||||
{
|
||||
m_listeners.Delete(x,true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WebServerBaseClass::removeListenIdx(int idx)
|
||||
{
|
||||
m_listeners.Delete(idx,true);
|
||||
}
|
||||
|
||||
int WebServerBaseClass::getListenPort(int idx, int *err)
|
||||
{
|
||||
JNL_IListen *p=m_listeners.Get(idx);
|
||||
if (p)
|
||||
{
|
||||
if (err) *err=p->is_error();
|
||||
return p->port();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebServerBaseClass::attachConnection(JNL_IConnection *con, int port)
|
||||
{
|
||||
m_connections.Add(new WS_conInst(con,port));
|
||||
}
|
||||
|
||||
void WebServerBaseClass::run(void)
|
||||
{
|
||||
int nl;
|
||||
if (m_connections.GetSize() < m_max_con && (nl=m_listeners.GetSize()))
|
||||
{
|
||||
JNL_IListen *l=m_listeners.Get(m_listener_rot++ % nl);
|
||||
JNL_IConnection *c=l->get_connect();
|
||||
if (c)
|
||||
{
|
||||
// char buf[512];
|
||||
// sprintf(buf,"got new connection at %.3f",GetTickCount()/1000.0);
|
||||
// OutputDebugString(buf);
|
||||
attachConnection(c,l->port());
|
||||
}
|
||||
}
|
||||
int x;
|
||||
for (x = 0; x < m_connections.GetSize(); x ++)
|
||||
{
|
||||
WS_conInst *ci = m_connections.Get(x);
|
||||
int rv=0;
|
||||
for (int y = 0; y < 4 && !(rv=run_connection(ci)); y ++); // keep latency down
|
||||
|
||||
if (rv==-1)
|
||||
{
|
||||
if (ci->m_serv.want_keepalive_reset())
|
||||
{
|
||||
time(&ci->m_connect_time);
|
||||
delete ci->m_pagegen;
|
||||
ci->m_pagegen=0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (rv>0)
|
||||
{
|
||||
m_connections.Delete(x--,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WebServerBaseClass::run_connection(WS_conInst *con)
|
||||
{
|
||||
int s=con->m_serv.run();
|
||||
if (s < 0)
|
||||
{
|
||||
// m_serv.geterrorstr()
|
||||
return 1;
|
||||
}
|
||||
if (s < 2)
|
||||
{
|
||||
// return 1 if we timed out
|
||||
return time(NULL)-con->m_connect_time > m_timeout_s;
|
||||
}
|
||||
if (s < 3)
|
||||
{
|
||||
con->m_pagegen=onConnection(&con->m_serv,con->m_port);
|
||||
return 0;
|
||||
}
|
||||
if (s < 4)
|
||||
{
|
||||
if (!con->m_pagegen)
|
||||
{
|
||||
if (con->m_serv.canKeepAlive()) return -1;
|
||||
|
||||
return !con->m_serv.bytes_inqueue();
|
||||
}
|
||||
char buf[16384];
|
||||
int l=con->m_serv.bytes_cansend();
|
||||
if (l > 0)
|
||||
{
|
||||
if (l > (int)sizeof(buf)) l=(int)sizeof(buf);
|
||||
l=con->m_pagegen->GetData(buf,l);
|
||||
if (l < (con->m_pagegen->IsNonBlocking() ? 0 : 1)) // if nonblocking, this is l < 0, otherwise it's l<1
|
||||
{
|
||||
if (con->m_serv.canKeepAlive())
|
||||
{
|
||||
con->m_serv.write_bytes("",0);
|
||||
return -1;
|
||||
}
|
||||
return !con->m_serv.bytes_inqueue();
|
||||
}
|
||||
if (l>0)
|
||||
con->m_serv.write_bytes(buf,l);
|
||||
}
|
||||
return l > 0 ? 0 : -2; // -2 = no more data to send, but all is well
|
||||
}
|
||||
if (con->m_serv.canKeepAlive()) return -1;
|
||||
return 1; // we're done by this point
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WebServerBaseClass::url_encode(const char *in, char *out, int max_out)
|
||||
{
|
||||
while (*in && max_out > 4)
|
||||
{
|
||||
if ((*in >= 'A' && *in <= 'Z')||
|
||||
(*in >= 'a' && *in <= 'z')||
|
||||
(*in >= '0' && *in <= '9')|| *in == '.' || *in == '_' || *in == '-')
|
||||
{
|
||||
*out++=*in++;
|
||||
max_out--;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i=*in++;
|
||||
*out++ = '%';
|
||||
int b=(i>>4)&15;
|
||||
if (b < 10) *out++='0'+b;
|
||||
else *out++='A'+b-10;
|
||||
b=i&15;
|
||||
if (b < 10) *out++='0'+b;
|
||||
else *out++='A'+b-10;
|
||||
max_out-=3;
|
||||
}
|
||||
}
|
||||
*out=0;
|
||||
}
|
||||
|
||||
|
||||
void WebServerBaseClass::url_decode(const char *in, char *out, int maxlen)
|
||||
{
|
||||
while (*in && maxlen>1)
|
||||
{
|
||||
if (*in == '+')
|
||||
{
|
||||
in++;
|
||||
*out++=' ';
|
||||
}
|
||||
else if (*in == '%' && in[1] != '%' && in[1])
|
||||
{
|
||||
int a=0;
|
||||
int b=0;
|
||||
for ( b = 0; b < 2; b ++)
|
||||
{
|
||||
int r=in[1+b];
|
||||
if (r>='0'&&r<='9') r-='0';
|
||||
else if (r>='a'&&r<='f') r-='a'-10;
|
||||
else if (r>='A'&&r<='F') r-='A'-10;
|
||||
else break;
|
||||
a*=16;
|
||||
a+=r;
|
||||
}
|
||||
if (b < 2) *out++=*in++;
|
||||
else { *out++=a; in += 3;}
|
||||
}
|
||||
else *out++=*in++;
|
||||
maxlen--;
|
||||
}
|
||||
*out=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void WebServerBaseClass::base64decode(const char *src, char *dest, int destsize)
|
||||
{
|
||||
int accum=0;
|
||||
int nbits=0;
|
||||
while (*src)
|
||||
{
|
||||
int x=0;
|
||||
char c=*src++;
|
||||
if (c >= 'A' && c <= 'Z') x=c-'A';
|
||||
else if (c >= 'a' && c <= 'z') x=c-'a' + 26;
|
||||
else if (c >= '0' && c <= '9') x=c-'0' + 52;
|
||||
else if (c == '+') x=62;
|
||||
else if (c == '/') x=63;
|
||||
else break;
|
||||
|
||||
accum <<= 6;
|
||||
accum |= x;
|
||||
nbits += 6;
|
||||
|
||||
while (nbits >= 8)
|
||||
{
|
||||
if (--destsize<=0) break;
|
||||
nbits-=8;
|
||||
*dest++ = (char)((accum>>nbits)&0xff);
|
||||
}
|
||||
|
||||
}
|
||||
*dest=0;
|
||||
}
|
||||
|
||||
void WebServerBaseClass::base64encode(const char *in, char *out)
|
||||
{
|
||||
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
int shift = 0;
|
||||
int accum = 0;
|
||||
|
||||
while (*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;
|
||||
}
|
||||
|
||||
int WebServerBaseClass::parseAuth(const char *auth_header, char *out, int out_len)//returns 0 on unknown auth, 1 on basic
|
||||
{
|
||||
const char *authstr=auth_header;
|
||||
*out=0;
|
||||
if (!auth_header || !*auth_header) return 0;
|
||||
while (*authstr == ' ') authstr++;
|
||||
if (strnicmp(authstr,"basic ",6)) return 0;
|
||||
authstr+=6;
|
||||
while (*authstr == ' ') authstr++;
|
||||
base64decode(authstr,out,out_len);
|
||||
return 1;
|
||||
}
|
||||
243
oversampling/WDL/jnetlib/webserver.h
Normal file
243
oversampling/WDL/jnetlib/webserver.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
** JNetLib
|
||||
** Copyright (C) 2008-2014 Cockos Inc
|
||||
** Copyright (C) 2003 Nullsoft, Inc.
|
||||
** Author: Justin Frankel
|
||||
** File: webserver.h - Generic simple webserver baseclass
|
||||
** License: see jnetlib.h
|
||||
**
|
||||
** You can derive your object from WebServerBaseClass to do simple web serving. Example:
|
||||
|
||||
class wwwServer : public WebServerBaseClass
|
||||
{
|
||||
public:
|
||||
wwwServer() { }
|
||||
virtual IPageGenerator *onConnection(JNL_HTTPServ *serv, int port)
|
||||
{
|
||||
serv->set_reply_header("Server:jnetlib_test/0.0");
|
||||
if (!strcmp(serv->get_request_file(),"/"))
|
||||
{
|
||||
serv->set_reply_string("HTTP/1.1 200 OK");
|
||||
serv->set_reply_header("Content-Type:text/html");
|
||||
serv->send_reply();
|
||||
|
||||
return new MemPageGenerator(strdup("Test Web Server v0.0"));
|
||||
}
|
||||
else
|
||||
{
|
||||
serv->set_reply_string("HTTP/1.1 404 NOT FOUND");
|
||||
serv->send_reply();
|
||||
return 0; // no data
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
wwwServer foo;
|
||||
foo.addListenPort(8080);
|
||||
while (1)
|
||||
{
|
||||
foo.run();
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
You will also need to derive from the IPageGenerator interface to provide a data stream, here is an
|
||||
example of MemPageGenerator:
|
||||
|
||||
class MemPageGenerator : public IPageGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~MemPageGenerator() { free(m_buf); }
|
||||
MemPageGenerator(char *buf, int buf_len=-1) { m_buf=buf; if (buf_len >= 0) m_buf_size=buf_len; else m_buf_size=strlen(buf); m_buf_pos=0; }
|
||||
virtual int GetData(char *buf, int size) // return 0 when done
|
||||
{
|
||||
int a=m_buf_size-m_buf_pos;
|
||||
if (a < size) size=a;
|
||||
memcpy(buf,m_buf+m_buf_pos,size);
|
||||
m_buf_pos+=size;
|
||||
return size;
|
||||
}
|
||||
|
||||
private:
|
||||
char *m_buf;
|
||||
int m_buf_size;
|
||||
int m_buf_pos;
|
||||
};
|
||||
|
||||
|
||||
**
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _JNL_WEBSERVER_H_
|
||||
#define _JNL_WEBSERVER_H_
|
||||
|
||||
#include "httpserv.h"
|
||||
#include "../wdlcstring.h"
|
||||
#include "../ptrlist.h"
|
||||
|
||||
class IPageGenerator
|
||||
{
|
||||
public:
|
||||
virtual ~IPageGenerator() { };
|
||||
virtual int IsNonBlocking() { return 0; } // override this and return 1 if GetData should be allowed to return 0
|
||||
virtual int GetData(char *buf, int size)=0; // return < 0 when done (or 0 if IsNonBlocking() is 1)
|
||||
};
|
||||
|
||||
|
||||
class WebServerBaseClass
|
||||
{
|
||||
protected: // never create one of these directly, always derive
|
||||
WebServerBaseClass();
|
||||
|
||||
public:
|
||||
virtual ~WebServerBaseClass();
|
||||
|
||||
// stuff for setting limits/timeouts
|
||||
void setMaxConnections(int max_con);
|
||||
void setRequestTimeout(int timeout_s);
|
||||
|
||||
// stuff for setting listener port
|
||||
int addListenPort(int port, unsigned int which_interface=0);
|
||||
int getListenPort(int idx, int *err=0);
|
||||
void removeListenPort(int port);
|
||||
void removeListenIdx(int idx);
|
||||
|
||||
// call this a lot :)
|
||||
void run(void);
|
||||
|
||||
// if you want to manually attach a connection, use this:
|
||||
// you need to specify the port it came in on so the web server can build
|
||||
// links
|
||||
void attachConnection(JNL_IConnection *con, int port);
|
||||
|
||||
// derived classes need to override this one =)
|
||||
virtual IPageGenerator *onConnection(JNL_HTTPServ *serv, int port)=0;
|
||||
|
||||
// stats getting functions
|
||||
|
||||
// these can be used externally, as well as are used by the web server
|
||||
static void url_encode(const char *in, char *out, int max_out);
|
||||
static void url_decode(const char *in, char *out, int maxlen);
|
||||
static void base64decode(const char *src, char *dest, int destsize);
|
||||
static void base64encode(const char *in, char *out);
|
||||
|
||||
static int parseAuth(const char *auth_header, char *out, int out_len);//returns 0 on unknown auth, 1 on basic
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
class WS_conInst
|
||||
{
|
||||
public:
|
||||
WS_conInst(JNL_IConnection *c, int which_port) : m_serv(c), m_pagegen(NULL), m_port(which_port)
|
||||
{
|
||||
time(&m_connect_time);
|
||||
}
|
||||
~WS_conInst()
|
||||
{
|
||||
delete m_pagegen;
|
||||
}
|
||||
|
||||
// these will be used by WebServerBaseClass::onConnection yay
|
||||
JNL_HTTPServ m_serv;
|
||||
IPageGenerator *m_pagegen;
|
||||
|
||||
int m_port; // port this came in on
|
||||
time_t m_connect_time;
|
||||
};
|
||||
|
||||
int run_connection(WS_conInst *con);
|
||||
|
||||
int m_timeout_s;
|
||||
int m_max_con;
|
||||
|
||||
JNL_AsyncDNS m_dns;
|
||||
|
||||
WDL_PtrList<JNL_IListen> m_listeners;
|
||||
WDL_PtrList<WS_conInst> m_connections;
|
||||
int m_listener_rot;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef JNETLIB_WEBSERVER_WANT_UTILS
|
||||
|
||||
#include "../fileread.h"
|
||||
#include "../wdlstring.h"
|
||||
|
||||
class JNL_FilePageGenerator : public IPageGenerator
|
||||
{
|
||||
public:
|
||||
JNL_FilePageGenerator(WDL_FileRead *fr) { m_file = fr; }
|
||||
virtual ~JNL_FilePageGenerator() { delete m_file; }
|
||||
virtual int GetData(char *buf, int size) { return m_file ? m_file->Read(buf,size) : -1; }
|
||||
|
||||
private:
|
||||
|
||||
WDL_FileRead *m_file;
|
||||
};
|
||||
class JNL_StringPageGenerator : public IPageGenerator
|
||||
{
|
||||
public:
|
||||
JNL_StringPageGenerator() { m_pos=0; }
|
||||
virtual ~JNL_StringPageGenerator() { }
|
||||
virtual int GetData(char *buf, int size)
|
||||
{
|
||||
if (size > str.GetLength() - m_pos) size=str.GetLength()-m_pos;
|
||||
if (size>0)
|
||||
{
|
||||
memcpy(buf,str.Get()+m_pos,size);
|
||||
m_pos+=size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
WDL_FastString str; // set this before sending it off
|
||||
|
||||
private:
|
||||
int m_pos;
|
||||
};
|
||||
|
||||
static void JNL_get_mime_type_for_file(const char *fn, char *strout, int stroutsz)
|
||||
{
|
||||
const char *ext = fn;
|
||||
while (*ext) ext++;
|
||||
while (ext > fn && *ext != '.' && *ext != '/' && *ext != '\\') ext--;
|
||||
|
||||
const char *type = "application/octet-stream";
|
||||
|
||||
if (!stricmp(ext,".jpg")) type = "image/jpeg";
|
||||
else if (!stricmp(ext,".png")) type = "image/png";
|
||||
else if (!stricmp(ext,".gif")) type = "image/gif";
|
||||
else if (!stricmp(ext,".txt")) type = "text/plain";
|
||||
else if (!strnicmp(ext,".htm",4)) type = "text/html";
|
||||
else if (!stricmp(ext,".js")) type = "application/javascript";
|
||||
else if (!stricmp(ext,".css")) type = "text/css";
|
||||
else if (!stricmp(ext,".xml")) type = "text/xml";
|
||||
else if (!stricmp(ext,".svg")) type = "image/svg+xml";
|
||||
|
||||
lstrcpyn_safe(strout,type,stroutsz);
|
||||
}
|
||||
|
||||
static void JNL_Format_RFC1123(time_t t, char *buf)
|
||||
{
|
||||
|
||||
buf[0]=0;
|
||||
static const char days[] = { "SunMonTueWedThuFriSat" };
|
||||
static const char mons[] = { "JanFebMarAprMayJunJulAugSepOctNovDec" };
|
||||
|
||||
struct tm *tm = gmtime(&t);
|
||||
if (!tm) return;
|
||||
memcpy(buf, days + (tm->tm_wday%7)*3, 3);
|
||||
strcpy(buf+3,", ");
|
||||
char *p=buf+5;
|
||||
strftime(p, 64, "%d xxx %Y %H:%M:%S GMT", tm);
|
||||
while (*p && *p != 'x') p++;
|
||||
if (*p) memcpy(p, mons + (tm->tm_mon%12)*3, 3);
|
||||
}
|
||||
|
||||
#endif //JNETLIB_WEBSERVER_WANT_UTILS
|
||||
|
||||
|
||||
#endif//_JNL_WEBSERVER_H_
|
||||
Reference in New Issue
Block a user