Esempio n. 1
0
/*
 * XXX this is nearly as ugly as proxyconnect().
 */
int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn)
{
	fd_set fds, wfds;
	struct timeval tv;
	int res, error = ETIMEDOUT;
	aim_rxcallback_t userfunc;

	if (!conn || (conn->fd == -1))
		return -1;

	if (!(conn->status & AIM_CONN_STATUS_INPROGRESS))
		return -1;

	FD_ZERO(&fds);
	FD_SET(conn->fd, &fds);
	FD_ZERO(&wfds);
	FD_SET(conn->fd, &wfds);
	tv.tv_sec = 0;
	tv.tv_usec = 0;

	if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) {
		error = errno;
		aim_conn_close(conn);
		errno = error;
		return -1;
	} else if (res == 0) {
		return 0; /* hasn't really completed yet... */
	} 

	if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) {
		socklen_t len = sizeof(error);

		if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
			error = errno;
	}

	if (error) {
		aim_conn_close(conn);
		errno = error;
		return -1;
	}

	sock_make_blocking(conn->fd);

	conn->status &= ~AIM_CONN_STATUS_INPROGRESS;

	if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE)))
		userfunc(sess, NULL, conn);

	/* Flush out the queues if there was something waiting for this conn  */
	aim_tx_flushqueue(sess);

	return 0;
}
Esempio n. 2
0
static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
{

	aim_rxqueue_cleanbyconn(sess, *deadconn);
	aim_tx_cleanqueue(sess, *deadconn);

	if ((*deadconn)->fd != -1) 
		aim_conn_close(*deadconn);

	/*
	 * This will free ->internal if it necessary...
	 */
	if ((*deadconn)->type == AIM_CONN_TYPE_CHAT)
		aim_conn_kill_chat(sess, *deadconn);

	if ((*deadconn)->inside) {
		aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside;

		connkill_snacgroups(&inside->groups);
		connkill_rates(&inside->rates);

		free(inside);
	}

	free(*deadconn);
	*deadconn = NULL;

	return;
}
Esempio n. 3
0
/*
 * Read a FLAP header from conn into fr, and return the number of bytes in the payload.
 */
static int aim_get_command_flap(aim_session_t *sess, aim_conn_t *conn,
	aim_frame_t *fr)
{
	fu8_t flaphdr_raw[6];
	aim_bstream_t flaphdr;
	fu16_t payloadlen;

	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;
	}

	/* we're doing FLAP if we're here */
	fr->hdrtype = AIM_FRAMETYPE_FLAP;

	fr->hdr.flap.type = aimbs_get8(&flaphdr);
	fr->hdr.flap.seqnum = aimbs_get16(&flaphdr);
	payloadlen = aimbs_get16(&flaphdr);	/* length of payload */

	return payloadlen;
}
Esempio n. 4
0
faim_export int aim_chat_leaveroom(aim_session_t *sess, const char *name)
{
	aim_conn_t *conn;

	if (!(conn = aim_chat_getconn(sess, name)))
		return -ENOENT;

	aim_conn_close(conn);

	return 0;
}
Esempio n. 5
0
/**
 * aim_connrst - Clears out connection list, killing remaining connections.
 * @sess: Session to be cleared
 *
 * Clears out the connection list and kills any connections left.
 *
 */
static void aim_connrst(aim_session_t *sess)
{

	if (sess->connlist) {
		aim_conn_t *cur = sess->connlist, *tmp;

		while (cur) {
			tmp = cur->next;
			aim_conn_close(cur);
			connkill_real(sess, &cur);
			cur = tmp;
		}
	}

	sess->connlist = NULL;

	return;
}
Esempio n. 6
0
/*
 * Read a rendezvous header from conn into fr, and return the number of bytes in the payload.
 */
