]> jfr.im git - irc/gameservirc.git/blobdiff - gameserv/sockhelp.cpp
updated the Change log w/ new additions
[irc/gameservirc.git] / gameserv / sockhelp.cpp
index a5af1e3564ee5744db41a0cc605d027051725d32..e6e25d270702c5579af3e4b1ecef4f2693e588fb 100644 (file)
@@ -146,7 +146,119 @@ int get_connection(int socket_type, u_short port, int *listener)
   else
     return listening_socket;
 }
+#if !HAVE_GETHOSTBYNAME
 
+/* Translate an IP dotted-quad address to a 4-byte character string.
+ * Return NULL if the given string is not in dotted-quad format.
+ */
+
+static char *pack_ip(const char *ipaddr)
+{
+  static char ipbuf[4];
+  int tmp[4], i;
+
+  if (sscanf(ipaddr, "%d.%d.%d.%d", &tmp[0], &tmp[1], &tmp[2], &tmp[3])
+      != 4)
+    return NULL;
+  for (i = 0; i < 4; i++) {
+    if (tmp[i] < 0 || tmp[i] > 255)
+      return NULL;
+    ipbuf[i] = tmp[i];
+  }
+  return ipbuf;
+}
+
+#endif
+
+/*************************************************************************/
+
+/*************************************************************************/
+
+/* lhost/lport specify the local side of the connection.  If they are not
+ * given (lhost==NULL, lport==0), then they are left free to vary.
+ */
+
+int conn(const char *host, int port, const char *lhost, int lport)
+{
+#if HAVE_GETHOSTBYNAME
+  struct hostent *hp;
+#else
+  char *addr;
+#endif
+  struct sockaddr_in sa, lsa;
+  int sock;
+  
+  memset(&lsa, 0, sizeof(lsa));
+  if (lhost)
+    {
+#if HAVE_GETHOSTBYNAME
+      if ((hp = gethostbyname(lhost)) != NULL) 
+       {
+         memcpy((char *) &lsa.sin_addr, hp->h_addr, hp->h_length);
+         lsa.sin_family = hp->h_addrtype;
+#else
+         if (addr = pack_ip(lhost)) 
+           {
+             memcpy((char *) &lsa.sin_addr, addr, 4);
+             lsa.sin_family = AF_INET;
+#endif
+           }
+         else 
+           {
+             lhost = NULL;
+           }
+     }
+      if (lport)
+       {
+         lsa.sin_port = htons((unsigned short) lport);
+       }
+    
+      memset(&sa, 0, sizeof(sa));
+#if HAVE_GETHOSTBYNAME
+      if (!(hp = gethostbyname(host)))
+       {
+         return -1;
+       }
+      memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);
+      sa.sin_family = hp->h_addrtype;
+#else
+      if (!(addr = pack_ip(host))) 
+       {
+         log("conn(): `%s' is not a valid IP address", host);
+         errno = EINVAL;
+         return -1;
+       }
+      memcpy((char *) &sa.sin_addr, addr, 4);
+      sa.sin_family = AF_INET;
+#endif
+      sa.sin_port = htons((unsigned short) port);
+      
+      if ((sock = socket(sa.sin_family, SOCK_STREAM, 0)) < 0)
+       {
+         return -1;
+       }
+    
+      if ((lhost || lport)
+         && bind(sock, (struct sockaddr *) &lsa, sizeof(lsa)) < 0) 
+       {
+         int errno_save = errno;
+         close(sock);
+         errno = errno_save;
+         return -1;
+       }
+      
+      if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0) 
+       {
+         int errno_save = errno;
+         close(sock);
+         errno = errno_save;
+         return -1;
+       }
+      
+  return sock;
+}
+
+  
 /* This is a generic function to make a connection to a given server/port.
    service is the port name/number,
    type is either SOCK_STREAM or SOCK_DGRAM, and