about summary refs log tree commit diff
path: root/src/base
diff options
context:
space:
mode:
Diffstat (limited to 'src/base')
-rw-r--r--src/base/detect.h51
-rw-r--r--src/base/math.h11
-rw-r--r--src/base/system.c270
-rw-r--r--src/base/system.h94
-rw-r--r--src/base/tl/threading.h106
-rw-r--r--src/base/vmath.h15
6 files changed, 438 insertions, 109 deletions
diff --git a/src/base/detect.h b/src/base/detect.h
index 0b66acef..0e2ef86a 100644
--- a/src/base/detect.h
+++ b/src/base/detect.h
@@ -25,7 +25,7 @@
 #endif
 
 /* unix family */
-#if defined(__FreeBSD__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 	#define CONF_FAMILY_UNIX 1
 	#define CONF_FAMILY_STRING "unix"
 	#define CONF_PLATFORM_FREEBSD 1
@@ -46,6 +46,13 @@
 	#define CONF_PLATFORM_STRING "linux"
 #endif
 
+#if defined(__GNU__) || defined(__gnu__)
+	#define CONF_FAMILY_UNIX 1
+	#define CONF_FAMILY_STRING "unix"
+	#define CONF_PLATFORM_HURD 1
+	#define CONF_PLATFORM_STRING "gnu"
+#endif
+
 #if defined(MACOSX) || defined(__APPLE__) || defined(__DARWIN__)
 	#define CONF_FAMILY_UNIX 1
 	#define CONF_FAMILY_STRING "unix"
@@ -56,7 +63,7 @@
 #if defined(__sun)
 	#define CONF_FAMILY_UNIX 1
 	#define CONF_FAMILY_STRING "unix"
-	#define CONF_PLATFROM_SOLARIS 1
+	#define CONF_PLATFORM_SOLARIS 1
 	#define CONF_PLATFORM_STRING "solaris"
 #endif
 
@@ -69,35 +76,61 @@
 #endif
 
 
+/* use gcc endianness definitions when available */
+#if defined(__GNUC__) && !defined(__APPLE__) && !defined(__MINGW32__) && !defined(__sun)
+	#if defined(__FreeBSD__) || defined(__OpenBSD__)
+		#include <sys/endian.h>
+	#else
+		#include <endian.h>
+	#endif
+
+	#if __BYTE_ORDER == __LITTLE_ENDIAN
+		#define CONF_ARCH_ENDIAN_LITTLE 1
+	#elif __BYTE_ORDER == __BIG_ENDIAN
+		#define CONF_ARCH_ENDIAN_BIG 1
+	#endif
+#endif
+
+
 /* architectures */
 #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(CONF_PLATFORM_WIN32)
 	#define CONF_ARCH_IA32 1
 	#define CONF_ARCH_STRING "ia32"
-	#define CONF_ARCH_ENDIAN_LITTLE 1
+	#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
+		#define CONF_ARCH_ENDIAN_LITTLE 1
+	#endif
 #endif
 
-#if defined(__ia64__)
+#if defined(__ia64__) || defined(_M_IA64)
 	#define CONF_ARCH_IA64 1
 	#define CONF_ARCH_STRING "ia64"
-	#define CONF_ARCH_ENDIAN_LITTLE 1
+	#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
+		#define CONF_ARCH_ENDIAN_LITTLE 1
+	#endif
 #endif
 
-#if defined(__amd64__) || defined(__x86_64__)
+#if defined(__amd64__) || defined(__x86_64__) || defined(_M_X64)
 	#define CONF_ARCH_AMD64 1
 	#define CONF_ARCH_STRING "amd64"
-	#define CONF_ARCH_ENDIAN_LITTLE 1
+	#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
+		#define CONF_ARCH_ENDIAN_LITTLE 1
+	#endif
 #endif
 
 #if defined(__powerpc__) || defined(__ppc__)
 	#define CONF_ARCH_PPC 1
 	#define CONF_ARCH_STRING "ppc"
-	#define CONF_ARCH_ENDIAN_BIG 1
+	#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
+		#define CONF_ARCH_ENDIAN_BIG 1
+	#endif
 #endif
 
 #if defined(__sparc__)
 	#define CONF_ARCH_SPARC 1
 	#define CONF_ARCH_STRING "sparc"
-	#define CONF_ARCH_ENDIAN_BIG 1
+	#if !defined(CONF_ARCH_ENDIAN_LITTLE) && !defined(CONF_ARCH_ENDIAN_BIG)
+		#define CONF_ARCH_ENDIAN_BIG 1
+	#endif
 #endif
 
 
