]> andersk Git - libfaim.git/commitdiff
- Mon Jun 26 07:53:02 UTC 2000
authormid <mid>
Mon, 26 Jun 2000 08:09:09 +0000 (08:09 +0000)
committermid <mid>
Mon, 26 Jun 2000 08:09:09 +0000 (08:09 +0000)
   - Added utils/aimdebugd for playing with things -- see the README
   - Added aim_im.c::aim_parse_outgoing_im().  Probably not useful
      unless you're writing a server or something (or hacking aimdebugd).
   - aim_send_im() now sends the same data as AIM4 does (three more bytes)
   - Added aim_debugconn_sendconnect() for aimdebugd-enablement.

17 files changed:
CHANGES
aim_im.c
aim_misc.c
aim_rxhandlers.c
faim/aim.h
faim/aim_cbtypes.h
tcpdumps/newim.txt
utils/Makefile
utils/aimdebugd/Makefile [new file with mode: 0644]
utils/aimdebugd/README [new file with mode: 0644]
utils/aimdebugd/aimdebugd.c [new file with mode: 0644]
utils/aimdebugd/file.c [new file with mode: 0644]
utils/aimdebugd/icbm.c [new file with mode: 0644]
utils/aimdebugd/network.c [new file with mode: 0644]
utils/aimdebugd/network.h [new file with mode: 0644]
utils/aimdebugd/samplescript [new file with mode: 0644]
utils/faimtest/faimtest.c

diff --git a/CHANGES b/CHANGES
index 3dabe0a12d258542709a7ff1f3bf6fcdfff58db3..dd976bc42ddc8af6d31bc0905a35b30049d61bfe 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,13 @@
 
 No release numbers
 ------------------
+ - Mon Jun 26 07:53:02 UTC 2000
+   - Added utils/aimdebugd for playing with things -- see the README
+   - Added aim_im.c::aim_parse_outgoing_im().  Probably not useful
+      unless you're writing a server or something (or hacking aimdebugd).
+   - aim_send_im() now sends the same data as AIM4 does (three more bytes)
+   - Added aim_debugconn_sendconnect() for aimdebugd-enablement.
+
  - Sat Jun 24 02:14:07 UTC 2000
    - Added fakelocks for platforms without pthreads or that have no
       use for them.
index f82ecfa23bc521e7e3fd604314b97f83c7f131c3..8c619086c92ad804b5d9ea81dabc21e488c71dfc 100644 (file)
--- a/aim_im.c
+++ b/aim_im.c
@@ -64,15 +64,22 @@ u_long aim_send_im(struct aim_session_t *sess,
    * metaTLV start.
    */
   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
-  curbyte += aimutil_put16(newpacket->data+curbyte, strlen(msg) + 0x0d);
+  curbyte += aimutil_put16(newpacket->data+curbyte, strlen(msg) + 0x10);
 
   /*
-   * Flag data?
+   * Flag data / ICBM Parameters?
    */
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0501);
-  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x05);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x01);
+
+  /* number of bytes to follow */
+  curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x01);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x01);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x01);
+  curbyte += aimutil_put8(newpacket->data+curbyte, 0x02);
+
   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0101);
