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