added session manager and support for an external login system
[TransparentIRC.git] / src / UserClient.c
1 /* UserClient.c - TransparentIRC 0.1
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "UserClient.h"
18 #include "IOHandler.h"
19 #include "ServerSocket.h"
20 #include "UserSession.h"
21 #include "tools.h"
22
23 static void userclient_callback(struct IOEvent *event);
24
25 static struct UserClient *userclients = NULL;
26
27 void userclient_accepted(struct ServerSocket *server, int sockfd) {
28     struct UserClient *client;
29     struct IODescriptor *iofd = iohandler_add(sockfd, IOTYPE_CLIENT, userclient_callback);
30     if(!iofd) return;
31     iofd->state = IO_CONNECTED;
32     iofd->read_lines = 1;
33     iohandler_update(iofd);
34     client = calloc(1, sizeof(*client));
35     client->iofd = iofd;
36     iofd->data = client;
37     client->server = server;
38     server->clientcount++;
39     
40     struct UserLogin *login = calloc(1, sizeof(*login));
41     client->user = login;
42     login->client = client;
43     
44     
45     //add UserClient to the list
46     client->prev = NULL;
47     client->next = userclients;
48     if(userclients)
49         userclients->prev = client;
50     userclients = client;
51     
52     //let's say hello to the client
53     iohandler_printf(iofd, "NOTICE AUTH :*** [TransparentIRC] TransparentIRC v" TRANSIRC_VERSION " (use /quote transirc for more information)");
54 }
55
56 void userclient_close(struct UserClient *client) {
57     if(client->flags & USERCLIENT_LOGGED_IN) {
58         usersession_client_close(client->user);
59     } else {
60         struct UserLogin *login = client->user;
61         if(client->flags & USERCLIENT_LOGIN_PROCESSING) {
62             usersession_login_abort(login);
63         }
64         if(login->username)
65             free(login->username);
66         if(login->password)
67             free(login->password);
68         if(login->nick)
69             free(login->nick);
70         if(login->reject_reason)
71             free(login->reject_reason);
72         if(login->session_class)
73             free(login->session_class);
74         free(login);
75     }
76     iohandler_close(client->iofd);
77     client->server->clientcount--;
78     if(client->prev)
79         client->prev->next = client->next;
80     else
81         userclients = client->next;
82     if(client->next)
83         client->next->prev = client->prev;
84     
85     free(client);
86 }
87
88 void userclient_close_server(struct ServerSocket *server, int keep_clients) {
89     struct UserClient *client, *next_client;
90     for(client = userclients; client; client = next_client) {
91         next_client = client->next;
92         if(client->server == server) {
93             if(keep_clients)
94                 client->server = NULL;
95             else
96                 userclient_close(client);
97         }
98     }
99 }
100
101 static void userclient_recv(struct UserClient *client, char *line) {
102     if(!stricmplen(line, "TRANSIRC ", 9)) {
103         /*
104         char *argv[MAXNUMPARAMS];
105         int argc = parse_line(line, argv, 1);
106         */
107         
108     } else if(!(client->flags & USERCLIENT_LOGGED_IN)) {
109         struct UserLogin *login = client->user;
110         char *argv[MAXNUMPARAMS];
111         int argc = parse_line(line, argv, 1);
112         if(argc < 3) return;
113         if(!stricmp(argv[1], "PASS")) {
114             char *delimiter = strchr(argv[2], ':');
115             if(login->password)
116                 free(login->password);
117             if(delimiter) {
118                 *delimiter = '\0';
119                 delimiter++;
120                 if(login->username)
121                     free(login->username);
122                 login->username = strdup(argv[2]);
123                 login->password = strdup(delimiter);
124             } else 
125                 login->password = strdup(argv[2]);
126         } else if(!stricmp(argv[1], "USER")) {
127             if(!login->username)
128                 login->username = strdup(argv[2]);
129         } else if(!stricmp(argv[1], "NICK")) {
130             if(login->nick)
131                 free(login->nick);
132             login->nick = strdup(argv[2]);
133             if(!login->password) {
134                 iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] You need to send your LOC data. Try /quote PASS <username>:<password>");
135             }
136         }
137         if(login->username && login->password && login->nick && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) {
138             //try to login
139             iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Checking login...");
140             usersession_login(login);
141         }
142     } else {
143         
144     }
145 }
146
147 void userclient_login_failed(struct UserLogin *login, char *reason) {
148     iohandler_printf(login->client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login rejected");
149     userclient_close(login->client);
150 }
151
152 void userclient_login_successful(struct UserLogin *login, struct UserSession *session, int recover) {
153     struct UserClient *client = login->client;
154     iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Login accepted.");
155     if(login->username)
156         free(login->username);
157     if(login->password)
158         free(login->password);
159     if(login->nick)
160         free(login->nick);
161     free(login);
162     client->user = session;
163     if(recover) {
164         iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Recovering previous link (Nick: %s).", session->nick);
165         
166         
167     }
168 }
169
170 static void userclient_callback(struct IOEvent *event) {
171     struct UserClient *client = event->iofd->data;
172     switch(event->type) {
173         case IOEVENT_RECV:
174             userclient_recv(client, event->data.recv_str);
175             break;
176         case IOEVENT_CLOSED:
177             userclient_close(client);
178             break;
179         default:
180             break;
181     }
182 }