-  curbyte += aimutil_put8 (newpacket->data+curbyte, 0x01);
 
   /* 
    * Message block length.
@@ -214,6 +221,74 @@ int aim_send_im_direct(struct aim_session_t *sess,
   return 0;
 }
 
+int aim_parse_outgoing_im_middle(struct aim_session_t *sess,
+                                struct command_rx_struct *command)
+{
+  unsigned int i = 0, z;
+  rxcallback_t userfunc = NULL;
+  unsigned char cookie[8];
+  int channel;
+  struct aim_tlvlist_t *tlvlist;
+  char sn[MAXSNLEN];
+  unsigned short icbmflags = 0;
+  unsigned char flag1 = 0, flag2 = 0;
+  unsigned char *msgblock = NULL, *msg = NULL;
+
+  i = 10;
+  
+  /* ICBM Cookie. */
+  for (z=0; z<8; z++,i++)
+    cookie[z] = command->data[i];
+
+  /* Channel ID */
+  channel = aimutil_get16(command->data+i);
+  i += 2;
+
+  if (channel != 0x01) {
+    printf("faim: icbm: ICBM recieved on unsupported channel.  Ignoring. (chan = %04x)\n", channel);
+    return 1;
+  }
+
+  strncpy(sn, command->data+i+1, (int) *(command->data+i));
+  i += 1 + (int) *(command->data+i);
+
+  tlvlist = aim_readtlvchain(command->data+i, command->commandlen-i);
+
+  if (aim_gettlv(tlvlist, 0x0003, 1))
+    icbmflags |= AIM_IMFLAGS_ACK;
+  if (aim_gettlv(tlvlist, 0x0004, 1))
+    icbmflags |= AIM_IMFLAGS_AWAY;
+
+  if (aim_gettlv(tlvlist, 0x0002, 1)) {
+    int j = 0;
+
+    msgblock = aim_gettlv_str(tlvlist, 0x0002, 1);
+
+    /* no, this really is correct.  I'm not high or anything either. */
+    j += 2;
+    j += 2 + aimutil_get16(msgblock+j);
+    j += 2;
+    
+    j += 2; /* final block length */
+
+    flag1 = aimutil_get16(msgblock);
+    j += 2;
+    flag2 = aimutil_get16(msgblock);
+    j += 2;
+    
+    msg = msgblock+j;
+  }
+
+  if ((userfunc = aim_callhandler(command->conn, 0x0004, 0x0006)) || (i = 0))
+    i = userfunc(sess, command, channel, sn, msg, icbmflags, flag1, flag2);
+  
+  if (msgblock)
+    free(msgblock);
+  aim_freetlvchain(&tlvlist);
+
+  return 0;
+}
+
 /*
  * It can easily be said that parsing ICBMs is THE single
  * most difficult thing to do in the in AIM protocol.  In
index a909eb37372f4977d7d31bf4e1317e02b525a309..420165f37ad5b8bffaf2feb6e34f47fe81441147 100644 (file)
@@ -539,6 +539,17 @@ u_long aim_bos_reqbuddyrights(struct aim_session_t *sess,
   return aim_genericreq_n(sess, conn, 0x0003, 0x0002);
 }
 
+/*
+ * aim_debugconn_sendconnect()
+ *
+ * For aimdebugd.  If you don't know what it is, you don't want to.
+ */
+u_long aim_debugconn_sendconnect(struct aim_session_t *sess,
+                                struct aim_conn_t *conn)
+{
+  return aim_genericreq_n(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT);
+}
+
 /*
  * Generic routine for sending commands.
  *
index 7c0b00c593ca92ac06be1d819eef80ec6200259f..736fd83e4b1554eea5f8bf478d1656d7a7ecec40 100644 (file)
@@ -372,6 +372,11 @@ int aim_rxdispatch(struct aim_session_t *sess)
            if (subtype == 0x0005)
              workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_ADM, AIM_CB_ADM_INFOCHANGE_REPLY, workingPtr);
            break;
+         case AIM_CB_FAM_SPECIAL:
+           if (subtype == AIM_CB_SPECIAL_DEBUGCONN_CONNECT) {
+             workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
+             break;
+           } /* others fall through */
          default:
            /* Old login protocol */
            /* any user callbacks will be called from here */
@@ -468,6 +473,9 @@ int aim_rxdispatch(struct aim_session_t *sess)
          case 0x0005:
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, 0x0004, 0x0005, workingPtr);
            break;
+         case 0x0006:
+           workingPtr->handled = aim_parse_outgoing_im_middle(sess, workingPtr);
+           break;
          case 0x0007:
            workingPtr->handled = aim_parse_incoming_im_middle(sess, workingPtr);
            break;
@@ -506,6 +514,9 @@ int aim_rxdispatch(struct aim_session_t *sess)
          else
            workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_STS, AIM_CB_STS_DEFAULT, workingPtr);
          break;
+      case AIM_CB_FAM_SPECIAL: 
+       workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, family, subtype, workingPtr);
+       break;
        default:
          workingPtr->handled = aim_callhandler_noparam(sess, workingPtr->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_UNKNOWN, workingPtr);
          break;
index 6d6ec251b744c4f61927d183f61774a9f8674303..dce12e49b9d8895d2558bc8b8c3ba831c3a807a5 100644 (file)
@@ -359,7 +359,8 @@ int aim_counttlvchain(struct aim_tlvlist_t **list);
  */
 int aim_get_command(struct aim_session_t *, struct aim_conn_t *);
 int aim_rxdispatch(struct aim_session_t *);
-
+u_long aim_debugconn_sendconnect(struct aim_session_t *sess,
+                                struct aim_conn_t *conn);
 int aim_logoff(struct aim_session_t *);
 
 void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn);
