📄 sessions.c
字号:
/* Clean up and get out */ aim_conn_kill(ass, &authconn); return NULL; } else { aim_conn_addhandler(ass, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_FLAPVER, at_flapversion, 0); aim_conn_addhandler(ass, authconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, at_conncomplete, 0); aim_conn_addhandler(ass, authconn, 0x0017, 0x0007, at_parse_login, 0); aim_conn_addhandler(ass, authconn, 0x0017, 0x0003, at_parse_authresp, 0); //m = mio_new(authconn->fd, &at_handle_mio, authconn, mio_handlers_new(at_session_handle_read, at_session_handle_write, NULL)); //m->rated = 0; p = pool_new(); new = pmalloc(p, sizeof(_at_session)); new->m = NULL; new->p = p; new->ti = ti; new->mp_to = pth_msgport_create("aimsession_to"); new->cur=jid_new(new->p, jid_full(j)); new->from=jid_new(new->p, jid_full(from)); jid_set(new->from, "registered", JID_RESOURCE); new->ass = ass; new->exit_flag = 0; new->loggedin = 0; new->status = NULL; new->away = 0; new->icq = isdigit(user[0]); new->buddies = xhash_new(137); new->profile = NULL; new->at_PPDB = NULL; new->screenname = pstrdup(new->p, user); new->password = pstrdup(new->p, pword); new->icq_vcard_response = NULL; new->ass->aux_data = (void *)new; fpres = jutil_presnew(JPACKET__AVAILABLE, ti->i->id, "Online"); xmlnode_put_attrib(fpres, "from", jid_full(new->cur)); new->at_PPDB = ppdb_insert(new->at_PPDB, new->cur, fpres); xmlnode_free(fpres); /* am = pmalloco(new->p, sizeof(_at_mio)); am->p = new->p; am->s = new; am->conn = authconn; am->ass = ass; */ /* mio_reset(m, &at_handle_mio, am); */ /* Ok everything is good, put this in the session hash */ jput = jid_new(new->p, jid_full(new->cur)); jid_set(jput, NULL, JID_RESOURCE); xhash_put(ti->session__list, jid_full(jput), new); log_debug(ZONE, "[AT] User Login: %s", jid_full(new->cur)); aim_request_login(ass, authconn, user); attr = pth_attr_new(); new->tid = pth_spawn(attr, at_session_main, (void *)new); return new; } return NULL;}void *at_session_main(void *arg){ at_session s; ati ti; pth_event_t to; jpq q; xmlnode x; aim_conn_t *waitingconn = NULL; int status; s = (at_session)arg; ti = s->ti; to = pth_event(PTH_EVENT_MSG, s->mp_to); /* Do stuff */ log_debug(ZONE, "[AIM] In our main session"); while ((waitingconn = _aim_select(s->ass, to, &status)) >= 0) { if(s->exit_flag) break; switch(status) { case -1: /* There was an error */ s->exit_flag = 1; break; case 0: /* Nothing to do */ break; case 1: log_debug(ZONE, "[AIM] Flushing outgoing queue"); aim_tx_flushqueue(s->ass); break; case 2: if (aim_get_command(s->ass, waitingconn) < 0) { /* XXX do something like send an error */ log_debug(ZONE,"[AIM] connection error (type 0x%04x:0x%04x)", waitingconn->type, waitingconn->subtype); aim_conn_kill(s->ass, &waitingconn); if (!aim_getconn_type(s->ass, AIM_CONN_TYPE_BOS)) log_debug(ZONE,"major connection error"); s->exit_flag = 1; } else { aim_rxdispatch(s->ass); } break; case 3: while(1) { q = (jpq)pth_msgport_get(s->mp_to); if(q == NULL) { break; } at_aim_session_parser(s, q->p); if(s->exit_flag) break; } break; } if(s->exit_flag) break; } /* Close up */ log_debug(ZONE,"[AIM] Closing up a main thread"); pth_event_free(to, PTH_FREE_ALL); at_session_end(s); pth_exit(NULL); return NULL;} void at_aim_session_parser(at_session s, jpacket jp){ ati ti; int freed; char *ns; ti = s->ti; log_debug(ZONE, "[AIM] Parsing Packet on sessions"); if(s->exit_flag > 0) { xmlnode_free(jp->x); return; } switch(jp->type) { case JPACKET_IQ: if(NSCHECK(xmlnode_get_tag(jp->x, "query"),NS_REGISTER)) { /* Register the user */ freed = at_register(ti, jp); break; } ns = xmlnode_get_attrib(jp->iq,"xmlns"); freed = at_run_iqcb(ti, ns, jp); if(freed < 0) { /* XXX We could dup here and then return 0... */ jutil_error(jp->x, TERROR_NOTFOUND); at_deliver(ti,jp->x); freed = 1; } break; case JPACKET_MESSAGE: /* Put the message on the line for the session to handle */ at_session_deliver(s, jp->x, jp->to); freed = 1; break; case JPACKET_S10N: /* Handle a S10N packet based on their subtype */ log_debug(ZONE, "[AT] We got a s10n packet"); freed = at_session_s10n(s, jp); break; case JPACKET_PRESENCE: freed = at_session_pres(s, jp); break; default: /* XXX do more!? */ /*jutil_error(jp->x, TERROR_NOTACCEPTABLE); at_deliver(ti,jp->x); */ xmlnode_free(jp->x); freed = 1; break; } if(freed==0) xmlnode_free(jp->x);}void at_session_deliver(at_session s, xmlnode x, jid from){ /* XXX We need to check for the XHTML version of the msg */ char *body; char *dest; struct aim_sendimext_args args; unsigned char *utf8_str; unsigned char *unistr; unsigned short unilen; if(s->icq) body = UTF8_to_str(xmlnode_pool(x),xmlnode_get_tag_data(x, "body")); else body = xmlnode_get_tag_data(x, "body"); if(body == NULL || from->user == NULL) return; // don't forget to free! utf8_str = malloc(8192); unistr = malloc(8192); // only convert if AIM if(!s->icq) { msgconv_plain2aim(body, utf8_str, 8192); body = utf8_str; } if(!s->icq || (strstr(body, "SEND-SMS") != body)) { log_debug(ZONE, "[AIM] Sending a Message"); args.destsn = from->user; args.flags = s->icq ? AIM_IMFLAGS_OFFLINE : 0; // simple enough to be ascii ? if(isAscii(body) || s->icq) { args.msg = body; args.msglen = strlen(body); } // unicode else { unilen = utf8_to_unicode(body, unistr, 8192); args.flags |= AIM_IMFLAGS_UNICODE; args.msg = unistr; args.msglen = unilen * 2; // length has to be in bytes, not wchars } aim_send_im_ext(s->ass, &args); //aim_send_im(s->ass, from->user, s->icq ? AIM_IMFLAGS_OFFLINE : 0, body); /* XXX set offline flag only if destination is really offline */ } else { log_debug(ZONE, "[AIM] Sending a SMS"); aim_strsep(&body, ":"); dest = aim_strsep(&body, ":"); aim_icq_sendsms(s->ass,dest,body); } xmlnode_free(x); free(utf8_str); free(unistr); return;}void _at_session_save_buddies(xht ht, const char *key, void *data, void *arg){ xmlnode item; xmlnode roster; char *user; roster = (xmlnode)arg; user = (char *)key; item = xmlnode_insert_tag(roster, "item"); xmlnode_put_attrib(item, "name", user); return;}void at_session_end(at_session s){ ati ti; xmlnode x; xmlnode xset; int ret; jid jend; if(s == NULL) log_warn(ZONE,"NULL Session told to end!"); else { ti = s->ti; log_debug(ZONE, "[AT] Session (%s) told to end.", jid_full(s->cur)); printf("Ending session for %s\n", jid_full(s->cur)); jend = jid_new(s->p, jid_full(s->cur)); jid_set(jend, NULL, JID_RESOURCE); xhash_zap(ti->session__list, jid_full(jend)); x = jutil_presnew(JPACKET__UNAVAILABLE, jid_full(s->cur), "Disconnected"); xmlnode_put_attrib(x, "from", jid_full(s->from)); at_deliver(ti,x); xset = xmlnode_new_tag("buddies"); xhash_walk(s->buddies, &_at_session_save_buddies, xset); log_debug(ZONE, "Saving buddies: %s", xmlnode2str(xset)); ret = at_xdb_set(ti, ti->i->id, s->cur, xset, AT_NS_ROSTER); if(ret == 1) xmlnode_free(xset); pth_msgport_destroy(s->mp_to); aim_logoff(s->ass); aim_session_kill(s->ass); log_debug(ZONE,"[AT] unlinking session"); at_session_unlink_buddies(s); xhash_free(s->buddies); log_warn(ZONE, "[AT] Closing down session for %s", jid_full(s->cur)); ppdb_free(s->at_PPDB); free(s->ass); pool_free(s->p); } return;}void _at_session_unlink_buddies(xht ht, const char *key, void *data, void *arg){ ati ti; at_session s; xmlnode p; at_buddy buddy; s = (at_session)arg; buddy = (at_buddy)data; ti = s->ti; p = jutil_presnew(JPACKET__UNAVAILABLE, jid_full(s->cur), "Transport Disconnected"); xmlnode_put_attrib(p, "from", jid_full(buddy->full)); at_deliver(ti,p); return;}void at_session_unlink_buddies(at_session s){ at_buddy cur, next; xhash_walk(s->buddies, &_at_session_unlink_buddies, s);}int session_walk(void *user_data, const void *key, void *data){ log_debug(ZONE, "[AT] Walking key: %s data: %x", key, data); return 0;}at_session at_session_find_by_jid(ati ti, jid j){ at_session s; char *res; if(j == NULL) return NULL; res = j->resource; jid_set(j, NULL, JID_RESOURCE); log_debug(ZONE, "[AT] Finding session for %s", jid_full(j)); s = (at_session)xhash_get(ti->session__list, jid_full(j)); j->resource = res; /* XXX LEAK ALERT! This is a jid handling problem that we're working on */ j->full = NULL; return s;}aim_conn_t *_aim_select(aim_session_t *sess, pth_event_t ev, int *status){ aim_conn_t *cur; fd_set fds, wfds; int maxfd = 0; int i, haveconnecting = 0; if (sess->connlist == NULL) { *status = -1; return NULL; } FD_ZERO(&fds); FD_ZERO(&wfds); maxfd = 0; for (cur = sess->connlist; cur; cur = cur->next) { if (cur->status & AIM_CONN_STATUS_INPROGRESS) { FD_SET(cur->fd, &wfds); haveconnecting++; } FD_SET(cur->fd, &fds); if (cur->fd > maxfd) maxfd = cur->fd; } /* * If we have data waiting to be sent, return immediatly */ if (!haveconnecting && (sess->queue_outgoing != NULL)) { *status = 1; return NULL; } if ((i = pth_select_ev(maxfd+1, &fds, &wfds, NULL, NULL, ev))>=1) { for (cur = sess->connlist; cur; cur = cur->next) { if (FD_ISSET(cur->fd, &fds) || ((cur->status & AIM_CONN_STATUS_INPROGRESS) && FD_ISSET(cur->fd, &wfds))) { *status = 2; return cur; } } *status = 0; /* shouldn't happen */ } else if ((i == -1) && (errno == EINTR))/* treat inerpts as a timeout */ *status = 0; else *status = i; /* can be 0 or -1 */ if(pth_event_occurred(ev)) { /* Possible msgport event (should be, no timeout) */ *status = 3; return (aim_conn_t *)1; } return NULL; /* no waiting or error, return */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -