mirror of
https://gitlab.xiph.org/xiph/icecast-server.git
synced 2024-11-03 04:17:17 -05:00
update to server side socket creation. Where IPv6-aware functions are available,
use them to create dual IPv4/6 capable sockets. svn path=/icecast/trunk/net/; revision=13491
This commit is contained in:
parent
e663a238ee
commit
916a4a4cd1
115
src/net/sock.c
115
src/net/sock.c
@ -58,6 +58,11 @@
|
|||||||
#include "sock.h"
|
#include "sock.h"
|
||||||
#include "resolver.h"
|
#include "resolver.h"
|
||||||
|
|
||||||
|
/* for older C libraries */
|
||||||
|
#ifndef AI_NUMERICSERV
|
||||||
|
#define AI_NUMERICSERV 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* sock_initialize
|
/* sock_initialize
|
||||||
**
|
**
|
||||||
** initializes the socket library. you must call this
|
** initializes the socket library. you must call this
|
||||||
@ -621,8 +626,55 @@ sock_t sock_connect_wto(const char *hostname, int port, int timeout)
|
|||||||
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));
|
||||||
|
|
||||||
|
if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0)
|
||||||
|
{
|
||||||
|
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 (int sock, const char *hostname, const unsigned port)
|
||||||
{
|
{
|
||||||
struct sockaddr_in sin, server;
|
struct sockaddr_in sin, server;
|
||||||
@ -700,7 +752,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
|
||||||
@ -709,14 +760,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];
|
||||||
|
|
||||||
@ -725,58 +772,43 @@ 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(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(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;
|
||||||
|
|
||||||
/* reuse it if we can */
|
/* reuse it if we can */
|
||||||
opt = 1;
|
opt = 1;
|
||||||
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
|
||||||
|
|
||||||
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))
|
||||||
@ -788,9 +820,9 @@ 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)
|
int 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;
|
||||||
@ -798,24 +830,17 @@ int sock_accept(sock_t serversock, char *ip, int len)
|
|||||||
int ret;
|
int 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 >= 0)
|
||||||
#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);
|
||||||
|
@ -129,9 +129,9 @@ int sock_read_bytes(sock_t sock, char *buff, const int len);
|
|||||||
int sock_read_line(sock_t sock, char *string, const int len);
|
int sock_read_line(sock_t sock, char *string, const int len);
|
||||||
|
|
||||||
/* 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);
|
int 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);
|
||||||
|
Loading…
Reference in New Issue
Block a user