1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-11-03 04:17:17 -05:00

sync these up with trunk

svn path=/icecast/branches/kh/net/; revision=15864
This commit is contained in:
Karl Heyes 2009-03-27 23:09:45 +00:00
parent 733c048a42
commit 02c6f8ccc5
5 changed files with 518 additions and 117 deletions

226
src/net/resolver.c Normal file
View File

@ -0,0 +1,226 @@
/*
* resolver.c - name resolver library
*
* Copyright (C) 1999 the icecast team <team@icecast.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#ifndef NO_THREAD
#include <thread/thread.h>
#else
#define thread_mutex_create(x) do{}while(0)
#define thread_mutex_destroy(x) do{}while(0)
#define thread_mutex_lock(x) do{}while(0)
#define thread_mutex_unlock(x) do{}while(0)
#endif
#include "resolver.h"
#include "sock.h"
/* internal function */
static int _isip(const char *what);
/* internal data */
#ifndef NO_THREAD
static mutex_t _resolver_mutex;
#endif
static int _initialized = 0;
#ifdef HAVE_INET_PTON
static int _isip(const char *what)
{
union {
struct in_addr v4addr;
struct in6_addr v6addr;
} addr_u;
if (inet_pton(AF_INET, what, &addr_u.v4addr) <= 0)
return inet_pton(AF_INET6, what, &addr_u.v6addr) > 0 ? 1 : 0;
return 1;
}
#else
static int _isip(const char *what)
{
struct in_addr inp;
return inet_aton(what, &inp);
}
#endif
#if defined (HAVE_GETNAMEINFO) && defined (HAVE_GETADDRINFO)
char *resolver_getname(const char *ip, char *buff, int len)
{
struct addrinfo *head = NULL, hints;
char *ret = NULL;
if (!_isip(ip)) {
strncpy(buff, ip, len);
buff [len-1] = '\0';
return buff;
}
memset (&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
if (getaddrinfo (ip, NULL, &hints, &head))
return NULL;
if (head)
{
if (getnameinfo(head->ai_addr, head->ai_addrlen, buff, len, NULL,
0, NI_NAMEREQD) == 0)
ret = buff;
freeaddrinfo (head);
}
return ret;
}
char *resolver_getip(const char *name, char *buff, int len)
{
struct addrinfo *head, hints;
char *ret = NULL;
if (_isip(name)) {
strncpy(buff, name, len);
buff [len-1] = '\0';
return buff;
}
memset (&hints, 0, sizeof (hints));
hints . ai_family = AF_UNSPEC;
hints . ai_socktype = SOCK_STREAM;
if (getaddrinfo (name, NULL, &hints, &head))
return NULL;
if (head)
{
if (getnameinfo(head->ai_addr, head->ai_addrlen, buff, len, NULL,
0, NI_NUMERICHOST) == 0)
ret = buff;
freeaddrinfo (head);
}
return ret;
}
#else
char *resolver_getname(const char *ip, char *buff, int len)
{
struct hostent *host;
char *ret = NULL;
struct in_addr addr;
if (! _isip(ip))
{
strncpy(buff, ip, len);
buff [len-1] = '\0';
return buff;
}
thread_mutex_lock(&_resolver_mutex);
if (inet_aton (ip, &addr)) {
if ((host=gethostbyaddr ((void*)&addr, sizeof (struct in_addr), AF_INET)))
{
ret = strncpy (buff, host->h_name, len);
buff [len-1] = '\0';
}
}
thread_mutex_unlock(&_resolver_mutex);
return ret;
}
char *resolver_getip(const char *name, char *buff, int len)
{
struct hostent *host;
char *ret = NULL;
if (_isip(name))
{
strncpy(buff, name, len);
buff [len-1] = '\0';
return buff;
}
thread_mutex_lock(&_resolver_mutex);
host = gethostbyname(name);
if (host)
{
char * temp = inet_ntoa(*(struct in_addr *)host->h_addr);
ret = strncpy(buff, temp, len);
buff [len-1] = '\0';
}
thread_mutex_unlock(&_resolver_mutex);
return ret;
}
#endif
void resolver_initialize()
{
/* initialize the lib if we havne't done so already */
if (!_initialized)
{
_initialized = 1;
thread_mutex_create (&_resolver_mutex);
/* keep dns connects (TCP) open */
#ifdef HAVE_SETHOSTENT
sethostent(1);
#endif
}
}
void resolver_shutdown(void)
{
if (_initialized)
{
thread_mutex_destroy(&_resolver_mutex);
_initialized = 0;
#ifdef HAVE_ENDHOSTENT
endhostent();
#endif
}
}

View File

@ -30,6 +30,9 @@
#include <string.h> #include <string.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_POLL
#include <poll.h>
#endif
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
#endif #endif
@ -44,20 +47,23 @@
#include <netdb.h> #include <netdb.h>
#else #else
#include <winsock2.h> #include <winsock2.h>
#define vsnprintf _vsnprintf
#define EINPROGRESS WSAEINPROGRESS #define EINPROGRESS WSAEINPROGRESS
#define ENOTSOCK WSAENOTSOCK #define ENOTSOCK WSAENOTSOCK
#define EWOULDBLOCK WSAEWOULDBLOCK #define EWOULDBLOCK WSAEWOULDBLOCK
#define EALREADY WSAEALREADY #define EALREADY WSAEALREADY
#define socklen_t int
#ifndef __MINGW32__
#define va_copy(ap1, ap2) memcpy(&ap1, &ap2, sizeof(va_list))
#endif
#endif #endif
#include "sock.h" #include "sock.h"
#include "resolver.h" #include "resolver.h"
/* for older C libraries */
#ifndef AI_NUMERICSERV
# define AI_NUMERICSERV 0
#endif
#ifndef AI_ADDRCONFIG
# define AI_ADDRCONFIG 0
#endif
/* sock_initialize /* sock_initialize
** **
** initializes the socket library. you must call this ** initializes the socket library. you must call this
@ -196,6 +202,21 @@ int sock_valid_socket(sock_t sock)
return (ret == 0); return (ret == 0);
} }
/* determines if the passed socket is still connected */
int sock_active (sock_t sock)
{
char c;
int l;
l = recv (sock, &c, 1, MSG_PEEK);
if (l == 0)
return 0;
if (l == SOCK_ERROR && sock_recoverable (sock_error()))
return 1;
return 0;
}
/* inet_aton /* inet_aton
** **
** turns an ascii ip address into a binary representation ** turns an ascii ip address into a binary representation
@ -216,28 +237,26 @@ int inet_aton(const char *s, struct in_addr *a)
#endif /* _WIN32 */ #endif /* _WIN32 */
/* sock_set_blocking /* sock_set_blocking
** *
** set the sock blocking or nonblocking * set the sock blocking or nonblocking
** SOCK_BLOCK for blocking * 1 for blocking
** SOCK_NONBLOCK for nonblocking * 0 for nonblocking
*/ */
int sock_set_blocking(sock_t sock, const int block) int sock_set_blocking(sock_t sock, int block)
{ {
#ifdef _WIN32 if ((block < 0) || (block > 1))
#ifdef __MINGW32__
u_long varblock = block;
#else
int varblock = block;
#endif
#endif
if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1))
return SOCK_ERROR; return SOCK_ERROR;
#ifdef _WIN32 #ifdef _WIN32
return ioctlsocket(sock, FIONBIO, &varblock); else
{
long nonblock = 0;
if (block == 0)
nonblock = 1;
return ioctlsocket(sock, FIONBIO, &nonblock);
}
#else #else
return fcntl(sock, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK); return fcntl(sock, F_SETFL, (block) ? 0 : O_NONBLOCK);
#endif #endif
} }
@ -256,6 +275,14 @@ int sock_set_nodelay(sock_t sock)
sizeof(int)); sizeof(int));
} }
int sock_set_delay(sock_t sock)
{
int nodelay = 0;
return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay,
sizeof(int));
}
int sock_set_keepalive(sock_t sock) int sock_set_keepalive(sock_t sock)
{ {
int keepalive = 1; int keepalive = 1;
@ -282,14 +309,14 @@ int sock_close(sock_t sock)
*/ */
#ifdef HAVE_WRITEV #ifdef HAVE_WRITEV
ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count) ssize_t sock_writev (sock_t sock, const struct iovec *iov, size_t count)
{ {
return writev (sock, iov, count); return writev (sock, iov, count);
} }
#else #else
ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count) ssize_t sock_writev (sock_t sock, const struct iovec *iov, size_t count)
{ {
int i = count, accum = 0, ret; int i = count, accum = 0, ret;
const struct iovec *v = iov; const struct iovec *v = iov;
@ -320,7 +347,7 @@ ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count)
** write bytes to the socket ** write bytes to the socket
** this function will _NOT_ block ** this function will _NOT_ block
*/ */
int sock_write_bytes(sock_t sock, const void *buff, const size_t len) int sock_write_bytes(sock_t sock, const void *buff, size_t len)
{ {
/* sanity check */ /* sanity check */
if (!buff) { if (!buff) {
@ -509,7 +536,27 @@ int sock_read_line(sock_t sock, char *buff, const int len)
* return 0 for try again, interrupted * return 0 for try again, interrupted
* return 1 for ok * return 1 for ok
*/ */
int sock_connected (int sock, int timeout) #ifdef HAVE_POLL
int sock_connected (sock_t sock, int timeout)
{
struct pollfd check;
check.fd = sock;
check.events = POLLOUT;
switch (poll (&check, 1, timeout*1000))
{
case 0: return SOCK_TIMEOUT;
case -1:
if (sock_recoverable (sock_error()))
return 0;
return SOCK_ERROR;
default: return 1;
}
}
#else
int sock_connected (sock_t sock, int timeout)
{ {
fd_set wfds; fd_set wfds;
int val = SOCK_ERROR; int val = SOCK_ERROR;
@ -546,10 +593,16 @@ int sock_connected (int sock, int timeout)
return SOCK_ERROR; return SOCK_ERROR;
} }
} }
#endif
sock_t sock_connect_wto (const char *hostname, int port, int timeout)
{
return sock_connect_wto_bind(hostname, port, NULL, timeout);
}
#ifdef HAVE_GETADDRINFO #ifdef HAVE_GETADDRINFO
int sock_connect_non_blocking (const char *hostname, const unsigned port) sock_t sock_connect_non_blocking (const char *hostname, unsigned port)
{ {
int sock = SOCK_ERROR; int sock = SOCK_ERROR;
struct addrinfo *ai, *head, hints; struct addrinfo *ai, *head, hints;
@ -570,7 +623,7 @@ int sock_connect_non_blocking (const char *hostname, const unsigned port)
if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol))
> -1) > -1)
{ {
sock_set_blocking (sock, SOCK_NONBLOCK); sock_set_blocking (sock, 0);
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
!sock_connect_pending(sock_error())) !sock_connect_pending(sock_error()))
{ {
@ -591,10 +644,10 @@ int sock_connect_non_blocking (const char *hostname, const unsigned port)
* timeout is 0 or less then we will wait until the OS gives up on the connect * timeout is 0 or less then we will wait until the OS gives up on the connect
* The socket is returned * The socket is returned
*/ */
sock_t sock_connect_wto(const char *hostname, int port, int timeout) sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, int timeout)
{ {
int sock = SOCK_ERROR; sock_t sock = SOCK_ERROR;
struct addrinfo *ai, *head, hints; struct addrinfo *ai, *head, *b_head=NULL, hints;
char service[8]; char service[8];
memset (&hints, 0, sizeof (hints)); memset (&hints, 0, sizeof (hints));
@ -611,7 +664,23 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) >= 0) if ((sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol)) >= 0)
{ {
if (timeout > 0) if (timeout > 0)
sock_set_blocking (sock, SOCK_NONBLOCK); sock_set_blocking (sock, 0);
if (bnd)
{
struct addrinfo b_hints;
memset (&b_hints, 0, sizeof(b_hints));
b_hints.ai_family = ai->ai_family;
b_hints.ai_socktype = ai->ai_socktype;
b_hints.ai_protocol = ai->ai_protocol;
if (getaddrinfo (bnd, NULL, &b_hints, &b_head) ||
bind (sock, b_head->ai_addr, b_head->ai_addrlen) < 0)
{
sock_close (sock);
sock = SOCK_ERROR;
break;
}
}
if (connect (sock, ai->ai_addr, ai->ai_addrlen) == 0) if (connect (sock, ai->ai_addr, ai->ai_addrlen) == 0)
break; break;
@ -627,7 +696,7 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
if (connected == 1) /* connected */ if (connected == 1) /* connected */
{ {
if (timeout >= 0) if (timeout >= 0)
sock_set_blocking(sock, SOCK_BLOCK); sock_set_blocking(sock, 1);
break; break;
} }
} }
@ -639,15 +708,67 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
} }
ai = ai->ai_next; ai = ai->ai_next;
} }
if (head) if (b_head)
freeaddrinfo (b_head);
freeaddrinfo (head); freeaddrinfo (head);
return sock; return sock;
} }
sock_t sock_get_server_socket (int port, const char *sinterface)
{
struct sockaddr_storage sa;
struct addrinfo hints, *res, *ai;
char service [10];
int sock;
if (port < 0)
return SOCK_ERROR;
memset (&sa, 0, sizeof(sa));
memset (&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG | AI_NUMERICSERV | AI_NUMERICHOST;
hints.ai_socktype = SOCK_STREAM;
snprintf (service, sizeof (service), "%d", port);
if (getaddrinfo (sinterface, service, &hints, &res))
return SOCK_ERROR;
ai = res;
do
{
int on = 1;
sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock < 0)
continue;
setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on));
on = 0;
#ifdef IPV6_V6ONLY
setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on);
#endif
if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0)
{
sock_close (sock);
continue;
}
freeaddrinfo (res);
return sock;
} while ((ai = ai->ai_next));
freeaddrinfo (res);
return SOCK_ERROR;
}
#else #else
int sock_try_connection (int sock, const char *hostname, const unsigned port)
int sock_try_connection (sock_t sock, const char *hostname, unsigned int port)
{ {
struct sockaddr_in sin, server; struct sockaddr_in sin, server;
char ip[MAX_ADDR_LEN]; char ip[MAX_ADDR_LEN];
@ -673,36 +794,51 @@ int sock_try_connection (int sock, const char *hostname, const unsigned port)
memcpy(&server.sin_addr, &sin.sin_addr, sizeof(struct sockaddr_in)); memcpy(&server.sin_addr, &sin.sin_addr, sizeof(struct sockaddr_in));
server.sin_family = AF_INET; server.sin_family = AF_INET;
server.sin_port = htons(port); server.sin_port = htons((short)port);
return connect(sock, (struct sockaddr *)&server, sizeof(server)); return connect(sock, (struct sockaddr *)&server, sizeof(server));
} }
int sock_connect_non_blocking (const char *hostname, const unsigned port) sock_t sock_connect_non_blocking (const char *hostname, unsigned port)
{ {
int sock; sock_t sock;
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) if (sock == SOCK_ERROR)
return -1; return SOCK_ERROR;
sock_set_blocking (sock, SOCK_NONBLOCK); sock_set_blocking (sock, 0);
sock_try_connection (sock, hostname, port); sock_try_connection (sock, hostname, port);
return sock; return sock;
} }
sock_t sock_connect_wto(const char *hostname, const int port, const int timeout) sock_t sock_connect_wto_bind (const char *hostname, int port, const char *bnd, int timeout)
{ {
int sock; sock_t sock;
sock = socket(AF_INET, SOCK_STREAM, 0); sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) if (sock == SOCK_ERROR)
return -1; return SOCK_ERROR;
if (bnd)
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
if (inet_aton (bnd, &sa.sin_addr) == 0 ||
bind (sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
{
sock_close (sock);
return SOCK_ERROR;
}
}
if (timeout) if (timeout)
{ {
sock_set_blocking (sock, SOCK_NONBLOCK); sock_set_blocking (sock, 0);
if (sock_try_connection (sock, hostname, port) < 0) if (sock_try_connection (sock, hostname, port) < 0)
{ {
int ret = sock_connected (sock, timeout); int ret = sock_connected (sock, timeout);
@ -712,7 +848,7 @@ sock_t sock_connect_wto(const char *hostname, const int port, const int timeout)
return SOCK_ERROR; return SOCK_ERROR;
} }
} }
sock_set_blocking(sock, SOCK_BLOCK); sock_set_blocking(sock, 1);
} }
else else
{ {
@ -724,7 +860,6 @@ sock_t sock_connect_wto(const char *hostname, const int port, const int timeout)
} }
return sock; return sock;
} }
#endif
/* sock_get_server_socket /* sock_get_server_socket
@ -733,14 +868,10 @@ sock_t sock_connect_wto(const char *hostname, const int port, const int timeout)
** interface. if interface is null, listen on all interfaces. ** interface. if interface is null, listen on all interfaces.
** returns the socket, or SOCK_ERROR on failure ** returns the socket, or SOCK_ERROR on failure
*/ */
sock_t sock_get_server_socket(const int port, char *sinterface) sock_t sock_get_server_socket(int port, const char *sinterface)
{ {
#ifdef HAVE_INET_PTON
struct sockaddr_storage sa;
#else
struct sockaddr_in sa; struct sockaddr_in sa;
#endif int error, opt;
int family, len, error, opt;
sock_t sock; sock_t sock;
char ip[MAX_ADDR_LEN]; char ip[MAX_ADDR_LEN];
@ -749,43 +880,26 @@ sock_t sock_get_server_socket(const int port, char *sinterface)
/* defaults */ /* defaults */
memset(&sa, 0, sizeof(sa)); memset(&sa, 0, sizeof(sa));
family = AF_INET;
len = sizeof(struct sockaddr_in);
/* set the interface to bind to if specified */ /* set the interface to bind to if specified */
if (sinterface != NULL) { if (sinterface != NULL) {
if (!resolver_getip(sinterface, ip, sizeof (ip))) if (!resolver_getip(sinterface, ip, sizeof (ip)))
return SOCK_ERROR; return SOCK_ERROR;
#ifdef HAVE_INET_PTON
if (inet_pton(AF_INET, ip, &((struct sockaddr_in*)&sa)->sin_addr) > 0) {
((struct sockaddr_in*)&sa)->sin_family = AF_INET;
((struct sockaddr_in*)&sa)->sin_port = htons(port);
} else if (inet_pton(AF_INET6, ip,
&((struct sockaddr_in6*)&sa)->sin6_addr) > 0) {
family = AF_INET6;
len = sizeof (struct sockaddr_in6);
((struct sockaddr_in6*)&sa)->sin6_family = AF_INET6;
((struct sockaddr_in6*)&sa)->sin6_port = htons(port);
} else {
return SOCK_ERROR;
}
#else
if (!inet_aton(ip, &sa.sin_addr)) { if (!inet_aton(ip, &sa.sin_addr)) {
return SOCK_ERROR; return SOCK_ERROR;
} else { } else {
sa.sin_family = AF_INET; sa.sin_family = AF_INET;
sa.sin_port = htons(port); sa.sin_port = htons((short)port);
} }
#endif
} else { } else {
((struct sockaddr_in*)&sa)->sin_addr.s_addr = INADDR_ANY; sa.sin_addr.s_addr = INADDR_ANY;
((struct sockaddr_in*)&sa)->sin_family = AF_INET; sa.sin_family = AF_INET;
((struct sockaddr_in*)&sa)->sin_port = htons(port); sa.sin_port = htons((short)port);
} }
/* get a socket */ /* get a socket */
sock = socket(family, SOCK_STREAM, 0); sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock == -1) if (sock == -1)
return SOCK_ERROR; return SOCK_ERROR;
@ -794,13 +908,20 @@ sock_t sock_get_server_socket(const int port, char *sinterface)
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int)); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int));
/* bind socket to port */ /* bind socket to port */
error = bind(sock, (struct sockaddr *)&sa, len); error = bind(sock, (struct sockaddr *)&sa, sizeof (struct sockaddr_in));
if (error == -1) if (error == -1)
return SOCK_ERROR; return SOCK_ERROR;
return sock; return sock;
} }
#endif
void sock_set_send_buffer (sock_t sock, int win_size)
{
setsockopt (sock, SOL_SOCKET, SO_SNDBUF, (char *) &win_size, sizeof(win_size));
}
int sock_listen(sock_t serversock, int backlog) int sock_listen(sock_t serversock, int backlog)
{ {
if (!sock_valid_socket(serversock)) if (!sock_valid_socket(serversock))
@ -812,34 +933,27 @@ int sock_listen(sock_t serversock, int backlog)
return (listen(serversock, backlog) == 0); return (listen(serversock, backlog) == 0);
} }
int sock_accept(sock_t serversock, char *ip, int len) sock_t sock_accept(sock_t serversock, char *ip, size_t len)
{ {
#ifdef HAVE_INET_PTON #ifdef HAVE_GETNAMEINFO
struct sockaddr_storage sa; struct sockaddr_storage sa;
#else #else
struct sockaddr_in sa; struct sockaddr_in sa;
#endif #endif
int ret; sock_t ret;
socklen_t slen; socklen_t slen;
if (!sock_valid_socket(serversock)) if (ip == NULL || len == 0 || !sock_valid_socket(serversock))
return SOCK_ERROR; return SOCK_ERROR;
slen = sizeof(sa); slen = sizeof(sa);
ret = accept(serversock, (struct sockaddr *)&sa, &slen); ret = accept(serversock, (struct sockaddr *)&sa, &slen);
if (ret >= 0 && ip != NULL) { if (ret != SOCK_ERROR)
#ifdef HAVE_INET_PTON {
if(((struct sockaddr_in *)&sa)->sin_family == AF_INET) #ifdef HAVE_GETNAMEINFO
inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr, if (getnameinfo ((struct sockaddr *)&sa, slen, ip, len, NULL, 0, NI_NUMERICHOST))
ip, len); snprintf (ip, len, "unknown");
else if(((struct sockaddr_in6 *)&sa)->sin6_family == AF_INET6)
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&sa)->sin6_addr,
ip, len);
else {
strncpy(ip, "ERROR", len-1);
ip[len-1] = 0;
}
#else #else
/* inet_ntoa is not reentrant, we should protect this */ /* inet_ntoa is not reentrant, we should protect this */
strncpy(ip, inet_ntoa(sa.sin_addr), len); strncpy(ip, inet_ntoa(sa.sin_addr), len);

View File

@ -31,7 +31,7 @@
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#elif _WIN32 #elif _WIN32
#include <os.h> #include <compat.h>
#endif #endif
#ifdef HAVE_SYS_UIO_H #ifdef HAVE_SYS_UIO_H
@ -56,16 +56,15 @@ struct iovec
#define MAX_ADDR_LEN 46 #define MAX_ADDR_LEN 46
#endif #endif
typedef int sock_t; #ifndef sock_t
#define sock_t int
#endif
/* The following values are based on unix avoiding errno value clashes */ /* The following values are based on unix avoiding errno value clashes */
#define SOCK_SUCCESS 0 #define SOCK_SUCCESS 0
#define SOCK_ERROR -1 #define SOCK_ERROR (sock_t)-1
#define SOCK_TIMEOUT -2 #define SOCK_TIMEOUT -2
#define SOCK_BLOCK 0
#define SOCK_NONBLOCK 1
/* sock connect macro */ /* sock connect macro */
#define sock_connect(h, p) sock_connect_wto(h, p, 0) #define sock_connect(h, p) sock_connect_wto(h, p, 0)
@ -81,9 +80,11 @@ typedef int sock_t;
# define sock_set_blocking _mangle(sock_set_blocking) # define sock_set_blocking _mangle(sock_set_blocking)
# define sock_set_nolinger _mangle(sock_set_nolinger) # define sock_set_nolinger _mangle(sock_set_nolinger)
# define sock_set_nodelay _mangle(sock_set_nodelay) # define sock_set_nodelay _mangle(sock_set_nodelay)
# define sock_set_delay _mangle(sock_set_delay)
# define sock_set_keepalive _mangle(sock_set_keepalive) # define sock_set_keepalive _mangle(sock_set_keepalive)
# define sock_close _mangle(sock_close) # define sock_close _mangle(sock_close)
# define sock_connect_wto _mangle(sock_connect_wto) # define sock_connect_wto _mangle(sock_connect_wto)
# define sock_connect_wto_bind _mangle(sock_connect_wto_bind)
# define sock_connect_non_blocking _mangle(sock_connect_non_blocking) # define sock_connect_non_blocking _mangle(sock_connect_non_blocking)
# define sock_connected _mangle(sock_connected) # define sock_connected _mangle(sock_connected)
# define sock_write_bytes _mangle(sock_write_bytes) # define sock_write_bytes _mangle(sock_write_bytes)
@ -95,6 +96,7 @@ typedef int sock_t;
# define sock_read_line _mangle(sock_read_line) # define sock_read_line _mangle(sock_read_line)
# define sock_get_server_socket _mangle(sock_get_server_socket) # define sock_get_server_socket _mangle(sock_get_server_socket)
# define sock_listen _mangle(sock_listen) # define sock_listen _mangle(sock_listen)
# define sock_set_send_buffer _mangle(sock_set_send_buffer)
# define sock_accept _mangle(sock_accept) # define sock_accept _mangle(sock_accept)
#endif #endif
@ -106,24 +108,28 @@ int sock_error(void);
int sock_recoverable(int error); int sock_recoverable(int error);
int sock_stalled(int error); int sock_stalled(int error);
int sock_valid_socket(sock_t sock); int sock_valid_socket(sock_t sock);
int sock_set_blocking(sock_t sock, const int block); int sock_active (sock_t sock);
int sock_set_blocking(sock_t sock, int block);
int sock_set_nolinger(sock_t sock); int sock_set_nolinger(sock_t sock);
int sock_set_keepalive(sock_t sock); int sock_set_keepalive(sock_t sock);
int sock_set_nodelay(sock_t sock); int sock_set_nodelay(sock_t sock);
void sock_set_send_buffer (sock_t sock, int win_size);
int sock_set_delay(sock_t sock);
void sock_set_error(int val); void sock_set_error(int val);
int sock_close(sock_t sock); int sock_close(sock_t sock);
/* Connection related socket functions */ /* Connection related socket functions */
sock_t sock_connect_wto(const char *hostname, int port, int timeout); sock_t sock_connect_wto(const char *hostname, int port, int timeout);
int sock_connect_non_blocking(const char *host, const unsigned port); sock_t sock_connect_wto_bind(const char *hostname, int port, const char *bnd, int timeout);
int sock_connected(int sock, int timeout); sock_t sock_connect_non_blocking(const char *host, unsigned port);
int sock_connected(sock_t sock, int timeout);
/* Socket write functions */ /* Socket write functions */
int sock_write_bytes(sock_t sock, const void *buff, const size_t len); int sock_write_bytes(sock_t sock, const void *buff, size_t len);
int sock_write(sock_t sock, const char *fmt, ...); int sock_write(sock_t sock, const char *fmt, ...);
int sock_write_fmt(sock_t sock, const char *fmt, va_list ap); int sock_write_fmt(sock_t sock, const char *fmt, va_list ap);
int sock_write_string(sock_t sock, const char *buff); int sock_write_string(sock_t sock, const char *buff);
ssize_t sock_writev (int sock, const struct iovec *iov, const size_t count); ssize_t sock_writev (sock_t sock, const struct iovec *iov, size_t count);
/* Socket read functions */ /* Socket read functions */
@ -132,9 +138,9 @@ int sock_read_line(sock_t sock, char *string, const int len);
int sock_read_pending(sock_t sock, unsigned timeout); int sock_read_pending(sock_t sock, unsigned timeout);
/* server socket functions */ /* server socket functions */
sock_t sock_get_server_socket(const int port, char *sinterface); sock_t sock_get_server_socket(int port, const char *sinterface);
int sock_listen(sock_t serversock, int backlog); int sock_listen(sock_t serversock, int backlog);
int sock_accept(sock_t serversock, char *ip, int len); sock_t sock_accept(sock_t serversock, char *ip, size_t len);
#ifdef _WIN32 #ifdef _WIN32
int inet_aton(const char *s, struct in_addr *a); int inet_aton(const char *s, struct in_addr *a);

View File

@ -165,8 +165,8 @@ void thread_initialize(void)
log_set_level(_logid, 4); log_set_level(_logid, 4);
#endif #endif
thread_mutex_create("threadtree", &_threadtree_mutex); thread_mutex_create(&_threadtree_mutex);
thread_mutex_create("thread lib", &_library_mutex); thread_mutex_create(&_library_mutex);
/* initialize the thread tree and insert the main thread */ /* initialize the thread tree and insert the main thread */
@ -199,6 +199,7 @@ void thread_shutdown(void)
avl_tree_free(_mutextree, _free_mutex); avl_tree_free(_mutextree, _free_mutex);
#endif #endif
avl_tree_free(_threadtree, _free_thread); avl_tree_free(_threadtree, _free_thread);
_threadtree = NULL;
} }
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
@ -339,12 +340,13 @@ static void _mutex_create(mutex_t *mutex)
pthread_mutex_init(&mutex->sys_mutex, NULL); pthread_mutex_init(&mutex->sys_mutex, NULL);
} }
void thread_mutex_create_c(const char *name, mutex_t *mutex, int line, const char *file) void thread_mutex_create_c(mutex_t *mutex, int line, const char *file)
{ {
_mutex_create(mutex); _mutex_create(mutex);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
mutex->name = strdup (name); mutex->name = malloc (strlen (name)+20);
sprintf (mutex->name, "%s:%d", file, line);
_mutex_lock(&_mutextree_mutex); _mutex_lock(&_mutextree_mutex);
mutex->mutex_id = _next_mutex_id++; mutex->mutex_id = _next_mutex_id++;
avl_insert(_mutextree, (void *)mutex); avl_insert(_mutextree, (void *)mutex);
@ -376,6 +378,7 @@ void thread_mutex_lock_c(mutex_t *mutex, int line, char *file)
mutex->lock_start = get_count(); mutex->lock_start = get_count();
mutex->file = strdup (file); mutex->file = strdup (file);
mutex->line = line; mutex->line = line;
LOG_DEBUG3("Lock on %s acquired at %s:%d", mutex->name, file, line);
#endif /* THREAD_DEBUG */ #endif /* THREAD_DEBUG */
} }
@ -446,6 +449,7 @@ void thread_rwlock_destroy(rwlock_t *rwlock)
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_DEBUG1 ("rwlock %s destroyed", rwlock->name); LOG_DEBUG1 ("rwlock %s destroyed", rwlock->name);
free (rwlock->name); free (rwlock->name);
rwlock->name = NULL;
#endif #endif
} }
@ -455,6 +459,9 @@ void thread_rwlock_rlock_c(rwlock_t *rwlock, int line, const char *file)
LOG_DEBUG3("rLock on %s requested at %s:%d", rwlock->name, file, line); LOG_DEBUG3("rLock on %s requested at %s:%d", rwlock->name, file, line);
#endif #endif
pthread_rwlock_rdlock(&rwlock->sys_rwlock); pthread_rwlock_rdlock(&rwlock->sys_rwlock);
#ifdef THREAD_DEBUG
LOG_DEBUG3("rLock on %s acquired at %s:%d", rwlock->name, file, line);
#endif
} }
void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, const char *file) void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, const char *file)
@ -463,13 +470,16 @@ void thread_rwlock_wlock_c(rwlock_t *rwlock, int line, const char *file)
LOG_DEBUG3("wLock on %s requested at %s:%d", rwlock->name, file, line); LOG_DEBUG3("wLock on %s requested at %s:%d", rwlock->name, file, line);
#endif #endif
pthread_rwlock_wrlock(&rwlock->sys_rwlock); pthread_rwlock_wrlock(&rwlock->sys_rwlock);
#ifdef THREAD_DEBUG
LOG_DEBUG3("wLock on %s acquired at %s:%d", rwlock->name, file, line);
#endif
} }
void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, const char *file) void thread_rwlock_unlock_c(rwlock_t *rwlock, int line, const char *file)
{ {
pthread_rwlock_unlock(&rwlock->sys_rwlock); pthread_rwlock_unlock(&rwlock->sys_rwlock);
#ifdef THREAD_DEBUG #ifdef THREAD_DEBUG
LOG_DEBUG3 ("rwlock %s, at %s:%d", rwlock->name, file, line); LOG_DEBUG3 ("unlock %s, at %s:%d", rwlock->name, file, line);
#endif #endif
} }
@ -576,7 +586,7 @@ static void *_start_routine(void *arg)
(start_routine)(real_arg); (start_routine)(real_arg);
#ifdef __OpenBSD__ #ifdef __OpenBSD__
th->running = 0; thread->running = 0;
#endif #endif
if (thread->detached) if (thread->detached)
@ -741,3 +751,29 @@ static int _free_thread(void *key)
} }
#ifdef HAVE_PTHREAD_SPIN_LOCK
void thread_spin_create (spin_t *spin)
{
int x = pthread_spin_init (&spin->lock, PTHREAD_PROCESS_PRIVATE);
if (x)
abort();
}
void thread_spin_destroy (spin_t *spin)
{
pthread_spin_destroy (&spin->lock);
}
void thread_spin_lock (spin_t *spin)
{
int x = pthread_spin_lock (&spin->lock);
if (x != 0)
abort();
}
void thread_spin_unlock (spin_t *spin)
{
pthread_spin_unlock (&spin->lock);
}
#endif

View File

@ -99,8 +99,27 @@ typedef struct {
pthread_rwlock_t sys_rwlock; pthread_rwlock_t sys_rwlock;
} rwlock_t; } rwlock_t;
#ifdef HAVE_PTHREAD_SPIN_LOCK
typedef struct
{
pthread_spinlock_t lock;
} spin_t;
void thread_spin_create (spin_t *spin);
void thread_spin_destroy (spin_t *spin);
void thread_spin_lock (spin_t *spin);
void thread_spin_unlock (spin_t *spin);
#else
typedef mutex_t spin_t;
#define thread_spin_create(x) thread_mutex_create(x)
#define thread_spin_destroy(x) thread_mutex_destroy(x)
#define thread_spin_lock(x) thread_mutex_lock(x)
#define thread_spin_unlock(x) thread_mutex_unlock(x)
#endif
#define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__) #define thread_create(n,x,y,z) thread_create_c(n,x,y,z,__LINE__,__FILE__)
#define thread_mutex_create(name,x) thread_mutex_create_c(name,x,__LINE__,__FILE__) #define thread_mutex_create(x) thread_mutex_create_c(x,__LINE__,__FILE__)
#define thread_mutex_lock(x) thread_mutex_lock_c(x,__LINE__,__FILE__) #define thread_mutex_lock(x) thread_mutex_lock_c(x,__LINE__,__FILE__)
#define thread_mutex_unlock(x) thread_mutex_unlock_c(x,__LINE__,__FILE__) #define thread_mutex_unlock(x) thread_mutex_unlock_c(x,__LINE__,__FILE__)
#define thread_cond_create(x) thread_cond_create_c(x,__LINE__,__FILE__) #define thread_cond_create(x) thread_cond_create_c(x,__LINE__,__FILE__)
@ -157,7 +176,7 @@ void thread_shutdown(void);
/* creation, destruction, locking, unlocking, signalling and waiting */ /* creation, destruction, locking, unlocking, signalling and waiting */
thread_type *thread_create_c(char *name, void *(*start_routine)(void *), thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
void *arg, int detached, int line, char *file); void *arg, int detached, int line, char *file);
void thread_mutex_create_c(const char *name, mutex_t *mutex, int line, const char *file); void thread_mutex_create_c(mutex_t *mutex, int line, const char *file);
void thread_mutex_lock_c(mutex_t *mutex, int line, char *file); void thread_mutex_lock_c(mutex_t *mutex, int line, char *file);
void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file); void thread_mutex_unlock_c(mutex_t *mutex, int line, char *file);
void thread_mutex_destroy(mutex_t *mutex); void thread_mutex_destroy(mutex_t *mutex);