]> andersk Git - libfaim.git/blob - aim_rxqueue.c
- Sun May 21 14:59:20 GMT 2000
[libfaim.git] / aim_rxqueue.c
1 /*
2  *  aim_rxqueue.c
3  *
4  * This file contains the management routines for the receive
5  * (incoming packet) queue.  The actual packet handlers are in
6  * aim_rxhandlers.c.
7  */
8
9 #include <faim/aim.h> 
10
11 /*
12  * Grab a single command sequence off the socket, and enqueue
13  * it in the incoming event queue in a seperate struct.
14  */
15 int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
16 {
17   u_char generic[6]; 
18   struct command_rx_struct *newrx = NULL;
19
20   if (!sess || !conn)
21     return 0;
22
23   if (conn->fd < 3)  /* can happen when people abuse the interface */
24     return 0;
25
26   /*
27    * Read FLAP header.  Six bytes:
28    *    
29    *   0 char  -- Always 0x2a
30    *   1 char  -- Channel ID.  Usually 2 -- 1 and 4 are used during login.
31    *   2 short -- Sequence number 
32    *   4 short -- Number of data bytes that follow.
33    */
34   if (read(conn->fd, generic, 6) < 6){
35     aim_conn_close(conn);
36     return -1;
37   }
38
39   /*
40    * This shouldn't happen unless the socket breaks, the server breaks,
41    * or we break.  We must handle it just in case.
42    */
43   if (generic[0] != 0x2a) {
44     faimdprintf(1, "Bad incoming data!");
45     return -1;
46   }     
47
48   /* allocate a new struct */
49   newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct));
50   if (!newrx)
51     return -1;
52   memset(newrx, 0x00, sizeof(struct command_rx_struct));
53
54   newrx->lock = 1;  /* lock the struct */
55
56   /* store channel -- byte 2 */
57   newrx->type = (char) generic[1];
58
59   /* store seqnum -- bytes 3 and 4 */
60   newrx->seqnum = aimutil_get16(generic+2);
61
62   /* store commandlen -- bytes 5 and 6 */
63   newrx->commandlen = aimutil_get16(generic+4);
64
65   newrx->nofree = 0; /* free by default */
66
67   /* malloc for data portion */
68   newrx->data = (u_char *) malloc(newrx->commandlen);
69   if (!newrx->data) {
70     free(newrx);
71     return -1;
72   }
73
74   /* read the data portion of the packet */
75   if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){
76     free(newrx->data);
77     free(newrx);
78     aim_conn_close(conn);
79     return -1;
80   }
81
82   newrx->conn = conn;
83
84   newrx->next = NULL;  /* this will always be at the bottom */
85   newrx->lock = 0; /* unlock */
86
87   /* enqueue this packet */
88   if (sess->queue_incoming == NULL) {
89     sess->queue_incoming = newrx;
90   } else {
91     struct command_rx_struct *cur;
92
93     /*
94      * This append operation takes a while.  It might be faster
95      * if we maintain a pointer to the last entry in the queue
96      * and just update that.  Need to determine if the overhead
97      * to maintain that is lower than the overhead for this loop.
98      */
99     for (cur = sess->queue_incoming; cur->next; cur = cur->next)
100       ;
101     cur->next = newrx;
102   }
103   
104   newrx->conn->lastactivity = time(NULL);
105
106   return 0;  
107 }
108
109 /*
110  * Purge recieve queue of all handled commands (->handled==1).  Also
111  * allows for selective freeing using ->nofree so that the client can
112  * keep the data for various purposes.  
113  *
114  * If ->nofree is nonzero, the frame will be delinked from the global list, 
115  * but will not be free'ed.  The client _must_ keep a pointer to the
116  * data -- libfaim will not!  If the client marks ->nofree but
117  * does not keep a pointer, it's lost forever.
118  *
119  */
120 void aim_purge_rxqueue(struct aim_session_t *sess)
121 {
122   struct command_rx_struct *cur = NULL;
123   struct command_rx_struct *tmp;
124
125   if (sess->queue_incoming == NULL)
126     return;
127   
128   if (sess->queue_incoming->next == NULL) {
129     if (sess->queue_incoming->handled) {
130       tmp = sess->queue_incoming;
131       sess->queue_incoming = NULL;
132
133       if (!tmp->nofree) {
134         free(tmp->data);
135         free(tmp);
136       } else
137         tmp->next = NULL;
138     }
139     return;
140   }
141
142   for(cur = sess->queue_incoming; cur->next != NULL; ) {
143     if (cur->next->handled) {
144       tmp = cur->next;
145       cur->next = tmp->next;
146       if (!tmp->nofree) {
147         free(tmp->data);
148         free(tmp);
149       } else
150         tmp->next = NULL;
151     }   
152     cur = cur->next;
153
154     /* 
155      * Be careful here.  Because of the way we just
156      * manipulated the pointer, cur may be NULL and 
157      * the for() will segfault doing the check unless
158      * we find this case first.
159      */
160     if (cur == NULL)    
161       break;
162   }
163
164   return;
165 }
This page took 0.052887 seconds and 5 git commands to generate.