<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/24435">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">socket: add function to wait until a socket becomes writeable<br><br>In cases where a socket is created using the option OSMO_SOCK_F_NONBLOCK<br>it is not possible to detect a connection error because<br>osmo_sock_init() will return early while the connection is still in<br>progress.<br><br>One way to make sure that the socket is connected is to use select to<br>wait until the socket becomes writeable and to use getsockopt to check<br>SO_ERROR.<br><br>The function osmo_sock_wait() waits until the socket becomes writeable.<br>From the error code the API user can determine whether the connection<br>was successful or not.<br><br>Change-Id: I1c68185120fa2a6c9b6cb8aa2a25232a44ff5508<br>Related: SYS#4971<br>---<br>M include/osmocom/core/socket.h<br>M src/socket.c<br>2 files changed, 53 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/35/24435/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h</span><br><span>index a053391..ce6ee3c 100644</span><br><span>--- a/include/osmocom/core/socket.h</span><br><span>+++ b/include/osmocom/core/socket.h</span><br><span>@@ -113,7 +113,6 @@</span><br><span> int osmo_sock_get_remote_ip(int fd, char *host, size_t len);</span><br><span> int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> int osmo_sock_mcast_loop_set(int fd, bool enable);</span><br><span> int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl);</span><br><span> int osmo_sock_mcast_all_set(int fd, bool enable);</span><br><span>@@ -134,5 +133,7 @@</span><br><span> int osmo_sock_set_dscp(int fd, uint8_t dscp);</span><br><span> int osmo_sock_set_priority(int fd, int prio);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_wait(int fd, time_t timeout_sec, suseconds_t timeout_usec);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* (!EMBEDDED) */</span><br><span> /*! @} */</span><br><span>diff --git a/src/socket.c b/src/socket.c</span><br><span>index 34972b8..810e39c 100644</span><br><span>--- a/src/socket.c</span><br><span>+++ b/src/socket.c</span><br><span>@@ -1868,6 +1868,57 @@</span><br><span>  return setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Wait until a socket becomes writeable.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] fd file descriptor of related scoket.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] timeout_sec timeout seconds.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] timeout_usec timeout microseconds.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 on success; negative otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  The function returns 0 when the socket becomes writeable and no errors are</span><br><span style="color: hsl(120, 100%, 40%);">+ *  detected. The return code is -EIO if one of the syscalls (select,</span><br><span style="color: hsl(120, 100%, 40%);">+ *  getsockopt) fails, -EINPROGRESS if the (select) timout expires while waiting</span><br><span style="color: hsl(120, 100%, 40%);">+ *  for the socket to become writeable. If the error is socket specific then the</span><br><span style="color: hsl(120, 100%, 40%);">+ *  SO_ERROR related return values from errno.h will be used. */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_sock_wait(int fd, time_t timeout_sec, suseconds_t timeout_usec)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int so_error;</span><br><span style="color: hsl(120, 100%, 40%);">+ socklen_t so_error_len = sizeof(so_error);</span><br><span style="color: hsl(120, 100%, 40%);">+    fd_set write_fds;</span><br><span style="color: hsl(120, 100%, 40%);">+     fd_set except_fds;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct timeval timeout;</span><br><span style="color: hsl(120, 100%, 40%);">+       int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     timeout.tv_sec = timeout_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout.tv_usec = timeout_usec;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* We monitor the given file descriptor for writeability and</span><br><span style="color: hsl(120, 100%, 40%);">+   * exceptional conditions. */</span><br><span style="color: hsl(120, 100%, 40%);">+ FD_ZERO(&write_fds);</span><br><span style="color: hsl(120, 100%, 40%);">+      FD_ZERO(&except_fds);</span><br><span style="color: hsl(120, 100%, 40%);">+     FD_SET(fd, &write_fds);</span><br><span style="color: hsl(120, 100%, 40%);">+   FD_SET(fd, &except_fds);</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = select(fd + 1, NULL, &write_fds, &except_fds, &timeout);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* The socket did not become writeable, nor did it exhibit any</span><br><span style="color: hsl(120, 100%, 40%);">+         * exeptional behaviour (select timeout). */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (rc == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+          return -EINPROGRESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (FD_ISSET(fd, &write_fds) || FD_ISSET(fd, &except_fds)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, &so_error,</span><br><span style="color: hsl(120, 100%, 40%);">+                              &so_error_len);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (rc < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+                        return -EIO;</span><br><span style="color: hsl(120, 100%, 40%);">+          return so_error;        /* 0 if no error occured */</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Should not be reached as either select will return 0 on timeout</span><br><span style="color: hsl(120, 100%, 40%);">+     * or at least one of the fd sets will contain fd. */</span><br><span style="color: hsl(120, 100%, 40%);">+ return -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* HAVE_SYS_SOCKET_H */</span><br><span> </span><br><span> /*! @} */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/24435">change 24435</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/24435"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I1c68185120fa2a6c9b6cb8aa2a25232a44ff5508 </div>
<div style="display:none"> Gerrit-Change-Number: 24435 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>