src/ServerSocket.c \
src/tools.c \
src/UserSession.c \
- src/UserClient.c
+ src/UserClient.c \
+ src/IRCClient.c
transirc_LDADD = $(MYSQL_LIBS) $(SYSTEM_LIBS)
if(iofd->type == IOTYPE_SERVER || iofd->type == IOTYPE_CLIENT || iofd->type == IOTYPE_STDIN) {
if(FD_ISSET(iofd->fd, &read_fds) || FD_ISSET(iofd->fd, &write_fds)) {
iohandler_events(iofd, FD_ISSET(iofd->fd, &read_fds), FD_ISSET(iofd->fd, &write_fds));
+ continue;
}
}
if(iofd->type == IOTYPE_TIMER || iofd->timeout.tv_sec || iofd->timeout.tv_usec) {
return descriptor;
}
-struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bindhost, iohandler_callback *callback) {
+struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, int ssl, const char *bindhost, iohandler_callback *callback) {
//non-blocking connect
int sockfd;
struct addrinfo hints, *res, *freeres;
return descriptor;
}
-struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback) {
+struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, int ssl, iohandler_callback *callback) {
int sockfd;
struct addrinfo hints, *res, *freeres;
struct sockaddr_in *ip4 = NULL;
if(used_bytes) {
if(used_bytes == iofd->readbuf.bufpos)
iofd->readbuf.bufpos = 0;
- else
+ else {
memmove(iofd->readbuf.buffer, iofd->readbuf.buffer + used_bytes, iofd->readbuf.bufpos - used_bytes);
+ iofd->readbuf.bufpos -= used_bytes;
+ }
}
callback_event.type = IOEVENT_IGNORE;
}
struct IOBuffer writebuf;
void *data;
int read_lines : 1;
+ int ssl : 1;
struct IODescriptor *next, *prev;
};
struct IODescriptor *iohandler_add(int sockfd, enum IOType type, iohandler_callback *callback);
struct IODescriptor *iohandler_file(FILE *file, iohandler_callback *callback);
struct IODescriptor *iohandler_timer(struct timeval timeout, iohandler_callback *callback);
-struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, const char *bind, iohandler_callback *callback);
-struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, iohandler_callback *callback);
+struct IODescriptor *iohandler_connect(const char *hostname, unsigned int port, int ssl, const char *bind, iohandler_callback *callback);
+struct IODescriptor *iohandler_listen(const char *hostname, unsigned int port, int ssl, iohandler_callback *callback);
void iohandler_write(struct IODescriptor *iofd, const char *line);
void iohandler_send(struct IODescriptor *iofd, const char *data, size_t datalen);
void iohandler_printf(struct IODescriptor *iofd, const char *text, ...);
--- /dev/null
+/* IRCClient.c - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "IRCClient.h"
+#include "IOHandler.h"
+#include "UserSession.h"
+#include "UserClient.h"
+#include "tools.h"
+#include "ConfigParser.h"
+
+static void ircclient_callback(struct IOEvent *event);
+
+void ircclient_initialize(struct UserSession *session, struct UserLogin *login) {
+ struct IRCClient *client = calloc(1, sizeof(*client));
+ if(!client) {
+ usersession_error(session, "Could not initialize IRC connection.");
+ return;
+ }
+ client->session = session;
+ session->irc = client;
+
+ char *server_address = (login->server_address ? login->server_address : get_string_field("server.host"));
+ int server_port = (login->server_override_port ? login->server_port : get_int_field("server.port"));
+ int server_ssl = (login->server_override_port ? login->server_ssl : get_int_field("server.ssl"));
+ char *bind_address = (login->bind_address ? login->bind_address : get_string_field("server.bind"));
+
+ char notification[LINELEN];
+ sprintf(notification, "Connecting to %s (%s%d)", server_address, (server_ssl ? "+" : ""), server_port);
+ usersession_client_notification(session, notification);
+
+ client->iofd = iohandler_connect(server_address, server_port, server_ssl, bind_address, ircclient_callback);
+ if(!client->iofd) {
+ usersession_error(session, "Could not initialize IRC connection.");
+ return;
+ }
+ client->iofd->data = client;
+}
+
+void ircclient_close(struct IRCClient *client) {
+ client->session->irc = NULL;
+ iohandler_printf(client->iofd, "QUIT :[TransparentIRC] Quit");
+ iohandler_close(client->iofd);
+ free(client);
+}
+
+static void ircclient_handshake(struct IRCClient *client) {
+ struct UserSession *session = client->session;
+ struct IODescriptor *iofd = client->iofd;
+ iohandler_printf(iofd, "PASS %s:%s", session->username, session->password);
+ iohandler_printf(iofd, "NICK %s", session->nick);
+ iohandler_printf(iofd, "USER %s 0 * :%s", session->username, session->realname);
+ free(session->realname);
+ session->realname = NULL;
+}
+
+static void ircclient_recv(struct IRCClient *client, char *line) {
+ struct UserSession *session = client->session;
+ char *argv[MAXNUMPARAMS];
+ char tmp[LINELEN];
+ strcpy(tmp, line);
+ int argc = parse_line(tmp, argv, 1);
+ int pass_to_client = 1;
+ if(argc > 2 && !stricmp(argv[1], "PING")) {
+ iohandler_printf(client->iofd, "PONG :%s", argv[2]);
+ pass_to_client = 0;
+ }
+ if(!client->auth_confirmed) {
+ if(argc == 4 && !stricmp(argv[1], "NOTICE") && !stricmp(argv[2], "AUTH") && !stricmp(argv[3], "*** Login accepted")) {
+ client->auth_confirmed = 1;
+ } else if(argc > 1 && !stricmp(argv[1], "001")) {
+ usersession_error(session, "IRC Session closed (Please use Login on Connect)");
+ pass_to_client = 0;
+ }
+ } else {
+
+ }
+ if(pass_to_client)
+ usersession_client_raw(session, line);
+}
+
+static void ircclient_callback(struct IOEvent *event) {
+ struct IRCClient *client = event->iofd->data;
+ switch(event->type) {
+ case IOEVENT_NOTCONNECTED:
+ usersession_error(client->session, "Could not connect to the Server.");
+ break;
+ case IOEVENT_CONNECTED:
+ ircclient_handshake(client);
+ break;
+ case IOEVENT_RECV:
+ ircclient_recv(client, event->data.recv_str);
+ break;
+ case IOEVENT_CLOSED:
+ usersession_error(client->session, "Disconnected from the IRC Server.");
+ break;
+ default:
+ break;
+ }
+}
+
+void ircclient_send(struct IRCClient *client, char *line) {
+ iohandler_printf(client->iofd, "%s", line);
+}
--- /dev/null
+/* IRCClient.h - TransparentIRC 0.1
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _IRCClient_h
+#define _IRCClient_h
+#include "overall.h"
+
+struct IODescriptor;
+struct UserSession;
+struct UserLogin;
+
+struct IRCClient {
+ struct IODescriptor *iofd;
+
+ struct UserSession *session;
+
+ int auth_confirmed : 1;
+
+ struct IRCClient *next, *prev;
+};
+
+void ircclient_initialize(struct UserSession *session, struct UserLogin *login);
+void ircclient_close(struct IRCClient *client);
+void ircclient_send(struct IRCClient *client, char *line);
+
+#endif
free(server);
}
-struct ServerSocket *serversocket_listen(char *hostname, int port) {
- struct IODescriptor *iofd = iohandler_listen(hostname, port, serversocket_callback);
+struct ServerSocket *serversocket_listen(char *hostname, int port, int ssl) {
+ struct IODescriptor *iofd = iohandler_listen(hostname, port, ssl, serversocket_callback);
if(!iofd) return NULL;
struct ServerSocket *server = serversocket_create(iofd);
return server;
struct ServerSocket *next, *prev;
};
-struct ServerSocket *serversocket_listen(char *hostname, int port);
+struct ServerSocket *serversocket_listen(char *hostname, int port, int ssl);
void serversocket_close(struct ServerSocket *server, int keep_clients);
#endif
#include "ServerSocket.h"
#include "UserSession.h"
#include "tools.h"
+#include "IRCClient.h"
static void userclient_callback(struct IOEvent *event);
}
if(login->username)
free(login->username);
+ if(login->realname)
+ free(login->realname);
if(login->password)
free(login->password);
if(login->nick)
free(login->reject_reason);
if(login->session_class)
free(login->session_class);
+ if(login->bind_address)
+ free(login->bind_address);
+ if(login->server_address)
+ free(login->server_address);
free(login);
}
iohandler_close(client->iofd);
login->password = strdup(delimiter);
} else
login->password = strdup(argv[2]);
- } else if(!stricmp(argv[1], "USER")) {
+ } else if(!stricmp(argv[1], "USER") && argc >= 6) {
if(!login->username)
login->username = strdup(argv[2]);
+ login->realname = strdup(argv[5]);
} else if(!stricmp(argv[1], "NICK")) {
if(login->nick)
free(login->nick);
iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] You need to send your LOC data. Try /quote PASS <username>:<password>");
}
}
- if(login->username && login->password && login->nick && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) {
+ if(login->username && login->password && login->nick && login->realname && !(client->flags & USERCLIENT_LOGIN_PROCESSING)) {
//try to login
iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Checking login...");
usersession_login(login);
}
} else {
+ struct UserSession *session = client->user;
+ if(!stricmplen(line, "QUIT", 4))
+ return;
+ if(session->irc)
+ ircclient_send(session->irc, line);
}
}
free(login->nick);
free(login);
client->user = session;
+ client->flags |= USERCLIENT_LOGGED_IN;
if(recover) {
iohandler_printf(client->iofd, "NOTICE AUTH :*** [TransparentIRC] Recovering previous link (Nick: %s).", session->nick);
char *username;
char *password;
char *nick;
+ char *realname;
int login_accepted : 1;
char *reject_reason;
char *session_class;
+ char *bind_address;
+ char *server_address;
+ int server_override_port : 1;
+ int server_port : 17;
+ int server_ssl : 1;
struct IODescriptor *login_iofd;
};
#include "UserClient.h"
#include "ConfigParser.h"
#include "tools.h"
+#include "IRCClient.h"
static struct UserSession *usersessions = NULL;
return session;
}
-/*
static void usersession_close(struct UserSession *session) {
if(session->client)
userclient_close(session->client);
+ if(session->irc)
+ ircclient_close(session->irc);
if(session->prev)
session->prev->next = session->next;
free(session->username);
free(session->password);
free(session->nick);
+ if(session->realname)
+ free(session->realname);
free(session);
}
-*/
-/* ****************** SESSION FUNCTIONS ****************** */
+/* ****************** EXTERNAL EVENTS ****************** */
-static void usersession_initialize_session(struct UserSession *session) {
-
+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);
+ }
+ usersession_close(session);
}
-/* ****************** EXTERNAL EVENTS ****************** */
-
void usersession_client_close(struct UserSession *session) {
session->client = NULL;
session->idle_since = time(0);
}
+void usersession_client_raw(struct UserSession *session, char *raw) {
+ if(session->client) {
+ iohandler_printf(session->client->iofd, "%s", raw);
+ }
+}
+
void usersession_client_notification(struct UserSession *session, char *notification) {
if(session->client) {
iohandler_printf(session->client->iofd, ":*TransparentIRC!TransIRC@TransparentIRC.system.notification NOTICE %s :[TransparentIRC] %s", session->nick, notification);
userclient_login_failed(login, "Could not create Session.");
return;
}
+ active_session->client = login->client;
+ active_session->realname = strdup(login->realname);
+ ircclient_initialize(active_session, login);
userclient_login_successful(login, active_session, 0);
- usersession_initialize_session(active_session);
}
}
if(argc < 2) return;
if(!stricmp(argv[0], "CLASS")) {
login->session_class = strdup(argv[1]);
+ } else if(!stricmp(argv[0], "SERVER")) {
+ login->server_address = strdup(argv[1]);
+ if(argc > 2) {
+ login->server_override_port = 1;
+ if(argv[2][0] == '+') {
+ argv[2]++;
+ login->server_ssl = 1;
+ }
+ login->server_port = atoi(argv[2]);
+ }
+ } else if(!stricmp(argv[0], "BIND")) {
+ login->bind_address = strdup(argv[1]);
}
}
char *username;
char *password;
char *nick;
+ char *realname; //only valid till IRC handshake
struct UserClient *client;
+ struct IRCClient *irc;
time_t idle_since;
time_t connected_since;
struct UserSession *next, *prev;
};
+void usersession_error(struct UserSession *session, char *error);
+void usersession_client_raw(struct UserSession *session, char *raw);
void usersession_client_notification(struct UserSession *session, char *notification);
void usersession_login(struct UserLogin *login);
void usersession_login_abort(struct UserLogin *login);
parseParameters(argc, argv);
loadConfig(configFile);
- serversocket_listen("0.0.0.0", 9001);
+ serversocket_listen("0.0.0.0", 9001, 0);
while(1) {
iohandler_poll();
}
}
+char* merge_argv(char **argv, int start, int end) {
+ return merge_argv_char(argv, start, end, ' ');
+}
+
+char* merge_argv_char(char **argv, int start, int end, char seperator) {
+ int i;
+ char *p = NULL;
+ while(!argv[start]) start++;
+ if(start >= end)
+ return NULL;
+ for(i = start; i < end; i++) {
+ p = argv[i];
+ if(!p) continue;
+ while(*p) p++;
+ if(i < end-1) {
+ while(p != argv[i+1]) {
+ *p++ = seperator;
+ }
+ } else
+ *p = seperator;
+ }
+ if(p) *p = '\0';
+ return argv[start];
+}
int parse_line(char *line, char **argv, int irc_raw);
void build_var_string(char *buffer, char *format, struct variable_replace_map *map);
int run_external_process(char *command, char **parameters);
+char *merge_argv(char **argv, int start, int end);
+char *merge_argv_char(char **argv, int start, int end, char seperator);
#endif