view libfaim/aim_rxqueue.c @ 142:fbabd28795d2

[gaim-migrate @ 152] Added auto-load for plugins. Rob pointed out this might be a bad idea: what if plugins modify the buddy list; the plugins are loaded before signon, thus before the buddy list appears. That would cause errors; then when the list does appear, the plugin doesn't work right because it didn't start off well. My response: EWarmenhoven: there are ways around that EWarmenhoven: in gaim_plugin_init you could have: EWarmenhoven: if (blist) { do_the_normal_thing(); } else { gaim_signal_connect(handle, event_signon, now_the_buddy_list_is_here, NULL); } EWarmenhoven: and actually, that's the way it should be for all plugins that modify the buddy list, because there will be at least one point during execution that it could be loaded when the person is signed off (and i'm not talking about when they first start it up, i'm talking about when they choose 'sign off' instead of 'close' in the buddy list menu) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Thu, 20 Apr 2000 00:12:58 +0000
parents 68b230f8da5f
children 6ced2f1c8b24
line wrap: on
line source

/*
  aim_rxqueue.c

  This file contains the management routines for the receive
  (incoming packet) queue.  The actual packet handlers are in
  aim_rxhandlers.c.

 */

#include "aim.h"

/*
  This is a modified read() to make SURE we get the number
  of bytes we are told to, otherwise block.
 */
int Read(int fd, u_char *buf, int len)
{
  int i = 0;
  int j = 0;

  while ((i < len) && (!(i < 0)))
    {
      j = read(fd, &(buf[i]), len-i);
      if ( (j < 0) && (errno != EAGAIN))
	return -errno; /* fail */
      else
	i += j; /* success, continue */
    }
#if 0
  printf("\nRead Block: (%d/%04x)\n", len, len);
  printf("\t");
  for (j = 0; j < len; j++)
    {
      if (j % 8 == 0)
	printf("\n\t");
      if (buf[j] >= ' ' && buf[j] < 127)
	 printf("%c=%02x ",buf[j], buf[j]);
      else
	 printf("0x%02x ", buf[j]);
    }
  printf("\n\n");
#endif
  return i;
}

/*
  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;
  
  printf("%d\n", workingStruct->commandlen);

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

/*
  purge_rxqueue()

  This is just what it sounds.  It purges the receive (rx) queue of
  all handled commands.  This is normally called from inside 
  aim_rxdispatch() after it's processed all the commands in the queue.
  
 */
struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue)
{
  int i = 0;
  struct command_rx_struct *workingPtr = NULL;
  struct command_rx_struct *workingPtr2 = NULL;

  workingPtr = queue;
  if (queue == NULL)
    {
      return queue;
    }
  else if (queue->next == NULL)
    {
      if (queue->handled == 1)
	{
	  workingPtr2 = queue;
	  queue = NULL;
	  free(workingPtr2->data);
	  free(workingPtr2);
	}
      return queue;
    }
  else
    {
      for (i = 0; workingPtr != NULL; i++)
	{
	  if (workingPtr->next->handled == 1)
	    {
	      /* save struct */
	      workingPtr2 = workingPtr->next;
	      /* dequeue */
	      workingPtr->next = workingPtr2->next;
	      /* free */
	      free(workingPtr2->data);
	      free(workingPtr2);
	    }

	  workingPtr = workingPtr->next;  
	}
    }

  return queue;
}