mirror of https://gerrit.osmocom.org/libosmocore
socket: add OSMO_SOCK_F_[CONNECT|BIND|NON_BLOCK] flags
This extends the socket infrastructure in libosmocore to allow to create non-blocking sockets. Basically, it replaces the connect0_bind1 parameter by one flags parameter.
This commit is contained in:
parent
139e12782c
commit
0849c9af2a
|
@ -5,14 +5,19 @@
|
||||||
|
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
|
|
||||||
|
/* flags for osmo_sock_init. */
|
||||||
|
#define OSMO_SOCK_F_CONNECT (1 << 0)
|
||||||
|
#define OSMO_SOCK_F_BIND (1 << 1)
|
||||||
|
#define OSMO_SOCK_F_NONBLOCK (1 << 2)
|
||||||
|
|
||||||
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
const char *host, uint16_t port, int connect0_bind1);
|
const char *host, uint16_t port, unsigned int flags);
|
||||||
|
|
||||||
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
||||||
const char *host, uint16_t port, int connect0_bind1);
|
const char *host, uint16_t port, unsigned int flags);
|
||||||
|
|
||||||
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
||||||
uint8_t proto, int connect0_bind1);
|
uint8_t proto, unsigned int flags);
|
||||||
|
|
||||||
/* determine if the given address is a local address */
|
/* determine if the given address is a local address */
|
||||||
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
|
int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen);
|
||||||
|
|
|
@ -124,7 +124,8 @@ int gsmtap_source_init_fd(const char *host, uint16_t port)
|
||||||
if (host == NULL)
|
if (host == NULL)
|
||||||
host = "localhost";
|
host = "localhost";
|
||||||
|
|
||||||
return osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host, port, 0);
|
return osmo_sock_init(AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, host, port,
|
||||||
|
OSMO_SOCK_F_CONNECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gsmtap_source_add_sink_fd(int gsmtap_fd)
|
int gsmtap_source_add_sink_fd(int gsmtap_fd)
|
||||||
|
@ -138,7 +139,8 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (osmo_sockaddr_is_local((struct sockaddr *)&ss, ss_len) == 1) {
|
if (osmo_sockaddr_is_local((struct sockaddr *)&ss, ss_len) == 1) {
|
||||||
rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM, IPPROTO_UDP, 1);
|
rc = osmo_sock_init_sa((struct sockaddr *)&ss, SOCK_DGRAM,
|
||||||
|
IPPROTO_UDP, OSMO_SOCK_F_BIND);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
38
src/socket.c
38
src/socket.c
|
@ -6,6 +6,7 @@
|
||||||
#include <osmocom/core/select.h>
|
#include <osmocom/core/select.h>
|
||||||
#include <osmocom/core/socket.h>
|
#include <osmocom/core/socket.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
@ -18,12 +19,16 @@
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
||||||
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
const char *host, uint16_t port, int connect0_bind1)
|
const char *host, uint16_t port, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *result, *rp;
|
struct addrinfo hints, *result, *rp;
|
||||||
int sfd, rc, on = 1;
|
int sfd, rc, on = 1;
|
||||||
char portbuf[16];
|
char portbuf[16];
|
||||||
|
|
||||||
|
if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) ==
|
||||||
|
(OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
sprintf(portbuf, "%u", port);
|
sprintf(portbuf, "%u", port);
|
||||||
memset(&hints, 0, sizeof(struct addrinfo));
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
hints.ai_family = family;
|
hints.ai_family = family;
|
||||||
|
@ -31,7 +36,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
hints.ai_flags = 0;
|
hints.ai_flags = 0;
|
||||||
hints.ai_protocol = proto;
|
hints.ai_protocol = proto;
|
||||||
|
|
||||||
if (connect0_bind1)
|
if (flags & OSMO_SOCK_F_BIND)
|
||||||
hints.ai_flags |= AI_PASSIVE;
|
hints.ai_flags |= AI_PASSIVE;
|
||||||
|
|
||||||
rc = getaddrinfo(host, portbuf, &hints, &result);
|
rc = getaddrinfo(host, portbuf, &hints, &result);
|
||||||
|
@ -44,10 +49,24 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
if (sfd == -1)
|
if (sfd == -1)
|
||||||
continue;
|
continue;
|
||||||
if (connect0_bind1 == 0) {
|
if (flags & OSMO_SOCK_F_NONBLOCK) {
|
||||||
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
if (ioctl(sfd, FIONBIO, (unsigned char *)&on) < 0) {
|
||||||
|
perror("cannot set this socket unblocking");
|
||||||
|
close(sfd);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags & OSMO_SOCK_F_CONNECT) {
|
||||||
|
rc = connect(sfd, rp->ai_addr, rp->ai_addrlen);
|
||||||
|
if (rc != -1 || (rc == -1 && errno == EINPROGRESS))
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
&on, sizeof(on));
|
||||||
|
if (rc < 0) {
|
||||||
|
perror("cannot setsockopt socket");
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +82,7 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||||
|
|
||||||
/* Make sure to call 'listen' on a bound, connection-oriented sock */
|
/* Make sure to call 'listen' on a bound, connection-oriented sock */
|
||||||
if (connect0_bind1 == 1) {
|
if (flags & OSMO_SOCK_F_BIND) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SOCK_STREAM:
|
case SOCK_STREAM:
|
||||||
case SOCK_SEQPACKET:
|
case SOCK_SEQPACKET:
|
||||||
|
@ -75,11 +94,11 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto,
|
||||||
}
|
}
|
||||||
|
|
||||||
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
||||||
const char *host, uint16_t port, int connect0_bind1)
|
const char *host, uint16_t port, unsigned int flags)
|
||||||
{
|
{
|
||||||
int sfd, rc;
|
int sfd, rc;
|
||||||
|
|
||||||
sfd = osmo_sock_init(family, type, proto, host, port, connect0_bind1);
|
sfd = osmo_sock_init(family, type, proto, host, port, flags);
|
||||||
if (sfd < 0)
|
if (sfd < 0)
|
||||||
return sfd;
|
return sfd;
|
||||||
|
|
||||||
|
@ -96,7 +115,7 @@ int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto,
|
||||||
}
|
}
|
||||||
|
|
||||||
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
||||||
uint8_t proto, int connect0_bind1)
|
uint8_t proto, unsigned int flags)
|
||||||
{
|
{
|
||||||
char host[NI_MAXHOST];
|
char host[NI_MAXHOST];
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
|
@ -127,8 +146,7 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type,
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return osmo_sock_init(ss->sa_family, type, proto, host,
|
return osmo_sock_init(ss->sa_family, type, proto, host, port, flags);
|
||||||
port, connect0_bind1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sockaddr_equal(const struct sockaddr *a,
|
static int sockaddr_equal(const struct sockaddr *a,
|
||||||
|
|
Loading…
Reference in New Issue