Exemple #1
0
/*
 * 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;
}
Exemple #2
0
/*
 * 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;  
}
Exemple #3
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;
}
Exemple #4
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;
}