-faim_export int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
-{
- unsigned char generic[6];
- struct command_rx_struct *newrx = NULL;
-
- if (!sess || !conn)
- return 0;
-
- if (conn->fd == -1)
- return -1; /* its a aim_conn_close()'d connection */
-
- if (conn->fd < 3) /* can happen when people abuse the interface */
- return 0;
-
- if (conn->status & AIM_CONN_STATUS_INPROGRESS)
- return aim_conn_completeconnect(sess, conn);
-
- /*
- * Rendezvous (client-client) connections do not speak
- * FLAP, so this function will break on them.
- */
- if (conn->type == AIM_CONN_TYPE_RENDEZVOUS)
- return aim_get_command_rendezvous(sess, conn);
- if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
- printf("out on fd %d\n", conn->fd);
- return 0;
- }
-
- /*
- * Read FLAP header. Six bytes:
- *
- * 0 char -- Always 0x2a
- * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login.
- * 2 short -- Sequence number
- * 4 short -- Number of data bytes that follow.
- */
- faim_mutex_lock(&conn->active);
- if (aim_recv(conn->fd, generic, 6) < 6){
- aim_conn_close(conn);
- faim_mutex_unlock(&conn->active);
- return -1;
- }
-
- /*
- * This shouldn't happen unless the socket breaks, the server breaks,
- * or we break. We must handle it just in case.
- */
- if (generic[0] != 0x2a) {
- faimdprintf(1, "Bad incoming data!");
- aim_conn_close(conn);
- faim_mutex_unlock(&conn->active);
- return -1;
- }
-
- /* allocate a new struct */
- if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) {
- faim_mutex_unlock(&conn->active);
- return -1;
- }
- memset(newrx, 0x00, sizeof(struct command_rx_struct));
-
- newrx->lock = 1; /* lock the struct */
-
- /* we're doing OSCAR if we're here */
- newrx->hdrtype = AIM_FRAMETYPE_OSCAR;
-
- /* store channel -- byte 2 */
- newrx->hdr.oscar.type = (char) generic[1];
-
- /* store seqnum -- bytes 3 and 4 */
- newrx->hdr.oscar.seqnum = aimutil_get16(generic+2);
-
- /* store commandlen -- bytes 5 and 6 */
- newrx->commandlen = aimutil_get16(generic+4);
-
- newrx->nofree = 0; /* free by default */
-
- /* malloc for data portion */
- if (!(newrx->data = (u_char *) malloc(newrx->commandlen))) {
- free(newrx);
- faim_mutex_unlock(&conn->active);
- return -1;
- }
-
- /* read the data portion of the packet */
- if (aim_recv(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){
- free(newrx->data);
- free(newrx);
- aim_conn_close(conn);
- faim_mutex_unlock(&conn->active);
- return -1;
- }
- faim_mutex_unlock(&conn->active);
-
- newrx->conn = conn;
-
- newrx->next = NULL; /* this will always be at the bottom */
- newrx->lock = 0; /* unlock */
-
- /* enqueue this packet */
- if (sess->queue_incoming == NULL) {
- sess->queue_incoming = newrx;
- } else {
- struct command_rx_struct *cur;
-
- /*
- * This append operation takes a while. It might be faster
- * if we maintain a pointer to the last entry in the queue
- * and just update that. Need to determine if the overhead
- * to maintain that is lower than the overhead for this loop.
- */
- for (cur = sess->queue_incoming; cur->next; cur = cur->next)
- ;
- cur->next = newrx;
- }
-
- newrx->conn->lastactivity = time(NULL);
-
- return 0;
+faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn)
+{
+ fu8_t flaphdr_raw[6];
+ aim_bstream_t flaphdr;
+ aim_frame_t *newrx;
+ fu16_t payloadlen;
+
+ if (!sess || !conn)
+ return 0;
+
+ if (conn->fd == -1)
+ return -1; /* its a aim_conn_close()'d connection */
+
+ if (conn->fd < 3) /* can happen when people abuse the interface */
+ return 0;
+
+ if (conn->status & AIM_CONN_STATUS_INPROGRESS)
+ return aim_conn_completeconnect(sess, conn);
+
+ /*
+ * Rendezvous (client-client) connections do not speak
+ * FLAP, so this function will break on them.
+ */
+ if (conn->type == AIM_CONN_TYPE_RENDEZVOUS)
+ return aim_get_command_rendezvous(sess, conn);
+ else if (conn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
+ faimdprintf(sess, 0, "AIM_CONN_TYPE_RENDEZVOUS_OUT on fd %d\n", conn->fd);
+ return 0;
+ }
+
+ aim_bstream_init(&flaphdr, flaphdr_raw, sizeof(flaphdr_raw));
+
+ /*
+ * Read FLAP header. Six bytes:
+ *
+ * 0 char -- Always 0x2a
+ * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login.
+ * 2 short -- Sequence number
+ * 4 short -- Number of data bytes that follow.
+ */
+ if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) {
+ aim_conn_close(conn);
+ return -1;
+ }
+
+ aim_bstream_rewind(&flaphdr);
+
+ /*
+ * This shouldn't happen unless the socket breaks, the server breaks,
+ * or we break. We must handle it just in case.
+ */
+ if (aimbs_get8(&flaphdr) != 0x2a) {
+ faimdprintf(sess, 0, "FLAP framing disrupted");
+ aim_conn_close(conn);
+ return -1;
+ }
+
+ /* allocate a new struct */
+ if (!(newrx = (aim_frame_t *)malloc(sizeof(aim_frame_t))))
+ return -1;
+ memset(newrx, 0, sizeof(aim_frame_t));
+
+ /* we're doing FLAP if we're here */
+ newrx->hdrtype = AIM_FRAMETYPE_FLAP;
+
+ newrx->hdr.flap.type = aimbs_get8(&flaphdr);
+ newrx->hdr.flap.seqnum = aimbs_get16(&flaphdr);
+ payloadlen = aimbs_get16(&flaphdr);
+
+ newrx->nofree = 0; /* free by default */
+
+ if (payloadlen) {
+ fu8_t *payload = NULL;
+
+ if (!(payload = (fu8_t *) malloc(payloadlen))) {
+ aim_frame_destroy(newrx);
+ return -1;
+ }
+
+ aim_bstream_init(&newrx->data, payload, payloadlen);
+
+ /* read the payload */
+ if (aim_bstream_recv(&newrx->data, conn->fd, payloadlen) < payloadlen) {
+ free(payload);
+ aim_frame_destroy(newrx);
+ aim_conn_close(conn);
+ return -1;
+ }
+ } else
+ aim_bstream_init(&newrx->data, NULL, 0);
+
+
+ aim_bstream_rewind(&newrx->data);
+
+ newrx->conn = conn;
+
+ newrx->next = NULL; /* this will always be at the bottom */
+
+ if (!sess->queue_incoming)
+ sess->queue_incoming = newrx;
+ else {
+ aim_frame_t *cur;
+
+ for (cur = sess->queue_incoming; cur->next; cur = cur->next)
+ ;
+ cur->next = newrx;
+ }
+
+ newrx->conn->lastactivity = time(NULL);
+
+ return 0;