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