@@ -490,6 +491,7 @@ int aim_parsemotd_middle(struct aim_session_t *sess, struct command_rx_struct *c
 
 u_long aim_send_im(struct aim_session_t *, struct aim_conn_t *, char *, u_int, char *);
 int aim_parse_incoming_im_middle(struct aim_session_t *, struct command_rx_struct *);
+int aim_parse_outgoing_im_middle(struct aim_session_t *, struct command_rx_struct *);
 u_long aim_seticbmparam(struct aim_session_t *, struct aim_conn_t *conn);
 int aim_parse_msgerror_middle(struct aim_session_t *, struct command_rx_struct *);
 int aim_negchan_middle(struct aim_session_t *sess, struct command_rx_struct *command);
index 9c0e773a5bc49633b5c9bd9b9d9002a1d5ed20a2..3943e10aa78581c33fdcc029029bfdd65194b93a 100644 (file)
 #define AIM_CB_SPECIAL_AUTHSUCCESS 0x0001
 #define AIM_CB_SPECIAL_AUTHOTHER 0x0002
 #define AIM_CB_SPECIAL_CONNERR 0x0003
+#define AIM_CB_SPECIAL_DEBUGCONN_CONNECT 0xe001
 #define AIM_CB_SPECIAL_UNKNOWN 0xffff
 #define AIM_CB_SPECIAL_DEFAULT AIM_CB_SPECIAL_UNKNOWN
 
index a02544d0b45f89dfa64087f6b2f8228a41e88b65..8e559f9f24e80a53d439d08bfe69efe85f883aff 100644 (file)
@@ -8,7 +8,12 @@
 096d 6964 656e 6469 616e 
 
 0003 0000
-0002 003a 0501 0003 01 01 01 01 01
+0002 003a 
+     05 
+     01 
+     0003 
+       0101 01 
+     0101
 
 002f 00
 0000 00
         G=47 o=6f o=6f d=64  =20 d=64 a=61 y=79
          =20 t=74 o=6f  =20 y=79 o=6f u=75  =20
         t=74 o=6f o=6f .=2e
+
+---------
+
+       2a02 602f 006f 
+            0004 0006 0000 0000 8001 
+                 3135 3642 4538 3800
+                  0001 
+                 06 xx xxxx xxxx xx
+                 0002 0050 
+                      0501 
+                      0004 
+                           0101 0102 
+                      0101 
+                      0044 
+                        0000 0000
+
+                        3c 4854
+                         4d4c 3e3c 424f 4459 2042 4743 4f4c 4f52
+                         3d22 2366 6666 6666 6622 3e3c 464f 4e54
+                         3e6b 3b73 616a 6466 3c2f 464f 4e54 3e3c
+                         2f42 4f44 593e 3c2f 4854 4d4c 3e
\ No newline at end of file
index a0c92b851b55342ceb2178399bd4a5d4b50c155a..9eac332175f4be771e2eee2a549585d2d3979264 100644 (file)
@@ -1,20 +1,16 @@
 include Makefile.dynamicrules
 
-UTIL_DIRS = faimtest #aimdump aimpasswd
+UTIL_DIRS = faimtest aimdebugd #aimdump aimpasswd
 
 utils_all: 
        @dirs='$(UTIL_DIRS)'; \
        for i in $$dirs; do \
-         cd $$i; \
-         $(MAKE); \
-         cd ..; \
+         $(MAKE) -C $$i; \
        done; 
 
 clean:
        @dirs='$(UTIL_DIRS)'; \
        for i in $$dirs; do \
-         cd $$i; \
-         $(MAKE) clean; \
-         cd ..; \
+         $(MAKE) -C $$i clean; \
        done;
        @rm -f Makefile.dynamicrules
diff --git a/utils/aimdebugd/Makefile b/utils/aimdebugd/Makefile
new file mode 100644 (file)
index 0000000..3649a53
--- /dev/null
@@ -0,0 +1,15 @@
+include ../Makefile.dynamicrules
+include $(LIBFAIM_LIB)/Makefile.rules
+
+EXEC_NAME = aimdebugd
+EXEC_OBJECTS = \
+       aimdebugd.o \
+       network.o \
+       file.o \
+       icbm.o
+
+all: $(EXEC_OBJECTS)
+       $(CC) $(CFLAGS) -o $(EXEC_NAME) $(EXEC_OBJECTS) $(LDFLAGS)
+
+clean:
+       rm -f *~ $(EXEC_OBJECTS) $(EXEC_NAME)
diff --git a/utils/aimdebugd/README b/utils/aimdebugd/README
new file mode 100644 (file)
index 0000000..4977fec
--- /dev/null
@@ -0,0 +1,70 @@
+
+aimdebugd.  Slightly ambiguous name.  Basically, its a
+micro-aim-server thats meant to be hacked.  Its completely useless the
+way it is, but it does let you poke and prod at clients while they're
+in their main loop.  It won't help for debugging the login process,
+but it will allow you to test various ICBM types, etc -- anything you
+want to implement packet handlers and transmitters for.  
+
+How to make your client work with aimdebugd
+-------------------------------------------
+       1. Create a handler for the debug connection SNAC like this:
+
+int debugconn_connect_handler(struct aim_session_t *sess, struct command_rx_struct *command, ...) {
+
+       printf("connecting to an aimdebugd!\n");
+
+       /* convert the authorizer connection to a BOS connection */
+       command->conn->type = AIM_CONN_TYPE_BOS;
+
+       /* You may want to add some of your BOS callbacks here */
+
+       /* tell the aimdebugd we're ready */
+       aim_debugconn_sendconnect(sess, command->conn); 
+
+       /* go right into main loop (don't open a BOS connection, etc) */
+       return 1;
+}
+
+       2. Connect the handler to your authorizer connection before 
+               calling aim_send_login() or aim_select():
+
+       ...
+       aim_conn_addhandler(sess, authconn, AIM_CB_FAM_SPECIAL,
+                               AIM_CB_SPECIAL_DEBUGCONN_CONNECT, 
+                               debugconn_connect_handler, 0);
+       ...
+
+       3. Start your client with the authorizer host set to the box
+               running the aimddebugd.
+
+
+Writing Halfscripts
+-------------------
+
+Some hacking of aimdebugd can be done without writing any C.  But it
+its write-only.  
+
+Once aimdebugd gets the acknowledgment from the client, it can begin
+to run through a file (passed through a command line) that contains a
+listing of excruciatingly simple "commands" and react to it.  The
+commandset is very small, and, as mentioned above, is write-only --
+its not event driven.  The list of commands is executed linearly and
+does not stop until it hits the break command, hits the end of the
+file, hits the disconnect command, or the connection to the client
+dies.
+
+Commands:
+       # -- Comment
+       b -- Breaks execution, leaves connection open
+       d -- Disconnects from client (results in connection termination)
+       e <msg> -- Prints msg to stderr
+       m <srcsn>/<msg> -- Sends msg from srcsn to the client
+       s <seconds> -- Sleeps for an arbitrary number of seconds
+       
+Note that the client must have callbacks connected to the appropriate
+handlers if it wants to react to any of the output from these commands
+(except 'e', thats just there).
+
+
+
diff --git a/utils/aimdebugd/aimdebugd.c b/utils/aimdebugd/aimdebugd.c
new file mode 100644 (file)
index 0000000..1779a4d
--- /dev/null
@@ -0,0 +1,229 @@
+
+#include <faim/aim.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include "network.h"
+
+#define RUNNAME "aimdebugd"
+#define RUNPREFIX RUNNAME ": "
+
+typedef struct {
+  struct aim_session_t sess;
+} client_t;
+
+int stayalive = 1;
+
+int clientready = 0;
+int scriptfd = -1;
+
+void sigchld(int signum)
+{
+  pid_t pid;
+  int status;
+
+  pid = wait(&status);
+  
+  return;
+}
+
+int cb_login(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  return 1;
+}
+
+int incomingim(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  int channel;
+  va_list ap;
+
+  va_start(ap, command);
+  channel = va_arg(ap, int);
+
+  if (channel == 1) {
+    char *sn = NULL;
+    char *msg = NULL;
+    u_int icbmflags = 0;
+    u_short flag1, flag2;
+    
+    sn = va_arg(ap, char *);
+    msg = va_arg(ap, char *);
+    icbmflags = va_arg(ap, u_int);
+    flag1 = va_arg(ap, u_short);
+    flag2 = va_arg(ap, u_short);
+    va_end(ap);
+    
+    printf("aimdebugd: client %d: %s/0x%04x/0x%02x/0x%02x/%s\n",
+          getpid(),
+          sn,
+          icbmflags, flag1,
+          flag2, msg);
+
+  } else
+    printf("aimdebugd: client %d: unsupported ICBM channel %d\n", getpid(), channel);
+
+  return 1;
+}
+
+int debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{
+  struct aim_conn_t *scriptconn;
+
+  clientready = 1;
+
+  if (!(scriptconn = aim_newconn(sess, 0, NULL))) {
+    printf(RUNPREFIX "unable to allocate script structures\n");
+    aim_logoff(sess);
+    return 1;
+  }
+  scriptconn->fd = scriptfd;
+
+  return 1;
+}
+
+int parsescriptline(struct aim_session_t *sess, struct aim_conn_t **conn); /* file.c */
+
+int handlechild(int fd, char *scriptname)
+{      
+  int stayalive = 1, selstat;
+  client_t client;
+  struct aim_conn_t *inconn, *waitingconn;
+
+  aim_session_init(&client.sess);
+  
+  if (!(inconn = aim_newconn(&client.sess, AIM_CONN_TYPE_BOS, NULL))) {
+    printf(RUNPREFIX "unable to allocate client structures\n");
+    exit(-1);
+  }
+  inconn->fd = fd;
+
+  if (scriptname) {
+    if (scriptname[0] == '-') 
+      scriptfd = STDIN_FILENO; 
+    else if ((scriptfd = open(scriptname, O_RDONLY)) < 0) {
+      perror(RUNPREFIX "open");
+      return -1;
+    }
+  }
+
+  aim_conn_addhandler(&client.sess, inconn, 0x0000, 0x0001, cb_login, 0);
+  aim_conn_addhandler(&client.sess, inconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, debugconn_connect, 0);
+  aim_conn_addhandler(&client.sess, inconn, 0x0004, 0x0006, incomingim, 0);
+
+  aim_debugconn_sendconnect(&client.sess, inconn);
+
+  while (stayalive) {
+    waitingconn = aim_select(&client.sess, NULL, &selstat);
+    
+    switch(selstat) {
+    case -1: /* error */
+      stayalive = 0; /* fall through and hit aim_logoff() */
+      break;
+    case 0: /* nothing pending */
+      break;
+    case 1: /* outgoing data pending */
+      aim_tx_flushqueue(&client.sess);
+      break;
+    case 2: /* incoming data pending */
+      if (waitingconn->fd == scriptfd) {
+       if (clientready) {
+         if (parsescriptline(&client.sess, &waitingconn) < 0) {
+           stayalive = 0;
+         }
+       }
+      } else {
+       if (aim_get_command(&client.sess, waitingconn) < 0) {
+         printf(RUNPREFIX "connection error\n");
+         stayalive = 0; /* fall through to aim_logoff() */
+       } else {
+         aim_rxdispatch(&client.sess);
+       }
+      }
+      break;
+    default: /* invalid */
+      break;
+    }
+  }
+
+  printf(RUNPREFIX "client disconnected\n");
+
+  aim_logoff(&client.sess);
+
+  return fd;
+}
+
+int main(int argc, char **argv)
+{
+  int listener = -1;
+  int client = -1;
+  int n;
+  char *scriptname = NULL;
+  int nofork = 0;
+  int runonce = 0, runsleft = 1;
+  
+  while ((n = getopt(argc, argv, "c:noh")) != EOF) {
+    switch(n) {
+    case 'c':
+      scriptname = optarg;
+      break;
+    case 'n': /* don't fork */
+      nofork = 1;
+      break;
+    case 'o': /* run once only */
+      runonce = 1;
+      break;
+    usage:
+    case 'h':
+      printf("aimdebugd v0.10 -- Adam Fritzler (mid@auk.cx)\n");
+      printf("Usage:\n");
+      printf("\taimdebugd [-c file] [-n] [-o]\n");
+      printf("\t\t-c file\tScript file or - for stdin\n");
+      printf("\t\t-n\tDo not fork for each client, process serially\n");
+      printf("\t\t-o\tRun once and exit (required if script from stdin)\n");
+      printf("\n");
+      exit(2);
+    }
+  }
+
+  if (scriptname && (scriptname[0] == '-') && (!nofork || !runonce)) {
+    printf(RUNPREFIX "stdin script is not valid without -n and -o\n");
+    return -1;
+  }
+
+  printf(RUNPREFIX "starting\n");
+
+  signal(SIGCHLD, sigchld);
+  
+  if ((listener = establish(5190)) < 0) {
+    perror(RUNPREFIX "establish");
+    exit(-1);
+  }
+
+  while (stayalive) {
+    if (runonce && !runsleft)
+      break;
+    if ((client = get_connection(listener)) < 0) {
+      perror(RUNPREFIX "get_connection");
+      stayalive = 0;
+    } else {
+      runsleft--;
+      if (nofork)
+       handlechild(client, scriptname);
+      else {
+       switch(fork()) {
+       case -1:
+         perror(RUNPREFIX "fork");
+         break;
+       case 0:
+         return handlechild(client, scriptname);
+         break;
+       default:
+         close(client); /* let the child have it */
+         break;
+       }
+      }
+    }
+  }
+  
+  printf(RUNPREFIX "stopping\n");
+  return 0;
+}
diff --git a/utils/aimdebugd/file.c b/utils/aimdebugd/file.c
new file mode 100644 (file)
index 0000000..a8e9867
--- /dev/null
@@ -0,0 +1,101 @@
+
+#include <faim/aim.h>
+
+static int readln(int fd, char *buf, int buflen)
+{
+  int i = 0;
+  int ret = 0;
+
+  while ((i < buflen) && ((ret = read(fd, buf, 1)) > 0)) {
+    if (*buf == '\n') {
+      *buf = '\0';
+      return i;
+    }
+    buf++;
+    i++;
+  }
+
+  if (ret == 0) {
+    *buf = '\0';
+    return i;
+  }
+
+  if (ret == -1)
+    perror("read");
+
+  return -1;
+}
+
+static inline char *killwhite(char *inbuf)
+{
+  char *buf;
+  buf = inbuf;
+  while(buf && ((*buf==' ') || (*buf=='\t'))) /* skip leading whitespace */
+    buf++;
+  return buf;
+}
+
+static inline char *nextwhite(char *inbuf)
+{
+  char *buf;
+  buf = inbuf;
+  while(buf) {
+    if ((*buf != ' '))
+      buf++;
+    else
+      return buf;
+  }
+  return buf;
+}
+
+int parsescriptline2(struct aim_session_t *sess, struct aim_conn_t **scriptconn, char *buf)
+{
+  if (!buf)
+    return 0;
+
+  switch (buf[0]) {
+  case '#': /* comment */
+    break;
+  case 'b': /* break */
+    aim_conn_kill(sess, scriptconn);
+    break;
+  case 'd': /* disconnect */
+    aim_conn_kill(sess, scriptconn);
+    aim_logoff(sess);
+    return -1;
+    break;
+  case 'e': /* print to stderr */
+    buf = nextwhite(buf)+1;
+    fprintf(stderr, "%s\n", buf);
+    break;
+  case 'm': /* message */
+    {  
+      char *sn, *msg;
+      buf = nextwhite(buf)+1;
+      sn = strsep(&buf, "/");
+      msg = strsep(&buf, "/");
+      sendimtoclient(sess, aim_getconn_type(sess, AIM_CONN_TYPE_BOS), sn, 0, msg);
+    }
+    break;
+  case 's': /* sleep */
+    buf = nextwhite(buf)+1;
+    printf("sleeping for %d seconds\n", atoi(buf));
+    sleep(atoi(buf));
+    break;
+  default:
+    printf("unknown script command %c\n", buf[0]);
+    break;
+  }
+  return 0;
+}
+
+int parsescriptline(struct aim_session_t *sess, struct aim_conn_t **conn)
+{
+  char buf[256];
+  if (readln((*conn)->fd, buf, 255) > 0) 
+    return parsescriptline2(sess, conn, buf);
+  else {
+    aim_conn_kill(sess, conn);
+  }
+  return 0;
+}
diff --git a/utils/aimdebugd/icbm.c b/utils/aimdebugd/icbm.c
new file mode 100644 (file)
index 0000000..db42969
--- /dev/null
@@ -0,0 +1,106 @@
+
+#include <faim/aim.h>
+
+int sendimtoclient(struct aim_session_t *sess, struct aim_conn_t *conn,
+                  char *srcsn, u_int flags, char *msg)
+{
+  struct command_tx_struct *tx;
+  struct aimd_clientinfo *client = NULL;
+  struct aim_tlvlist_t *tlvlist = NULL;
+  struct aim_tlvlist_t *tlvlist2 = NULL;
+  int i = 0, y, z;
+  char *msgblock;
+
+  if (!(tx = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, strlen(msg)+256)))
+    return -1;
+
+  tx->lock = 1;
+
+  msgblock = malloc(strlen(msg)+128); /* ?? */
+  memset(msgblock, 0, strlen(msg)+128);
+
+  z = 0;
+  z += aimutil_put8(msgblock+z, 0x00);
+  z += aimutil_put8(msgblock+z, 0x00);
+
+  z += aimutil_put16(msgblock+z, 0x02);
+  z += aimutil_put8(msgblock+z, 0x00);
+  z += aimutil_put8(msgblock+z, 0x00);
+
+  z += aimutil_put8(msgblock+z, 0x00);
+  z += aimutil_put8(msgblock+z, 0x00);
+
+  z += aimutil_put16(msgblock+z, strlen(msg)+4);
+  /* flag words */
+  z += aimutil_put16(msgblock+z, 0x0000);
+  z += aimutil_put16(msgblock+z, 0x0000);
+
+  /* msg */
+  z += aimutil_putstr(msgblock+z, msg, strlen(msg));
+
+  /*
+   * SNAC header
+   */
+  i = 0;
+  i += aimutil_put16(tx->data+i, 0x0004);
+  i += aimutil_put16(tx->data+i, 0x0007);
+  i += aimutil_put16(tx->data+i, 0x0000);
+  i += aimutil_put16(tx->data+i, 0x0000);
+  i += aimutil_put16(tx->data+i, 0x0000);
+
+  /*
+   * Message cookie
+   */
+  for (y=0;y<8;y++)
+    i += aimutil_put8(tx->data+i+y, (u_char) random());
+
+  /*
+   * Channel ID
+   */
+  i += aimutil_put16(tx->data+i, 0x0001);
+
+  /*
+   * Source SN
+   */
+  i += aimutil_put8(tx->data+i, strlen(srcsn));
+  i += aimutil_putstr(tx->data+i, srcsn, strlen(srcsn));
+
+  /*
+   * Warning level
+   */
+  i += aimutil_put16(tx->data+i, 0x0000);
+
+  /* class */
+  aim_addtlvtochain16(&tlvlist, 0x0001, AIM_CLASS_FREE | AIM_CLASS_TRIAL);
+
+  /* member-since date */
+  aim_addtlvtochain32(&tlvlist, 0x0002, 0);
+
+  /* on-since date */
+  aim_addtlvtochain32(&tlvlist, 0x0003, 0);
+
+  /* idle-time */
+  aim_addtlvtochain16(&tlvlist, 0x0004, 0);
+
+  /* session length (AIM) */
+  aim_addtlvtochain16(&tlvlist, 0x000f, 0);
+
+  /* add msgblock to chain */
+  aim_addtlvtochain_str(&tlvlist2, 0x0002, msgblock, z);
+
+  i += aimutil_put16(tx->data+i, aim_counttlvchain(&tlvlist));
+  i += aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist);
+  tx->commandlen = aim_writetlvchain(tx->data+i, tx->commandlen-i, &tlvlist2)+i;
+  
+
+  free(msgblock);
+  aim_freetlvchain(&tlvlist);
+
+  tx->lock = 0;
+
+  aim_tx_enqueue(sess, tx);
+
+  sess->snac_nextid++;
+
+  return 0;
+}
diff --git a/utils/aimdebugd/network.c b/utils/aimdebugd/network.c
new file mode 100644 (file)
index 0000000..6c873b4
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Misc network functions
+ *
+ */
+
+#include <faim/aim.h>
+
+int Read(int fd, unsigned char *buf, int len)
+{
+  int i = 0;
+  int j = 0;
+  int err_count=0;
+  
+  while ((i < len) && (!(i < 0)))
+    {
+      j = read(fd, &(buf[i]), len-i);
+      if ( (j < 0) && (errno != EAGAIN))
+        return -errno; /* fail */
+      else if (j==0) 
+        {
+          err_count++;
+          if (err_count> 100)  {
+            /*
+             * Reached maximum number of allowed read errors.
+             *
+             * Lets suppose the connection is lost and errno didn't
+             * know it.
+             *
+             */
+          return (-1); 
+        }
+      } 
+      else
+        i += j; /* success, continue */
+    }
+  return i;
+}
+
+/*
+ *  Create a listener socket.
+ *
+ *  We go out of our way to make this interesting. (The Easy Way is not
+ *  thread-safe.)
+ *
+ */
+int establish(u_short portnum)
+{
+  int listenfd;
+  const int on = 1;
+  struct addrinfo hints, *res, *ressave;
+  char serv[5];
+  
+  sprintf(serv, "%d", portnum);
+
+  memset(&hints, 0, sizeof(struct addrinfo));
+  hints.ai_flags = AI_PASSIVE;
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  if (getaddrinfo(NULL/*any IP*/, serv, &hints, &res) != 0) {
+    perror("getaddrinfo");
+    return -1;
+  }
+
+  ressave = res;
+  do { 
+    listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (listenfd < 0)
+      continue;
+    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
+      break; /* sucess */
+    close(listenfd);
+  } while ( (res = res->ai_next) );
+
+  if (!res)
+    return -1;
+
+  if (listen(listenfd, 1024)!=0) {
+    perror("listen");
+    return -1;
+  }
+
+  freeaddrinfo(ressave);
+
+  return listenfd;
+}
+
+int get_connection(int s)
+{
+  struct sockaddr isa;
+  int addrlen = 0;
+  int t;  /* socket of connection */
+  memset(&isa, 0, sizeof(struct sockaddr));
+  if ((t = accept(s,&isa,&addrlen)) < 0) {
+    perror("accept");
+    return -1;
+  }
+
+  return t;
+}
+
+int openconn(char *hostname, int port)
+{      
+  struct sockaddr_in sa;
+  struct hostent *hp;
+  int ret;
+  
+  if (!(hp = gethostbyname(hostname))) {
+    perror("gethostbyname");
+    return -1;
+  }
+
+  memset(&sa.sin_zero, 0, 8);
+  sa.sin_port = htons(port);
+  memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
+  sa.sin_family = hp->h_addrtype;
+  
+  ret = socket(hp->h_addrtype, SOCK_STREAM, 0);
+  if (connect(ret, (struct sockaddr *)&sa, sizeof(struct sockaddr_in))<0) {
+    perror("connect");
+    return -1;
+  }
+
+  return ret;
+}
diff --git a/utils/aimdebugd/network.h b/utils/aimdebugd/network.h
new file mode 100644 (file)
index 0000000..57cd97b
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * Common functions used in all apps
+ */
+
+int Read(int fd, unsigned char *buf, int len);
+int establish(u_short portnum);
+int get_connection(int s);
+int openconn(char *hostname, int port);
diff --git a/utils/aimdebugd/samplescript b/utils/aimdebugd/samplescript
new file mode 100644 (file)
index 0000000..ab23ffa
--- /dev/null
@@ -0,0 +1,5 @@
+# Simple test script
+e Starting test script...
+m bleu/goodday
+e Breaking...
+b
index 4763eda445d512982b0500b291f5c7ef44526871..fc00748c02233e4ac61de9f15d0db3c0c3b0a91e 100644 (file)
@@ -65,6 +65,7 @@ int faimtest_chat_infoupdate(struct aim_session_t *sess, struct command_rx_struc
 int faimtest_chat_leave(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 int faimtest_chat_join(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct *command, ...);
+int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...);
 
 int faimtest_reportinterval(struct aim_session_t *sess, struct command_rx_struct *command, ...)
 {
@@ -128,6 +129,7 @@ int main(void)
   aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, faimtest_authsvrready, 0);
   aim_send_login(&aimsess, authconn, screenname, password, &info);
 #endif
+  aim_conn_addhandler(&aimsess, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_DEBUGCONN_CONNECT, faimtest_debugconn_connect, 0);
   printf("faimtest: login sent\n");
 
   while (keepgoing) {
@@ -973,3 +975,19 @@ int faimtest_parse_connerr(struct aim_session_t *sess, struct command_rx_struct
 
   return 1;
 }
+
+int faimtest_debugconn_connect(struct aim_session_t *sess, struct command_rx_struct *command, ...)
+{      
+  printf("faimtest: connecting to an aimdebugd!\n");
+
+  /* convert the authorizer connection to a BOS connection */
+  command->conn->type = AIM_CONN_TYPE_BOS;
+
+  aim_conn_addhandler(sess, command->conn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, faimtest_parse_incoming_im, 0);
+
+  /* tell the aimddebugd we're ready */
+  aim_debugconn_sendconnect(sess, command->conn); 
+
+  /* go right into main loop (don't open a BOS connection, etc) */
+  return 1;
+}
This page took 0.08987 seconds and 5 git commands to generate.