+ if (!sess || !conn || !args)
+ return -EINVAL;
+
+ if (!args->msg || (args->msglen <= 0))
+ return -EINVAL;
+
+ if (args->msglen >= MAXMSGLEN)
+ return -E2BIG;
+
+ if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, args->msglen+512)))
+ return -ENOMEM;
+
+ newpacket->lock = 1; /* lock struct */
+
+ curbyte = 0;
+ curbyte += aim_putsnac(newpacket->data+curbyte,
+ 0x0004, 0x0006, 0x0000, sess->snac_nextid);
+
+ /*
+ * Generate a random message cookie
+ *
+ * We could cache these like we do SNAC IDs. (In fact, it
+ * might be a good idea.) In the message error functions,
+ * the 8byte message cookie is returned as well as the
+ * SNAC ID.
+ *
+ */
+ for (i = 0; i < 8; i++) {
+ curbyte += aimutil_put8(newpacket->data+curbyte,
+ (unsigned char) rand());
+ }
+
+ /*
+ * Channel ID
+ */
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
+
+ /*
+ * Destination SN (prepended with byte length)
+ */
+ curbyte += aimutil_put8(newpacket->data+curbyte, strlen(args->destsn));
+ curbyte += aimutil_putstr(newpacket->data+curbyte,
+ args->destsn, strlen(args->destsn));
+
+ /*
+ * metaTLV start.
+ */
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
+ curbyte += aimutil_put16(newpacket->data+curbyte, args->msglen + 0x10);
+
+ /*
+ * Flag data / ICBM Parameters?
+ *
+ * I don't know what these are...
+ *
+ */
+ 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);
+
+ /*
+ * Message block length.
+ */
+ curbyte += aimutil_put16(newpacket->data+curbyte, args->msglen + 0x04);
+
+ /*
+ * Character set.
+ */
+ if (args->flags & AIM_IMFLAGS_UNICODE)
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
+ else if (args->flags & AIM_IMFLAGS_ISO_8859_1)
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
+ else
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
+
+ curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
+
+ /*
+ * Message. Not terminated.
+ */
+ curbyte += aimutil_putstr(newpacket->data+curbyte,
+ args->msg, args->msglen);
+
+ /*
+ * Set the Request Acknowledge flag.
+ */
+ if (args->flags & AIM_IMFLAGS_ACK) {
+ curbyte += aimutil_put16(newpacket->data+curbyte,0x0003);
+ curbyte += aimutil_put16(newpacket->data+curbyte,0x0000);
+ }