view libfaim/aim_rxqueue.c @ 133:e277d5f0c1dd

[gaim-migrate @ 143] Let's see if I can remember everything I did: - Fixed a bug I let slip. If you choose the new option to not play login sounds when you log in, and then quit before the timeout is up, it would save that you didn't want login sounds at all. - Added two new plugin events: event_away and event_buddy_away. - Made GtkWidget *imaway in away.c and void play(uchar *, int) in sound.c not static any more (though not referenced in gaim.h). This is so plugins can use those (and not have to worry about writing their own sound code). - Wrote a quick plugin to auto-iconify windows when you go away. I had just been locally patching my own copy, since I figured it wasn't worth including as an option. It also demonstrates some of the issues of deciding between USE_APPLET and not. Perhaps plugins are the way to go with some things that would otherwise have been options (for example, the Lag-O-Meter is one of those things that could possibly have been a plugin instead of hard-coded in). I think that's everything. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Wed, 19 Apr 2000 02:04:30 +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;
}