| 260 * See joscar's javadoc for the RateClassInfo class for a great |
260 * See joscar's javadoc for the RateClassInfo class for a great |
| 261 * explanation. You might be able to find it at |
261 * explanation. You might be able to find it at |
| 262 * http://dscoder.com/RateClassInfo.html |
262 * http://dscoder.com/RateClassInfo.html |
| 263 */ |
263 */ |
| 264 |
264 |
| |
265 static struct rateclass * |
| |
266 rateclass_find(GSList *rateclasses, guint16 id) |
| |
267 { |
| |
268 GSList *tmp; |
| |
269 struct rateclass *rateclass; |
| |
270 |
| |
271 for (tmp = rateclasses; tmp != NULL; tmp = tmp->next) |
| |
272 { |
| |
273 rateclass = tmp->data; |
| |
274 if (rateclass->classid == id) |
| |
275 return rateclass; |
| |
276 } |
| |
277 |
| |
278 return NULL; |
| |
279 } |
| |
280 |
| 265 static void |
281 static void |
| 266 rc_addclass(struct rateclass **head, struct rateclass *inrc) |
282 rateclass_addpair(struct rateclass *rateclass, guint16 group, guint16 type) |
| 267 { |
283 { |
| 268 struct rateclass *rc, *rc2; |
284 struct snacpair *snacpair; |
| 269 |
285 |
| 270 rc = g_memdup(inrc, sizeof(struct rateclass)); |
286 snacpair = g_new(struct snacpair, 1); |
| 271 rc->next = NULL; |
287 snacpair->group = group; |
| 272 |
288 snacpair->subtype = type; |
| 273 for (rc2 = *head; rc2 && rc2->next; rc2 = rc2->next) |
289 |
| 274 ; |
290 rateclass->members = g_slist_prepend(rateclass->members, snacpair); |
| 275 |
|
| 276 if (!rc2) |
|
| 277 *head = rc; |
|
| 278 else |
|
| 279 rc2->next = rc; |
|
| 280 |
|
| 281 return; |
|
| 282 } |
|
| 283 |
|
| 284 static struct rateclass * |
|
| 285 rc_findclass(struct rateclass **head, guint16 id) |
|
| 286 { |
|
| 287 struct rateclass *rc; |
|
| 288 |
|
| 289 for (rc = *head; rc; rc = rc->next) { |
|
| 290 if (rc->classid == id) |
|
| 291 return rc; |
|
| 292 } |
|
| 293 |
|
| 294 return NULL; |
|
| 295 } |
|
| 296 |
|
| 297 static void |
|
| 298 rc_addpair(struct rateclass *rc, guint16 group, guint16 type) |
|
| 299 { |
|
| 300 struct snacpair *sp, *sp2; |
|
| 301 |
|
| 302 sp = g_new0(struct snacpair, 1); |
|
| 303 sp->group = group; |
|
| 304 sp->subtype = type; |
|
| 305 sp->next = NULL; |
|
| 306 |
|
| 307 for (sp2 = rc->members; sp2 && sp2->next; sp2 = sp2->next) |
|
| 308 ; |
|
| 309 |
|
| 310 if (!sp2) |
|
| 311 rc->members = sp; |
|
| 312 else |
|
| 313 sp2->next = sp; |
|
| 314 |
|
| 315 return; |
|
| 316 } |
291 } |
| 317 |
292 |
| 318 /* Subtype 0x0007 - Rate Parameters */ |
293 /* Subtype 0x0007 - Rate Parameters */ |
| 319 static int |
294 static int |
| 320 rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) |
295 rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs) |
| 324 |
299 |
| 325 /* |
300 /* |
| 326 * First are the parameters for each rate class. |
301 * First are the parameters for each rate class. |
| 327 */ |
302 */ |
| 328 numclasses = byte_stream_get16(bs); |
303 numclasses = byte_stream_get16(bs); |
| 329 for (i = 0; i < numclasses; i++) { |
304 for (i = 0; i < numclasses; i++) |
| 330 struct rateclass rc; |
305 { |
| 331 |
306 struct rateclass *rateclass; |
| 332 memset(&rc, 0, sizeof(struct rateclass)); |
307 |
| 333 |
308 rateclass = g_new0(struct rateclass, 1); |
| 334 rc.classid = byte_stream_get16(bs); |
309 |
| 335 rc.windowsize = byte_stream_get32(bs); |
310 rateclass->classid = byte_stream_get16(bs); |
| 336 rc.clear = byte_stream_get32(bs); |
311 rateclass->windowsize = byte_stream_get32(bs); |
| 337 rc.alert = byte_stream_get32(bs); |
312 rateclass->clear = byte_stream_get32(bs); |
| 338 rc.limit = byte_stream_get32(bs); |
313 rateclass->alert = byte_stream_get32(bs); |
| 339 rc.disconnect = byte_stream_get32(bs); |
314 rateclass->limit = byte_stream_get32(bs); |
| 340 rc.current = byte_stream_get32(bs); |
315 rateclass->disconnect = byte_stream_get32(bs); |
| 341 rc.max = byte_stream_get32(bs); |
316 rateclass->current = byte_stream_get32(bs); |
| |
317 rateclass->max = byte_stream_get32(bs); |
| 342 |
318 |
| 343 /* |
319 /* |
| 344 * The server will send an extra five bytes of parameters |
320 * The server will send an extra five bytes of parameters |
| 345 * depending on the version we advertised in 1/17. If we |
321 * depending on the version we advertised in 1/17. If we |
| 346 * didn't send 1/17 (evil!), then this will crash and you |
322 * didn't send 1/17 (evil!), then this will crash and you |
| 347 * die, as it will default to the old version but we have |
323 * die, as it will default to the old version but we have |
| 348 * the new version hardcoded here. |
324 * the new version hardcoded here. |
| 349 */ |
325 */ |
| 350 if (mod->version >= 3) |
326 if (mod->version >= 3) |
| 351 byte_stream_getrawbuf(bs, rc.unknown, sizeof(rc.unknown)); |
327 byte_stream_getrawbuf(bs, rateclass->unknown, sizeof(rateclass->unknown)); |
| 352 |
328 |
| 353 rc_addclass(&conn->rates, &rc); |
329 conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass); |
| 354 } |
330 } |
| |
331 conn->rateclasses = g_slist_reverse(conn->rateclasses); |
| 355 |
332 |
| 356 /* |
333 /* |
| 357 * Then the members of each class. |
334 * Then the members of each class. |
| 358 */ |
335 */ |
| 359 for (i = 0; i < numclasses; i++) { |
336 for (i = 0; i < numclasses; i++) |
| |
337 { |
| 360 guint16 classid, count; |
338 guint16 classid, count; |
| 361 struct rateclass *rc; |
339 struct rateclass *rateclass; |
| 362 int j; |
340 int j; |
| 363 |
341 |
| 364 classid = byte_stream_get16(bs); |
342 classid = byte_stream_get16(bs); |
| 365 count = byte_stream_get16(bs); |
343 count = byte_stream_get16(bs); |
| 366 |
344 |
| 367 rc = rc_findclass(&conn->rates, classid); |
345 rateclass = rateclass_find(conn->rateclasses, classid); |
| 368 |
346 |
| 369 for (j = 0; j < count; j++) { |
347 for (j = 0; j < count; j++) |
| |
348 { |
| 370 guint16 group, subtype; |
349 guint16 group, subtype; |
| 371 |
350 |
| 372 group = byte_stream_get16(bs); |
351 group = byte_stream_get16(bs); |
| 373 subtype = byte_stream_get16(bs); |
352 subtype = byte_stream_get16(bs); |
| 374 |
353 |
| 375 if (rc) |
354 if (rateclass != NULL) |
| 376 rc_addpair(rc, group, subtype); |
355 rateclass_addpair(rateclass, group, subtype); |
| 377 } |
356 } |
| |
357 rateclass->members = g_slist_reverse(rateclass->members); |
| 378 } |
358 } |
| 379 |
359 |
| 380 /* |
360 /* |
| 381 * We don't pass the rate information up to the client, as it really |
361 * We don't pass the rate information up to the client, as it really |
| 382 * doesn't care. The information is stored in the connection, however |
362 * doesn't care. The information is stored in the connection, however |
| 383 * so that we can do more fun stuff later (not really). |
363 * so that we can do rate limiting management when sending SNACs. |
| 384 */ |
364 */ |
| 385 |
365 |
| 386 /* |
366 /* |
| 387 * Last step in the conn init procedure is to acknowledge that we |
367 * Last step in the conn init procedure is to acknowledge that we |
| 388 * agree to these draconian limitations. |
368 * agree to these draconian limitations. |
| 402 void |
382 void |
| 403 aim_srv_rates_addparam(OscarData *od, FlapConnection *conn) |
383 aim_srv_rates_addparam(OscarData *od, FlapConnection *conn) |
| 404 { |
384 { |
| 405 FlapFrame *frame; |
385 FlapFrame *frame; |
| 406 aim_snacid_t snacid; |
386 aim_snacid_t snacid; |
| 407 struct rateclass *rc; |
387 GSList *tmp; |
| 408 |
388 |
| 409 frame = flap_frame_new(od, 0x02, 512); |
389 frame = flap_frame_new(od, 0x02, 512); |
| 410 |
390 |
| 411 snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0); |
391 snacid = aim_cachesnac(od, 0x0001, 0x0008, 0x0000, NULL, 0); |
| 412 aim_putsnac(&frame->data, 0x0001, 0x0008, 0x0000, snacid); |
392 aim_putsnac(&frame->data, 0x0001, 0x0008, 0x0000, snacid); |
| 413 |
393 |
| 414 for (rc = conn->rates; rc; rc = rc->next) |
394 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next) |
| 415 byte_stream_put16(&frame->data, rc->classid); |
395 { |
| |
396 struct rateclass *rateclass; |
| |
397 rateclass = tmp->data; |
| |
398 byte_stream_put16(&frame->data, rateclass->classid); |
| |
399 } |
| 416 |
400 |
| 417 flap_connection_send(conn, frame); |
401 flap_connection_send(conn, frame); |
| 418 } |
402 } |
| 419 |
403 |
| 420 /* Subtype 0x0009 - Delete Rate Parameter */ |
404 /* Subtype 0x0009 - Delete Rate Parameter */ |
| 421 void |
405 void |
| 422 aim_srv_rates_delparam(OscarData *od, FlapConnection *conn) |
406 aim_srv_rates_delparam(OscarData *od, FlapConnection *conn) |
| 423 { |
407 { |
| 424 FlapFrame *frame; |
408 FlapFrame *frame; |
| 425 aim_snacid_t snacid; |
409 aim_snacid_t snacid; |
| 426 struct rateclass *rc; |
410 GSList *tmp; |
| 427 |
411 |
| 428 frame = flap_frame_new(od, 0x02, 512); |
412 frame = flap_frame_new(od, 0x02, 512); |
| 429 |
413 |
| 430 snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0); |
414 snacid = aim_cachesnac(od, 0x0001, 0x0009, 0x0000, NULL, 0); |
| 431 aim_putsnac(&frame->data, 0x0001, 0x0009, 0x0000, snacid); |
415 aim_putsnac(&frame->data, 0x0001, 0x0009, 0x0000, snacid); |
| 432 |
416 |
| 433 for (rc = conn->rates; rc; rc = rc->next) |
417 for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next) |
| 434 byte_stream_put16(&frame->data, rc->classid); |
418 { |
| |
419 struct rateclass *rateclass; |
| |
420 rateclass = tmp->data; |
| |
421 byte_stream_put16(&frame->data, rateclass->classid); |
| |
422 } |
| 435 |
423 |
| 436 flap_connection_send(conn, frame); |
424 flap_connection_send(conn, frame); |
| 437 } |
425 } |
| 438 |
426 |
| 439 /* Subtype 0x000a - Rate Change */ |
427 /* Subtype 0x000a - Rate Change */ |