From a5ac3da4bb20b989218781c720fcc8b96e6611e1 Mon Sep 17 00:00:00 2001 From: Aleteoryx Date: Mon, 28 Jul 2025 15:10:17 -0400 Subject: [PATCH] The wall is built. Implements: https://todo.amehut.dev/~aleteoryx/sexchat/15 --- src/common/dcc.c | 10 +- src/common/hexchat.c | 18 +- src/common/hexchat.h | 119 +++++++------ src/common/inbound.c | 62 +++---- src/common/modes.c | 4 +- src/common/notify.c | 14 +- src/common/outbound.c | 77 +++++---- src/common/plugin.c | 18 +- src/common/proto-irc.c | 354 ++++++++++++++++++++++++++++----------- src/common/proto-irc.h | 11 +- src/common/server.c | 234 ++++++-------------------- src/common/server.h | 25 +-- src/common/servlist.c | 19 +-- src/common/userlist.c | 8 +- src/fe-gtk/banlist.c | 2 +- src/fe-gtk/chanlist.c | 4 +- src/fe-gtk/fe-gtk.c | 6 +- src/fe-gtk/maingui.c | 20 +-- src/fe-gtk/menu.c | 6 +- src/fe-gtk/plugin-tray.c | 6 +- src/fe-gtk/servlistgui.c | 4 +- src/fe-gtk/userlistgui.c | 4 +- 22 files changed, 521 insertions(+), 504 deletions(-) diff --git a/src/common/dcc.c b/src/common/dcc.c index 1044e18ef5d72d7a861bd867ab7b196dc70967ad..8515cf96c3287ebcad87541527fc27d5ecc767cc 100644 --- a/src/common/dcc.c +++ b/src/common/dcc.c @@ -499,7 +499,7 @@ dcc_write_chat (char *nick, char *text) if (dcc && dcc->dccstat == STAT_ACTIVE) { len = strlen (text); - tcp_send_real (NULL, dcc->sok, dcc->serv->write_converter, text, len); + tcp_send_real (NULL, dcc->sok, dcc->serv->c.write_converter, text, len); send (dcc->sok, "\n", 1, 0); dcc->size += len; fe_dcc_update (dcc); @@ -521,7 +521,7 @@ dcc_chat_line (struct DCC *dcc, char *line) char portbuf[32]; message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT; - line = text_convert_invalid (line, -1, dcc->serv->read_converter, unicode_fallback_string, NULL); + line = text_convert_invalid (line, -1, dcc->serv->c.read_converter, unicode_fallback_string, NULL); sess = find_dialog (dcc->serv, dcc->nick); if (!sess) @@ -1656,7 +1656,7 @@ dcc_listen_init (struct DCC *dcc, session *sess) memset (&SAddr, 0, sizeof (struct sockaddr_in)); len = sizeof (SAddr); - getsockname (dcc->serv->sok, (struct sockaddr *) &SAddr, &len); + getsockname (dcc->serv->c.sok, (struct sockaddr *) &SAddr, &len); SAddr.sin_family = AF_INET; @@ -1978,7 +1978,7 @@ dcc_change_nick (struct ircconn *serv, char *oldnick, char *newnick) dcc = (struct DCC *) list->data; if (dcc->serv == serv) { - if (!serv->p_cmp (dcc->nick, oldnick)) + if (!serv->cmp_fn (dcc->nick, oldnick)) { g_free (dcc->nick); dcc->nick = g_strdup (newnick); @@ -2215,7 +2215,7 @@ dcc_get_nick (struct session *sess, char *nick) while (list) { dcc = (struct DCC *) list->data; - if (!sess->server->p_cmp (nick, dcc->nick)) + if (!sess->server->cmp_fn (nick, dcc->nick)) { if (dcc->dccstat == STAT_QUEUED && dcc->type == TYPE_RECV) { diff --git a/src/common/hexchat.c b/src/common/hexchat.c index 6742f241ce8fdbe0152a7b5f695b4ec3e6ead5d2..851c0a05c8912629aeca1a741604075eb07996cb 100644 --- a/src/common/hexchat.c +++ b/src/common/hexchat.c @@ -198,7 +198,7 @@ find_dialog (ircconn *serv, char *nick) sess = list->data; if (sess->server == serv && sess->type == SESS_DIALOG) { - if (!serv->p_cmp (nick, sess->channel)) + if (!serv->cmp_fn (nick, sess->channel)) return (sess); } list = list->next; @@ -216,7 +216,7 @@ find_channel (ircconn *serv, char *chan) sess = list->data; if ((serv == sess->server) && sess->type == SESS_CHANNEL) { - if (!serv->p_cmp (chan, sess->channel)) + if (!serv->cmp_fn (chan, sess->channel)) return sess; } list = list->next; @@ -258,7 +258,7 @@ lag_check (void) while (list) { serv = list->data; - if (serv->connected && serv->end_of_motd) + if (serv->c.connected && serv->end_of_motd) { lag = now - serv->ping_recv; if (prefs.hex_net_ping_timeout != 0 && lag > prefs.hex_net_ping_timeout && lag > 0) @@ -267,7 +267,7 @@ lag_check (void) EMIT_SIGNAL (XP_TE_PINGTIMEOUT, serv->server_session, tbuf, NULL, NULL, NULL, 0); if (prefs.hex_net_auto_reconnect) - serv->auto_reconnect (serv, FALSE, -1); + irc_auto_reconnect (serv, FALSE, -1); } else { @@ -304,7 +304,7 @@ doover: { sess = list->data; - if (sess->server->connected && + if (sess->server->c.connected && sess->type == SESS_CHANNEL && sess->channel[0] && (sess->total <= prefs.hex_away_size_max || !prefs.hex_away_size_max)) @@ -600,14 +600,14 @@ send_quit_or_part (session * killsess) if (hexchat_is_quitting) willquit = TRUE; - if (killserv->connected) + if (killserv->c.connected) { if (willquit) { if (!killserv->sent_quit) { - killserv->flush_queue (killserv); - killserv->p_quit (killserv); + server_flush_queue (killserv); + irc_quit (killserv); killserv->sent_quit = TRUE; } } else @@ -703,7 +703,7 @@ session_free (session *killsess) list = list->next; } - server_free (killserv); + ircconn_free (killserv); } static void diff --git a/src/common/hexchat.h b/src/common/hexchat.h index 275093a42e9abb1a6ed72fe84d9a06b1a2870567..acd793c45acfec3a2b92475dc68dced9426e8acb 100644 --- a/src/common/hexchat.h +++ b/src/common/hexchat.h @@ -435,51 +435,36 @@ typedef struct session typedef struct conn { - -} conn; - -typedef struct ircconn -{ - struct conn c; - - /* server control operations (in server*.c) */ - int (*cleanup)(struct ircconn *); - void (*flush_queue)(struct ircconn *); - void (*auto_reconnect)(struct ircconn *, int send_quit, int err); - /* irc protocol functions (in proto*.c) */ - void (*p_inline)(struct ircconn *, char *buf, int len); - void (*p_connected)(struct ircconn *); - void (*p_disconnected)(struct ircconn *, int, int); - void (*p_ssl_message)(struct ircconn *, const char *); - void (*p_serverlookup)(struct ircconn *, const char *); - void (*p_connfail)(struct ircconn *, const char *); - void (*p_connstop)(struct ircconn *, const char *); - void (*p_connecting)(struct ircconn *, const char *, const char *, const char *); - void (*p_unknhost)(struct ircconn *); - void (*p_readerr)(struct ircconn *, int); - void (*p_log)(struct ircconn *, const char *); - char *(*p_get_network)(struct ircconn *, gboolean); - void (*p_rawlog)(struct ircconn *, char *, int, int); - void (*p_throttle_update)(struct ircconn *); - void (*p_cleanup)(struct ircconn *); - void (*p_stopconnect)(struct ircconn *); - int (*p_cmp)(const char *s1, const char *s2); - void (*p_quit)(struct ircconn *); - + void (*p_inline)(struct conn *, char *buf, int len); + void (*p_connected)(struct conn *); + void (*p_disconnected)(struct conn *, int, int); + void (*p_ssl_message)(struct conn *, const char *); + void (*p_serverlookup)(struct conn *, const char *); + void (*p_connfail)(struct conn *, const char *); + void (*p_connstop)(struct conn *, const char *); + void (*p_connecting)(struct conn *, const char *, const char *, const char *); + void (*p_unknhost)(struct conn *); + void (*p_readerr)(struct conn *, int); + void (*p_log)(struct conn *, const char *); + char *(*p_get_network)(struct conn *, gboolean); + void (*p_rawlog)(struct conn *, char *, int, int); + void (*p_throttle_update)(struct conn *); + gboolean (*p_cleanup)(struct conn *); + void (*p_stopconnect)(struct conn *); + void (*p_quit)(struct conn *); + void (*p_reset)(struct conn *); + int port; - int sok; /* is equal to sok4 or sok6 (the one we are using) */ - int sok4; /* tcp4 socket */ - int sok6; /* tcp6 socket */ + int sok; /* is equal to sok4 or sok6 (the one we are using) */ + int sok4; /* tcp4 socket */ + int sok6; /* tcp6 socket */ int proxy_type; int proxy_sok; /* Additional information for MS Proxy beast */ int proxy_sok4; int proxy_sok6; - int id; /* unique ID number (for plugin API) */ - - /* dcc_ip moved from hexchatprefs to make it per-server */ - guint32 dcc_ip; + char hostname[128]; /* real ip number */ #ifdef USE_OPENSSL SSL_CTX *ctx; SSL *ssl; @@ -491,15 +476,47 @@ typedef struct ircconn int childwrite; int childpid; int iotag; + int pos; /* current position in linebuf */ + char linebuf[8704]; /* RFC says 512 chars including \r\n, + IRCv3 message tags add 8191, plus the NUL byte */ + + GSList *outbound_queue; + time_t next_send; /* cptr->since in ircu */ + time_t prev_now; /* previous now-time */ + int sendq_len; /* queue size */ + + char *encoding; + GIConv read_converter; /* iconv converter for converting from server encoding to UTF-8. */ + GIConv write_converter; /* iconv converter for converting from UTF-8 to server encoding. */ + + unsigned int connected:1; + unsigned int connecting:1; + unsigned int dont_use_proxy:1; /* to proxy or not to proxy */ + unsigned int have_cert:1; /* have loaded a cert */ +#ifdef USE_OPENSSL + unsigned int use_ssl:1; /* is server SSL capable? */ + unsigned int accept_invalid_cert:1; /* ignore result of server's cert. verify */ + scram_session *scram_session; /* session for SASL SCRAM authentication */ +#endif +} conn; + +typedef struct ircconn +{ + struct conn c; + + int (*cmp_fn)(const char *s1, const char *s2); + + int id; /* unique ID number (for plugin API) */ + + /* dcc_ip moved from hexchatprefs to make it per-server */ + guint32 dcc_ip; + int recondelay_tag; /* reconnect delay timeout */ int joindelay_tag; /* waiting before we send JOIN */ - char hostname[128]; /* real ip number */ char servername[128]; /* what the server says is its name */ char password[1024]; char nick[NICKLEN]; - char linebuf[8704]; /* RFC says 512 chars including \r\n, IRCv3 message tags add 8191, plus the NUL byte */ char *last_away_reason; - int pos; /* current position in linebuf */ int nickcount; int loginmethod; /* see login_types[] */ @@ -512,12 +529,6 @@ typedef struct ircconn void *network; /* points to entry in servlist.c or NULL! */ - GSList *outbound_queue; - time_t next_send; /* cptr->since in ircu */ - time_t prev_now; /* previous now-time */ - int sendq_len; /* queue size */ - int lag; /* milliseconds */ - char *quitreason; struct session *front_session; /* front-most window/tab */ @@ -531,21 +542,16 @@ typedef struct ircconn unsigned int msg_counter; /*counts the msg tab opened in a certain time */ time_t msg_last_time; + int lag; /* milliseconds */ unsigned long lag_sent; /* we are still waiting for this ping response*/ time_t ping_recv; /* when we last got a ping reply */ time_t away_time; /* when we were marked away */ - char *encoding; - GIConv read_converter; /* iconv converter for converting from server encoding to UTF-8. */ - GIConv write_converter; /* iconv converter for converting from UTF-8 to server encoding. */ - GSList *favlist; /* list of channels & keys to join */ GSList *batches; /* list of batches */ unsigned int motd_skipped:1; - unsigned int connected:1; - unsigned int connecting:1; unsigned int no_login:1; unsigned int skip_next_userhost:1;/* used for "get my ip from server" */ unsigned int skip_next_whois:1; /* hide whois output */ @@ -556,7 +562,6 @@ typedef struct ircconn unsigned int use_listargs:1; /* undernet and dalnet need /list >0,<10000 */ unsigned int is_away:1; unsigned int reconnect_away:1; /* whether to reconnect in is_away state */ - unsigned int dont_use_proxy:1; /* to proxy or not to proxy */ unsigned int supports_watch:1; /* supports the WATCH command */ unsigned int supports_monitor:1; /* supports the MONITOR command */ unsigned int bad_prefix:1; /* gave us a bad PREFIX= 005 number */ @@ -574,17 +579,11 @@ typedef struct ircconn unsigned int have_sasl:1; /* SASL capability */ unsigned int have_except:1; /* ban exemptions +e */ unsigned int have_invite:1; /* invite exemptions +I */ - unsigned int have_cert:1; /* have loaded a cert */ unsigned int use_who:1; /* whether to use WHO command to get dcc_ip */ unsigned int sasl_mech; /* mechanism for sasl auth */ unsigned int sent_capend:1; /* have sent CAP END yet */ unsigned int waiting_on_cap:1; /* waiting on another line of CAP LS */ unsigned int waiting_on_sasl:1; /* waiting on sasl */ -#ifdef USE_OPENSSL - unsigned int use_ssl:1; /* is server SSL capable? */ - unsigned int accept_invalid_cert:1;/* ignore result of server's cert. verify */ - scram_session *scram_session; /* session for SASL SCRAM authentication */ -#endif } ircconn; typedef int (*cmd_callback) (struct session * sess, char *tbuf, char *word[], diff --git a/src/common/inbound.c b/src/common/inbound.c index a5a8c2772a7f17d9d8a6b71b83b5acb2bd87807f..71bf88e701ede8b72d6f594c913e6ec4a5463ba0 100644 --- a/src/common/inbound.c +++ b/src/common/inbound.c @@ -498,7 +498,7 @@ inbound_newnick (ircconn *serv, char *nick, char *newnick, int quiet, session *sess; GSList *list = sess_list; - if (!serv->p_cmp (nick, serv->nick)) + if (!serv->cmp_fn (nick, serv->nick)) { me = TRUE; safe_strcpy (serv->nick, newnick, NICKLEN); @@ -519,7 +519,7 @@ inbound_newnick (ircconn *serv, char *nick, char *newnick, int quiet, EMIT_SIGNAL_TAGS (XP_TE_CHANGENICK, sess, nick, newnick, NULL, NULL, 0, tags_data); } } - if (sess->type == SESS_DIALOG && !serv->p_cmp (sess->channel, nick)) + if (sess->type == SESS_DIALOG && !serv->cmp_fn (sess->channel, nick)) { safe_strcpy (sess->channel, newnick, CHANLEN); fe_set_channel (sess); @@ -565,7 +565,7 @@ find_session_from_waitchannel (char *chan, struct ircconn *serv) sess = (session *) list->data; if (sess->server == serv && sess->channel[0] == 0 && sess->type == SESS_CHANNEL) { - if (!serv->p_cmp (chan, sess->waitchannel)) + if (!serv->cmp_fn (chan, sess->waitchannel)) return sess; } list = list->next; @@ -832,7 +832,7 @@ inbound_quit (ircconn *serv, char *nick, char *ip, char *reason, { EMIT_SIGNAL_TAGS (XP_TE_QUIT, sess, nick, reason, ip, NULL, 0, tags_data); userlist_remove_user (sess, user); - } else if (sess->type == SESS_DIALOG && !serv->p_cmp (sess->channel, nick)) + } else if (sess->type == SESS_DIALOG && !serv->cmp_fn (sess->channel, nick)) { EMIT_SIGNAL_TAGS (XP_TE_QUIT, sess, nick, reason, ip, NULL, 0, tags_data); } @@ -1020,7 +1020,7 @@ inbound_notice (ircconn *serv, char *to, char *nick, char *msg, char *ip, int id void inbound_away (ircconn *serv, char *nick, char *msg, const message_tags_data *tags_data) { - struct away_msg *away = server_away_find_message (serv, nick); + struct away_msg *away = irc_away_find_message (serv, nick); session *sess = NULL; GSList *list; @@ -1030,7 +1030,7 @@ inbound_away (ircconn *serv, char *nick, char *msg, const message_tags_data *tag return; } else { - server_away_save_message (serv, nick, msg); + irc_away_save_message (serv, nick, msg); } if (prefs.hex_irc_whois_front) @@ -1125,7 +1125,7 @@ check_autojoin_channels (ircconn *serv) favchannel *fav; /* shouldn't really happen, the io tag is destroyed in server.c */ - if (!is_server (serv)) + if (!is_server (&serv->c)) { return FALSE; } @@ -1183,7 +1183,7 @@ check_autojoin_channels (ircconn *serv) irc_join_list (serv, serv->favlist); i++; - /* FIXME this is not going to work and is not needed either. server_free() does the job already. */ + /* FIXME this is not going to work and is not needed either. ircconn_free() does the job already. */ /* g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free); */ } } @@ -1451,7 +1451,7 @@ inbound_user_info (session *sess, char *chan, char *user, char *host, { userlist_add_hostname (sess, nick, uhost, realname, servname, account, away); } - else if (sess->type == SESS_DIALOG && uhost && !serv->p_cmp (sess->channel, nick)) + else if (sess->type == SESS_DIALOG && uhost && !serv->cmp_fn (sess->channel, nick)) { set_topic (sess, uhost, uhost); } @@ -1671,7 +1671,7 @@ inbound_toggle_caps (ircconn *serv, const char *extensions_str, gboolean enable) serv->sasl_mech = MECH_SCRAM_SHA_512; #endif /* Mechanism either defaulted to PLAIN or server gave us list */ - tcp_sendf (serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE %s\r\n", sasl_mechanisms[serv->sasl_mech]); } } } @@ -1862,7 +1862,7 @@ inbound_cap_ls (ircconn *serv, char *nick, char *extensions_str, { /* buffer + 9 = emit buffer without "CAP REQ :" */ EMIT_SIGNAL_TAGS (XP_TE_CAPREQ, serv->server_session, buffer + 9, NULL, NULL, NULL, 0, tags_data); - tcp_sendf (serv, "%s\r\n", g_strchomp (buffer)); + tcp_sendf ((struct conn *)serv, "%s\r\n", g_strchomp (buffer)); } if (!serv->waiting_on_sasl && !serv->waiting_on_cap) { @@ -1914,7 +1914,7 @@ plain_authenticate (ircconn *serv, char *user, char *password) if (pass == NULL) { /* something went wrong abort */ - tcp_sendf (serv, "AUTHENTICATE *\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE *\r\n"); return; } @@ -1922,20 +1922,20 @@ plain_authenticate (ircconn *serv, char *user, char *password) https://ircv3.net/specs/extensions/sasl-3.1#the-authenticate-command */ size_t pass_len = strlen (pass); if (pass_len <= 400) - tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE %s\r\n", pass); else { size_t sent = 0; while (sent < pass_len) { char *pass_chunk = g_strndup (pass + sent, 400); - tcp_sendf (serv, "AUTHENTICATE %s\r\n", pass_chunk); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE %s\r\n", pass_chunk); sent += 400; g_free (pass_chunk); } } if (pass_len % 400 == 0) - tcp_sendf (serv, "AUTHENTICATE +\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE +\r\n"); } #ifdef USE_OPENSSL @@ -1951,49 +1951,49 @@ scram_authenticate (ircconn *serv, const char *data, const char *digest, size_t output_len; gsize decoded_len; - if (serv->scram_session == NULL) + if (serv->c.scram_session == NULL) { - serv->scram_session = scram_session_create (digest, user, password); + serv->c.scram_session = scram_session_create (digest, user, password); - if (serv->scram_session == NULL) + if (serv->c.scram_session == NULL) { PrintTextf (serv->server_session, _("Could not create SCRAM session with digest %s"), digest); g_warning ("Could not create SCRAM session with digest %s", digest); - tcp_sendf (serv, "AUTHENTICATE *\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE *\r\n"); return; } } decoded = g_base64_decode (data, &decoded_len); - status = scram_process (serv->scram_session, decoded, &output, &output_len); + status = scram_process (serv->c.scram_session, decoded, &output, &output_len); g_free (decoded); if (status == SCRAM_IN_PROGRESS) { // Authentication is still in progress encoded = g_base64_encode ((guchar *) output, output_len); - tcp_sendf (serv, "AUTHENTICATE %s\r\n", encoded); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE %s\r\n", encoded); g_free (encoded); g_free (output); } else if (status == SCRAM_SUCCESS) { // Authentication succeeded - tcp_sendf (serv, "AUTHENTICATE +\r\n"); - g_clear_pointer (&serv->scram_session, scram_session_free); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE +\r\n"); + g_clear_pointer (&serv->c.scram_session, scram_session_free); } else if (status == SCRAM_ERROR) { // Authentication failed - tcp_sendf (serv, "AUTHENTICATE *\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE *\r\n"); - if (serv->scram_session->error != NULL) + if (serv->c.scram_session->error != NULL) { - PrintTextf (serv->server_session, _("SASL SCRAM authentication failed: %s"), serv->scram_session->error); - g_info ("SASL SCRAM authentication failed: %s", serv->scram_session->error); + PrintTextf (serv->server_session, _("SASL SCRAM authentication failed: %s"), serv->c.scram_session->error); + g_info ("SASL SCRAM authentication failed: %s", serv->c.scram_session->error); } - g_clear_pointer (&serv->scram_session, scram_session_free); + g_clear_pointer (&serv->c.scram_session, scram_session_free); } } #endif @@ -2022,7 +2022,7 @@ inbound_sasl_authenticate (ircconn *serv, char *data) break; #ifdef USE_OPENSSL case MECH_EXTERNAL: - tcp_sendf (serv, "AUTHENTICATE +\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE +\r\n"); break; case MECH_SCRAM_SHA_1: scram_authenticate(serv, data, "SHA1", user, serv->password); @@ -2043,8 +2043,8 @@ void inbound_sasl_error (ircconn *serv) { #ifdef USE_OPENSSL - g_clear_pointer (&serv->scram_session, scram_session_free); + g_clear_pointer (&serv->c.scram_session, scram_session_free); #endif /* Just abort, not much we can do */ - tcp_sendf (serv, "AUTHENTICATE *\r\n"); + tcp_sendf ((struct conn *)serv, "AUTHENTICATE *\r\n"); } diff --git a/src/common/modes.c b/src/common/modes.c index da6c018c18e02277a72862489adf4252152a56a0..6f1122c62ade4b1fed4b1adf9f6c5fe84474605b 100644 --- a/src/common/modes.c +++ b/src/common/modes.c @@ -541,7 +541,7 @@ handle_single_mode (mode_run *mr, char sign, char mode, char *nick, genmode: /* Received umode +e. If we're waiting to send JOIN then send now! */ - if (mode == 'e' && sign == '+' && !serv->p_cmp (chan, serv->nick)) + if (mode == 'e' && sign == '+' && !serv->cmp_fn (chan, serv->nick)) inbound_identified (serv); if (!quiet) @@ -886,7 +886,7 @@ inbound_005 (ircconn * serv, char *word[], const message_tags_data *tags_data) } else if (g_strcmp0 (tokname, "CASEMAPPING") == 0) { if (g_strcmp0 (tokvalue, "ascii") == 0) - serv->p_cmp = (void *)g_ascii_strcasecmp; + serv->cmp_fn = (void *)g_ascii_strcasecmp; } else if (g_strcmp0 (tokname, "CHARSET") == 0) { if (g_ascii_strcasecmp (tokvalue, "UTF-8") == 0) diff --git a/src/common/notify.c b/src/common/notify.c index 0d57524b3d2db4f9bee0324697ec94f7cc3df3a3..db2524adf628ed67a48ce06501e96dd3a0b75616 100644 --- a/src/common/notify.c +++ b/src/common/notify.c @@ -196,7 +196,7 @@ notify_find (ircconn *serv, char *nick) continue; } - if (!serv->p_cmp (notify->name, nick)) + if (!serv->cmp_fn (notify->name, nick)) return servnot; list = list->next; @@ -362,7 +362,7 @@ notify_watch_all (struct notify *notify, int add) while (list) { serv = list->data; - if (serv->connected && serv->end_of_motd && notify_do_network (notify, serv)) + if (serv->c.connected && serv->end_of_motd && notify_do_network (notify, serv)) notify_watch (serv, notify->name, add); list = list->next; } @@ -466,7 +466,7 @@ notify_markonline (ircconn *serv, char *word[], const message_tags_data *tags_da seen = FALSE; while (*word[i]) { - if (!serv->p_cmp (notify->name, word[i])) + if (!serv->cmp_fn (notify->name, word[i])) { seen = TRUE; notify_announce_online (serv, servnot, notify->name, tags_data); @@ -534,7 +534,7 @@ notify_checklist (void) /* check ISON list */ while (list) { serv = list->data; - if (serv->connected && serv->end_of_motd && !serv->supports_watch && !serv->supports_monitor) + if (serv->c.connected && serv->end_of_motd && !serv->supports_watch && !serv->supports_monitor) { notify_checklist_for_server (serv); } @@ -633,7 +633,7 @@ notify_is_in_list (ircconn *serv, char *name) while (list) { notify = (struct notify *) list->data; - if (!serv->p_cmp (notify->name, name)) + if (!serv->cmp_fn (notify->name, name)) return TRUE; list = list->next; } @@ -651,7 +651,7 @@ notify_isnotify (struct session *sess, char *name) while (list) { notify = (struct notify *) list->data; - if (!sess->server->p_cmp (notify->name, name)) + if (!sess->server->cmp_fn (notify->name, name)) { servnot = notify_find_server_entry (notify, sess->server); if (servnot && servnot->ison) @@ -691,7 +691,7 @@ notify_cleanup () serv = (struct ircconn *) srvlist->data; if (servnot->server == serv) { - valid = serv->connected; /* Only valid if server is too */ + valid = serv->c.connected; /* Only valid if server is too */ break; } srvlist = srvlist->next; diff --git a/src/common/outbound.c b/src/common/outbound.c index 58a0873adbb92ebb74ac072b5fb1f07a5475cc4c..d101dd7bbaced5a7d623232ea4ce32802b0a3ffe 100644 --- a/src/common/outbound.c +++ b/src/common/outbound.c @@ -242,7 +242,7 @@ cmd_allchannels (session *sess, char *tbuf, char *word[], char *word_eol[]) while (list) { sess = list->data; - if (sess->type == SESS_CHANNEL && sess->channel[0] && sess->server->connected) + if (sess->type == SESS_CHANNEL && sess->channel[0] && sess->server->c.connected) { handle_command (sess, word_eol[2], FALSE); } @@ -265,7 +265,7 @@ cmd_allchannelslocal (session *sess, char *tbuf, char *word[], char *word_eol[]) { sess = list->data; if (sess->type == SESS_CHANNEL && sess->channel[0] && - sess->server->connected && sess->server == serv) + sess->server->c.connected && sess->server == serv) { handle_command (sess, word_eol[2], FALSE); } @@ -289,7 +289,7 @@ cmd_allservers (struct session *sess, char *tbuf, char *word[], while (list) { serv = list->data; - if (serv->connected) + if (serv->c.connected) handle_command (serv->front_session, word_eol[2], FALSE); list = list->next; } @@ -329,7 +329,7 @@ cmd_away (struct session *sess, char *tbuf, char *word[], char *word_eol[]) sess->server->last_away_reason = reason; } - if (!sess->server->connected) + if (!sess->server->c.connected) sess->server->reconnect_away = 1; return TRUE; @@ -539,13 +539,13 @@ cmd_charset (struct session *sess, char *tbuf, char *word[], char *word_eol[]) if (!word[2 + offset][0]) { - PrintTextf (sess, "Current charset: %s\n", serv->encoding); + PrintTextf (sess, "Current charset: %s\n", serv->c.encoding); return TRUE; } if (servlist_check_encoding (word[2 + offset])) { - server_set_encoding (serv, word[2 + offset]); + server_set_encoding ((struct conn *)serv, word[2 + offset]); if (offset < 1) PrintTextf (sess, "Charset changed to: %s\n", word[2 + offset]); } else @@ -846,7 +846,7 @@ cmd_debug (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { v = (struct ircconn *) list->data; sprintf (tbuf, "%p %-5d %s\n", - v, v->sok, v->servername); + v, v->c.sok, v->servername); PrintText (sess, tbuf); list = list->next; } @@ -1356,7 +1356,7 @@ cmd_devoice (struct session *sess, char *tbuf, char *word[], char *word_eol[]) static int cmd_discon (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { - if (server_disconnect (sess->server, TRUE, -1)) + if (server_disconnect ((struct conn *)sess->server, TRUE, -1)) notc_msg (sess); return TRUE; } @@ -1905,9 +1905,9 @@ cmd_exportconf (struct session *sess, char *tbuf, char *word[], char *word_eol[] static int cmd_flushq (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { - sprintf (tbuf, "Flushing server send queue, %d bytes.\n", sess->server->sendq_len); + sprintf (tbuf, "Flushing server send queue, %d bytes.\n", sess->server->c.sendq_len); PrintText (sess, tbuf); - sess->server->flush_queue (sess->server); + server_flush_queue ((struct conn *)sess->server); return TRUE; } @@ -1918,7 +1918,7 @@ cmd_quit (struct session *sess, char *tbuf, char *word[], char *word_eol[]) if (*word_eol[2]) serv->quitreason = word_eol[2]; - if (server_disconnect (serv, TRUE, -1)) + if (server_disconnect ((struct conn *)serv, TRUE, -1)) notc_msg (sess); serv->quitreason = NULL; return 2; @@ -1933,13 +1933,12 @@ cmd_gate (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { char *port = word[3]; #ifdef USE_OPENSSL - serv->use_ssl = FALSE; + serv->c.use_ssl = FALSE; #endif - server_fill_her_up (serv); if (*port) - server_connect (serv, server_name, atoi (port), TRUE); + server_connect ((struct conn *)serv, server_name, atoi (port), TRUE); else - server_connect (serv, server_name, 23, TRUE); + server_connect ((struct conn *)serv, server_name, 23, TRUE); return TRUE; } return FALSE; @@ -2685,7 +2684,7 @@ cmd_me (struct session *sess, char *tbuf, char *word[], char *word_eol[]) } else { /* DCC CHAT failed, try through server */ - if (sess->server->connected) + if (sess->server->c.connected) { while ((split_text = split_up_text (sess, act + offset, cmd_length, split_text))) { @@ -2802,7 +2801,7 @@ cmd_msg (struct session *sess, char *tbuf, char *word[], char *word_eol[]) } } else { - if (!sess->server->connected) + if (!sess->server->c.connected) { notc_msg (sess); return TRUE; @@ -2904,7 +2903,7 @@ cmd_nick (struct session *sess, char *tbuf, char *word[], char *word_eol[]) char *nick = word[2]; if (*nick) { - if (sess->server->connected) + if (sess->server->c.connected) irc_change_nick (sess->server, nick); else { @@ -3078,7 +3077,7 @@ cmd_query (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { message_tags_data no_tags = MESSAGE_TAGS_DATA_INIT; - if (!sess->server->connected) + if (!sess->server->c.connected) { notc_msg (sess); return TRUE; @@ -3185,8 +3184,8 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[]) while (list) { serv = list->data; - if (serv->connected) - serv->auto_reconnect (serv, TRUE, -1); + if (serv->c.connected) + irc_auto_reconnect (serv, TRUE, -1); list = list->next; } } @@ -3215,20 +3214,20 @@ cmd_reconnect (struct session *sess, char *tbuf, char *word[], char *word_eol[]) use_ssl_noverify = FALSE; offset++; /* args move up by 1 word */ } - serv->use_ssl = use_ssl; - serv->accept_invalid_cert = use_ssl_noverify; + serv->c.use_ssl = use_ssl; + serv->c.accept_invalid_cert = use_ssl_noverify; #endif if (*word[4+offset]) safe_strcpy (serv->password, word[4+offset], sizeof (serv->password)); if (*word[3+offset]) - serv->port = atoi (word[3+offset]); - safe_strcpy (serv->hostname, word[2+offset], sizeof (serv->hostname)); - serv->auto_reconnect (serv, TRUE, -1); + serv->c.port = atoi (word[3+offset]); + safe_strcpy (serv->c.hostname, word[2+offset], sizeof (serv->c.hostname)); + irc_auto_reconnect (serv, TRUE, -1); } else { - serv->auto_reconnect (serv, TRUE, -1); + irc_auto_reconnect (serv, TRUE, -1); } prefs.hex_net_reconnect_delay = tmp; @@ -3240,7 +3239,7 @@ cmd_recv (struct session *sess, char *tbuf, char *word[], char *word_eol[]) { if (*word_eol[2]) { - sess->server->p_inline (sess->server, word_eol[2], strlen (word_eol[2])); + irc_inline (sess->server, word_eol[2], strlen (word_eol[2])); return TRUE; } @@ -3275,7 +3274,7 @@ cmd_send (struct session *sess, char *tbuf, char *word[], char *word_eol[]) /* use the one from our connected server socket */ memset (&SAddr, 0, sizeof (struct sockaddr_in)); len = sizeof (SAddr); - getsockname (sess->server->sok, (struct sockaddr *) &SAddr, &len); + getsockname (sess->server->c.sok, (struct sockaddr *) &SAddr, &len); addr = SAddr.sin_addr.s_addr; } addr = ntohl (addr); @@ -3501,8 +3500,8 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[]) } #ifdef USE_OPENSSL - serv->use_ssl = use_ssl; - serv->accept_invalid_cert = use_ssl_noverify; + serv->c.use_ssl = use_ssl; + serv->c.accept_invalid_cert = use_ssl_noverify; #endif /* try to connect by Network name */ @@ -3511,17 +3510,17 @@ cmd_server (struct session *sess, char *tbuf, char *word[], char *word_eol[]) if (*port) { - server_connect (serv, server_name, atoi (port), FALSE); + server_connect ((struct conn *)serv, server_name, atoi (port), FALSE); } else { /* -1 for default port */ - server_connect (serv, server_name, -1, FALSE); + server_connect ((struct conn *)serv, server_name, -1, FALSE); } /* try to associate this connection with a listed network */ /* may return NULL, but that's OK */ if ((serv->network = servlist_net_find_from_server (server_name))) - server_set_encoding (serv, ((ircnet*)serv->network)->encoding); + server_set_encoding ((struct conn *)serv, ((ircnet*)serv->network)->encoding); return TRUE; } @@ -3673,7 +3672,7 @@ find_server_from_hostname (char *hostname) while (list) { serv = list->data; - if (!g_ascii_strcasecmp (hostname, serv->hostname) && serv->connected) + if (!g_ascii_strcasecmp (hostname, serv->c.hostname) && serv->c.connected) return serv; list = list->next; } @@ -3690,7 +3689,7 @@ find_server_from_net (void *net) while (list) { serv = list->data; - if (serv->network == net && serv->connected) + if (serv->network == net && serv->c.connected) return serv; list = list->next; } @@ -4589,7 +4588,7 @@ handle_say (session *sess, char *text, int check_spch) } } - if (sess->server->connected) + if (sess->server->c.connected) { char *split_text = NULL; int cmd_length = 13; /* " PRIVMSG ", " ", :, \r, \n */ @@ -4785,7 +4784,7 @@ handle_command (session *sess, char *cmd, int check_spch) if (int_cmd) { - if (int_cmd->needserver && !sess->server->connected) + if (int_cmd->needserver && !sess->server->c.connected) { notc_msg (sess); } @@ -4808,7 +4807,7 @@ handle_command (session *sess, char *cmd, int check_spch) } else { - if (!sess->server->connected) + if (!sess->server->c.connected) { PrintTextf (sess, _("Unknown Command %s. Try /help\n"), word[1]); } diff --git a/src/common/plugin.c b/src/common/plugin.c index 313b08d09714acdf7cebcfe415a379142d174eb5..176904ab93f0fac8a8985729ff572ff6c6a64aea 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -923,7 +923,7 @@ plugin_find_context (const char *servname, const char *channel, ircconn *current if (servname == NULL || rfc_casecmp (servname, serv->servername) == 0 || - g_ascii_strcasecmp (servname, serv->hostname) == 0 || + g_ascii_strcasecmp (servname, serv->c.hostname) == 0 || g_ascii_strcasecmp (servname, netname) == 0) { if (channel == NULL) @@ -1109,7 +1109,7 @@ hexchat_commandf (hexchat_plugin *ph, const char *format, ...) int hexchat_nickcmp (hexchat_plugin *ph, const char *s1, const char *s2) { - return ((session *)ph->context)->server->p_cmp (s1, s2); + return ((session *)ph->context)->server->cmp_fn (s1, s2); } hexchat_context * @@ -1190,8 +1190,8 @@ hexchat_get_info (hexchat_plugin *ph, const char *id) { const char *locale; - if (sess->server->encoding) - return sess->server->encoding; + if (sess->server->c.encoding) + return sess->server->c.encoding; locale = NULL; g_get_charset (&locale); @@ -1199,7 +1199,7 @@ hexchat_get_info (hexchat_plugin *ph, const char *id) } case 0x30f5a8: /* host */ - return sess->server->hostname; + return sess->server->c.hostname; case 0x1c0e99c1: /* inputbox */ return fe_get_inputbox_contents (sess); @@ -1220,7 +1220,7 @@ hexchat_get_info (hexchat_plugin *ph, const char *id) return NULL; case 0xca022f43: /* server */ - if (!sess->server->connected) + if (!sess->server->c.connected) return NULL; return sess->server->servername; @@ -1614,8 +1614,8 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name) case 0xd1b: /* id */ return ((struct session *)data)->server->id; case 0x5cfee87: /* flags */ - channel_flags[0] = ((struct session *)data)->server->connected; - channel_flags[1] = ((struct session *)data)->server->connecting; + channel_flags[0] = ((struct session *)data)->server->c.connected; + channel_flags[1] = ((struct session *)data)->server->c.connecting; channel_flags[2] = ((struct session *)data)->server->is_away; channel_flags[3] = ((struct session *)data)->server->end_of_motd; channel_flags[4] = ((struct session *)data)->server->have_whox; @@ -1651,7 +1651,7 @@ hexchat_list_int (hexchat_plugin *ph, hexchat_list *xlist, const char *name) case 0x1916144c: /* maxmodes */ return ((struct session *)data)->server->modes_per_line; case 0x66f1911: /* queue */ - return ((struct session *)data)->server->sendq_len; + return ((struct session *)data)->server->c.sendq_len; case 0x368f3a: /* type */ return ((struct session *)data)->type; case 0x6a68e08: /* users */ diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c index 4b0e1f8a8b971318e8155f4a0d501fb6b28cfd6b..59ec968a76857f84bc0f3d405d69432a4fe8f3ea 100644 --- a/src/common/proto-irc.c +++ b/src/common/proto-irc.c @@ -50,20 +50,80 @@ #include "servlist.h" #include "batch.h" +static GSList *away_list = NULL; + +struct away_msg * +irc_away_find_message (ircconn *serv, char *nick) +{ + struct away_msg *away; + GSList *list = away_list; + while (list) + { + away = (struct away_msg *) list->data; + if (away->server == serv && !serv->cmp_fn (nick, away->nick)) + return away; + list = list->next; + } + return NULL; +} + +static void +irc_away_free_messages (ircconn *serv) +{ + GSList *list, *next; + struct away_msg *away; + + list = away_list; + while (list) + { + away = list->data; + next = list->next; + if (away->server == serv) + { + away_list = g_slist_remove (away_list, away); + g_free (away->message); + g_free (away); + next = away_list; + } + list = next; + } +} + +void +irc_away_save_message (ircconn *serv, char *nick, char *msg) +{ + struct away_msg *away = irc_away_find_message (serv, nick); + + if (away) /* Change message for known user */ + { + g_free (away->message); + away->message = g_strdup (msg); + } + else + { + /* Create brand new entry */ + away = g_new(struct away_msg, 1); + away->server = serv; + safe_strcpy (away->nick, nick, sizeof (away->nick)); + away->message = g_strdup (msg); + away_list = g_slist_prepend (away_list, away); + } +} + static void irc_login (ircconn *serv, char *user, char *realname) { - tcp_sendf (serv, "CAP LS 302\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */ + tcp_sendf ((struct conn *)serv, "CAP LS 302\r\n"); /* start with CAP LS as Charybdis sasl.txt suggests */ serv->sent_capend = FALSE; /* track if we have finished */ if (serv->password[0] && serv->loginmethod == LOGIN_PASS) { - tcp_sendf (serv, "PASS %s%s\r\n", + tcp_sendf ((struct conn *)serv, "PASS %s%s\r\n", (serv->password[0] == ':' || strchr (serv->password, ' ')) ? ":" : "", serv->password); } - tcp_sendf (serv, + tcp_sendf ((struct conn *)serv, "NICK %s\r\n" "USER %s 0 * :%s\r\n", serv->nick, user, realname); @@ -76,24 +136,24 @@ irc_nickserv (ircconn *serv, char *cmd, char *arg1, char *arg2, char *arg3) switch (serv->loginmethod) { case LOGIN_MSG_NICKSERV: - tcp_sendf (serv, "PRIVMSG NICKSERV :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); + tcp_sendf ((struct conn *)serv, "PRIVMSG NICKSERV :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; case LOGIN_NICKSERV: - tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); + tcp_sendf ((struct conn *)serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; default: /* This may not work but at least it tries something when using /id or /ghost cmd */ - tcp_sendf (serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); + tcp_sendf ((struct conn *)serv, "NICKSERV %s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; #if 0 case LOGIN_MSG_NS: - tcp_sendf (serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); + tcp_sendf ((struct conn *)serv, "PRIVMSG NS :%s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; case LOGIN_NS: - tcp_sendf (serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3); + tcp_sendf ((struct conn *)serv, "NS %s %s%s%s\r\n", cmd, arg1, arg2, arg3); break; case LOGIN_AUTH: /* why couldn't QuakeNet implement one of the existing ones? */ - tcp_sendf (serv, "AUTH %s %s\r\n", arg1, arg2); + tcp_sendf ((struct conn *)serv, "AUTH %s %s\r\n", arg1, arg2); break; #endif } @@ -105,7 +165,7 @@ irc_ns_identify (ircconn *serv, char *pass) switch (serv->loginmethod) { case LOGIN_CHALLENGEAUTH: - tcp_sendf (serv, "PRIVMSG %s :CHALLENGE\r\n", CHALLENGEAUTH_NICK); /* request a challenge from Q */ + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :CHALLENGE\r\n", CHALLENGEAUTH_NICK); /* request a challenge from Q */ break; #if 0 case LOGIN_AUTH: @@ -130,9 +190,9 @@ void irc_join (ircconn *serv, char *channel, char *key) { if (key[0]) - tcp_sendf (serv, "JOIN %s %s\r\n", channel, key); + tcp_sendf ((struct conn *)serv, "JOIN %s %s\r\n", channel, key); else - tcp_sendf (serv, "JOIN %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "JOIN %s\r\n", channel); } static void @@ -146,11 +206,11 @@ irc_join_list_flush (ircconn *serv, GString *channels, GString *keys, int send_k if (send_keys) { - tcp_sendf (serv, "JOIN %s %s\r\n", chanstr, keystr); /* send the actual command */ + tcp_sendf ((struct conn *)serv, "JOIN %s %s\r\n", chanstr, keystr); /* send the actual command */ } else { - tcp_sendf (serv, "JOIN %s\r\n", chanstr); /* send the actual command */ + tcp_sendf ((struct conn *)serv, "JOIN %s\r\n", chanstr); /* send the actual command */ } g_free (chanstr); @@ -233,12 +293,12 @@ void irc_part (ircconn *serv, char *channel, char *reason) { if (reason[0]) - tcp_sendf (serv, "PART %s :%s\r\n", channel, reason); + tcp_sendf ((struct conn *)serv, "PART %s :%s\r\n", channel, reason); else - tcp_sendf (serv, "PART %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "PART %s\r\n", channel); } -static void +void irc_quit (ircconn *serv) { char *reason, *colrea = NULL; @@ -252,9 +312,9 @@ irc_quit (ircconn *serv) reason = serv->quitreason; if (reason[0]) - tcp_sendf (serv, "QUIT :%s\r\n", reason); + tcp_sendf ((struct conn *)serv, "QUIT :%s\r\n", reason); else - tcp_send_len (serv, "QUIT\r\n", 6); + tcp_send_len ((struct conn *)serv, "QUIT\r\n", 6); if (colrea) { @@ -266,7 +326,7 @@ irc_quit (ircconn *serv) void irc_set_back (ircconn *serv) { - tcp_send_len (serv, "AWAY\r\n", 6); + tcp_send_len ((struct conn *)serv, "AWAY\r\n", 6); } void @@ -282,46 +342,46 @@ irc_set_away (ircconn *serv, char *reason) reason = " "; } - tcp_sendf (serv, "AWAY :%s\r\n", reason); + tcp_sendf ((struct conn *)serv, "AWAY :%s\r\n", reason); } void irc_ctcp (ircconn *serv, char *to, char *msg) { - tcp_sendf (serv, "PRIVMSG %s :\001%s\001\r\n", to, msg); + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :\001%s\001\r\n", to, msg); } void irc_nctcp (ircconn *serv, char *to, char *msg) { - tcp_sendf (serv, "NOTICE %s :\001%s\001\r\n", to, msg); + tcp_sendf ((struct conn *)serv, "NOTICE %s :\001%s\001\r\n", to, msg); } void irc_cycle (ircconn *serv, char *channel, char *key) { - tcp_sendf (serv, "PART %s\r\nJOIN %s %s\r\n", channel, channel, key); + tcp_sendf ((struct conn *)serv, "PART %s\r\nJOIN %s %s\r\n", channel, channel, key); } void irc_kick (ircconn *serv, char *channel, char *nick, char *reason) { if (reason[0]) - tcp_sendf (serv, "KICK %s %s :%s\r\n", channel, nick, reason); + tcp_sendf ((struct conn *)serv, "KICK %s %s :%s\r\n", channel, nick, reason); else - tcp_sendf (serv, "KICK %s %s\r\n", channel, nick); + tcp_sendf ((struct conn *)serv, "KICK %s %s\r\n", channel, nick); } void irc_invite (ircconn *serv, char *channel, char *nick) { - tcp_sendf (serv, "INVITE %s %s\r\n", nick, channel); + tcp_sendf ((struct conn *)serv, "INVITE %s %s\r\n", nick, channel); } void irc_mode (ircconn *serv, char *target, char *mode) { - tcp_sendf (serv, "MODE %s %s\r\n", target, mode); + tcp_sendf ((struct conn *)serv, "MODE %s %s\r\n", target, mode); } /* find channel info when joined */ @@ -329,16 +389,16 @@ irc_mode (ircconn *serv, char *target, char *mode) void irc_join_info (ircconn *serv, char *channel) { - tcp_sendf (serv, "MODE %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "MODE %s\r\n", channel); } void irc_who (ircconn *serv, char *channel) { if (serv->have_whox) - tcp_sendf (serv, "WHO %s %%chtsunfra,152\r\n", channel); + tcp_sendf ((struct conn *)serv, "WHO %s %%chtsunfra,152\r\n", channel); else - tcp_sendf (serv, "WHO %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "WHO %s\r\n", channel); } /* userhost */ @@ -346,7 +406,7 @@ irc_who (ircconn *serv, char *channel) void irc_userhost (ircconn *serv, char *nick) { - tcp_sendf (serv, "USERHOST %s\r\n", nick); + tcp_sendf ((struct conn *)serv, "USERHOST %s\r\n", nick); } @@ -357,36 +417,36 @@ irc_userhost (ircconn *serv, char *nick) void irc_user_whois (ircconn *serv, char *nicks) { - tcp_sendf (serv, "WHOIS %s\r\n", nicks); + tcp_sendf ((struct conn *)serv, "WHOIS %s\r\n", nicks); } void irc_message (ircconn *serv, char *channel, char *text) { - tcp_sendf (serv, "PRIVMSG %s :%s\r\n", channel, text); + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :%s\r\n", channel, text); } void irc_action (ircconn *serv, char *channel, char *act) { - tcp_sendf (serv, "PRIVMSG %s :\001ACTION %s\001\r\n", channel, act); + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :\001ACTION %s\001\r\n", channel, act); } void irc_notice (ircconn *serv, char *channel, char *text) { - tcp_sendf (serv, "NOTICE %s :%s\r\n", channel, text); + tcp_sendf ((struct conn *)serv, "NOTICE %s :%s\r\n", channel, text); } void irc_topic (ircconn *serv, char *channel, char *topic) { if (!topic) - tcp_sendf (serv, "TOPIC %s :\r\n", channel); + tcp_sendf ((struct conn *)serv, "TOPIC %s :\r\n", channel); else if (topic[0]) - tcp_sendf (serv, "TOPIC %s :%s\r\n", channel, topic); + tcp_sendf ((struct conn *)serv, "TOPIC %s :%s\r\n", channel, topic); else - tcp_sendf (serv, "TOPIC %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "TOPIC %s\r\n", channel); } void @@ -394,35 +454,35 @@ irc_list_channels (ircconn *serv, char *arg, int min_users) { if (arg[0]) { - tcp_sendf (serv, "LIST %s\r\n", arg); + tcp_sendf ((struct conn *)serv, "LIST %s\r\n", arg); return; } if (serv->use_listargs) - tcp_sendf (serv, "LIST >%d,<10000\r\n", min_users - 1); + tcp_sendf ((struct conn *)serv, "LIST >%d,<10000\r\n", min_users - 1); else - tcp_send_len (serv, "LIST\r\n", 6); + tcp_send_len ((struct conn *)serv, "LIST\r\n", 6); } void irc_names (ircconn *serv, char *channel) { - tcp_sendf (serv, "NAMES %s\r\n", channel); + tcp_sendf ((struct conn *)serv, "NAMES %s\r\n", channel); } void irc_change_nick (ircconn *serv, char *new_nick) { - tcp_sendf (serv, "NICK %s\r\n", new_nick); + tcp_sendf ((struct conn *)serv, "NICK %s\r\n", new_nick); } void irc_ping (ircconn *serv, char *to, char *timestring) { if (*to) - tcp_sendf (serv, "PRIVMSG %s :\001PING %s\001\r\n", to, timestring); + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :\001PING %s\001\r\n", to, timestring); else - tcp_sendf (serv, "PING %s\r\n", timestring); + tcp_sendf ((struct conn *)serv, "PING %s\r\n", timestring); } int @@ -436,11 +496,11 @@ irc_raw (ircconn *serv, char *raw) if (len < sizeof (tbuf) - 3) { len = g_snprintf (tbuf, sizeof (tbuf), "%s\r\n", raw); - tcp_send_len (serv, tbuf, len); + tcp_send_len ((struct conn *)serv, tbuf, len); } else { - tcp_send_len (serv, raw, len); - tcp_send_len (serv, "\r\n", 2); + tcp_send_len ((struct conn *)serv, raw, len); + tcp_send_len ((struct conn *)serv, "\r\n", 2); } return TRUE; } @@ -531,7 +591,7 @@ process_numeric (session * sess, int n, if (eq) { *eq = 0; - if (!serv->p_cmp (word[4] + 1, serv->nick)) + if (!serv->cmp_fn (word[4] + 1, serv->nick)) { char *at = strrchr (eq + 1, '@'); if (at) @@ -953,7 +1013,7 @@ process_numeric (session * sess, int n, if (!serv->sent_capend) { serv->sent_capend = TRUE; - tcp_send_len (serv, "CAP END\r\n", 9); + tcp_send_len ((struct conn *)serv, "CAP END\r\n", 9); } break; case 908: /* Supported SASL Mechs */ @@ -1046,7 +1106,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], realname++; if (*chan == ':') chan++; - if (!serv->p_cmp (nick, serv->nick)) + if (!serv->cmp_fn (nick, serv->nick)) inbound_ujoin (serv, chan, nick, ip, tags_data); else inbound_join (serv, chan, nick, ip, account, realname, @@ -1198,7 +1258,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], return; text = STRIP_COLON(word, word_eol, 4); - if (serv->p_cmp (word[3], serv->nick)) + if (serv->cmp_fn (word[3], serv->nick)) EMIT_SIGNAL_TAGS (XP_TE_INVITEDOTHER, sess, text, nick, word[3], serv->servername, 0, tags_data); else @@ -1217,7 +1277,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], #ifdef USE_OPENSSL /* QuakeNet CHALLENGE upon our request */ - if (serv->loginmethod == LOGIN_CHALLENGEAUTH && !serv->p_cmp (word[1], CHALLENGEAUTH_FULLHOST) + if (serv->loginmethod == LOGIN_CHALLENGEAUTH && !serv->cmp_fn (word[1], CHALLENGEAUTH_FULLHOST) && !strncmp (text, "CHALLENGE ", 10) && *serv->password) { char *response; @@ -1226,7 +1286,7 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[], response = challengeauth_response (user, serv->password, word[5]); - tcp_sendf (serv, "PRIVMSG %s :CHALLENGEAUTH %s %s %s\r\n", + tcp_sendf ((struct conn *)serv, "PRIVMSG %s :CHALLENGEAUTH %s %s %s\r\n", CHALLENGEAUTH_NICK, user, response, @@ -1563,7 +1623,7 @@ handle_message_tags (ircconn *serv, const char *tags_str, } /* irc_inline() - 1 single line received from serv */ -static void +void irc_inline (ircconn *serv, char *buf, int len) { session *sess, *tmp; @@ -1692,7 +1752,7 @@ ircconn_set_name (ircconn *serv, char *name) session *sess; if (name[0] == 0) - name = serv->hostname; + name = serv->c.hostname; /* strncpy parameters must NOT overlap */ if (name != serv->servername) @@ -1725,6 +1785,9 @@ ircconn_set_name (ircconn *serv, char *name) static void irc_connected (ircconn *serv) { + serv->ping_recv = time (0); + serv->lag_sent = 0; + { /* FIXME: UGLY HACK!! should be handled with a hook or something. */ struct sockaddr_storage addr; int addr_len = sizeof (addr); @@ -1732,7 +1795,7 @@ irc_connected (ircconn *serv) ircnet *net = serv->network; char outbuf[512]; - if (!getsockname (serv->sok, (struct sockaddr *)&addr, &addr_len)) + if (!getsockname (serv->c.sok, (struct sockaddr *)&addr, &addr_len)) { if (addr.ss_family == AF_INET) port = ntohs(((struct sockaddr_in *)&addr)->sin_port); @@ -1785,6 +1848,11 @@ irc_disconnected (ircconn *serv, int shutup, int err) GSList *list; session *sess; + serv->motd_skipped = FALSE; + serv->no_login = FALSE; + serv->servername[0] = 0; + serv->lag_sent = 0; + fe_server_event (serv, FE_SE_DISCONNECT, 0); list = sess_list; @@ -1811,29 +1879,30 @@ irc_ssl_message (ircconn *serv, const char *msg) } static void -irc_serverlookup (ircconn *serv, const char *msg) +irc_serverlookup (ircconn *serv, const char *hostname) { fe_progressbar_start (serv->server_session); - EMIT_SIGNAL (XP_TE_SERVERLOOKUP, serv->server_session, (char *)msg, NULL, NULL, NULL, 0); + EMIT_SIGNAL (XP_TE_SERVERLOOKUP, serv->server_session, (char *)hostname, NULL, NULL, NULL, 0); + safe_strcpy (serv->servername, hostname, sizeof (serv->servername)); } static int timeout_auto_reconnect (ircconn *serv) { - if (is_server (serv)) /* make sure it hasnt been closed during the delay */ + if (is_server (&serv->c)) /* make sure it hasnt been closed during the delay */ { serv->recondelay_tag = 0; // afaict this check will never fail - if (!serv->connected && !serv->connecting /*&& serv->server_session*/) + if (!serv->c.connected && !serv->c.connecting /*&& serv->server_session*/) { - server_connect (serv, serv->hostname, serv->port, FALSE); + server_connect ((struct conn *)serv, serv->c.hostname, serv->c.port, FALSE); } } return 0; /* returning 0 should remove the timeout handler */ } -static void -auto_reconnect (ircconn *serv, int send_quit, int err) +void +irc_auto_reconnect (ircconn *serv, int send_quit, int err) { session *s; int del; @@ -1857,8 +1926,8 @@ auto_reconnect (ircconn *serv, int send_quit, int err) } } - if (serv->connected) - server_disconnect (serv, send_quit, err); + if (serv->c.connected) + server_disconnect ((struct conn *)serv, send_quit, err); del = prefs.hex_net_reconnect_delay * 1000; if (del < 1000) @@ -1889,7 +1958,7 @@ irc_connfail (ircconn *serv, const char *msg) if (!servlist_cycle (serv)) if (prefs.hex_net_auto_reconnectonfail) - auto_reconnect (serv, FALSE, -1); + irc_auto_reconnect (serv, FALSE, -1); } static void @@ -1916,7 +1985,7 @@ irc_unknhost (ircconn *serv) if (!servlist_cycle (serv)) if (prefs.hex_net_auto_reconnectonfail) - auto_reconnect (serv, FALSE, -1); + irc_auto_reconnect (serv, FALSE, -1); } static void @@ -1924,18 +1993,18 @@ irc_readerr (ircconn *serv, int error) { if (!serv->end_of_motd) { - server_disconnect (serv, FALSE, error); + server_disconnect ((struct conn *)serv, FALSE, error); if (!servlist_cycle (serv)) { if (prefs.hex_net_auto_reconnect) - auto_reconnect (serv, FALSE, error); + irc_auto_reconnect (serv, FALSE, error); } } else { if (prefs.hex_net_auto_reconnect) - auto_reconnect (serv, FALSE, error); + irc_auto_reconnect (serv, FALSE, error); else - server_disconnect (serv, FALSE, error); + server_disconnect ((struct conn *)serv, FALSE, error); } } @@ -1945,7 +2014,7 @@ irc_serverlog (ircconn *serv, const char *msg) PrintText (serv->server_session, (char *)msg); } -static void +static gboolean irc_cleanup (ircconn *serv) { if (serv->joindelay_tag) @@ -1956,6 +2025,15 @@ irc_cleanup (ircconn *serv) serv->end_of_motd = FALSE; fe_set_lag (serv, 0); + + if (!serv->c.connecting && !serv->c.connected && serv->recondelay_tag) + { + g_source_remove (serv->recondelay_tag); + serv->recondelay_tag = 0; + return TRUE; // shutup + } + + return FALSE; } static void @@ -1971,30 +2049,110 @@ irc_stopconnect (ircconn *serv) fe_server_event (serv, FE_SE_DISCONNECT, 0); } +static void +irc_reset (ircconn *serv) +{ + g_free (serv->chantypes); + g_free (serv->chanmodes); + g_free (serv->nick_prefixes); + g_free (serv->nick_modes); + + serv->chantypes = g_strdup ("#&!+"); + serv->chanmodes = g_strdup ("beI,k,l"); + serv->nick_prefixes = g_strdup ("@%+"); + serv->nick_modes = g_strdup ("ohv"); + serv->modes_per_line = 3; /* https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.3.1 */ + serv->sasl_mech = MECH_PLAIN; + + serv->nickcount = 1; + serv->end_of_motd = FALSE; + serv->sent_capend = FALSE; + serv->use_listargs = FALSE; + serv->is_away = FALSE; + serv->supports_watch = FALSE; + serv->supports_monitor = FALSE; + serv->bad_prefix = FALSE; + serv->use_who = TRUE; + serv->have_namesx = FALSE; + serv->have_awaynotify = FALSE; + serv->have_uhnames = FALSE; + serv->have_whox = FALSE; + serv->have_idmsg = FALSE; + serv->have_accnotify = FALSE; + serv->have_extjoin = FALSE; + serv->have_account_tag = FALSE; + serv->have_echo_message = FALSE; + serv->have_message_tags = FALSE; + serv->have_server_time = FALSE; + serv->have_sasl = FALSE; + serv->have_except = FALSE; + serv->have_invite = FALSE; +} + +static void +irc_fill_her_up (ircconn *serv) +{ + serv->c.p_connected = (void (*)(struct conn *))irc_connected; + serv->c.p_disconnected = (void (*)(struct conn *, int, int))irc_disconnected; + serv->c.p_ssl_message = (void (*)(struct conn *, const char *))irc_ssl_message; + serv->c.p_serverlookup = (void (*)(struct conn *, const char *))irc_serverlookup; + serv->c.p_connfail = (void (*)(struct conn *, const char *))irc_connfail; + serv->c.p_connstop = (void (*)(struct conn *, const char *))irc_connstop; + serv->c.p_connecting = (void (*)(struct conn *, const char *, const char *, const char *))irc_connecting; + serv->c.p_unknhost = (void (*)(struct conn *))irc_unknhost; + serv->c.p_readerr = (void (*)(struct conn *, int))irc_readerr; + serv->c.p_log = (void (*)(struct conn *, const char *))irc_serverlog; + serv->c.p_cleanup = (gboolean (*)(struct conn *))irc_cleanup; + serv->c.p_stopconnect = (void (*)(struct conn *))irc_stopconnect; + serv->c.p_rawlog = (void (*)(struct conn *, char *, int, int))fe_add_rawlog; + serv->c.p_throttle_update = (void (*)(struct conn *))fe_set_throttle; + serv->c.p_get_network = (char * (*)(struct conn *, gboolean))ircconn_get_network; + serv->c.p_quit = (void (*)(struct conn *))irc_quit; + serv->c.p_inline = (void (*)(struct conn *, char *, int))irc_inline; + serv->c.p_reset = (void (*)(struct conn *))irc_reset; + + serv->cmp_fn = rfc_casecmp; /* can be changed by 005 in modes.c */ +} +ircconn * +ircconn_new (void) +{ + ircconn *serv; + static int id = 0; + + + serv = g_new0 (struct ircconn, 1); + serv->id = id++; + + conn_fill (&serv->c); // calls irc_reset + irc_fill_her_up (serv); + + strcpy (serv->nick, prefs.hex_irc_nick1); + + fe_new_server (serv); + + return serv; +} + void -proto_fill_her_up (ircconn *serv) +ircconn_free (ircconn *conn) { - serv->auto_reconnect = auto_reconnect; - - serv->p_connected = irc_connected; - serv->p_disconnected = irc_disconnected; - serv->p_ssl_message = irc_ssl_message; - serv->p_serverlookup = irc_serverlookup; - serv->p_connfail = irc_connfail; - serv->p_connstop = irc_connstop; - serv->p_connecting = irc_connecting; - serv->p_unknhost = irc_unknhost; - serv->p_readerr = irc_readerr; - serv->p_log = irc_serverlog; - serv->p_cleanup = irc_cleanup; - serv->p_stopconnect = irc_stopconnect; - - serv->p_rawlog = fe_add_rawlog; - serv->p_throttle_update = fe_set_throttle; - - serv->p_get_network = ircconn_get_network; - - serv->p_quit = irc_quit; - serv->p_inline = irc_inline; - serv->p_cmp = rfc_casecmp; /* can be changed by 005 in modes.c */ + dcc_notify_kill (conn); + + irc_away_free_messages (conn); + + g_free (conn->nick_modes); + g_free (conn->nick_prefixes); + g_free (conn->chanmodes); + g_free (conn->chantypes); + g_free (conn->bad_nick_prefixes); + g_free (conn->last_away_reason); + + if (conn->favlist) + g_slist_free_full (conn->favlist, (GDestroyNotify) servlist_favchan_free); + + fe_server_callback (conn); + + conn_free ((struct conn *)conn); + + notify_cleanup (); } diff --git a/src/common/proto-irc.h b/src/common/proto-irc.h index 4566f49df7f8555462660842aa165028fbe06bd0..61b66d39204c0106329fae18688eb199f3381904 100644 --- a/src/common/proto-irc.h +++ b/src/common/proto-irc.h @@ -49,7 +49,10 @@ typedef struct void message_tags_data_free (message_tags_data *tags_data); -void proto_fill_her_up (ircconn *serv); +ircconn *ircconn_new (void); +void ircconn_free (ircconn *); +char *ircconn_get_network (ircconn *serv, gboolean fallback); +void ircconn_set_name (ircconn *serv, char *name); void irc_invite (ircconn *serv, char *channel, char *nick); void irc_cycle (ircconn *serv, char *channel, char *key); @@ -77,5 +80,11 @@ void irc_mode (ircconn *, char *target, char *mode); void irc_join (ircconn *serv, char *channel, char *key); void irc_ctcp (ircconn *serv, char *to, char *msg); void irc_nctcp (ircconn *serv, char *to, char *msg); +void irc_auto_reconnect (ircconn *serv, int send_quit, int err); +void irc_inline (ircconn *serv, char *buf, int len); +void irc_quit (ircconn *serv); + +void irc_away_save_message (ircconn *serv, char *nick, char *msg); +struct away_msg *irc_away_find_message (ircconn *serv, char *nick); #endif diff --git a/src/common/server.c b/src/common/server.c index 5d1d4c8a8c39aff82001d389bb136eeac3fcfef9..245170fbfcc6e549a737055ec59877c3ed1e2e63 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -41,7 +41,6 @@ #endif #include "hexchat.h" -#include "fe.h" #include "cfgfiles.h" #include "network.h" #include "notify.h" @@ -62,13 +61,13 @@ #ifdef USE_OPENSSL /* local variables */ -static struct ircconn *g_serv = NULL; +static struct conn *g_serv = NULL; #endif -static GSList *away_list = NULL; GSList *serv_list = NULL; -static int server_cleanup (ircconn * serv); +static int server_cleanup (conn *serv); +static void server_set_defaults (conn *serv); static void write_error (char *message, GError **error) @@ -104,13 +103,13 @@ tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len) } static int -server_send_real (ircconn *serv, char *buf, int len) +server_send_real (conn *conn, char *buf, int len) { - serv->p_rawlog (serv, buf, len, TRUE); + conn->p_rawlog (conn, buf, len, TRUE); url_check_line (buf); - return tcp_send_real (serv->ssl, serv->sok, serv->write_converter, buf, len); + return tcp_send_real (conn->ssl, conn->sok, conn->write_converter, buf, len); } /* new throttling system, uses the same method as the Undernet @@ -118,7 +117,7 @@ server_send_real (ircconn *serv, char *buf, int len) off the client */ static int -tcp_send_queue (ircconn *serv) +tcp_send_queue (conn *serv) { char *buf, *p; int len, i, pri; @@ -177,12 +176,13 @@ tcp_send_queue (ircconn *serv) } int -tcp_send_len (ircconn *serv, char *buf, int len) +tcp_send_len (conn *serv, char *buf, int len) { char *dbuf; int noqueue = !serv->outbound_queue; - if (!prefs.hex_net_throttle || !serv->end_of_motd || g_ascii_strncasecmp (buf, "PONG", 4) == 0) + if (!prefs.hex_net_throttle || // should wait on login, need to add a conn.proto_ready + g_ascii_strncasecmp (buf, "PONG", 4) == 0 || g_ascii_strncasecmp (buf, "CAP", 3) == 0) return server_send_real (serv, buf, len); dbuf = g_malloc (len + 2); /* first byte is the priority */ @@ -239,11 +239,11 @@ keep_priority: } void -tcp_sendf (ircconn *serv, const char *fmt, ...) +tcp_sendf (conn *serv, const char *fmt, ...) { va_list args; /* keep this buffer in BSS. Converting UTF-8 to ISO-8859-x might make the - string shorter, so allow alot more than 512 for now. */ + string shorter, so allow alot more than 512 for now. */ static char send_buf[1540]; /* good code hey (no it's not overflowable) */ int len; @@ -275,7 +275,7 @@ close_socket (int sok) /* handle 1 line of text received from the server */ static void -server_inline (ircconn *serv, char *line, gssize len) +server_inline (conn *serv, char *line, gssize len) { gsize len_utf8; if (!strcmp (serv->encoding, "UTF-8")) @@ -294,7 +294,7 @@ server_inline (ircconn *serv, char *line, gssize len) /* read data from socket */ static gboolean -server_read (GIOChannel *source, GIOCondition condition, ircconn *serv) +server_read (GIOChannel *source, GIOCondition condition, conn *serv) { int sok = serv->sok; int error, i, len; @@ -354,11 +354,9 @@ server_read (GIOChannel *source, GIOCondition condition, ircconn *serv) } static void -server_connected (ircconn *serv) +server_connected (conn *serv) { - prefs.wait_on_exit = TRUE; - serv->ping_recv = time (0); - serv->lag_sent = 0; + prefs.wait_on_exit = TRUE; // TODO: ??? serv->connected = TRUE; set_nonblocking (serv->sok); serv->iotag = net_input_add (serv->sok, NIA_READ|NIA_EX, server_read, serv); @@ -380,7 +378,7 @@ server_close_pipe (int *pipefd) /* see comments below */ #endif static void -server_stopconnecting (ircconn * serv) +server_stopconnecting (conn * serv) { if (serv->iotag) { @@ -461,7 +459,7 @@ ssl_cb_verify (int ok, X509_STORE_CTX *ctx) } static int -ssl_do_connect (ircconn *serv) +ssl_do_connect (conn *serv) { char buf[256]; // ERR_error_string() MUST have this size @@ -615,10 +613,10 @@ conn_fail: } #endif -static void -server_flush_queue (ircconn *serv) +void +server_flush_queue (conn *serv) { - list_free (&serv->outbound_queue); + list_free (&serv->outbound_queue); //FIXME: memory leak? serv->sendq_len = 0; serv->p_throttle_update (serv); } @@ -626,7 +624,7 @@ server_flush_queue (ircconn *serv) /* connect() successed */ static void -server_connect_success (ircconn *serv) +server_connect_success (conn *serv) { #ifdef USE_OPENSSL #define SSLDOCONNTMOUT 300 @@ -661,7 +659,7 @@ server_connect_success (ircconn *serv) /* receive info from the child-process about connection progress */ static gboolean -server_read_child (GIOChannel *source, GIOCondition condition, ircconn *serv) +server_read_child (GIOChannel *source, GIOCondition condition, conn *serv) { char tbuf[128]; char outbuf[512]; @@ -750,9 +748,11 @@ server_read_child (GIOChannel *source, GIOCondition condition, ircconn *serv) disconnect if already connected. */ static int -server_cleanup (ircconn * serv) +server_cleanup (conn *serv) { - serv->p_cleanup (serv); + gboolean shutup; + + shutup = serv->p_cleanup (serv); if (serv->iotag) { @@ -790,20 +790,12 @@ server_cleanup (ircconn * serv) serv->connected = FALSE; return 2; } - - /* is this server in a reconnect delay? remove it! */ - if (serv->recondelay_tag) - { - g_source_remove (serv->recondelay_tag); - serv->recondelay_tag = 0; - return 3; - } - return 0; + return shutup ? 3 : 0; } int -server_disconnect (ircconn *serv, int sendquit, int err) +server_disconnect (conn *serv, int sendquit, int err) { char tbuf[64]; gboolean shutup = FALSE; @@ -832,10 +824,6 @@ server_disconnect (ircconn *serv, int sendquit, int err) serv->p_disconnected (serv, shutup, err); serv->pos = 0; - serv->motd_skipped = FALSE; - serv->no_login = FALSE; - serv->servername[0] = 0; - serv->lag_sent = 0; notify_cleanup (); @@ -1160,7 +1148,7 @@ traverse_proxy (int proxy_type, int print_fd, int sok, char *ip, int port, netst /* this is the child process making the connection attempt */ static int -server_child (ircconn * serv) +server_child (conn *serv) { netstore *ns_server; netstore *ns_proxy = NULL; @@ -1348,7 +1336,7 @@ xit: } void -server_connect (ircconn *serv, char *hostname, int port, int no_login) +server_connect (conn *serv, char *hostname, int port, int no_login) { int pid, read_des[2]; @@ -1377,12 +1365,11 @@ server_connect (ircconn *serv, char *hostname, int port, int no_login) g_debug ("Attempted to connect to invalid port, assuming default port %d", port); } - if (serv->connected || serv->connecting || serv->recondelay_tag) + if (serv->connected || serv->connecting) // || serv->recondelay_tag) FIXME server_disconnect (serv, TRUE, -1); serv->p_serverlookup (serv, hostname); - safe_strcpy (serv->servername, hostname, sizeof (serv->servername)); /* overlap illegal in strncpy */ if (hostname != serv->hostname) safe_strcpy (serv->hostname, hostname, sizeof (serv->hostname)); @@ -1418,7 +1405,7 @@ server_connect (ircconn *serv, char *hostname, int port, int no_login) server_set_defaults (serv); serv->connecting = TRUE; serv->port = port; - serv->no_login = no_login; + // serv->no_login = no_login; FIXME server_flush_queue (serv); @@ -1474,16 +1461,7 @@ server_connect (ircconn *serv, char *hostname, int port, int no_login) } void -server_fill_her_up (ircconn *serv) -{ - serv->cleanup = server_cleanup; - serv->flush_queue = server_flush_queue; - - proto_fill_her_up (serv); -} - -void -server_set_encoding (ircconn *serv, char *new_encoding) +server_set_encoding (conn *serv, char *new_encoding) { char *space; @@ -1529,162 +1507,50 @@ server_set_encoding (ircconn *serv, char *new_encoding) serv->write_converter = g_iconv_open (serv->encoding, "UTF-8"); } -ircconn * -ircconn_new (void) +static void +server_set_defaults (conn *serv) { - static int id = 0; - ircconn *serv; - serv = g_new0 (struct ircconn, 1); + serv->p_reset (serv); - /* use server.c and proto-irc.c functions */ - server_fill_her_up (serv); - - serv->id = id++; - serv->sok = -1; - strcpy (serv->nick, prefs.hex_irc_nick1); - server_set_defaults (serv); - - serv_list = g_slist_prepend (serv_list, serv); - - fe_new_server (serv); - - return serv; -} - -int -is_server (ircconn *serv) -{ - return g_slist_find (serv_list, serv) ? 1 : 0; -} - -void -server_set_defaults (ircconn *serv) -{ - g_free (serv->chantypes); - g_free (serv->chanmodes); - g_free (serv->nick_prefixes); - g_free (serv->nick_modes); #ifdef USE_OPENSSL g_clear_pointer (&serv->scram_session, scram_session_free); #endif - serv->chantypes = g_strdup ("#&!+"); - serv->chanmodes = g_strdup ("beI,k,l"); - serv->nick_prefixes = g_strdup ("@%+"); - serv->nick_modes = g_strdup ("ohv"); - serv->modes_per_line = 3; /* https://datatracker.ietf.org/doc/html/rfc1459#section-4.2.3.1 */ - serv->sasl_mech = MECH_PLAIN; if (!serv->encoding) server_set_encoding (serv, "UTF-8"); - - serv->nickcount = 1; - serv->end_of_motd = FALSE; - serv->sent_capend = FALSE; - serv->use_listargs = FALSE; - serv->is_away = FALSE; - serv->supports_watch = FALSE; - serv->supports_monitor = FALSE; - serv->bad_prefix = FALSE; - serv->use_who = TRUE; - serv->have_namesx = FALSE; - serv->have_awaynotify = FALSE; - serv->have_uhnames = FALSE; - serv->have_whox = FALSE; - serv->have_idmsg = FALSE; - serv->have_accnotify = FALSE; - serv->have_extjoin = FALSE; - serv->have_account_tag = FALSE; - serv->have_echo_message = FALSE; - serv->have_message_tags = FALSE; - serv->have_server_time = FALSE; - serv->have_sasl = FALSE; - serv->have_except = FALSE; - serv->have_invite = FALSE; } -struct away_msg * -server_away_find_message (ircconn *serv, char *nick) +void +conn_fill (conn * conn) { - struct away_msg *away; - GSList *list = away_list; - while (list) - { - away = (struct away_msg *) list->data; - if (away->server == serv && !serv->p_cmp (nick, away->nick)) - return away; - list = list->next; - } - return NULL; -} + conn->sok = -1; + server_set_defaults (conn); -static void -server_away_free_messages (ircconn *serv) -{ - GSList *list, *next; - struct away_msg *away; + serv_list = g_slist_prepend (serv_list, conn); - list = away_list; - while (list) - { - away = list->data; - next = list->next; - if (away->server == serv) - { - away_list = g_slist_remove (away_list, away); - g_free (away->message); - g_free (away); - next = away_list; - } - list = next; - } } -void -server_away_save_message (ircconn *serv, char *nick, char *msg) +int +is_server (conn *serv) { - struct away_msg *away = server_away_find_message (serv, nick); - - if (away) /* Change message for known user */ - { - g_free (away->message); - away->message = g_strdup (msg); - } - else - { - /* Create brand new entry */ - away = g_new(struct away_msg, 1); - away->server = serv; - safe_strcpy (away->nick, nick, sizeof (away->nick)); - away->message = g_strdup (msg); - away_list = g_slist_prepend (away_list, away); - } + return g_slist_find (serv_list, serv) ? 1 : 0; } void -server_free (ircconn *serv) +conn_free (conn *serv) { - serv->cleanup (serv); + server_cleanup (serv); serv_list = g_slist_remove (serv_list, serv); - dcc_notify_kill (serv); - serv->flush_queue (serv); - server_away_free_messages (serv); + server_flush_queue (serv); - g_free (serv->nick_modes); - g_free (serv->nick_prefixes); - g_free (serv->chanmodes); - g_free (serv->chantypes); - g_free (serv->bad_nick_prefixes); - g_free (serv->last_away_reason); g_free (serv->encoding); g_iconv_close (serv->read_converter); g_iconv_close (serv->write_converter); - if (serv->favlist) - g_slist_free_full (serv->favlist, (GDestroyNotify) servlist_favchan_free); #ifdef USE_OPENSSL if (serv->ctx) _SSL_context_free (serv->ctx); @@ -1692,9 +1558,5 @@ server_free (ircconn *serv) g_clear_pointer (&serv->scram_session, scram_session_free); #endif - fe_server_callback (serv); - g_free (serv); - - notify_cleanup (); } diff --git a/src/common/server.h b/src/common/server.h index df1c6d32792793986bd32825ba297aa788ecb250..bf5d3d3157cba9a493e3436287c9d648a6585e7e 100644 --- a/src/common/server.h +++ b/src/common/server.h @@ -23,24 +23,17 @@ extern GSList *serv_list; /* eventually need to keep the tcp_* functions isolated to server.c */ -int tcp_send_len (ircconn *serv, char *buf, int len); -void tcp_sendf (ircconn *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3); +int tcp_send_len (conn *serv, char *buf, int len); +void tcp_sendf (conn *serv, const char *fmt, ...) G_GNUC_PRINTF (2, 3); int tcp_send_real (void *ssl, int sok, GIConv write_converter, char *buf, int len); -ircconn *ircconn_new (void); -int is_server (ircconn *serv); -void server_fill_her_up (ircconn *serv); -void server_set_encoding (ircconn *serv, char *new_encoding); -void server_set_defaults (ircconn *serv); -void server_free (ircconn *serv); -void server_connect (ircconn *serv, char *hostname, int port, int no_login); -int server_disconnect (ircconn *serv, int sendquit, int err); - -char *ircconn_get_network (ircconn *serv, gboolean fallback); -void ircconn_set_name (ircconn *serv, char *name); - -void server_away_save_message (ircconn *serv, char *nick, char *msg); -struct away_msg *server_away_find_message (ircconn *serv, char *nick); +void conn_fill (conn *conn); +int is_server (conn *serv); +void server_set_encoding (conn *serv, char *new_encoding); +void conn_free (conn *serv); +void server_connect (conn *serv, char *hostname, int port, int no_login); +int server_disconnect (conn *serv, int sendquit, int err); +void server_flush_queue (conn *serv); void base64_encode (char *to, char *from, unsigned int len); diff --git a/src/common/servlist.c b/src/common/servlist.c index 81c83ec122cf2ce7757c4e79c74e63b3ba5b0e0d..72f88f6bab8aecba505243ef18a128fb7cb13457 100644 --- a/src/common/servlist.c +++ b/src/common/servlist.c @@ -369,9 +369,6 @@ servlist_connect (session *sess, ircnet *net, gboolean join) return; ircserv = list->data; - /* in case a protocol switch is added to the servlist gui */ - server_fill_her_up (sess->server); - if (join) { sess->willjoinchannel[0] = 0; @@ -412,11 +409,11 @@ servlist_connect (session *sess, ircnet *net, gboolean join) strcpy (serv->nick, net->nick); } - serv->dont_use_proxy = (net->flags & FLAG_USE_PROXY) ? FALSE : TRUE; + serv->c.dont_use_proxy = (net->flags & FLAG_USE_PROXY) ? FALSE : TRUE; #ifdef USE_OPENSSL - serv->use_ssl = (net->flags & FLAG_USE_SSL) ? TRUE : FALSE; - serv->accept_invalid_cert = + serv->c.use_ssl = (net->flags & FLAG_USE_SSL) ? TRUE : FALSE; + serv->c.accept_invalid_cert = (net->flags & FLAG_ALLOW_INVALID) ? TRUE : FALSE; #endif @@ -431,19 +428,19 @@ servlist_connect (session *sess, ircnet *net, gboolean join) if (port[1] == '+') { #ifdef USE_OPENSSL - serv->use_ssl = TRUE; + serv->c.use_ssl = TRUE; #endif - server_connect (serv, ircserv->hostname, atoi (port + 2), FALSE); + server_connect ((struct conn *)serv, ircserv->hostname, atoi (port + 2), FALSE); } else { - server_connect (serv, ircserv->hostname, atoi (port + 1), FALSE); + server_connect ((struct conn *)serv, ircserv->hostname, atoi (port + 1), FALSE); } *port = '/'; } else - server_connect (serv, ircserv->hostname, -1, FALSE); + server_connect ((struct conn *)serv, ircserv->hostname, -1, FALSE); - server_set_encoding (serv, net->encoding); + server_set_encoding ((struct conn *)serv, net->encoding); } int diff --git a/src/common/userlist.c b/src/common/userlist.c index 9e5f98532d1fb3cec489345205585af9e2861c3c..211b4f2098117c7662c8b2eab958b1a6b602379d 100644 --- a/src/common/userlist.c +++ b/src/common/userlist.c @@ -49,13 +49,13 @@ nick_cmp_az_ops (ircconn *serv, struct User *user1, struct User *user2) } } - return serv->p_cmp (user1->nick, user2->nick); + return serv->cmp_fn (user1->nick, user2->nick); } int nick_cmp_alpha (struct User *user1, struct User *user2, ircconn *serv) { - return serv->p_cmp (user1->nick, user2->nick); + return serv->cmp_fn (user1->nick, user2->nick); } /* @@ -195,7 +195,7 @@ userlist_clear (session *sess) static int find_cmp (const char *name, struct User *user, ircconn *serv) { - return serv->p_cmp ((char *)name, user->nick); + return serv->cmp_fn ((char *)name, user->nick); } struct User * @@ -383,7 +383,7 @@ userlist_add (struct session *sess, char *name, char *hostname, user->hostname = g_strdup (hostname); safe_strcpy (user->nick, name + prefix_chars, NICKLEN); /* is it me? */ - if (!sess->server->p_cmp (user->nick, sess->server->nick)) + if (!sess->server->cmp_fn (user->nick, sess->server->nick)) user->me = TRUE; /* extended join info */ if (sess->server->have_extjoin) diff --git a/src/fe-gtk/banlist.c b/src/fe-gtk/banlist.c index 4253cad89a164ee079d36c2a579c617b1601c291..413a467ad2bee40a58366cde911db5965f6261ca 100644 --- a/src/fe-gtk/banlist.c +++ b/src/fe-gtk/banlist.c @@ -432,7 +432,7 @@ banlist_do_refresh (banlist_info *banl) banlist_sensitize (banl); - if (sess->server->connected) + if (sess->server->c.connected) { GtkListStore *store; diff --git a/src/fe-gtk/chanlist.c b/src/fe-gtk/chanlist.c index 869e8ac694e02cd933f8759c32f59ea121cb31f8..bcda21bb0cbeb008b2069165e3a983c805b8d174 100644 --- a/src/fe-gtk/chanlist.c +++ b/src/fe-gtk/chanlist.c @@ -287,7 +287,7 @@ chanlist_do_refresh (ircconn *serv) serv->gui->chanlist_flash_tag = 0; } - if (!serv->connected) + if (!serv->c.connected) { fe_message (_("Not connected."), FE_MSG_ERROR); return; @@ -454,7 +454,7 @@ chanlist_join (GtkWidget * wid, ircconn *serv) char *chan = chanlist_get_selected (serv, FALSE); if (chan) { - if (serv->connected && (strcmp (chan, "*") != 0)) + if (serv->c.connected && (strcmp (chan, "*") != 0)) { g_snprintf (tbuf, sizeof (tbuf), "join %s", chan); handle_command (serv->server_session, tbuf, FALSE); diff --git a/src/fe-gtk/fe-gtk.c b/src/fe-gtk/fe-gtk.c index 212a21f8fe9226957626d91296f8cc227ba953a5..203a92a0c0ac9e10b330319de10720fc9bd1628a 100644 --- a/src/fe-gtk/fe-gtk.c +++ b/src/fe-gtk/fe-gtk.c @@ -761,7 +761,7 @@ fe_set_throttle (ircconn *serv) char tbuf[96]; char tip[160]; - per = (float) serv->sendq_len / 1024.0; + per = (float) serv->c.sendq_len / 1024.0; if (per > 1.0) per = 1.0; @@ -770,8 +770,8 @@ fe_set_throttle (ircconn *serv) sess = list->data; if (sess->server == serv) { - g_snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->sendq_len); - g_snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->sendq_len); + g_snprintf (tbuf, sizeof (tbuf) - 1, _("%d bytes"), serv->c.sendq_len); + g_snprintf (tip, sizeof (tip) - 1, _("Network send queue: %d bytes"), serv->c.sendq_len); g_free (sess->res->queue_tip); sess->res->queue_tip = g_strdup (tip); diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index 2a7e81251b8568571711bcbb00c9ee58aa7aede0..9d81ba507fb419dbaedbd4b2e496833e5e5bea13 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -388,7 +388,7 @@ fe_set_title (session *sess) type = sess->type; - if (sess->server->connected == FALSE && sess->type != SESS_DIALOG) + if (sess->server->c.connected == FALSE && sess->type != SESS_DIALOG) goto def; switch (type) @@ -952,10 +952,10 @@ mg_populate (session *sess) /* menu items */ menu_set_away (gui, sess->server->is_away); - gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], sess->server->connected); + gtk_widget_set_sensitive (gui->menu_item[MENU_ID_AWAY], sess->server->c.connected); gtk_widget_set_sensitive (gui->menu_item[MENU_ID_JOIN], sess->server->end_of_motd); gtk_widget_set_sensitive (gui->menu_item[MENU_ID_DISCONNECT], - sess->server->connected || sess->server->recondelay_tag); + sess->server->c.connected || sess->server->recondelay_tag); mg_set_topic_tip (sess); @@ -1125,7 +1125,7 @@ mg_count_networks (void) for (list = serv_list; list; list = list->next) { - if (((ircconn *)list->data)->connected) + if (((ircconn *)list->data)->c.connected) cons++; } return cons; @@ -1765,7 +1765,7 @@ mg_topic_cb (GtkWidget *entry, gpointer userdata) session *sess = current_sess; char *text; - if (sess->channel[0] && sess->server->connected && sess->type == SESS_CHANNEL) + if (sess->channel[0] && sess->server->c.connected && sess->type == SESS_CHANNEL) { text = (char *)gtk_entry_get_text (GTK_ENTRY (entry)); if (text[0] == 0) @@ -1907,7 +1907,7 @@ mg_change_flag (GtkWidget * wid, session *sess, char flag) mode[1] = flag; mode[2] = '\0'; - if (serv->connected && sess->channel[0]) + if (serv->c.connected && sess->channel[0]) { if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid))) mode[0] = '+'; @@ -1929,7 +1929,7 @@ flagl_hit (GtkWidget * wid, struct session *sess) if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (wid))) { - if (serv->connected && sess->channel[0]) + if (serv->c.connected && sess->channel[0]) { limit_str = gtk_entry_get_text (GTK_ENTRY (sess->gui->limit_entry)); if (check_is_number ((char *)limit_str) == FALSE) @@ -1953,7 +1953,7 @@ flagk_hit (GtkWidget * wid, struct session *sess) char modes[512]; ircconn *serv = sess->server; - if (serv->connected && sess->channel[0]) + if (serv->c.connected && sess->channel[0]) { g_snprintf (modes, sizeof (modes), "-k %s", gtk_entry_get_text (GTK_ENTRY (sess->gui->key_entry))); @@ -2026,7 +2026,7 @@ mg_key_entry_cb (GtkWidget * igad, gpointer userdata) session *sess = current_sess; ircconn *serv = sess->server; - if (serv->connected && sess->channel[0]) + if (serv->c.connected && sess->channel[0]) { g_snprintf (modes, sizeof (modes), "+k %s", gtk_entry_get_text (GTK_ENTRY (igad))); @@ -2042,7 +2042,7 @@ mg_limit_entry_cb (GtkWidget * igad, gpointer userdata) session *sess = current_sess; ircconn *serv = sess->server; - if (serv->connected && sess->channel[0]) + if (serv->c.connected && sess->channel[0]) { if (check_is_number ((char *)gtk_entry_get_text (GTK_ENTRY (igad))) == FALSE) { diff --git a/src/fe-gtk/menu.c b/src/fe-gtk/menu.c index f6cccdded4219ae795ecf02ccdd169c2aa0fa20c..303fff7c38f5db14168a208787312b80dea8823d 100644 --- a/src/fe-gtk/menu.c +++ b/src/fe-gtk/menu.c @@ -673,7 +673,7 @@ menu_create_nickinfo_menu (struct User *user, GtkWidget *submenu) if (user->away) { - away = server_away_find_message (current_sess->server, user->nick); + away = irc_away_find_message (current_sess->server, user->nick); if (away) { char *msg = strip_color (away->message ? away->message : unknown, -1, STRIP_ALL|STRIP_ESCMARKUP); @@ -700,7 +700,7 @@ fe_userlist_update (session *sess, struct User *user) return; /* not the same nick as the menu? */ - if (sess->server->p_cmp (user->nick, str_copy)) + if (sess->server->cmp_fn (user->nick, str_copy)) return; /* get rid of the "show" signal */ @@ -1316,7 +1316,7 @@ menu_disconnect (GtkWidget * wid, gpointer none) static void menu_reconnect (GtkWidget * wid, gpointer none) { - if (current_sess->server->hostname[0]) + if (current_sess->server->c.hostname[0]) handle_command (current_sess, "RECONNECT", FALSE); else fe_serverlist_open (current_sess); diff --git a/src/fe-gtk/plugin-tray.c b/src/fe-gtk/plugin-tray.c index 987f9dbe0d1910258f298632cb0dffd709d840c9..39e164bc149047ed912ccd8b923f289e11a92639 100644 --- a/src/fe-gtk/plugin-tray.c +++ b/src/fe-gtk/plugin-tray.c @@ -115,7 +115,7 @@ tray_count_channels (void) for (list = sess_list; list; list = list->next) { sess = list->data; - if (sess->server->connected && sess->channel[0] && + if (sess->server->c.connected && sess->channel[0] && sess->type == SESS_CHANNEL) cons++; } @@ -130,7 +130,7 @@ tray_count_networks (void) for (list = serv_list; list; list = list->next) { - if (((ircconn *)list->data)->connected) + if (((ircconn *)list->data)->c.connected) cons++; } return cons; @@ -444,7 +444,7 @@ tray_foreach_server (GtkWidget *item, char *cmd) for (list = serv_list; list; list = list->next) { serv = list->data; - if (serv->connected) + if (serv->c.connected) handle_command (serv->server_session, cmd, FALSE); } } diff --git a/src/fe-gtk/servlistgui.c b/src/fe-gtk/servlistgui.c index 0e5e108bc8de60da3cbcf324d1f826d120c15066..a41e684d2409464a50eff48ae9db5e12a7e5f3d8 100644 --- a/src/fe-gtk/servlistgui.c +++ b/src/fe-gtk/servlistgui.c @@ -1154,7 +1154,7 @@ servlist_connect_cb (GtkWidget *button, gpointer userdata) if (sess->server->network == selected_net) { servlist_sess = sess; - if (sess->server->connected) + if (sess->server->c.connected) servlist_sess = NULL; /* open a new one */ break; } @@ -1163,7 +1163,7 @@ servlist_connect_cb (GtkWidget *button, gpointer userdata) /* use the chosen one, if it's empty */ if (!servlist_sess && chosen && - !chosen->server->connected && + !chosen->server->c.connected && chosen->server->server_session->channel[0] == 0) { servlist_sess = chosen; diff --git a/src/fe-gtk/userlistgui.c b/src/fe-gtk/userlistgui.c index 485fa9ed72d5d04284e36bc7bee6275d5675a09c..4cd9ec8de82ca6624e1ed57e923d81ad5ed700db 100644 --- a/src/fe-gtk/userlistgui.c +++ b/src/fe-gtk/userlistgui.c @@ -145,7 +145,7 @@ userlist_select (session *sess, char *name) do { gtk_tree_model_get (model, &iter, COL_USER, &row_user, -1); - if (sess->server->p_cmp (row_user->nick, name) == 0) + if (sess->server->cmp_fn (row_user->nick, name) == 0) { if (gtk_tree_selection_iter_is_selected (selection, &iter)) gtk_tree_selection_unselect_iter (selection, &iter); @@ -737,7 +737,7 @@ fe_uselect (session *sess, char *word[], int do_clear, int scroll_to) thisname = 0; while ( *(name = word[thisname++]) ) { - if (sess->server->p_cmp (row_user->nick, name) == 0) + if (sess->server->cmp_fn (row_user->nick, name) == 0) { gtk_tree_selection_select_iter (selection, &iter); if (scroll_to)