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:
parent
733c048a42
commit
02c6f8ccc5
226
src/net/resolver.c
Normal file
226
src/net/resolver.c
Normal 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
|
||||
}
|
||||
}
|
||||
|
304
src/net/sock.c
304
src/net/sock.c
@ -30,6 +30,9 @@
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_POLL
|
||||
#include <poll.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
@ -44,20 +47,23 @@
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#define vsnprintf _vsnprintf
|
||||
#define EINPROGRESS WSAEINPROGRESS
|
||||
#define ENOTSOCK WSAENOTSOCK
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EALREADY WSAEALREADY
|
||||
#define socklen_t int
|
||||
#ifndef __MINGW32__
|
||||
#define va_copy(ap1, ap2) memcpy(&ap1, &ap2, sizeof(va_list))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "sock.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
|
||||
**
|
||||
** initializes the socket library. you must call this
|
||||
@ -196,6 +202,21 @@ int sock_valid_socket(sock_t sock)
|
||||
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
|
||||
**
|
||||
** 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 */
|
||||
|
||||
/* sock_set_blocking
|
||||
**
|
||||
** set the sock blocking or nonblocking
|
||||
** SOCK_BLOCK for blocking
|
||||
** SOCK_NONBLOCK for nonblocking
|
||||
*/
|
||||
int sock_set_blocking(sock_t sock, const int block)
|
||||
*
|
||||
* set the sock blocking or nonblocking
|
||||
* 1 for blocking
|
||||
* 0 for nonblocking
|
||||
*/
|
||||
int sock_set_blocking(sock_t sock, int block)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef __MINGW32__
|
||||
u_long varblock = block;
|
||||
#else
|
||||
int varblock = block;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((!sock_valid_socket(sock)) || (block < 0) || (block > 1))
|
||||
if ((block < 0) || (block > 1))
|
||||
return SOCK_ERROR;
|
||||
|
||||
#ifdef _WIN32
|
||||
return ioctlsocket(sock, FIONBIO, &varblock);
|
||||
else
|
||||
{
|
||||
long nonblock = 0;
|
||||
if (block == 0)
|
||||
nonblock = 1;
|
||||
return ioctlsocket(sock, FIONBIO, &nonblock);
|
||||
}
|
||||
#else
|
||||
return fcntl(sock, F_SETFL, (block == SOCK_BLOCK) ? 0 : O_NONBLOCK);
|
||||
return fcntl(sock, F_SETFL, (block) ? 0 : O_NONBLOCK);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -256,6 +275,14 @@ int sock_set_nodelay(sock_t sock)
|
||||
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 keepalive = 1;
|
||||
@ -282,14 +309,14 @@ int sock_close(sock_t sock)
|
||||
*/
|
||||
#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);
|
||||
}
|
||||
|
||||
#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;
|
||||
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
|
||||
** 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 */
|
||||
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 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;
|
||||
int val = SOCK_ERROR;
|
||||
@ -546,10 +593,16 @@ int sock_connected (int sock, int timeout)
|
||||
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
|
||||
|
||||
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;
|
||||
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))
|
||||
> -1)
|
||||
{
|
||||
sock_set_blocking (sock, SOCK_NONBLOCK);
|
||||
sock_set_blocking (sock, 0);
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
|
||||
!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
|
||||
* 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;
|
||||
struct addrinfo *ai, *head, hints;
|
||||
sock_t sock = SOCK_ERROR;
|
||||
struct addrinfo *ai, *head, *b_head=NULL, hints;
|
||||
char service[8];
|
||||
|
||||
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 (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)
|
||||
break;
|
||||
@ -627,7 +696,7 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
|
||||
if (connected == 1) /* connected */
|
||||
{
|
||||
if (timeout >= 0)
|
||||
sock_set_blocking(sock, SOCK_BLOCK);
|
||||
sock_set_blocking(sock, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -639,15 +708,67 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
|
||||
}
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
if (head)
|
||||
freeaddrinfo (head);
|
||||
if (b_head)
|
||||
freeaddrinfo (b_head);
|
||||
freeaddrinfo (head);
|
||||
|
||||
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
|
||||
|
||||
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;
|
||||
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));
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
server.sin_port = htons((short)port);
|
||||
|
||||
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);
|
||||
if (sock == -1)
|
||||
return -1;
|
||||
if (sock == SOCK_ERROR)
|
||||
return SOCK_ERROR;
|
||||
|
||||
sock_set_blocking (sock, SOCK_NONBLOCK);
|
||||
sock_set_blocking (sock, 0);
|
||||
sock_try_connection (sock, hostname, port);
|
||||
|
||||
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);
|
||||
if (sock == -1)
|
||||
return -1;
|
||||
if (sock == SOCK_ERROR)
|
||||
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)
|
||||
{
|
||||
sock_set_blocking (sock, SOCK_NONBLOCK);
|
||||
sock_set_blocking (sock, 0);
|
||||
if (sock_try_connection (sock, hostname, port) < 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
sock_set_blocking(sock, SOCK_BLOCK);
|
||||
sock_set_blocking(sock, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -724,7 +860,6 @@ sock_t sock_connect_wto(const char *hostname, const int port, const int timeout)
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* 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.
|
||||
** 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;
|
||||
#endif
|
||||
int family, len, error, opt;
|
||||
int error, opt;
|
||||
sock_t sock;
|
||||
char ip[MAX_ADDR_LEN];
|
||||
|
||||
@ -749,58 +880,48 @@ sock_t sock_get_server_socket(const int port, char *sinterface)
|
||||
|
||||
/* defaults */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
family = AF_INET;
|
||||
len = sizeof(struct sockaddr_in);
|
||||
|
||||
/* set the interface to bind to if specified */
|
||||
if (sinterface != NULL) {
|
||||
if (!resolver_getip(sinterface, ip, sizeof (ip)))
|
||||
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)) {
|
||||
return SOCK_ERROR;
|
||||
} else {
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(port);
|
||||
sa.sin_port = htons((short)port);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
((struct sockaddr_in*)&sa)->sin_addr.s_addr = INADDR_ANY;
|
||||
((struct sockaddr_in*)&sa)->sin_family = AF_INET;
|
||||
((struct sockaddr_in*)&sa)->sin_port = htons(port);
|
||||
sa.sin_addr.s_addr = INADDR_ANY;
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons((short)port);
|
||||
}
|
||||
|
||||
/* get a socket */
|
||||
sock = socket(family, SOCK_STREAM, 0);
|
||||
sock = socket (AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
return SOCK_ERROR;
|
||||
|
||||
/* reuse it if we can */
|
||||
opt = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(int));
|
||||
|
||||
|
||||
/* bind socket to port */
|
||||
error = bind(sock, (struct sockaddr *)&sa, len);
|
||||
error = bind(sock, (struct sockaddr *)&sa, sizeof (struct sockaddr_in));
|
||||
if (error == -1)
|
||||
return SOCK_ERROR;
|
||||
|
||||
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)
|
||||
{
|
||||
if (!sock_valid_socket(serversock))
|
||||
@ -812,34 +933,27 @@ int sock_listen(sock_t serversock, int backlog)
|
||||
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;
|
||||
#else
|
||||
struct sockaddr_in sa;
|
||||
#endif
|
||||
int ret;
|
||||
sock_t ret;
|
||||
socklen_t slen;
|
||||
|
||||
if (!sock_valid_socket(serversock))
|
||||
if (ip == NULL || len == 0 || !sock_valid_socket(serversock))
|
||||
return SOCK_ERROR;
|
||||
|
||||
slen = sizeof(sa);
|
||||
ret = accept(serversock, (struct sockaddr *)&sa, &slen);
|
||||
|
||||
if (ret >= 0 && ip != NULL) {
|
||||
#ifdef HAVE_INET_PTON
|
||||
if(((struct sockaddr_in *)&sa)->sin_family == AF_INET)
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr,
|
||||
ip, len);
|
||||
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;
|
||||
}
|
||||
if (ret != SOCK_ERROR)
|
||||
{
|
||||
#ifdef HAVE_GETNAMEINFO
|
||||
if (getnameinfo ((struct sockaddr *)&sa, slen, ip, len, NULL, 0, NI_NUMERICHOST))
|
||||
snprintf (ip, len, "unknown");
|
||||
#else
|
||||
/* inet_ntoa is not reentrant, we should protect this */
|
||||
strncpy(ip, inet_ntoa(sa.sin_addr), len);
|
||||
|
@ -30,8 +30,8 @@
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#elif _WIN32
|
||||
#include <os.h>
|
||||
#elif _WIN32
|
||||
#include <compat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
@ -56,16 +56,15 @@ struct iovec
|
||||
#define MAX_ADDR_LEN 46
|
||||
#endif
|
||||
|
||||
typedef int sock_t;
|
||||
#ifndef sock_t
|
||||
#define sock_t int
|
||||
#endif
|
||||
|
||||
/* The following values are based on unix avoiding errno value clashes */
|
||||
#define SOCK_SUCCESS 0
|
||||
#define SOCK_ERROR -1
|
||||
#define SOCK_ERROR (sock_t)-1
|
||||
#define SOCK_TIMEOUT -2
|
||||
|
||||
#define SOCK_BLOCK 0
|
||||
#define SOCK_NONBLOCK 1
|
||||
|
||||
/* sock connect macro */
|
||||
#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_nolinger _mangle(sock_set_nolinger)
|
||||
# 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_close _mangle(sock_close)
|
||||
# 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_connected _mangle(sock_connected)
|
||||
# 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_get_server_socket _mangle(sock_get_server_socket)
|
||||
# define sock_listen _mangle(sock_listen)
|
||||
# define sock_set_send_buffer _mangle(sock_set_send_buffer)
|
||||
# define sock_accept _mangle(sock_accept)
|
||||
#endif
|
||||
|
||||
@ -106,24 +108,28 @@ int sock_error(void);
|
||||
int sock_recoverable(int error);
|
||||
int sock_stalled(int error);
|
||||
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_keepalive(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);
|
||||
int sock_close(sock_t sock);
|
||||
|
||||
/* Connection related socket functions */
|
||||
sock_t sock_connect_wto(const char *hostname, int port, int timeout);
|
||||
int sock_connect_non_blocking(const char *host, const unsigned port);
|
||||
int sock_connected(int sock, int timeout);
|
||||
sock_t sock_connect_wto_bind(const char *hostname, int port, const char *bnd, int timeout);
|
||||
sock_t sock_connect_non_blocking(const char *host, unsigned port);
|
||||
int sock_connected(sock_t sock, int timeout);
|
||||
|
||||
/* 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_fmt(sock_t sock, const char *fmt, va_list ap);
|
||||
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 */
|
||||
@ -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);
|
||||
|
||||
/* 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_accept(sock_t serversock, char *ip, int len);
|
||||
sock_t sock_accept(sock_t serversock, char *ip, size_t len);
|
||||
|
||||
#ifdef _WIN32
|
||||
int inet_aton(const char *s, struct in_addr *a);
|
||||
|
@ -165,8 +165,8 @@ void thread_initialize(void)
|
||||
log_set_level(_logid, 4);
|
||||
#endif
|
||||
|
||||
thread_mutex_create("threadtree", &_threadtree_mutex);
|
||||
thread_mutex_create("thread lib", &_library_mutex);
|
||||
thread_mutex_create(&_threadtree_mutex);
|
||||
thread_mutex_create(&_library_mutex);
|
||||
|
||||
/* initialize the thread tree and insert the main thread */
|
||||
|
||||
@ -199,6 +199,7 @@ void thread_shutdown(void)
|
||||
avl_tree_free(_mutextree, _free_mutex);
|
||||
#endif
|
||||
avl_tree_free(_threadtree, _free_thread);
|
||||
_threadtree = NULL;
|
||||
}
|
||||
|
||||
#ifdef THREAD_DEBUG
|
||||
@ -339,12 +340,13 @@ static void _mutex_create(mutex_t *mutex)
|
||||
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);
|
||||
|
||||
#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->mutex_id = _next_mutex_id++;
|
||||
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->file = strdup (file);
|
||||
mutex->line = line;
|
||||
LOG_DEBUG3("Lock on %s acquired at %s:%d", mutex->name, file, line);
|
||||
#endif /* THREAD_DEBUG */
|
||||
}
|
||||
|
||||
@ -446,6 +449,7 @@ void thread_rwlock_destroy(rwlock_t *rwlock)
|
||||
#ifdef THREAD_DEBUG
|
||||
LOG_DEBUG1 ("rwlock %s destroyed", rwlock->name);
|
||||
free (rwlock->name);
|
||||
rwlock->name = NULL;
|
||||
#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);
|
||||
#endif
|
||||
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)
|
||||
@ -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);
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
pthread_rwlock_unlock(&rwlock->sys_rwlock);
|
||||
#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
|
||||
}
|
||||
|
||||
@ -576,7 +586,7 @@ static void *_start_routine(void *arg)
|
||||
(start_routine)(real_arg);
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
th->running = 0;
|
||||
thread->running = 0;
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
|
@ -99,8 +99,27 @@ typedef struct {
|
||||
pthread_rwlock_t sys_rwlock;
|
||||
} 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_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_unlock(x) thread_mutex_unlock_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 */
|
||||
thread_type *thread_create_c(char *name, void *(*start_routine)(void *),
|
||||
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_unlock_c(mutex_t *mutex, int line, char *file);
|
||||
void thread_mutex_destroy(mutex_t *mutex);
|
||||
|
Loading…
Reference in New Issue
Block a user