added channel rejoin faker (session recover)
authorpk910 <philipp@zoelle1.de>
Thu, 10 May 2012 16:02:57 +0000 (18:02 +0200)
committerpk910 <philipp@zoelle1.de>
Thu, 10 May 2012 23:34:02 +0000 (01:34 +0200)
src/IRCClient.c
src/IRCClient.h
src/UserClient.c
src/UserSession.c
src/UserSession.h
transirc.conf

index eb91bafdbf684f3e6671269bb03c2dcbdfd6c61f..eee86b1f8162d78e6f4fc81cc0416dfed58b17ef 100644 (file)
@@ -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);
+    }
 }
index 00c3180f9cc38c4215c68d37115c23fa0417a8b0..707400b968d261deef6a07749cfd3e9d8d91f32a 100644 (file)
@@ -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;
 };
index bb43793981b87fa6fdadf84f9d64aa5670fd2085..5cc083441ec01cc81ec1dffec2d20ab7f8ec3ced 100644 (file)
@@ -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];
index 8b90299df4dcf40fac073954edff9fd9db1240e9..644332f416873916749342181a2238f18a25223a 100644 (file)
@@ -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");
index 534a3023f41dffb871a08dd42fb9f67a2cb741a7..37b297aba87574008e4d7ab9fefcdf71b2c90d89 100644 (file)
@@ -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;
 };
index 9729f84f3cc1f64fb819ea419e7dedad4ba6006c..cfd4d2003e34a92b132e9961ad7535e5e095ba92 100644 (file)
         "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;
+};