Sun, 30 Apr 2000 21:47:04 +0000
[gaim-migrate @ 210]
Made the receive non-blocking, added a cancel button, and a few other updates.
No, sending a file to someone does not work yet. Be patient.
| 2 | 1 | /* |
| 2 | * aim_im.c | |
| 3 | * | |
| 4 | * The routines for sending/receiving Instant Messages. | |
| 5 | * | |
| 6 | */ | |
| 7 | ||
| 8 | #include "aim.h" | |
| 9 | ||
| 10 | /* | |
| 11 | * Send an ICBM (instant message). | |
| 12 | * | |
| 13 | * | |
| 14 | * Possible flags: | |
| 15 | * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse | |
| 16 | * AIM_IMFLAGS_ACK -- Requests that the server send an ack | |
| 17 | * when the message is received (of type 0x0004/0x000c) | |
| 18 | * | |
| 19 | * | |
| 20 | * TODO: Update to new standard form | |
| 21 | * | |
| 22 | * | |
| 23 | */ | |
| 24 | ||
| 25 | u_long aim_send_im(struct aim_conn_t *conn, char *destsn, int flags, char *msg) | |
| 26 | { | |
| 27 | ||
| 28 | int curbyte; | |
| 29 | struct command_tx_struct newpacket; | |
| 30 | ||
| 31 | newpacket.lock = 1; /* lock struct */ | |
| 32 | newpacket.type = 0x02; /* IMs are always family 0x02 */ | |
| 33 | if (conn) | |
| 34 | newpacket.conn = conn; | |
| 35 | else | |
| 36 | newpacket.conn = aim_getconn_type(AIM_CONN_TYPE_BOS); | |
| 37 | ||
| 38 | newpacket.commandlen = 20+1+strlen(destsn)+1+1+2+7+2+4+strlen(msg)+2; | |
| 39 | ||
| 40 | if (flags & AIM_IMFLAGS_ACK) | |
| 41 | newpacket.commandlen += 4; | |
| 42 | if (flags & AIM_IMFLAGS_AWAY) | |
| 43 | newpacket.commandlen += 4; | |
| 44 | ||
| 45 | newpacket.data = (char *) calloc(1, newpacket.commandlen); | |
| 46 | ||
| 47 | curbyte = 0; | |
| 48 | curbyte += aim_putsnac(newpacket.data+curbyte, 0x0004, 0x0006, 0x0000, aim_snac_nextid); | |
| 49 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 50 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 51 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 52 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 53 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); | |
| 54 | curbyte += aimutil_put8(newpacket.data+curbyte,strlen(destsn)); | |
| 55 | curbyte += aimutil_putstr(newpacket.data+curbyte, destsn, strlen(destsn)); | |
| 56 | ||
| 57 | if (flags & AIM_IMFLAGS_ACK) | |
| 58 | { | |
| 59 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0003); | |
| 60 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 61 | } | |
| 62 | ||
| 63 | if (flags & AIM_IMFLAGS_AWAY) | |
| 64 | { | |
| 65 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0004); | |
| 66 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 67 | } | |
| 68 | ||
| 69 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0002); | |
| 70 | curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+0xf); | |
| 71 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0501); | |
| 72 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0001); | |
| 73 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); | |
| 74 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0101); | |
| 75 | curbyte += aimutil_put8(newpacket.data+curbyte,0x01); | |
| 76 | curbyte += aimutil_put16(newpacket.data+curbyte,strlen(msg)+4); | |
| 77 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 78 | curbyte += aimutil_put16(newpacket.data+curbyte,0x0000); | |
| 79 | curbyte += aimutil_putstr(newpacket.data+curbyte, msg, strlen(msg)); | |
| 80 | ||
| 81 | aim_tx_enqueue(&newpacket); | |
| 82 | ||
| 83 | #ifdef USE_SNAC_FOR_IMS | |
| 84 | { | |
| 85 | struct aim_snac_t snac; | |
| 86 | ||
| 87 | snac.id = aim_snac_nextid; | |
| 88 | snac.family = 0x0004; | |
| 89 | snac.type = 0x0006; | |
| 90 | snac.flags = 0x0000; | |
| 91 | ||
| 92 | snac.data = malloc(strlen(destsn)+1); | |
| 93 | memcpy(snac.data, destsn, strlen(destsn)+1); | |
| 94 | ||
| 95 | aim_newsnac(&snac); | |
| 96 | } | |
| 97 | ||
| 98 | aim_cleansnacs(60); /* clean out all SNACs over 60sec old */ | |
| 99 | #endif | |
| 100 | ||
| 101 | return (aim_snac_nextid++); | |
| 102 | } | |
| 103 | ||
| 104 | int aim_parse_incoming_im_middle(struct command_rx_struct *command) | |
| 105 | { | |
| 106 | int i = 0; | |
| 107 | char *srcsn = NULL; | |
| 108 | char *msg = NULL; | |
| 109 | unsigned int msglen = 0; | |
| 110 | int warninglevel = 0; | |
| 111 | int tlvcnt = 0; | |
| 112 | int class = 0; | |
| 113 | ulong membersince = 0; | |
| 114 | ulong onsince = 0; | |
| 115 | int idletime = 0; | |
| 116 | int isautoreply = 0; | |
| 117 | ||
| 118 | i = 20; | |
| 119 | ||
| 120 | srcsn = malloc(command->data[i] + 1); | |
| 121 | memcpy(srcsn, &(command->data[i+1]), command->data[i]); | |
| 122 | srcsn[(int)command->data[i]] = '\0'; | |
| 123 | ||
| 124 | i += (int) command->data[i] + 1; /* add SN len */ | |
| 125 | ||
| 126 | /* warning level */ | |
| 127 | warninglevel = (command->data[i] << 8); | |
| 128 | warninglevel += (command->data[i+1]); | |
| 129 | i += 2; | |
| 130 | ||
| 131 | tlvcnt = ((command->data[i++]) << 8) & 0xFF00; | |
| 132 | tlvcnt += (command->data[i++]) & 0x00FF; | |
| 133 | ||
| 134 | /* a mini TLV parser */ | |
| 135 | { | |
| 136 | int curtlv = 0; | |
| 137 | int tlv1 = 0; | |
| 138 | ||
| 139 | while (curtlv < tlvcnt) | |
| 140 | { | |
| 141 | if ((command->data[i] == 0x00) && | |
| 142 | (command->data[i+1] == 0x01) ) | |
| 143 | { | |
| 144 | if (tlv1) | |
| 145 | break; | |
| 146 | /* t(0001) = class */ | |
| 147 | if (command->data[i+3] != 0x02) | |
| 148 | printf("faim: userinfo: **warning: strange v(%x) for t(1)\n", command->data[i+3]); | |
| 149 | class = ((command->data[i+4]) << 8) & 0xFF00; | |
| 150 | class += (command->data[i+5]) & 0x00FF; | |
| 151 | i += (2 + 2 + command->data[i+3]); | |
| 152 | tlv1++; | |
| 153 | } | |
| 154 | else if ((command->data[i] == 0x00) && | |
| 155 | (command->data[i+1] == 0x02)) | |
| 156 | { | |
| 157 | /* t(0002) = member since date */ | |
| 158 | if (command->data[i+3] != 0x04) | |
| 159 | printf("faim: userinfo: **warning: strange v(%x) for t(2)\n", command->data[i+3]); | |
| 160 | ||
| 161 | membersince = ((command->data[i+4]) << 24) & 0xFF000000; | |
| 162 | membersince += ((command->data[i+5]) << 16) & 0x00FF0000; | |
| 163 | membersince += ((command->data[i+6]) << 8) & 0x0000FF00; | |
| 164 | membersince += ((command->data[i+7]) ) & 0x000000FF; | |
| 165 | i += (2 + 2 + command->data[i+3]); | |
| 166 | } | |
| 167 | else if ((command->data[i] == 0x00) && | |
| 168 | (command->data[i+1] == 0x03)) | |
| 169 | { | |
| 170 | /* t(0003) = on since date */ | |
| 171 | if (command->data[i+3] != 0x04) | |
| 172 | printf("faim: userinfo: **warning: strange v(%x) for t(3)\n", command->data[i+3]); | |
| 173 | ||
| 174 | onsince = ((command->data[i+4]) << 24) & 0xFF000000; | |
| 175 | onsince += ((command->data[i+5]) << 16) & 0x00FF0000; | |
| 176 | onsince += ((command->data[i+6]) << 8) & 0x0000FF00; | |
| 177 | onsince += ((command->data[i+7]) ) & 0x000000FF; | |
| 178 | i += (2 + 2 + command->data[i+3]); | |
| 179 | } | |
| 180 | else if ((command->data[i] == 0x00) && | |
| 181 | (command->data[i+1] == 0x04) ) | |
| 182 | { | |
| 183 | /* t(0004) = idle time */ | |
| 184 | if (command->data[i+3] != 0x02) | |
| 185 | printf("faim: userinfo: **warning: strange v(%x) for t(4)\n", command->data[i+3]); | |
| 186 | idletime = ((command->data[i+4]) << 8) & 0xFF00; | |
| 187 | idletime += (command->data[i+5]) & 0x00FF; | |
| 188 | i += (2 + 2 + command->data[i+3]); | |
| 189 | } | |
| 190 | else | |
| 191 | { | |
| 192 | printf("faim: userinfo: **warning: unexpected TLV t(%02x%02x) l(%02x%02x)\n", command->data[i], command->data[i+1], command->data[i+2], command->data[i+3]); | |
| 193 | i += (2 + 2 + command->data[i+3]); | |
| 194 | } | |
| 195 | curtlv++; | |
| 196 | } | |
| 197 | } | |
| 198 | ||
| 199 | { | |
| 200 | /* detect if this is an auto-response or not */ | |
| 201 | /* auto-responses can be detected by the presence of a *second* TLV with | |
| 202 | t(0004), but of zero length (and therefore no value portion) */ | |
| 203 | struct aim_tlv_t *tsttlv = NULL; | |
| 204 | tsttlv = aim_grabtlv((u_char *) &(command->data[i])); | |
| 205 | if (tsttlv->type == 0x04) | |
| 206 | isautoreply = 1; | |
| 207 | aim_freetlv(&tsttlv); | |
| 208 | } | |
| 209 | ||
| 210 | i += 2; | |
| 211 | ||
| 212 | i += 2; /* skip first msglen */ | |
| 213 | i += 7; /* skip garbage */ | |
| 214 | i -= 4; | |
| 215 | ||
| 216 | /* oh boy is this terrible... this comes from a specific of the spec */ | |
| 217 | while(1) | |
| 218 | { | |
| 219 | if ( ( (command->data[i] == 0x00) && | |
| 220 | (command->data[i+1] == 0x00) && | |
| 221 | (command->data[i+2] == 0x00) && | |
| 222 | (command->data[i+3] == 0x00) ) && | |
| 223 | (i < command->commandlen) ) /* prevent infinity */ | |
| 224 | break; | |
| 225 | else | |
| 226 | i++; | |
| 227 | } | |
| 228 | ||
| 229 | i -= 2; | |
| 230 | ||
| 231 | if ( (command->data[i] == 0x00) && | |
| 232 | (command->data[i+1] == 0x00) ) | |
| 233 | i += 2; | |
| 234 | ||
| 235 | msglen = ( (( (unsigned int) command->data[i]) & 0xFF ) << 8); | |
| 236 | msglen += ( (unsigned int) command->data[i+1]) & 0xFF; /* mask off garbage */ | |
| 237 | i += 2; | |
| 238 | ||
| 239 | msglen -= 4; /* skip four 0x00s */ | |
| 240 | i += 4; | |
| 241 | ||
| 242 | msg = malloc(msglen +1); | |
| 243 | ||
| 244 | memcpy(msg, &(command->data[i]), msglen); | |
| 245 | msg[msglen] = '\0'; | |
| 246 | ||
| 247 | i = (aim_callbacks[AIM_CB_INCOMING_IM])(command, srcsn, msg, warninglevel, class, membersince, onsince, idletime, isautoreply); | |
| 248 | ||
| 249 | free(srcsn); | |
| 250 | free(msg); | |
| 251 | ||
| 252 | return i; | |
| 253 | } |