static int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn,
	aim_frame_t *fr)
{
	fu8_t rendhdr_raw[8];
	aim_bstream_t rendhdr;

	aim_bstream_init(&rendhdr, rendhdr_raw, sizeof(rendhdr_raw));

	if (aim_bstream_recv(&rendhdr, conn->fd, 8) < 8) {
		aim_conn_close(conn);
		return -1;
	}

	aim_bstream_rewind(&rendhdr);

	fr->hdrtype = AIM_FRAMETYPE_OFT;	/* a misnomer--rendezvous */

	aimbs_getrawbuf(&rendhdr, fr->hdr.rend.magic, 4);
	fr->hdr.rend.hdrlen = aimbs_get16(&rendhdr) - 8;
	fr->hdr.rend.type = aimbs_get16(&rendhdr);

	return fr->hdr.rend.hdrlen;
}
Esempio n. 7
0
static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn)
{

	aim_rxqueue_cleanbyconn(sess, *deadconn);
	aim_tx_cleanqueue(sess, *deadconn);

	if ((*deadconn)->fd != -1) 
		aim_conn_close(*deadconn);

	/*
	 * XXX ->priv should never be touched by the library. I know
	 * it used to be, but I'm getting rid of all that.  Use
	 * ->internal instead.
	 */
	if ((*deadconn)->priv)
		free((*deadconn)->priv);

	/*
	 * This will free ->internal if it necessary...
	 */
	if ((*deadconn)->type == AIM_CONN_TYPE_CHAT)
		aim_conn_kill_chat(sess, *deadconn);

	if ((*deadconn)->inside) {
		aim_conn_inside_t *inside = (aim_conn_inside_t *)(*deadconn)->inside;

		connkill_snacgroups(&inside->groups);
		connkill_rates(&inside->rates);

		free(inside);
	}

	free(*deadconn);
	*deadconn = NULL;

	return;
}
Esempio n. 8
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;
}
Esempio n. 9
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;  
}
Esempio n. 10
0
/*
  struct command_struct *
                         get_generic(
                                     struct connection_info struct *,
				     struct command_struct * 
				     )
  
  Grab as many command sequences as we can off the socket, and enqueue
  each command in the incoming event queue in a seperate struct.

*/
int aim_get_command(void)
{
  int i, readgood, j, isav, err;
  int s;
  fd_set fds;
  struct timeval tv;
  char generic[6]; 
  struct command_rx_struct *workingStruct = NULL;
  struct command_rx_struct *workingPtr = NULL;
  struct aim_conn_t *conn = NULL;
#if debug > 0
  printf("Reading generic/unknown response...");
#endif
  
  
  /* dont wait at all (ie, never call this unless something is there) */
  tv.tv_sec = 0; 
  tv.tv_usec = 0;
  conn = aim_select(&tv);

  if (conn==NULL)
    return 0;  /* nothing waiting */

  s = conn->fd;

  FD_ZERO(&fds);
  FD_SET(s, &fds);
  tv.tv_sec = 0;  /* wait, but only for 10us */
  tv.tv_usec = 10;
  
  generic[0] = 0x00;  

  readgood = 0;
  i = 0;
  j = 0;
  /* read first 6 bytes (the FLAP header only) off the socket */
  while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6))
    {
      if ((err = Read(s, &(generic[i]), 1)) < 0)
	{
	  /* error is probably not recoverable...(must be a pessimistic day) */
	  aim_conn_close(conn);
	  return err;
   	}

      if (readgood == 0)
	{
	  if (generic[i] == 0x2a)
	  {
	    readgood = 1;
#if debug > 1
	    printf("%x ", generic[i]);
	    fflush(stdout);
#endif
	    i++;
	  }
	  else
	    {
#if debug > 1
	      printf("skipping 0x%d ", generic[i]);
	      fflush(stdout);
#endif
	      j++;
	    }
	}
      else
	{
#if debug > 1
	  printf("%x ", generic[i]);
#endif
	  i++;
	}
      FD_ZERO(&fds);
      FD_SET(s, &fds);
      tv.tv_sec= 2;
      tv.tv_usec= 2;
    }

  if (generic[0] != 0x2a)
    {
      /* this really shouldn't happen, since the main loop
	 select() should protect us from entering this function
	 without data waiting  */
      printf("Bad incoming data!");
      return -1;
    }

  isav = i;

  /* allocate a new struct */
  workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct));
  workingStruct->lock = 1;  /* lock the struct */

  /* store type -- byte 2 */
  workingStruct->type = (char) generic[1];

  /* store seqnum -- bytes 3 and 4 */
  workingStruct->seqnum = ( (( (unsigned int) generic[2]) & 0xFF) << 8);
  workingStruct->seqnum += ( (unsigned int) generic[3]) & 0xFF;

  /* store commandlen -- bytes 5 and 6 */
  workingStruct->commandlen = ( (( (unsigned int) generic[4]) & 0xFF ) << 8);
  workingStruct->commandlen += ( (unsigned int) generic[5]) & 0xFF;

  /* malloc for data portion */
  workingStruct->data = (char *) malloc(workingStruct->commandlen);

  /* read the data portion of the packet */
  i = Read(s, workingStruct->data, workingStruct->commandlen);
  if (i < 0)
    {
      aim_conn_close(conn);
      return i;
    }

#if debug > 0
  printf(" done. (%db+%db read, %db skipped)\n", isav, i, j);
#endif

  workingStruct->conn = conn;

  workingStruct->next = NULL;  /* this will always be at the bottom */
  workingStruct->lock = 0; /* unlock */

  /* enqueue this packet */
  if (aim_queue_incoming == NULL)
    aim_queue_incoming = workingStruct;
  else
    {
      workingPtr = aim_queue_incoming;
      while (workingPtr->next != NULL)
	workingPtr = workingPtr->next;
      workingPtr->next = workingStruct;
    }

  return 0;  
}
Esempio n. 11
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;
}