+ assert(rpc->magic == RPC_CONTEXT_MAGIC);
+
+ switch (s->ss_family) {
+ case AF_INET:
+ socksize = sizeof(struct sockaddr_in);
+ rpc->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+#ifdef HAVE_NETINET_TCP_H
+ if (rpc->tcp_syncnt != RPC_PARAM_UNDEFINED) {
+ set_tcp_sockopt(rpc->fd, TCP_SYNCNT, rpc->tcp_syncnt);
+ }
+#endif
+ break;
+ default:
+ rpc_set_error(rpc, "Can not handle AF_FAMILY:%d", s->ss_family);
+ return -1;
+ }
+
+ if (rpc->fd == -1) {
+ rpc_set_error(rpc, "Failed to open socket");
+ return -1;
+ }
+
+ /* Some systems allow you to set capabilities on an executable
+ * to allow the file to be executed with privilege to bind to
+ * privileged system ports, even if the user is not root.
+ *
+ * Opportunistically try to bind the socket to a low numbered
+ * system port in the hope that the user is either root or the
+ * executable has the CAP_NET_BIND_SERVICE.
+ *
+ * As soon as we fail the bind() with EACCES we know we will never
+ * be able to bind to a system port so we terminate the loop.
+ *
+ * On linux, use
+ * sudo setcap 'cap_net_bind_service=+ep' /path/executable
+ * to make the executable able to bind to a system port.
+ *
+ * On Windows, there is no concept of privileged ports. Thus
+ * binding will usually succeed.
+ */
+ {
+ struct sockaddr_in sin;
+ static int portOfs = 0;
+ const int firstPort = 512; /* >= 512 according to Sun docs */
+ const int portCount = IPPORT_RESERVED - firstPort;
+ int startOfs, port, rc;
+
+ if (portOfs == 0) {
+ portOfs = time(NULL) % 400;
+ }
+ startOfs = portOfs;
+ do {
+ rc = -1;
+ port = htons(firstPort + portOfs);
+ portOfs = (portOfs + 1) % portCount;
+
+ /* skip well-known ports */
+ if (!getservbyport(port, "tcp")) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_port = port;
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = 0;
+
+ rc = bind(rpc->fd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in));
+#if !defined(WIN32)
+ /* we got EACCES, so don't try again */
+ if (rc != 0 && errno == EACCES)
+ break;
+#endif
+ }
+ } while (rc != 0 && portOfs != startOfs);
+ }
+
+ set_nonblocking(rpc->fd);
+
+ if (connect(rpc->fd, (struct sockaddr *)s, socksize) != 0 && errno != EINPROGRESS) {
+ rpc_set_error(rpc, "connect() to server failed. %s(%d)", strerror(errno), errno);
+ return -1;
+ }
+
+ return 0;
+}
+
+int rpc_connect_async(struct rpc_context *rpc, const char *server, int port, rpc_cb cb, void *private_data)
+{
+ struct sockaddr_in *sin = (struct sockaddr_in *)&rpc->s;
+
+ assert(rpc->magic == RPC_CONTEXT_MAGIC);
+