aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2011-06-09 15:04:30 +0200
committerPablo Neira Ayuso <pablo@gnumonks.org>2011-06-13 19:15:59 +0200
commit0849c9af2a5637da5ce24118e2f4b9ab9da9c6d9 (patch)
treebe1811304975dcd416bba82217e4dbf3e9456957
parent139e12782c5cbbcb31ac89a1c59d8d5b4215ebf5 (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.h11
-rw-r--r--src/gsmtap_util.c6
-rw-r--r--src/socket.c38
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,