/* * Purge recieve queue of all handled commands (->handled==1). Also * allows for selective freeing using ->nofree so that the client can * keep the data for various purposes. * * If ->nofree is nonzero, the frame will be delinked from the global list, * but will not be free'ed. The client _must_ keep a pointer to the * data -- libfaim will not! If the client marks ->nofree but * does not keep a pointer, it's lost forever. * */ faim_export void aim_purge_rxqueue(aim_session_t *sess) { aim_frame_t *cur, **prev; for (prev = &sess->queue_incoming; (cur = *prev); ) { if (cur->handled) { *prev = cur->next; if (!cur->nofree) aim_frame_destroy(cur); } else prev = &cur->next; } return; }
/* * Grab a single command sequence off the socket, and enqueue * it in the incoming event queue in a seperate struct. */ int aim_get_command(aim_session_t *sess, aim_conn_t *conn) { guint8 flaphdr_raw[6]; aim_bstream_t flaphdr; aim_frame_t *newrx; guint16 payloadlen; if (!sess || !conn) return 0; if (conn->fd == -1) return -1; /* its a aim_conn_close()'d connection */ /* KIDS, THIS IS WHAT HAPPENS IF YOU USE CODE WRITTEN FOR GUIS IN A DAEMON! And wouldn't it make sense to return something that prevents this function from being called again IMMEDIATELY (and making the program suck up all CPU time)?... if (conn->fd < 3) return 0; */ if (conn->status & AIM_CONN_STATUS_INPROGRESS) return aim_conn_completeconnect(sess, conn); 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) { aim_bstream_rewind(&flaphdr); aimbs_get8(&flaphdr); imcb_error(sess->aux_data, "FLAP framing disrupted"); aim_conn_close(conn); return -1; } /* allocate a new struct */ if (!(newrx = (aim_frame_t *)g_new0(aim_frame_t,1))) return -1; /* 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) { guint8 *payload = NULL; if (!(payload = (guint8 *) g_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) { aim_frame_destroy(newrx); /* free's payload */ 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; }
/* * Grab a single command sequence off the socket, and enqueue * it in the incoming event queue in a seperate struct. */ 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) { fu8_t start; aim_bstream_rewind(&flaphdr); start = aimbs_get8(&flaphdr); faimdprintf(sess, 0, "FLAP framing disrupted (0x%02x)", start); 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; }
/* * Grab a single command sequence off the socket, and enqueue it in the incoming event queue * in a separate struct. */ faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn) { aim_frame_t *newrx; fu16_t payloadlen; if (!sess || !conn) return -EINVAL; if (conn->fd == -1) return -1; /* it's an aim_conn_close()'d connection */ if (conn->fd < 3) /* can happen when people abuse the interface */ return -1; if (conn->status & AIM_CONN_STATUS_INPROGRESS) return aim_conn_completeconnect(sess, conn); if (!(newrx = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) return -ENOMEM; /* * Rendezvous (client to client) connections do not speak FLAP, so this * function will break on them. */ if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { int ret = aim_get_command_rendezvous(sess, conn, newrx); if (ret < 0) { free(newrx); return -1; } payloadlen = ret; } else if (conn->type == AIM_CONN_TYPE_LISTENER) { faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); free(newrx); return -1; } else payloadlen = aim_get_command_flap(sess, conn, newrx); 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) { aim_frame_destroy(newrx); /* free's payload */ 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; }