diff options
author | Pablo Neira Ayuso <pablo@gnumonks.org> | 2011-06-09 15:04:30 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@gnumonks.org> | 2011-06-13 19:15:59 +0200 |
commit | 0849c9af2a5637da5ce24118e2f4b9ab9da9c6d9 (patch) | |
tree | be1811304975dcd416bba82217e4dbf3e9456957 | |
parent | 139e12782c5cbbcb31ac89a1c59d8d5b4215ebf5 (diff) |
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.
-rw-r--r-- | include/osmocom/core/socket.h | 11 | ||||
-rw-r--r-- | src/gsmtap_util.c | 6 | ||||
-rw-r--r-- | src/socket.c | 38 |
3 files changed, 40 insertions, 15 deletions
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h index b2601c76..612b12c8 100644 --- a/include/osmocom/core/socket.h +++ b/include/osmocom/core/socket.h @@ -5,14 +5,19 @@ 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, - 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, - 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, - uint8_t proto, int connect0_bind1); + uint8_t proto, unsigned int flags); /* determine if the given address is a local address */ int osmo_sockaddr_is_local(struct sockaddr *addr, unsigned int addrlen); diff --git a/src/gsmtap_util.c b/src/gsmtap_util.c index 95458657..c8c26c62 100644 --- a/src/gsmtap_util.c +++ b/src/gsmtap_util.c @@ -124,7 +124,8 @@ int gsmtap_source_init_fd(const char *host, uint16_t port) if (host == NULL) 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) @@ -138,7 +139,8 @@ int gsmtap_source_add_sink_fd(int gsmtap_fd) return rc; 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) return rc; } diff --git a/src/socket.c b/src/socket.c index 0be98b93..f1fcccd5 100644 --- a/src/socket.c +++ b/src/socket.c @@ -6,6 +6,7 @@ #include <osmocom/core/select.h> #include <osmocom/core/socket.h> +#include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> @@ -18,12 +19,16 @@ #include <ifaddrs.h> 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; int sfd, rc, on = 1; 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); memset(&hints, 0, sizeof(struct addrinfo)); 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_protocol = proto; - if (connect0_bind1) + if (flags & OSMO_SOCK_F_BIND) hints.ai_flags |= AI_PASSIVE; 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); if (sfd == -1) continue; - if (connect0_bind1 == 0) { - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + if (flags & OSMO_SOCK_F_NONBLOCK) { + 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; } 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) 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)); /* Make sure to call 'listen' on a bound, connection-oriented sock */ - if (connect0_bind1 == 1) { + if (flags & OSMO_SOCK_F_BIND) { switch (type) { case SOCK_STREAM: 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, - const char *host, uint16_t port, int connect0_bind1) + const char *host, uint16_t port, unsigned int flags) { 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) 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, - uint8_t proto, int connect0_bind1) + uint8_t proto, unsigned int flags) { char host[NI_MAXHOST]; uint16_t port; @@ -127,8 +146,7 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type, return s; } - return osmo_sock_init(ss->sa_family, type, proto, host, - port, connect0_bind1); + return osmo_sock_init(ss->sa_family, type, proto, host, port, flags); } static int sockaddr_equal(const struct sockaddr *a, |