📄 service.c
字号:
/* * Finally, tell the client it's ready to go... */ if ((userfunc = aim_callhandler(sess, rx->conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE))) userfunc(sess, rx); return 1;}/* Subtype 0x0008 - Add Rate Parameter */faim_internal int aim_rates_addparam(aim_session_t *sess, aim_conn_t *conn){ aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; aim_frame_t *fr; aim_snacid_t snacid; struct rateclass *rc; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0001, 0x0008, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0008, 0x0000, snacid); for (rc = ins->rates; rc; rc = rc->next) aimbs_put16(&fr->data, rc->classid); aim_tx_enqueue(sess, fr); return 0;}/* Subtype 0x0009 - Delete Rate Parameter */faim_internal int aim_rates_delparam(aim_session_t *sess, aim_conn_t *conn){ aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; aim_frame_t *fr; aim_snacid_t snacid; struct rateclass *rc; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 512))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0001, 0x0009, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0009, 0x0000, snacid); for (rc = ins->rates; rc; rc = rc->next) aimbs_put16(&fr->data, rc->classid); aim_tx_enqueue(sess, fr); return 0;}/* Subtype 0x000a - Rate Change */static int ratechange(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; fu16_t code, rateclass; fu32_t currentavg, maxavg, windowsize, clear, alert, limit, disconnect; code = aimbs_get16(bs); rateclass = aimbs_get16(bs); windowsize = aimbs_get32(bs); clear = aimbs_get32(bs); alert = aimbs_get32(bs); limit = aimbs_get32(bs); disconnect = aimbs_get32(bs); currentavg = aimbs_get32(bs); maxavg = aimbs_get32(bs); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, code, rateclass, windowsize, clear, alert, limit, disconnect, currentavg, maxavg); return ret;}/* * How Migrations work. * * The server sends a Server Pause message, which the client should respond to * with a Server Pause Ack, which contains the families it needs on this * connection. The server will send a Migration Notice with an IP address, and * then disconnect. Next the client should open the connection and send the * cookie. Repeat the normal login process and pretend this never happened. * * The Server Pause contains no data. * *//* Subtype 0x000b - Service Pause */static int serverpause(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx); return ret;}/* * Subtype 0x000c - Service Pause Acknowledgement * * It is rather important that aim_sendpauseack() gets called for the exact * same connection that the Server Pause callback was called for, since * libfaim extracts the data for the SNAC from the connection structure. * * Of course, if you don't do that, more bad things happen than just what * libfaim can cause. * */faim_export int aim_sendpauseack(aim_session_t *sess, aim_conn_t *conn){ aim_frame_t *fr; aim_snacid_t snacid; aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; struct snacgroup *sg; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1024))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0001, 0x000c, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x000c, 0x0000, snacid); /* * This list should have all the groups that the original * Host Online / Server Ready said this host supports. And * we want them all back after the migration. */ for (sg = ins->groups; sg; sg = sg->next) aimbs_put16(&fr->data, sg->group); aim_tx_enqueue(sess, fr); return 0;}/* Subtype 0x000d - Service Resume */static int serverresume(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx); return ret;}/* Subtype 0x000e - Request self-info */faim_export int aim_reqpersonalinfo(aim_session_t *sess, aim_conn_t *conn){ return aim_genericreq_n_snacid(sess, conn, 0x0001, 0x000e);}/* Subtype 0x000f - Self User Info */static int selfinfo(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; aim_userinfo_t userinfo; aim_info_extract(sess, bs, &userinfo); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, &userinfo); aim_info_free(&userinfo); return ret;}/* Subtype 0x0010 - Evil Notification */static int evilnotify(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ int ret = 0; aim_rxcallback_t userfunc; fu16_t newevil; aim_userinfo_t userinfo; memset(&userinfo, 0, sizeof(aim_userinfo_t)); newevil = aimbs_get16(bs); if (aim_bstream_empty(bs)) aim_info_extract(sess, bs, &userinfo); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, newevil, &userinfo); aim_info_free(&userinfo); return ret;}/* * Subtype 0x0011 - Idle Notification * * Should set your current idle time in seconds. Note that this should * never be called consecutively with a non-zero idle time. That makes * OSCAR do funny things. Instead, just set it once you go idle, and then * call it again with zero when you're back. * */faim_export int aim_srv_setidle(aim_session_t *sess, fu32_t idletime){ aim_conn_t *conn; if (!sess || !(conn = aim_conn_findbygroup(sess, AIM_CB_FAM_BOS))) return -EINVAL; return aim_genericreq_l(sess, conn, 0x0001, 0x0011, &idletime);}/* * Subtype 0x0012 - Service Migrate * * This is the final SNAC sent on the original connection during a migration. * It contains the IP and cookie used to connect to the new server, and * optionally a list of the SNAC groups being migrated. * */static int migrate(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ aim_rxcallback_t userfunc; int ret = 0; fu16_t groupcount, i; aim_tlvlist_t *tl; char *ip = NULL; aim_tlv_t *cktlv; /* * Apparently there's some fun stuff that can happen right here. The * migration can actually be quite selective about what groups it * moves to the new server. When not all the groups for a connection * are migrated, or they are all migrated but some groups are moved * to a different server than others, it is called a bifurcated * migration. * * Let's play dumb and not support that. * */ groupcount = aimbs_get16(bs); for (i = 0; i < groupcount; i++) { fu16_t group; group = aimbs_get16(bs); faimdprintf(sess, 0, "bifurcated migration unsupported -- group 0x%04x\n", group); } tl = aim_tlvlist_read(bs); if (aim_tlv_gettlv(tl, 0x0005, 1)) ip = aim_tlv_getstr(tl, 0x0005, 1); cktlv = aim_tlv_gettlv(tl, 0x0006, 1); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, ip, cktlv ? cktlv->value : NULL); aim_tlvlist_free(&tl); free(ip); return ret;}/* Subtype 0x0013 - Message of the Day */static int motd(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_bstream_t *bs){ aim_rxcallback_t userfunc; char *msg = NULL; int ret = 0; aim_tlvlist_t *tlvlist; fu16_t id; /* * Code. * * Valid values: * 1 Mandatory upgrade * 2 Advisory upgrade * 3 System bulletin * 4 Nothing's wrong ("top o the world" -- normal) * 5 Lets-break-something. * */ id = aimbs_get16(bs); /* * TLVs follow */ tlvlist = aim_tlvlist_read(bs); msg = aim_tlv_getstr(tlvlist, 0x000b, 1); if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype))) ret = userfunc(sess, rx, id, msg); free(msg); aim_tlvlist_free(&tlvlist); return ret;}/* * Subtype 0x0014 - Set privacy flags * * Normally 0x03. * * Bit 1: Allows other AIM users to see how long you've been idle. * Bit 2: Allows other AIM users to see how long you've been a member. * */faim_export int aim_bos_setprivacyflags(aim_session_t *sess, aim_conn_t *conn, fu32_t flags){ return aim_genericreq_l(sess, conn, 0x0001, 0x0014, &flags);}/* * Subtype 0x0016 - No-op * * WinAIM sends these every 4min or so to keep the connection alive. Its not * really necessary. * * Wha? No? Since when? I think WinAIM sends an empty channel 3 * SNAC as a no-op... */faim_export int aim_nop(aim_session_t *sess, aim_conn_t *conn){ return aim_genericreq_n(sess, conn, 0x0001, 0x0016);}/* * Subtype 0x0017 - Set client versions * * If you've seen the clientonline/clientready SNAC you're probably * wondering what the point of this one is. And that point seems to be * that the versions in the client online SNAC are sent too late for the * server to be able to use them to change the protocol for the earlier * login packets (client versions are sent right after Host Online is * received, but client online versions aren't sent until quite a bit later). * We can see them already making use of this by changing the format of * the rate information based on what version of group 1 we advertise here. * */faim_internal int aim_setversions(aim_session_t *sess, aim_conn_t *conn){ aim_conn_inside_t *ins = (aim_conn_inside_t *)conn->inside; struct snacgroup *sg; aim_frame_t *fr; aim_snacid_t snacid; if (!ins) return -EINVAL; if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 1152))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0001, 0x0017, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0001, 0x0017, 0x0000, snacid); /* * Send only the versions that the server cares about (that it * marked as supporting in the server ready SNAC). */ for (sg = ins->groups; sg; sg = sg->next) { aim_module_t *mod; if ((mod = aim__findmodulebygroup(sess, sg->group))) { aimbs_put16(&fr->data, mod->family);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -