diff libfaim/aim_conn.c @ 2:68b230f8da5f

[gaim-migrate @ 11] A few more commits :) committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Thu, 23 Mar 2000 03:16:06 +0000
parents
children 6ced2f1c8b24
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaim/aim_conn.c	Thu Mar 23 03:16:06 2000 +0000
@@ -0,0 +1,195 @@
+
+/*
+ *  aim_conn.c
+ *
+ * Does all this gloriously nifty connection handling stuff...
+ *
+ */
+
+#include "aim.h"
+
+void aim_connrst(void)
+{
+  int i;
+  for (i = 0; i < AIM_CONN_MAX; i++)
+    {
+      aim_conns[i].fd = -1;
+      aim_conns[i].type = -1;
+      aim_conns[i].status = 0;
+    }
+
+}
+
+struct aim_conn_t *aim_conn_getnext(void)
+{
+  int i;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd == -1)
+      return &(aim_conns[i]);
+  return NULL;
+}
+
+void aim_conn_close(struct aim_conn_t *deadconn)
+{
+  if (deadconn->fd >= 3)
+    close(deadconn->fd);
+  deadconn->fd = -1;
+  deadconn->type = -1;
+}
+
+struct aim_conn_t *aim_getconn_type(int type)
+{
+  int i;
+  for (i=0; i<AIM_CONN_MAX; i++)
+    if (aim_conns[i].type == type)
+      return &(aim_conns[i]);
+  return NULL;
+}
+
+/*
+ * aim_newconn(type, dest)
+ *
+ * Opens a new connection to the specified dest host of type type.
+ *
+ * TODO: fix for proxies
+ * FIXME: Return errors in a more sane way.
+ *
+ */
+struct aim_conn_t *aim_newconn(int type, char *dest)
+{
+  struct aim_conn_t *connstruct;
+  int ret;
+  struct sockaddr_in sa;
+  struct hostent *hp;
+  int port = FAIM_LOGIN_PORT;
+  int i=0;
+  
+  if (!dest || ((connstruct=aim_conn_getnext())==NULL))
+    return NULL;
+
+  connstruct->type = type;
+
+  /* 
+   * As of 23 Jul 1999, AOL now sends the port number, preceded by a 
+   * colon, in the BOS redirect.  This fatally breaks all previous 
+   * libfaims.  Bad, bad AOL.
+   *
+   * We put this here to catch every case. 
+   *
+   */
+  for(i=0;(i<strlen(dest));i++)
+    if (dest[i] == ':') break; 
+  if (i<strlen(dest))
+      {
+	port = atoi(dest+i);
+	dest[i] = '\0';
+      }
+
+  hp = gethostbyname2(dest, AF_INET);
+  if (hp == NULL)
+    {
+      connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
+      return connstruct;
+    }
+
+  memset(&sa.sin_zero, 0, 8);
+  sa.sin_port = htons(port);
+  memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
+  sa.sin_family = hp->h_addrtype;
+  
+  connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
+  ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
+  if( ret < 0)
+    {
+      connstruct->fd = -1;
+      connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
+      return connstruct;
+    }
+
+  return connstruct;
+}
+
+int aim_conngetmaxfd(void)
+{
+  int i,j;
+  j=0;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if(aim_conns[i].fd > j)
+      j = aim_conns[i].fd;
+  return j;
+}
+
+int aim_countconn(void)
+{
+  int i,cnt;
+  cnt = 0;
+  for (i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd > -1)
+      cnt++;
+  return cnt;
+}
+
+/*
+ * aim_select(timeout)
+ *
+ * Waits for a socket with data or for timeout, whichever comes first.
+ * See select(2).
+ * 
+ */ 
+struct aim_conn_t *aim_select(struct timeval *timeout)
+{
+  fd_set fds;
+  fd_set errfds;
+  int i;
+
+  if (aim_countconn() <= 0)
+    return 0;
+  
+  FD_ZERO(&fds);
+  FD_ZERO(&errfds);
+  
+  for(i=0;i<AIM_CONN_MAX;i++)
+    if (aim_conns[i].fd>-1)
+      {
+	FD_SET(aim_conns[i].fd, &fds);
+	FD_SET(aim_conns[i].fd, &errfds);
+      }
+  
+  i = select(aim_conngetmaxfd()+1, &fds, NULL, &errfds, timeout);
+  if (i>=1)
+    {
+      int j;
+      for (j=0;j<AIM_CONN_MAX;j++)
+	{
+	  if ((FD_ISSET(aim_conns[j].fd, &errfds)))
+	    {
+	      /* got an exception; close whats left of it up */
+	      aim_conn_close(&(aim_conns[j]));
+	      return (struct aim_conn_t *)-1;
+	    }
+	  else if ((FD_ISSET(aim_conns[j].fd, &fds)))
+	    return &(aim_conns[j]);  /* return the first waiting struct */
+	}
+      /* should never get here */
+    }
+  else
+    return (struct aim_conn_t *)i;  /* no waiting or error, return -- FIXME: return type funnies */
+  return NULL; /* NO REACH */
+}
+
+int aim_conn_isready(struct aim_conn_t *conn)
+{
+  if (conn)
+    return (conn->status & 0x0001);
+  else
+    return -1;
+}
+
+int aim_conn_setstatus(struct aim_conn_t *conn, int status)
+{
+  if (conn)
+    return (conn->status ^= status);
+  else
+    return -1;
+}
+