diff dbutil.c @ 26:0969767bca0d

snapshot of stuff
author Matt Johnston <matt@ucc.asn.au>
date Mon, 26 Jul 2004 02:44:20 +0000
parents f76c9389e9e0
children b4874d772210
line wrap: on
line diff
--- a/dbutil.c	Tue Jul 20 12:06:37 2004 +0000
+++ b/dbutil.c	Mon Jul 26 02:44:20 2004 +0000
@@ -113,6 +113,95 @@
 }
 #endif /* DEBUG_TRACE */
 
+/* Connect via TCP to a host. Connection will try ipv4 or ipv6, will
+ * return immediately if nonblocking is set */
+int connect_remote(const char* remotehost, const char* remoteport,
+		int nonblocking, char ** errstring) {
+
+	struct addrinfo *res0 = NULL, *res = NULL, hints;
+	int sock;
+	int err;
+
+	TRACE(("enter connect_remote"));
+
+	if (errstring != NULL) {
+		*errstring = NULL;
+	}
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_family = PF_UNSPEC;
+
+	err = getaddrinfo(remotehost, remoteport, &hints, &res0);
+	if (err) {
+		if (errstring != NULL && *errstring == NULL) {
+			int len;
+			len = 20 + strlen(gai_strerror(err));
+			*errstring = (char*)m_malloc(len);
+			snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
+		}
+		TRACE(("Error resolving: %s", gai_strerror(err)));
+		return -1;
+	}
+
+	sock = -1;
+	err = EADDRNOTAVAIL;
+	for (res = res0; res; res = res->ai_next) {
+
+		sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (sock < 0) {
+			err = errno;
+			continue;
+		}
+
+		if (nonblocking) {
+			if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
+				close(sock);
+				sock = -1;
+				if (errstring != NULL && *errstring == NULL) {
+					*errstring = m_strdup("Failed non-blocking");
+				}
+				TRACE(("Failed non-blocking: %s", strerror(errno)));
+				continue;
+			}
+		}
+
+		if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
+			if (errno == EINPROGRESS) {
+				TRACE(("Connect in progress"));
+				break;
+			} else {
+				err = errno;
+				close(sock);
+				sock = -1;
+				continue;
+			}
+		}
+
+		break; /* Success */
+	}
+
+	if (sock < 0) {
+		/* Failed */
+		if (errstring != NULL && *errstring == NULL) {
+			int len;
+			len = 20 + strlen(strerror(err));
+			*errstring = (char*)m_malloc(len);
+			snprintf(*errstring, len, "Error connecting: %s", strerror(err));
+		}
+		TRACE(("Error connecting: %s", strerror(err)));
+	} else {
+		/* Success */
+		/* (err is used as a dummy var here) */
+		setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&err, sizeof(err));
+	}
+
+	freeaddrinfo(res0);
+
+	TRACE(("leave connect_remote: sock %d", sock));
+	return sock;
+}
+
 /* Return a string representation of the socket address passed. The return
  * value is allocated with malloc() */
 unsigned char * getaddrstring(struct sockaddr * addr) {
@@ -304,3 +393,4 @@
 		*p++ = 0x66;
 	}
 }
+