diff --git a/src/base/math.h b/src/base/math.h
index 1234f681..d58dbf10 100644
--- a/src/base/math.h
+++ b/src/base/math.h
@@ -39,6 +39,17 @@ inline float frandom() { return rand()/(float)(RAND_MAX); }
 inline int f2fx(float v) { return (int)(v*(float)(1<<10)); }
 inline float fx2f(int v) { return v*(1.0f/(1<<10)); }
 
+inline int gcd(int a, int b)
+{
+	while(b != 0)
+	{
+		int c = a % b;
+		a = b;
+		b = c;
+	}
+	return a;
+}
+
 class fxp
 {
 	int value;
diff --git a/src/base/system.c b/src/base/system.c
index 94481f21..ed0f41ec 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -7,9 +7,7 @@
 #include <ctype.h>
 #include <time.h>
 
-/*#include "detect.h"*/
 #include "system.h"
-/*#include "e_console.h"*/
 
 #if defined(CONF_FAMILY_UNIX)
 	#include <sys/time.h>
@@ -42,14 +40,14 @@
 	#include <fcntl.h>
 	#include <direct.h>
 	#include <errno.h>
-
-	#ifndef EWOULDBLOCK
-		#define EWOULDBLOCK WSAEWOULDBLOCK
-	#endif
 #else
 	#error NOT IMPLEMENTED
 #endif
 
+#if defined(CONF_PLATFORM_SOLARIS)
+	#include <sys/filio.h>
+#endif
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -127,7 +125,7 @@ static IOHANDLE logfile = 0;
 static void logger_file(const char *line)
 {
 	io_write(logfile, line, strlen(line));
-	io_write(logfile, "\n", 1);
+	io_write_newline(logfile);
 	io_flush(logfile);
 }
 
@@ -144,8 +142,6 @@ void dbg_logger_file(const char *filename)
 }
 /* */
 
-int memory_alloced = 0;
-
 typedef struct MEMHEADER
 {
 	const char *filename;
@@ -167,8 +163,10 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al
 {
 	/* TODO: fix alignment */
 	/* TODO: add debugging */
+	MEMTAIL *tail;
 	MEMHEADER *header = (struct MEMHEADER *)malloc(size+sizeof(MEMHEADER)+sizeof(MEMTAIL));
-	MEMTAIL *tail = (struct MEMTAIL *)(((char*)(header+1))+size);
+	dbg_assert(header != 0, "mem_alloc failure");
+	tail = (struct MEMTAIL *)(((char*)(header+1))+size);
 	header->size = size;
 	header->filename = filename;
 	header->line = line;
@@ -224,8 +222,9 @@ void mem_debug_dump(IOHANDLE file)
 	{
 		while(header)
 		{
-			str_format(buf, sizeof(buf), "%s(%d): %d\n", header->filename, header->line, header->size);
+			str_format(buf, sizeof(buf), "%s(%d): %d", header->filename, header->line, header->size);
 			io_write(file, buf, strlen(buf));
+			io_write_newline(file);
 			header = header->next;
 		}
 
@@ -280,8 +279,13 @@ IOHANDLE io_open(const char *filename, int flags)
 		if(!filename || !length || filename[length-1] == '\\')
 			return 0x0;
 		handle = FindFirstFile(filename, &finddata);
-		if(handle == INVALID_HANDLE_VALUE || str_comp(filename+length-str_length(finddata.cFileName), finddata.cFileName))
+		if(handle == INVALID_HANDLE_VALUE)
+			return 0x0;
+		else if(str_comp(filename+length-str_length(finddata.cFileName), finddata.cFileName) != 0)
+		{
+			FindClose(handle);
 			return 0x0;
+		}
 		FindClose(handle);
 	#endif
 		return (IOHANDLE)fopen(filename, "rb");
@@ -316,9 +320,12 @@ int io_seek(IOHANDLE io, int offset, int origin)
 		break;
 	case IOSEEK_END:
 		real_origin = SEEK_END;
+		break;
+	default:
+		return -1;
 	}
 
-	return fseek((FILE*)io, offset, origin);
+	return fseek((FILE*)io, offset, real_origin);
 }
 
 long int io_tell(IOHANDLE io)
@@ -340,6 +347,15 @@ unsigned io_write(IOHANDLE io, const void *buffer, unsigned size)
 	return fwrite(buffer, 1, size, (FILE*)io);
 }
 
+unsigned io_write_newline(IOHANDLE io)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+	return fwrite("\r\n", 1, 2, (FILE*)io);
+#else
+	return fwrite("\n", 1, 1, (FILE*)io);
+#endif
+}
+
 int io_close(IOHANDLE io)
 {
 	fclose((FILE*)io);
@@ -408,6 +424,17 @@ void thread_sleep(int milliseconds)
 #endif
 }
 
+void thread_detach(void *thread)
+{
+#if defined(CONF_FAMILY_UNIX)
+	pthread_detach((pthread_t)(thread));
+#elif defined(CONF_FAMILY_WINDOWS)
+	CloseHandle(thread);
+#else
+	#error not implemented
+#endif
+}
+
 
 
 
@@ -478,6 +505,21 @@ void lock_release(LOCK lock)
 #endif
 }
 
+#if defined(CONF_FAMILY_UNIX)
+void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
+void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
+void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
+void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
+#elif defined(CONF_FAMILY_WINDOWS)
+void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
+void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, 0L); }
+void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
+void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
+#else
+	#error not implemented on this platform
+#endif
+
+
 /* -----  time ----- */
 int64 time_get()
 {
@@ -568,16 +610,26 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b)
 	return mem_comp(a, b, sizeof(NETADDR));
 }
 
-void net_addr_str(const NETADDR *addr, char *string, int max_length)
+void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port)
 {
 	if(addr->type == NETTYPE_IPV4)
-		str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port);
+	{
+		if(add_port != 0)
+			str_format(string, max_length, "%d.%d.%d.%d:%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3], addr->port);
+		else
+			str_format(string, max_length, "%d.%d.%d.%d", addr->ip[0], addr->ip[1], addr->ip[2], addr->ip[3]);
+	}
 	else if(addr->type == NETTYPE_IPV6)
 	{
-		str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
-			(addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7],
-			(addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15],
-			addr->port);
+		if(add_port != 0)
+			str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]:%d",
+				(addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7],
+				(addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15],
+				addr->port);
+		else
+			str_format(string, max_length, "[%x:%x:%x:%x:%x:%x:%x:%x]",
+				(addr->ip[0]<<8)|addr->ip[1], (addr->ip[2]<<8)|addr->ip[3], (addr->ip[4]<<8)|addr->ip[5], (addr->ip[6]<<8)|addr->ip[7],
+				(addr->ip[8]<<8)|addr->ip[9], (addr->ip[10]<<8)|addr->ip[11], (addr->ip[12]<<8)|addr->ip[13], (addr->ip[14]<<8)|addr->ip[15]);
 	}
 	else
 		str_format(string, max_length, "unknown type %d", addr->type);
@@ -799,43 +851,49 @@ static int priv_net_close_all_sockets(NETSOCKET sock)
 static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, int sockaddrlen)
 {
 	int sock, e;
-	unsigned long mode = 1;
-	int broadcast = 1;
 
 	/* create socket */
 	sock = socket(domain, type, 0);
 	if(sock < 0)
 	{
+#if defined(CONF_FAMILY_WINDOWS)
+		char buf[128];
+		int error = WSAGetLastError();
+		if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
+			buf[0] = 0;
+		dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
+#else
 		dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
+#endif
 		return -1;
 	}
 
 	/* set to IPv6 only if thats what we are creating */
+#if defined(IPV6_V6ONLY)	/* windows sdk 6.1 and higher */
 	if(domain == AF_INET6)
 	{
 		int ipv6only = 1;
 		setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&ipv6only, sizeof(ipv6only));
 	}
+#endif
 
 	/* bind the socket */
 	e = bind(sock, addr, sockaddrlen);
 	if(e != 0)
 	{
+#if defined(CONF_FAMILY_WINDOWS)
+		char buf[128];
+		int error = WSAGetLastError();
+		if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, buf, sizeof(buf), 0) == 0)
+			buf[0] = 0;
+		dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
+#else
 		dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
+#endif
 		priv_net_close_socket(sock);
 		return -1;
 	}
 
-	/* set non-blocking */
-#if defined(CONF_FAMILY_WINDOWS)
-	ioctlsocket(sock, FIONBIO, &mode);
-#else
-	ioctl(sock, FIONBIO, &mode);
-#endif
-
-	/* set boardcast */
-	setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
-
 	/* return the newly created socket */
 	return sock;
 }
@@ -844,6 +902,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 {
 	NETSOCKET sock = invalid_socket;
 	NETADDR tmpbindaddr = bindaddr;
+	int broadcast = 1;
 
 	if(bindaddr.type&NETTYPE_IPV4)
 	{
@@ -859,6 +918,12 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 			sock.type |= NETTYPE_IPV4;
 			sock.ipv4sock = socket;
 		}
+
+		/* set non-blocking */
+		net_set_non_blocking(sock);
+
+		/* set boardcast */
+		setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
 	}
 
 	if(bindaddr.type&NETTYPE_IPV6)
@@ -875,6 +940,12 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 			sock.type |= NETTYPE_IPV6;
 			sock.ipv6sock = socket;
 		}
+
+		/* set non-blocking */
+		net_set_non_blocking(sock);
+
+		/* set boardcast */
+		setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
 	}
 
 	/* return */
@@ -984,32 +1055,48 @@ int net_udp_close(NETSOCKET sock)
 	return priv_net_close_all_sockets(sock);
 }
 
-// TODO: make TCP stuff work again
-NETSOCKET net_tcp_create(const NETADDR *a)
+NETSOCKET net_tcp_create(NETADDR bindaddr)
 {
-	/* TODO: IPv6 support */
 	NETSOCKET sock = invalid_socket;
+	NETADDR tmpbindaddr = bindaddr;
 
-	if(a->type&NETTYPE_IPV4)
+	if(bindaddr.type&NETTYPE_IPV4)
 	{
 		struct sockaddr_in addr;
+		int socket = -1;
 
-		/* create socket */
-		sock.type |= NETTYPE_IPV4;
-		sock.ipv4sock = socket(AF_INET, SOCK_STREAM, 0);
-		if(sock.ipv4sock < 0)
-			return invalid_socket;
+		/* bind, we should check for error */
+		tmpbindaddr.type = NETTYPE_IPV4;
+		netaddr_to_sockaddr_in(&tmpbindaddr, &addr);
+		socket = priv_net_create_socket(AF_INET, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
+		if(socket >= 0)
+		{
+			sock.type |= NETTYPE_IPV4;
+			sock.ipv4sock = socket;
+		}
+	}
+
+	if(bindaddr.type&NETTYPE_IPV6)
+	{
+		struct sockaddr_in6 addr;
+		int socket = -1;
 
 		/* bind, we should check for error */
-		netaddr_to_sockaddr_in(a, &addr);
-		bind(sock.ipv4sock, (struct sockaddr *)&addr, sizeof(addr));
+		tmpbindaddr.type = NETTYPE_IPV6;
+		netaddr_to_sockaddr_in6(&tmpbindaddr, &addr);
+		socket = priv_net_create_socket(AF_INET6, SOCK_STREAM, (struct sockaddr *)&addr, sizeof(addr));
+		if(socket >= 0)
+		{
+			sock.type |= NETTYPE_IPV6;
+			sock.ipv6sock = socket;
+		}
 	}
 
 	/* return */
 	return sock;
 }
 
-int net_tcp_set_non_blocking(NETSOCKET sock)
+int net_set_non_blocking(NETSOCKET sock)
 {
 	unsigned long mode = 1;
 	if(sock.ipv4sock >= 0)
@@ -1033,7 +1120,7 @@ int net_tcp_set_non_blocking(NETSOCKET sock)
 	return 0;
 }
 
-int net_tcp_set_blocking(NETSOCKET sock)
+int net_set_blocking(NETSOCKET sock)
 {
 	unsigned long mode = 0;
 	if(sock.ipv4sock >= 0)
@@ -1059,30 +1146,31 @@ int net_tcp_set_blocking(NETSOCKET sock)
 
 int net_tcp_listen(NETSOCKET sock, int backlog)
 {
+	int err = -1;
 	if(sock.ipv4sock >= 0)
-		listen(sock.ipv4sock, backlog);
+		err = listen(sock.ipv4sock, backlog);
 	if(sock.ipv6sock >= 0)
-		listen(sock.ipv6sock, backlog);
-	return 0;
+		err = listen(sock.ipv6sock, backlog);
+	return err;
 }
 
 int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a)
 {
 	int s;
 	socklen_t sockaddr_len;
-	struct sockaddr addr;
 
 	*new_sock = invalid_socket;
 
-	sockaddr_len = sizeof(addr);
-
 	if(sock.ipv4sock >= 0)
 	{
-		s = accept(sock.ipv4sock, &addr, &sockaddr_len);
+		struct sockaddr_in addr;
+		sockaddr_len = sizeof(addr);
+
+		s = accept(sock.ipv4sock, (struct sockaddr *)&addr, &sockaddr_len);
 
 		if (s != -1)
 		{
-			sockaddr_to_netaddr(&addr, a);
+			sockaddr_to_netaddr((const struct sockaddr *)&addr, a);
 			new_sock->type = NETTYPE_IPV4;
 			new_sock->ipv4sock = s;
 			return s;
@@ -1091,55 +1179,74 @@ int net_tcp_accept(NETSOCKET sock, NETSOCKET *new_sock, NETADDR *a)
 
 	if(sock.ipv6sock >= 0)
 	{
-		s = accept(sock.ipv6sock, &addr, &sockaddr_len);
+		struct sockaddr_in6 addr;
+		sockaddr_len = sizeof(addr);
+
+		s = accept(sock.ipv6sock, (struct sockaddr *)&addr, &sockaddr_len);
 
 		if (s != -1)
 		{
-			sockaddr_to_netaddr(&addr, a);
+			sockaddr_to_netaddr((const struct sockaddr *)&addr, a);
 			new_sock->type = NETTYPE_IPV6;
 			new_sock->ipv6sock = s;
 			return s;
 		}
 	}
 
-	return 0;
+	return -1;
 }
 
 int net_tcp_connect(NETSOCKET sock, const NETADDR *a)
 {
-	/*struct sockaddr addr;
-	netaddr_to_sockaddr(a, &addr);
-	return connect(sock, &addr, sizeof(addr));
-	*/
-	return 0;
+	if(a->type&NETTYPE_IPV4)
+	{
+		struct sockaddr_in addr;
+		netaddr_to_sockaddr_in(a, &addr);
+		return connect(sock.ipv4sock, (struct sockaddr *)&addr, sizeof(addr));
+	}
+
+	if(a->type&NETTYPE_IPV6)
+	{
+		struct sockaddr_in6 addr;
+		netaddr_to_sockaddr_in6(a, &addr);
+		return connect(sock.ipv6sock, (struct sockaddr *)&addr, sizeof(addr));
+	}
+
+	return -1;
 }
 
-int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a)
+int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr)
 {
-	/* struct sockaddr addr; */
 	int res = 0;
 
-	/*
-	netaddr_to_sockaddr(a, &addr);
-	net_tcp_set_non_blocking(sock);
-	res = connect(sock, &addr, sizeof(addr));
-	net_tcp_set_blocking(sock);
-	*/
+	net_set_non_blocking(sock);
+	res = net_tcp_connect(sock, &bindaddr);
+	net_set_blocking(sock);
 
 	return res;
 }
 
 int net_tcp_send(NETSOCKET sock, const void *data, int size)
 {
-	int bytes = 0;
-	/* bytes = send((int)sock, (const char*)data, size, 0); */
+	int bytes = -1;
+
+	if(sock.ipv4sock >= 0)
+		bytes = send((int)sock.ipv4sock, (const char*)data, size, 0);
+	if(sock.ipv6sock >= 0)
+		bytes = send((int)sock.ipv6sock, (const char*)data, size, 0);
+
 	return bytes;
 }
 
 int net_tcp_recv(NETSOCKET sock, void *data, int maxsize)
 {
-	int bytes = 0;
-	/* bytes = recv((int)sock, (char*)data, maxsize, 0); */
+	int bytes = -1;
+
+	if(sock.ipv4sock >= 0)
+		bytes = recv((int)sock.ipv4sock, (char*)data, maxsize, 0);
+	if(sock.ipv6sock >= 0)
+		bytes = recv((int)sock.ipv6sock, (char*)data, maxsize, 0);
+
 	return bytes;
 }
 
@@ -1150,12 +1257,20 @@ int net_tcp_close(NETSOCKET sock)
 
 int net_errno()
 {
+#if defined(CONF_FAMILY_WINDOWS)
+	return WSAGetLastError();
+#else
 	return errno;
+#endif
 }
 
 int net_would_block()
 {
+#if defined(CONF_FAMILY_WINDOWS)
+	return net_errno() == WSAEWOULDBLOCK;
+#else
 	return net_errno() == EWOULDBLOCK;
+#endif
 }
 
 int net_init()
@@ -1410,7 +1525,7 @@ int net_socket_read_wait(NETSOCKET sock, int time)
 	return 0;
 }
 
-unsigned time_timestamp()
+int time_timestamp()
 {
 	return time(0);
 }
@@ -1522,6 +1637,15 @@ int str_comp_nocase(const char *a, const char *b)
 #endif
 }
 
+int str_comp_nocase_num(const char *a, const char *b, const int num)
+{
+#if defined(CONF_FAMILY_WINDOWS)
+	return _strnicmp(a, b, num);
+#else
+	return strncasecmp(a, b, num);
+#endif
+}
+
 int str_comp(const char *a, const char *b)
 {
 	return strcmp(a, b);
diff --git a/src/base/system.h b/src/base/system.h
index a486b89d..b3588dbf 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -240,6 +240,18 @@ unsigned io_skip(IOHANDLE io, int size);
 unsigned io_write(IOHANDLE io, const void *buffer, unsigned size);
 
 /*
+	Function: io_write_newline
+		Writes newline to file.
+
+	Parameters:
+		io - Handle to the file.
+
+	Returns:
+		Number of bytes written.
+*/
+unsigned io_write_newline(IOHANDLE io);
+
+/*
 	Function: io_seek
 		Seeks to a specified offset in the file.
 
@@ -367,6 +379,16 @@ void thread_destroy(void *thread);
 */
 void thread_yield();
 
+/*
+	Function: thread_detach
+		Puts the thread in the detached thread, guaranteeing that
+		resources of the thread will be freed immediately when the
+		thread terminates.
+
+	Parameters:
+		thread - Thread to detach
+*/
+void thread_detach(void *thread);
 
 /* Group: Locks */
 typedef void* LOCK;
@@ -378,6 +400,23 @@ int lock_try(LOCK lock);
 void lock_wait(LOCK lock);
 void lock_release(LOCK lock);
 
+
+/* Group: Semaphores */
+
+#if defined(CONF_FAMILY_UNIX)
+	#include <semaphore.h>
+	typedef sem_t SEMAPHORE;
+#elif defined(CONF_FAMILY_WINDOWS)
+	typedef void* SEMAPHORE;
+#else
+	#error missing sempahore implementation
+#endif
+
+void semaphore_init(SEMAPHORE *sem);
+void semaphore_wait(SEMAPHORE *sem);
+void semaphore_signal(SEMAPHORE *sem);
+void semaphore_destroy(SEMAPHORE *sem);
+
 /* Group: Timer */
 #ifdef __GNUC__
 /* if compiled with -pedantic-errors it will complain about long
@@ -415,7 +454,7 @@ int64 time_freq();
 	Returns:
 		The time as a UNIX timestamp
 */
-unsigned time_timestamp();
+int time_timestamp();
 
 /* Group: Network General */
 typedef struct
@@ -489,12 +528,13 @@ int net_addr_comp(const NETADDR *a, const NETADDR *b);
 		addr - Address to turn into a string.
 		string - Buffer to fill with the string.
 		max_length - Maximum size of the string.
+		add_port - add port to string or not
 
 	Remarks:
 		- The string will always be zero terminated
 
 */
-void net_addr_str(const NETADDR *addr, char *string, int max_length);
+void net_addr_str(const NETADDR *addr, char *string, int max_length, int add_port);
 
 /*
 	Function: net_addr_from_str
@@ -581,7 +621,7 @@ int net_udp_close(NETSOCKET sock);
 	Returns:
 		On success it returns an handle to the socket. On failure it returns NETSOCKET_INVALID.
 */
-NETSOCKET net_tcp_create(const NETADDR *a);
+NETSOCKET net_tcp_create(NETADDR bindaddr);
 
 /*
 	Function: net_tcp_listen
@@ -815,6 +855,25 @@ char *str_skip_whitespaces(char *str);
 */
 int str_comp_nocase(const char *a, const char *b);
 
+/*
+	Function: str_comp_nocase_num
+		Compares up to num characters of two strings case insensitive.
+
+	Parameters:
+		a - String to compare.
+		b - String to compare.
+		num - Maximum characters to compare
+
+	Returns:
+		<0 - String a is lesser than string b
+		0 - String a is equal to string b
+		>0 - String a is greater than string b
+
+	Remarks:
+		- Only garanted to work with a-z/A-Z.
+		- The strings are treated as zero-termineted strings.
+*/
+int str_comp_nocase_num(const char *a, const char *b, const int num);
 
 /*
 	Function: str_comp
@@ -1065,21 +1124,21 @@ int fs_rename(const char *oldname, const char *newname);
 
 	DOCTODO: serp
 */
-int net_tcp_connect_non_blocking(NETSOCKET sock, const NETADDR *a);
+int net_tcp_connect_non_blocking(NETSOCKET sock, NETADDR bindaddr);
 
 /*
-	Function: net_tcp_set_non_blocking
+	Function: net_set_non_blocking
 
 	DOCTODO: serp
 */
-int net_tcp_set_non_blocking(NETSOCKET sock);
+int net_set_non_blocking(NETSOCKET sock);
 
 /*
-	Function: net_tcp_set_non_blocking
+	Function: net_set_non_blocking
 
 	DOCTODO: serp
 */
-int net_tcp_set_blocking(NETSOCKET sock);
+int net_set_blocking(NETSOCKET sock);
 
 /*
 	Function: net_errno
@@ -1101,25 +1160,6 @@ void mem_debug_dump(IOHANDLE file);
 
 void swap_endian(void *data, unsigned elem_size, unsigned num);
 
-/* Group: Debug levels */
-//by format
-enum {
-	DBG_FMT_RAW				= 1,	//raw output
-	DBG_FMT_TIME			= 2,	//show time
-	DBG_FMT_SYS				= 3,	//show sys
-	DBG_FMT_FULL			= 4		//show both
-};
-
-enum {
-	DBG_LEVEL_IMPORTANT			= 0,	//important always showed messages
-	DBG_LEVEL_ERROR				= 1,	//error messages
-	DBG_LEVEL_WARNING			= 2,	//warning messages
-	DBG_LEVEL_MSG				= 3,	//extra debug messages
-	DBG_LEVEL_INFO				= 4		//info messages
-};
-
-#define DBG_LEVEL_LOW DBG_LEVEL_IMPORTANT
-#define DBG_LEVEL_HIGH DBG_LEVEL_INFO
 
 typedef void (*DBG_LOGGER)(const char *line);
 void dbg_logger(DBG_LOGGER logger);
diff --git a/src/base/tl/threading.h b/src/base/tl/threading.h
new file mode 100644
index 00000000..dbf788cd
--- /dev/null
+++ b/src/base/tl/threading.h
@@ -0,0 +1,106 @@
+
+#pragma once
+
+#include "../system.h"
+
+/*
+	atomic_inc - should return the value after increment
+	atomic_dec - should return the value after decrement
+	atomic_compswap - should return the value before the eventual swap
+	
+*/
+
+#if defined(__GNUC__)
+
+	inline unsigned atomic_inc(volatile unsigned *pValue)
+	{
+		return __sync_fetch_and_add(pValue, 1);
+	}
+
+	inline unsigned atomic_dec(volatile unsigned *pValue)
+	{
+		return __sync_fetch_and_add(pValue, -1);
+	}
+
+	inline unsigned atomic_compswap(volatile unsigned *pValue, unsigned comperand, unsigned value)
+	{
+		return __sync_val_compare_and_swap(pValue, comperand, value);
+	}
+
+	inline void sync_barrier()
+	{
+		__sync_synchronize();
+	}
+
+#elif defined(_MSC_VER)
+	#include <intrin.h>
+
+	inline unsigned atomic_inc(volatile unsigned *pValue)
+	{
+		return _InterlockedIncrement((volatile long *)pValue);
+	}
+	
+	inline unsigned atomic_dec(volatile unsigned *pValue)
+	{
+		return _InterlockedDecrement((volatile long *)pValue);
+	}
+
+	inline unsigned atomic_compswap(volatile unsigned *pValue, unsigned comperand, unsigned value)
+	{
+		return _InterlockedCompareExchange((volatile long *)pValue, (long)value, (long)comperand);
+	}
+
+	inline void sync_barrier()
+	{
+		_ReadWriteBarrier();
+	}
+#else
+	#error missing atomic implementation for this compiler
+#endif
+
+class semaphore
+{
+	SEMAPHORE sem;
+public:
+	semaphore() { semaphore_init(&sem); }
+	~semaphore() { semaphore_destroy(&sem); }
+	void wait() { semaphore_wait(&sem); }
+	void signal() { semaphore_signal(&sem); }
+};
+
+class lock
+{
+	friend class scope_lock;
+
+	LOCK var;
+
+	void take() { lock_wait(var); }
+	void release() { lock_release(var); }
+
+public:
+	lock()
+	{
+		var = lock_create();
+	}
+
+	~lock()
+	{
+		lock_destroy(var);
+	}
+};
+
+class scope_lock
+{
+	lock *var;
+public:
+	scope_lock(lock *l)
+	{
+		var = l;
+		var->take();
+	}
+
+	~scope_lock()
+	{
+		var->release();
+	}
+};
diff --git a/src/base/vmath.h b/src/base/vmath.h
index 3461adf8..df10d904 100644
--- a/src/base/vmath.h
+++ b/src/base/vmath.h
@@ -25,12 +25,18 @@ public:
 	vector2_base operator -(const vector2_base &v) const { return vector2_base(x-v.x, y-v.y); }
 	vector2_base operator +(const vector2_base &v) const { return vector2_base(x+v.x, y+v.y); }
 	vector2_base operator *(const T v) const { return vector2_base(x*v, y*v); }
+	vector2_base operator *(const vector2_base &v) const { return vector2_base(x*v.x, y*v.y); }
+	vector2_base operator /(const T v) const { return vector3_base(x/v, y/v); }
+	vector2_base operator /(const vector2_base &v) const { return vector2_base(x/v.x, y/v.y); }
 
 	const vector2_base &operator =(const vector2_base &v) { x = v.x; y = v.y; return *this; }
 
 	const vector2_base &operator +=(const vector2_base &v) { x += v.x; y += v.y; return *this; }
 	const vector2_base &operator -=(const vector2_base &v) { x -= v.x; y -= v.y; return *this; }
 	const vector2_base &operator *=(const T v) { x *= v; y *= v; return *this;	}
+	const vector2_base &operator *=(const vector2_base &v) { x *= v.x; y *= v.y; return *this; }
+	const vector2_base &operator /=(const T v) { x /= v; y /= v; return *this;	}
+	const vector2_base &operator /=(const vector2_base &v) { x /= v.x; y /= v.y; return *this; }
 
 	bool operator ==(const vector2_base &v) const { return x == v.x && y == v.y; } //TODO: do this with an eps instead
 
@@ -107,10 +113,14 @@ public:
 	vector3_base operator *(const T v) const { return vector3_base(x*v, y*v, z*v); }
 	vector3_base operator *(const vector3_base &v) const { return vector3_base(x*v.x, y*v.y, z*v.z); }
 	vector3_base operator /(const T v) const { return vector3_base(x/v, y/v, z/v); }
+	vector3_base operator /(const vector3_base &v) const { return vector3_base(x/v.x, y/v.y, z/v.z); }
 
 	const vector3_base &operator +=(const vector3_base &v) { x += v.x; y += v.y; z += v.z; return *this; }
 	const vector3_base &operator -=(const vector3_base &v) { x -= v.x; y -= v.y; z -= v.z; return *this; }
 	const vector3_base &operator *=(const T v) { x *= v; y *= v; z *= v; return *this;	}
+	const vector3_base &operator *=(const vector3_base &v) { x *= v.x; y *= v.y; z *= v.z; return *this; }
+	const vector3_base &operator /=(const T v) { x /= v; y /= v; z /= v; return *this;	}
+	const vector3_base &operator /=(const vector3_base &v) { x /= v.x; y /= v.y; z /= v.z; return *this; }
 
 	bool operator ==(const vector3_base &v) const { return x == v.x && y == v.y && z == v.z; } //TODO: do this with an eps instead
 
@@ -180,12 +190,17 @@ public:
 	vector4_base operator -() const { return vector4_base(-x, -y, -z, -w); }
 	vector4_base operator *(const vector4_base &v) const { return vector4_base(x*v.x, y*v.y, z*v.z, w*v.w); }
 	vector4_base operator *(const T v) const { return vector4_base(x*v, y*v, z*v, w*v); }
+	vector4_base operator /(const vector4_base &v) const { return vector4_base(x/v.x, y/v.y, z/v.z, w/v.w); }
+	vector4_base operator /(const T v) const { return vector4_base(x/v, y/v, z/v, w/v); }
 
 	const vector4_base &operator =(const vector4_base &v) { x = v.x; y = v.y; z = v.z; w = v.w; return *this; }
 
 	const vector4_base &operator +=(const vector4_base &v) { x += v.x; y += v.y; z += v.z; w += v.w; return *this; }
 	const vector4_base &operator -=(const vector4_base &v) { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; }
 	const vector4_base &operator *=(const T v) { x *= v; y *= v; z *= v; w *= v; return *this;	}
+	const vector4_base &operator *=(const vector4_base &v) { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; }
+	const vector4_base &operator /=(const T v) { x /= v; y /= v; z /= v; w /= v; return *this;	}
+	const vector4_base &operator /=(const vector4_base &v) { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; }
 
 	bool operator ==(const vector4_base &v) const { return x == v.x && y == v.y && z == v.z && w == v.w; } //TODO: do this with an eps instead