📄 simple.c
字号:
purple_debug(PURPLE_DEBUG_MISC, "simple", "received a incomplete sip msg: %s\n", conn->inbuf); }}static void simple_udp_process(gpointer data, gint source, PurpleInputCondition con) { PurpleConnection *gc = data; struct simple_account_data *sip = gc->proto_data; struct sipmsg *msg; int len; time_t currtime; static char buffer[65536]; if((len = recv(source, buffer, sizeof(buffer) - 1, 0)) > 0) { buffer[len] = '\0'; purple_debug_info("simple", "\n\nreceived - %s\n######\n%s\n#######\n\n", ctime(&currtime), buffer); msg = sipmsg_parse_msg(buffer); if(msg) process_input_message(sip, msg); }}static void simple_input_cb(gpointer data, gint source, PurpleInputCondition cond){ PurpleConnection *gc = data; struct simple_account_data *sip = gc->proto_data; int len; struct sip_connection *conn = connection_find(sip, source); if(!conn) { purple_debug_error("simple", "Connection not found!\n"); return; } if(conn->inbuflen < conn->inbufused + SIMPLE_BUF_INC) { conn->inbuflen += SIMPLE_BUF_INC; conn->inbuf = g_realloc(conn->inbuf, conn->inbuflen); } len = read(source, conn->inbuf + conn->inbufused, SIMPLE_BUF_INC - 1); if(len < 0 && errno == EAGAIN) return; else if(len <= 0) { purple_debug_info("simple", "simple_input_cb: read error\n"); connection_remove(sip, source); if(sip->fd == source) sip->fd = -1; return; } conn->inbufused += len; conn->inbuf[conn->inbufused] = '\0'; process_input(sip, conn);}/* Callback for new connections on incoming TCP port */static void simple_newconn_cb(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = data; struct simple_account_data *sip = gc->proto_data; struct sip_connection *conn; int newfd = accept(source, NULL, NULL); conn = connection_create(sip, newfd); conn->inputhandler = purple_input_add(newfd, PURPLE_INPUT_READ, simple_input_cb, gc);}static void login_cb(gpointer data, gint source, const gchar *error_message) { PurpleConnection *gc = data; struct simple_account_data *sip; struct sip_connection *conn; if (!PURPLE_CONNECTION_IS_VALID(gc)) { if (source >= 0) close(source); return; } if(source < 0) { purple_connection_error(gc, _("Could not connect")); return; } sip = gc->proto_data; sip->fd = source; conn = connection_create(sip, source); sip->registertimeout = purple_timeout_add((rand()%100)+10*1000, (GSourceFunc)subscribe_timeout, sip); do_register(sip); conn->inputhandler = purple_input_add(sip->fd, PURPLE_INPUT_READ, simple_input_cb, gc);}static guint simple_ht_hash_nick(const char *nick) { char *lc = g_utf8_strdown(nick, -1); guint bucket = g_str_hash(lc); g_free(lc); return bucket;}static gboolean simple_ht_equals_nick(const char *nick1, const char *nick2) { return (purple_utf8_strcasecmp(nick1, nick2) == 0);}static void simple_udp_host_resolved_listen_cb(int listenfd, gpointer data) { struct simple_account_data *sip = (struct simple_account_data*) data; sip->listen_data = NULL; if(listenfd == -1) { purple_connection_error(sip->gc, _("Could not create listen socket")); return; } sip->fd = listenfd; sip->listenport = purple_network_get_port_from_fd(sip->fd); sip->listenfd = sip->fd; sip->listenpa = purple_input_add(sip->fd, PURPLE_INPUT_READ, simple_udp_process, sip->gc); sip->resendtimeout = purple_timeout_add(2500, (GSourceFunc) resend_timeout, sip); sip->registertimeout = purple_timeout_add((rand()%100)+10*1000, (GSourceFunc)subscribe_timeout, sip); do_register(sip);}static void simple_udp_host_resolved(GSList *hosts, gpointer data, const char *error_message) { struct simple_account_data *sip = (struct simple_account_data*) data; int addr_size; sip->query_data = NULL; if (!hosts || !hosts->data) { purple_connection_error(sip->gc, _("Couldn't resolve host")); return; } addr_size = GPOINTER_TO_INT(hosts->data); hosts = g_slist_remove(hosts, hosts->data); memcpy(&(sip->serveraddr), hosts->data, addr_size); g_free(hosts->data); hosts = g_slist_remove(hosts, hosts->data); while(hosts) { hosts = g_slist_remove(hosts, hosts->data); g_free(hosts->data); hosts = g_slist_remove(hosts, hosts->data); } /* create socket for incoming connections */ sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_DGRAM, simple_udp_host_resolved_listen_cb, sip); if (sip->listen_data == NULL) { purple_connection_error(sip->gc, _("Could not create listen socket")); return; }}static voidsimple_tcp_connect_listen_cb(int listenfd, gpointer data) { struct simple_account_data *sip = (struct simple_account_data*) data; sip->listen_data = NULL; sip->listenfd = listenfd; if(sip->listenfd == -1) { purple_connection_error(sip->gc, _("Could not create listen socket")); return; } purple_debug_info("simple", "listenfd: %d\n", sip->listenfd); sip->listenport = purple_network_get_port_from_fd(sip->listenfd); sip->listenpa = purple_input_add(sip->listenfd, PURPLE_INPUT_READ, simple_newconn_cb, sip->gc); purple_debug_info("simple", "connecting to %s port %d\n", sip->realhostname, sip->realport); /* open tcp connection to the server */ if (purple_proxy_connect(sip->gc, sip->account, sip->realhostname, sip->realport, login_cb, sip->gc) == NULL) { purple_connection_error(sip->gc, _("Couldn't create socket")); }}static void srvresolved(PurpleSrvResponse *resp, int results, gpointer data) { struct simple_account_data *sip; gchar *hostname; int port; sip = data; sip->srv_query_data = NULL; port = purple_account_get_int(sip->account, "port", 0); /* find the host to connect to */ if(results) { hostname = g_strdup(resp->hostname); if(!port) port = resp->port; g_free(resp); } else { if(!purple_account_get_bool(sip->account, "useproxy", FALSE)) { hostname = g_strdup(sip->servername); } else { hostname = g_strdup(purple_account_get_string(sip->account, "proxy", sip->servername)); } } sip->realhostname = hostname; sip->realport = port; if(!sip->realport) sip->realport = 5060; /* TCP case */ if(!sip->udp) { /* create socket for incoming connections */ sip->listen_data = purple_network_listen_range(5060, 5160, SOCK_STREAM, simple_tcp_connect_listen_cb, sip); if (sip->listen_data == NULL) { purple_connection_error(sip->gc, _("Could not create listen socket")); return; } } else { /* UDP */ purple_debug_info("simple", "using udp with server %s and port %d\n", hostname, port); sip->query_data = purple_dnsquery_a(hostname, port, simple_udp_host_resolved, sip); if (sip->query_data == NULL) { purple_connection_error(sip->gc, _("Could not resolve hostname")); } }}static void simple_login(PurpleAccount *account){ PurpleConnection *gc; struct simple_account_data *sip; gchar **userserver; gchar *hosttoconnect; const char *username = purple_account_get_username(account); gc = purple_account_get_connection(account); if (strpbrk(username, " \t\v\r\n") != NULL) { gc->wants_to_die = TRUE; purple_connection_error(gc, _("SIP screen names may not contain whitespaces or @ symbols")); return; } gc->proto_data = sip = g_new0(struct simple_account_data, 1); sip->gc = gc; sip->account = account; sip->registerexpire = 900; sip->udp = purple_account_get_bool(account, "udp", FALSE); /* TODO: is there a good default grow size? */ if(!sip->udp) sip->txbuf = purple_circ_buffer_new(0); userserver = g_strsplit(username, "@", 2); purple_connection_set_display_name(gc, userserver[0]); sip->username = g_strdup(userserver[0]); sip->servername = g_strdup(userserver[1]); sip->password = g_strdup(purple_connection_get_password(gc)); g_strfreev(userserver); sip->buddies = g_hash_table_new((GHashFunc)simple_ht_hash_nick, (GEqualFunc)simple_ht_equals_nick); purple_connection_update_progress(gc, _("Connecting"), 1, 2); /* TODO: Set the status correctly. */ sip->status = g_strdup("available"); if(!purple_account_get_bool(account, "useproxy", FALSE)) { hosttoconnect = g_strdup(sip->servername); } else { hosttoconnect = g_strdup(purple_account_get_string(account, "proxy", sip->servername)); } sip->srv_query_data = purple_srv_resolve("sip", sip->udp ? "udp" : "tcp", hosttoconnect, srvresolved, sip); g_free(hosttoconnect);}static void simple_close(PurpleConnection *gc){ struct simple_account_data *sip = gc->proto_data; if(sip) { /* unregister */ do_register_exp(sip, 0); connection_free_all(sip); if (sip->query_data != NULL) purple_dnsquery_destroy(sip->query_data); if (sip->srv_query_data != NULL) purple_srv_cancel(sip->srv_query_data); if (sip->listen_data != NULL) purple_network_listen_cancel(sip->listen_data); g_free(sip->servername); g_free(sip->username); g_free(sip->password); g_free(sip->registrar.nonce); g_free(sip->registrar.opaque); g_free(sip->registrar.target); g_free(sip->registrar.realm); g_free(sip->registrar.digest_session_key); g_free(sip->proxy.nonce); g_free(sip->proxy.opaque); g_free(sip->proxy.target); g_free(sip->proxy.realm); g_free(sip->proxy.digest_session_key); if(sip->txbuf) purple_circ_buffer_destroy(sip->txbuf); g_free(sip->realhostname); if(sip->listenpa) purple_input_remove(sip->listenpa); if(sip->tx_handler) purple_input_remove(sip->tx_handler); if(sip->resendtimeout) purple_timeout_remove(sip->resendtimeout); if(sip->registertimeout) purple_timeout_remove(sip->registertimeout); } g_free(gc->proto_data); gc->proto_data = NULL;}/* not needed since privacy is checked for every subscribe */static void dummy_add_deny(PurpleConnection *gc, const char *name) {}static void dummy_permit_deny(PurpleConnection *gc) {}static PurplePluginProtocolInfo prpl_info ={ 0, NULL, /* user_splits */ NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ simple_list_icon, /* list_icon */ NULL, /* list_emblems */ NULL, /* status_text */ NULL, /* tooltip_text */ simple_status_types, /* away_states */ NULL, /* blist_node_menu */ NULL, /* chat_info */ NULL, /* chat_info_defaults */ simple_login, /* login */ simple_close, /* close */ simple_im_send, /* send_im */ NULL, /* set_info */ simple_typing, /* send_typing */ NULL, /* get_info */ simple_set_status, /* set_status */ NULL, /* set_idle */ NULL, /* change_passwd */ simple_add_buddy, /* add_buddy */ NULL, /* add_buddies */ simple_remove_buddy, /* remove_buddy */ NULL, /* remove_buddies */ dummy_add_deny, /* add_permit */ dummy_add_deny, /* add_deny */ dummy_add_deny, /* rem_permit */ dummy_add_deny, /* rem_deny */ dummy_permit_deny, /* set_permit_deny */ NULL, /* join_chat */ NULL, /* reject_chat */ NULL, /* get_chat_name */ NULL, /* chat_invite */ NULL, /* chat_leave */ NULL, /* chat_whisper */ NULL, /* chat_send */ simple_keep_alive, /* keepalive */ NULL, /* register_user */ NULL, /* get_cb_info */ NULL, /* get_cb_away */ NULL, /* alias_buddy */ NULL, /* group_buddy */ NULL, /* rename_group */ NULL, /* buddy_free */ NULL, /* convo_closed */ NULL, /* normalize */ NULL, /* set_buddy_icon */ NULL, /* remove_group */ NULL, /* get_cb_real_name */ NULL, /* set_chat_topic */ NULL, /* find_blist_chat */ NULL, /* roomlist_get_list */ NULL, /* roomlist_cancel */ NULL, /* roomlist_expand_category */ NULL, /* can_receive_file */ NULL, /* send_file */ NULL, /* new_xfer */ NULL, /* offline_message */ NULL, /* whiteboard_prpl_ops */ simple_send_raw, /* send_raw */ NULL, /* roomlist_room_serialize */ /* padding */ NULL, NULL, NULL, NULL};static PurplePluginInfo info ={ PURPLE_PLUGIN_MAGIC, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_PLUGIN_PROTOCOL, /**< type */ NULL, /**< ui_requirement */ 0, /**< flags */ NULL, /**< dependencies */ PURPLE_PRIORITY_DEFAULT, /**< priority */ "prpl-simple", /**< id */ "SIMPLE", /**< name */ VERSION, /**< version */ N_("SIP/SIMPLE Protocol Plugin"), /** summary */ N_("The SIP/SIMPLE Protocol Plugin"), /** description */ "Thomas Butter <butter@uni-mannheim.de>", /**< author */ PURPLE_WEBSITE, /**< homepage */ NULL, /**< load */ NULL, /**< unload */ NULL, /**< destroy */ NULL, /**< ui_info */ &prpl_info, /**< extra_info */ NULL, NULL, /* padding */ NULL, NULL, NULL, NULL};static void _init_plugin(PurplePlugin *plugin){ PurpleAccountUserSplit *split; PurpleAccountOption *option; split = purple_account_user_split_new(_("Server"), "", '@'); prpl_info.user_splits = g_list_append(prpl_info.user_splits, split); option = purple_account_option_bool_new(_("Publish status (note: everyone may watch you)"), "dopublish", TRUE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_int_new(_("Connect port"), "port", 0); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_bool_new(_("Use UDP"), "udp", FALSE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_bool_new(_("Use proxy"), "useproxy", FALSE); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_string_new(_("Proxy"), "proxy", ""); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_string_new(_("Auth User"), "authuser", ""); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); option = purple_account_option_string_new(_("Auth Domain"), "authdomain", ""); prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);}PURPLE_INIT_PLUGIN(simple, _init_plugin, info);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -