]> andersk Git - libfaim.git/blob - aim_conn.c
- Mon May 29 12:08:28 GMT 2000
[libfaim.git] / aim_conn.c
1
2 /*
3  *  aim_conn.c
4  *
5  * Does all this gloriously nifty connection handling stuff...
6  *
7  */
8
9 #include <faim/aim.h> 
10
11 void aim_connrst(struct aim_session_t *sess)
12 {
13   int i;
14   for (i = 0; i < AIM_CONN_MAX; i++) {
15     aim_conn_close(&sess->conns[i]);
16   }
17 }
18
19 struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
20 {
21   int i;
22   for (i=0;i<AIM_CONN_MAX;i++)
23     if (sess->conns[i].fd == -1)
24       return &(sess->conns[i]);
25   return NULL;
26 }
27
28 void aim_conn_close(struct aim_conn_t *deadconn)
29 {
30   if (deadconn->fd >= 3)
31     close(deadconn->fd);
32   deadconn->fd = -1;
33   deadconn->type = -1;
34   deadconn->seqnum = 0;
35   deadconn->lastactivity = 0;
36   deadconn->forcedlatency = 0;
37   aim_clearhandlers(deadconn);
38   deadconn->handlerlist = NULL;
39   if (deadconn->priv)
40     free(deadconn->priv);
41   deadconn->priv = NULL;
42   faim_mutex_init(&deadconn->active, NULL);
43 }
44
45 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
46                                     int type)
47 {
48   int i;
49   for (i=0; i<AIM_CONN_MAX; i++)
50     if (sess->conns[i].type == type)
51       return &(sess->conns[i]);
52   return NULL;
53 }
54
55 /*
56  * aim_newconn(type, dest)
57  *
58  * Opens a new connection to the specified dest host of type type.
59  *
60  * TODO: fix for proxies
61  * FIXME: Return errors in a more sane way.
62  *
63  */
64 struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
65                                int type, char *dest)
66 {
67   struct aim_conn_t *connstruct;
68   int ret;
69   struct sockaddr_in sa;
70   struct hostent *hp;
71   u_short port = FAIM_LOGIN_PORT;
72   char *host = NULL;
73   int i=0;
74   
75   if ((connstruct=aim_conn_getnext(sess))==NULL)
76     return NULL;
77
78   connstruct->type = type;
79
80   if (!dest) { /* just allocate a struct */
81     connstruct->fd = -1;
82     connstruct->status = 0;
83     return connstruct;
84   }
85
86   /* 
87    * As of 23 Jul 1999, AOL now sends the port number, preceded by a 
88    * colon, in the BOS redirect.  This fatally breaks all previous 
89    * libfaims.  Bad, bad AOL.
90    *
91    * We put this here to catch every case. 
92    *
93    */
94
95   for(i=0;i<strlen(dest);i++) {
96     if (dest[i] == ':') {
97       port = atoi(&(dest[i+1]));
98       break;
99     }
100   }
101   host = (char *)malloc(i+1);
102   strncpy(host, dest, i);
103   host[i] = '\0';
104
105   hp = gethostbyname2(host, AF_INET);
106   free(host);
107
108   if (hp == NULL) {
109     connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
110     return connstruct;
111   }
112
113   memset(&sa.sin_zero, 0, 8);
114   sa.sin_port = htons(port);
115   memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
116   sa.sin_family = hp->h_addrtype;
117   
118   connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
119   ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
120   if(ret < 0) {
121     connstruct->fd = -1;
122     connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
123     return connstruct;
124   }
125   
126   return connstruct;
127 }
128
129 int aim_conngetmaxfd(struct aim_session_t *sess)
130 {
131   int i,j;
132
133   for (i=0,j=0;i<AIM_CONN_MAX;i++)
134     if(sess->conns[i].fd > j)
135       j = sess->conns[i].fd;
136   return j;
137 }
138
139 int aim_countconn(struct aim_session_t *sess)
140 {
141   int i,cnt;
142
143   for (i=0,cnt=0;i<AIM_CONN_MAX;i++)
144     if (sess->conns[i].fd > -1)
145       cnt++;
146   return cnt;
147 }
148
149 /*
150  * aim_select(timeout)
151  *
152  * Waits for a socket with data or for timeout, whichever comes first.
153  * See select(2).
154  * 
155  * Return codes in *status:
156  *   -1  error in select() (NULL returned)
157  *    0  no events pending (NULL returned)
158  *    1  outgoing data pending (NULL returned)
159  *    2  incoming data pending (connection with pending data returned)
160  *
161  */ 
162 struct aim_conn_t *aim_select(struct aim_session_t *sess,
163                               struct timeval *timeout, int *status)
164 {
165   fd_set fds;
166   int i;
167
168   if (aim_countconn(sess) <= 0)
169     return 0;
170
171   /* 
172    * If we have data waiting to be sent, return immediatly
173    */
174   if (sess->queue_outgoing != NULL) {
175     *status = 1;
176     return NULL;
177   } 
178
179   FD_ZERO(&fds);
180   
181   for(i=0;i<AIM_CONN_MAX;i++)
182     if (sess->conns[i].fd>-1)
183       FD_SET(sess->conns[i].fd, &fds);
184   
185   if ((i = select(aim_conngetmaxfd(sess)+1, &fds, NULL, NULL, timeout))>=1) {
186     int j;
187     for (j=0;j<AIM_CONN_MAX;j++) {
188         if (sess->conns[j].fd > -1) {
189             if ((FD_ISSET(sess->conns[j].fd, &fds))) {
190               *status = 2;
191               return &(sess->conns[j]);  /* return the first waiting struct */
192             }
193           }     
194         }       
195     /* should never get here */
196   }
197
198   *status = i; /* may be 0 or -1 */
199   return NULL;  /* no waiting or error, return */
200 }
201
202 int aim_conn_isready(struct aim_conn_t *conn)
203 {
204   if (conn)
205     return (conn->status & 0x0001);
206   else
207     return -1;
208 }
209
210 int aim_conn_setstatus(struct aim_conn_t *conn, int status)
211 {
212   if (conn)
213     return (conn->status ^= status);
214   else
215     return -1;
216 }
217
218 int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
219 {
220   if (!conn)
221     return -1;
222   
223   conn->forcedlatency = newval;
224   conn->lastactivity = 0; /* reset this just to make sure */
225
226   return 0;
227 }
228
229 void aim_session_init(struct aim_session_t *sess)
230 {
231   if (!sess)
232     return;
233
234   memset(sess->logininfo.screen_name, 0x00, MAXSNLEN);
235   sess->logininfo.BOSIP = NULL;
236   memset(sess->logininfo.cookie, 0x00, AIM_COOKIELEN);
237   sess->logininfo.email = NULL;
238   sess->logininfo.regstatus = 0x00;
239
240   aim_connrst(sess);
241
242   sess->queue_outgoing = NULL;
243   sess->queue_incoming = NULL;
244   sess->pendingjoin = NULL;
245   sess->outstanding_snacs = NULL;
246   sess->snac_nextid = 0x00000001;
247
248   /*
249    * This must always be set.  Default to the queue-based
250    * version for back-compatibility.  
251    */
252   sess->tx_enqueue = &aim_tx_enqueue__queuebased;
253
254   return;
255 }
This page took 0.236084 seconds and 5 git commands to generate.