From 2d411320c5f1fbfff3862f5fa8c1f1e6b7b6f9d0 Mon Sep 17 00:00:00 2001 From: pk910 Date: Thu, 10 May 2012 18:02:57 +0200 Subject: [PATCH] added channel rejoin faker (session recover) --- src/IRCClient.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++- src/IRCClient.h | 14 +++++++ src/UserClient.c | 1 + src/UserSession.c | 34 +++++++++++++++- src/UserSession.h | 2 + transirc.conf | 10 ++++- 6 files changed, 157 insertions(+), 3 deletions(-) diff --git a/src/IRCClient.c b/src/IRCClient.c index eb91baf..eee86b1 100644 --- a/src/IRCClient.c +++ b/src/IRCClient.c @@ -72,6 +72,35 @@ static void ircclient_handshake(struct IRCClient *client) { session->realname = NULL; } +static struct IRCUser ircclient_parse_user(char *from) { + struct IRCUser user; + char *a = from, *b = from; + while(*b != '!') { + b++; + } + user.nick = a; + if(!*b) { + user.ident = ""; + user.host = ""; + return user; + } + *b = '\0'; + b++; + a = b; + while(*b && *b != '@') { + b++; + } + user.ident = a; + if(!*b) { + user.host = ""; + return user; + } + *b = '\0'; + b++; + user.host = b; + return user; +} + static void ircclient_recv(struct IRCClient *client, char *line) { struct UserSession *session = client->session; char *argv[MAXNUMPARAMS]; @@ -91,6 +120,11 @@ static void ircclient_recv(struct IRCClient *client, char *line) { pass_to_client = 0; } } else { + if(!stricmp(argv[1], "001")) { + free(session->nick); + session->nick = strdup(argv[2]); + client->fully_connected = 1; + } if(!stricmp(argv[1], "001") || !stricmp(argv[1], "002") || !stricmp(argv[1], "003") || @@ -113,6 +147,61 @@ static void ircclient_recv(struct IRCClient *client, char *line) { else client->recover_header = new_line; } + } else if(!stricmp(argv[1], "JOIN")) { + struct IRCUser from = ircclient_parse_user(argv[0]); + if(!stricmp(from.nick, session->nick)) { + struct IRCChannel *lchannel = NULL, *channel = malloc(sizeof(*channel)); + if(client->channel) + for(lchannel = client->channel; lchannel->next; lchannel = lchannel->next) {} + channel->name = strdup(argv[2]); + channel->next = NULL; + channel->prev = lchannel; + if(lchannel) + lchannel->next = channel; + else + client->channel = channel; + } + } else if(!stricmp(argv[1], "PART")) { + struct IRCUser from = ircclient_parse_user(argv[0]); + if(!stricmp(from.nick, session->nick)) { + struct IRCChannel *channel; + for(channel = client->channel; channel; channel = channel->next) { + if(!stricmp(channel->name, argv[2])) { + if(channel->prev) + channel->prev->next = channel->next; + else + client->channel = channel->next; + if(channel->next) + channel->next->prev = channel->prev; + free(channel->name); + free(channel); + break; + } + } + } + } else if(!stricmp(argv[1], "KICK")) { + if(!stricmp(argv[3], session->nick)) { + struct IRCChannel *channel; + for(channel = client->channel; channel; channel = channel->next) { + if(!stricmp(channel->name, argv[2])) { + if(channel->prev) + channel->prev->next = channel->next; + else + client->channel = channel->next; + if(channel->next) + channel->next->prev = channel->prev; + free(channel->name); + free(channel); + break; + } + } + } + } else if(!stricmp(argv[1], "NICK")) { + struct IRCUser from = ircclient_parse_user(argv[0]); + if(!stricmp(from.nick, session->nick)) { + free(session->nick); + session->nick = strdup(argv[2]); + } } } if(pass_to_client) @@ -150,5 +239,13 @@ void ircclient_recover_session(struct UserSession *session) { for(recover_line = client->recover_header; recover_line; recover_line = recover_line->next) { usersession_client_raw(session, recover_line->line); } - + struct IRCChannel *channel; + char raw[LINELEN]; + for(channel = client->channel; channel; channel = channel->next) { + sprintf(raw, ":%s!%s@TransparentIRC.session.recover JOIN %s", client->session->nick, client->session->username, channel->name); + usersession_client_raw(session, raw); + + sprintf(raw, "NAMES %s", channel->name); + ircclient_send(client, raw); + } } diff --git a/src/IRCClient.h b/src/IRCClient.h index 00c3180..707400b 100644 --- a/src/IRCClient.h +++ b/src/IRCClient.h @@ -23,12 +23,26 @@ struct IODescriptor; struct UserSession; struct UserLogin; +struct IRCChannel { + char *name; + + struct IRCChannel *next, *prev; +}; + +struct IRCUser { + char *nick; + char *ident; + char *host; +}; + struct IRCClient { struct IODescriptor *iofd; struct UserSession *session; int auth_confirmed : 1; + int fully_connected : 1; struct IRCLine *recover_header; + struct IRCChannel *channel; struct IRCClient *next, *prev; }; diff --git a/src/UserClient.c b/src/UserClient.c index bb43793..5cc0834 100644 --- a/src/UserClient.c +++ b/src/UserClient.c @@ -112,6 +112,7 @@ static void userclient_recv(struct UserClient *client, char *line) { int argc = parse_line(line, argv, 1); */ + return; } else if(!(client->flags & USERCLIENT_LOGGED_IN)) { struct UserLogin *login = client->user; char *argv[MAXNUMPARAMS]; diff --git a/src/UserSession.c b/src/UserSession.c index 8b90299..644332f 100644 --- a/src/UserSession.c +++ b/src/UserSession.c @@ -45,6 +45,8 @@ static void usersession_close(struct UserSession *session) { userclient_close(session->client); if(session->irc) ircclient_close(session->irc); + if(session->timer) + iohandler_close(session->timer); if(session->prev) session->prev->next = session->next; @@ -62,6 +64,8 @@ static void usersession_close(struct UserSession *session) { /* ****************** EXTERNAL EVENTS ****************** */ +static void usersession_timer_callback(struct IOEvent *event); + void usersession_error(struct UserSession *session, char *error) { if(session->client) { iohandler_printf(session->client->iofd, ":*TransparentIRC!TransIRC@TransparentIRC.system.notification NOTICE %s :[TransparentIRC] ERROR: %s", session->nick, error); @@ -71,8 +75,21 @@ void usersession_error(struct UserSession *session, char *error) { void usersession_client_close(struct UserSession *session) { session->client = NULL; + if(!session->irc || !session->irc->fully_connected) { + usersession_close(session); + return; + } session->idle_since = time(0); - + if(!session->timer) { + int timeout_sec = get_int_field("session.timeout"); + if(timeout_sec) { + struct timeval timeout; + gettimeofday(&timeout, NULL); + timeout.tv_sec += timeout_sec; + session->timer = iohandler_timer(timeout, usersession_timer_callback); + session->timer->data = session; + } + } } void usersession_client_raw(struct UserSession *session, char *raw) { @@ -87,6 +104,17 @@ void usersession_client_notification(struct UserSession *session, char *notifica } } +static void usersession_timer_callback(struct IOEvent *event) { + struct UserSession *session = event->iofd->data; + switch(event->type) { + case IOEVENT_TIMEOUT: + usersession_close(session); + break; + default: + break; + } +} + /* ****************** LOGIN FUNCTIONS ****************** */ static void usersession_login_accept(struct UserLogin *login); @@ -150,6 +178,10 @@ static void usersession_login_accept(struct UserLogin *login) { userclient_close(active_session->client); } //active_session->client is now NULL active_session->client = login->client; + if(active_session->timer) { + iohandler_close(active_session->timer); + active_session->timer = NULL; + } userclient_login_successful(login, active_session, 1); } else { int sessionlimit = get_int_field("auth.session_limit"); diff --git a/src/UserSession.h b/src/UserSession.h index 534a302..37b297a 100644 --- a/src/UserSession.h +++ b/src/UserSession.h @@ -21,6 +21,7 @@ struct UserClient; struct UserLogin; +struct IODescriptor; struct UserSession { char *username; @@ -32,6 +33,7 @@ struct UserSession { struct IRCClient *irc; time_t idle_since; time_t connected_since; + struct IODescriptor *timer; struct UserSession *next, *prev; }; diff --git a/transirc.conf b/transirc.conf index 9729f84..cfd4d20 100644 --- a/transirc.conf +++ b/transirc.conf @@ -11,4 +11,12 @@ "parameters" = "%U %P %N"; "timeout" = 5; }; -}; \ No newline at end of file +}; +"server" { + "host" = "127.0.0.1"; + "port" = 6667; + "ssl" = 0; +}; +"session" { + "timeout" = 300; +}; -- 2.20.1