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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
300
src/net/sock.c
300
src/net/sock.c
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user