New nick mgmt code

This commit is contained in:
nohar 2007-01-26 18:52:21 +00:00
parent a2a8e0a193
commit e6b7672a19
3 changed files with 51 additions and 222 deletions

View File

@ -1,3 +1,8 @@
2006-01-26 Arnaud Cornet <arnaud.cornet@gmail.com>
* Infamous nick bug: This changes pretty much everything and might fix
the damn thing. Needs testing.
2006-01-12 Arnaud Cornet <arnaud.cornet@gmail.com>
* src/irc.c: /msg to -bip is now equivalent to /quote bip.

262
src/irc.c
View File

@ -43,9 +43,9 @@ static int irc_366(struct link_server *server, struct line *line);
static int irc_367(struct link_server *server, struct line *l);
static int irc_368(struct link_server *server, struct line *l);
void irc_server_shutdown(struct link_server *s);
static int origin_is_me(struct line *l, struct link_server *server);
void irc_client_free(struct link_client *cli);
static char *make_irc_mask(char *nick, char *oldim);
extern int conf_backlog;
extern int conf_log_sync_interval;
extern int conf_error;
@ -60,7 +60,8 @@ static void irc_cli_make_join(struct link_client *ic);
#define LAGOUT_TIME (360)
#define LAGCHECK_TIME (90)
#define RECONN_TIMER (120)
/* XXX 10 => 120 */
#define RECONN_TIMER (10)
#define LOGGING_TIMEOUT (360)
#define CONN_INTERVAL 60
#define CONNECT_TIMEOUT 60
@ -76,26 +77,6 @@ struct channel *channel_new(const char *name)
return chan;
}
static char *make_irc_mask(char *nick, char *oldim)
{
char *nm;
char *imaskend = oldim;
if (!imaskend) {
imaskend = "!bip@bip.bip.bip";
} else {
while (*imaskend && *imaskend != '!')
imaskend++;
if (*imaskend == '\0')
imaskend = "!bip@bip.bip.bip";
}
nm = malloc(strlen(nick) + strlen(imaskend) + 1);
*nm = 0;
strcat(nm, nick);
strcat(nm, imaskend);
return nm;
}
char *nick_from_ircmask(char *mask)
{
char *nick = mask;
@ -118,28 +99,6 @@ char *nick_from_ircmask(char *mask)
return ret;
}
static int is_irc_mask(char *mask)
{
while (*mask && *mask != '!')
mask++;
if (*mask == 0)
return 0;
while (*mask && *mask != '@')
mask++;
if (*mask == 0)
return 0;
return 1;
}
static void set_ircmask(struct link_server *server, char *ircmask)
{
if (!is_irc_mask(ircmask))
return;
if (server->irc_mask)
free(server->irc_mask);
server->irc_mask = strdup(ircmask);
}
#define NAMESIZE 256
list_t *channel_name_list(struct channel *c)
@ -188,68 +147,21 @@ list_t *channel_name_list(struct channel *c)
static int irc_001(struct link_server *server, struct line *line)
{
int ret = OK_FORGET;
char *p, *ps, *pe;
size_t len;
char *ircmask, *oldircmask;
(void)line;
if (LINK(server)->s_state == IRCS_WAS_CONNECTED)
LINK(server)->s_state = IRCS_RECONNECTING;
else
LINK(server)->s_state = IRCS_CONNECTING;
if (line->elemc != 3)
return ERR_PROTOCOL;
ps = pe = line->elemv[2];
pe += strlen(pe);
p = strrchr(ps, ' ');
if (!p)
return ERR_PROTOCOL;
p++;
len = pe - p;
ircmask = malloc(len + 1);
if (!ircmask)
fatal("malloc");
memcpy(ircmask, p, len);
ircmask[len] = 0;
oldircmask = server->irc_mask;
server->irc_mask = NULL;
set_ircmask(server, ircmask);
if (server->nick)
free(server->nick);
server->nick = nick_from_ircmask(ircmask);
if (server->irc_mask == NULL)
server->irc_mask = make_irc_mask(server->nick, "");
/* 001 means the nick we sent is accepted by server, inform clients */
if (oldircmask && LINK(server)->s_state == IRCS_RECONNECTING &&
LINK(server)->prev_nick) {
if (strcmp(LINK(server)->prev_nick, server->nick) != 0) {
/*
* Inform connected clients that server<->proxy
* disconnection resulted in nick change
* sadly the oldircmask info is a guess only
*/
int i;
for (i = 0; i < LINK(server)->l_clientc; i++) {
struct link_client *c =
LINK(server)->l_clientv[i];
WRITE_LINE1(CONN(c), oldircmask, "NICK",
server->nick);
}
}
/* change nick on client */
int i;
for (i = 0; i < LINK(server)->l_clientc; i++) {
struct link_client *c = LINK(server)->l_clientv[i];
WRITE_LINE1(CONN(c), LINK(server)->cli_nick, "NICK",
server->nick);
}
if (LINK(server)->prev_nick)
free(LINK(server)->prev_nick);
LINK(server)->prev_nick = strdup(server->nick);
if (oldircmask)
free(oldircmask);
free(ircmask);
return ret;
return OK_COPY;
}
void irc_start_lagtest(struct link_server *l)
@ -302,21 +214,20 @@ static void irc_server_join(struct link_server *s)
static void irc_server_connected(struct link_server *server)
{
int i;
char *initmask;
LINK(server)->s_state = IRCS_CONNECTED;
irc_server_join(server);
log_connected(LINK(server)->log);
/* Tell already connected clients what the nick is */
initmask = make_irc_mask(server->nick, server->irc_mask);
/* we change nick on client */
for (i = 0; i < LINK(server)->l_clientc; i++) {
struct link_client *ic = LINK(server)->l_clientv[i];
WRITE_LINE1(CONN(ic), initmask, "NICK", server->nick);
if (LINK(server)->cli_nick) {
/* we change nick on client */
for (i = 0; i < LINK(server)->l_clientc; i++) {
struct link_client *ic = LINK(server)->l_clientv[i];
WRITE_LINE1(CONN(ic), LINK(server)->cli_nick, "NICK",
server->nick);
}
free(LINK(server)->cli_nick);
LINK(server)->cli_nick = NULL;
}
free(initmask);
/* basic helper for nickserv and co */
list_iterator_t itocs;
for (list_it_init(&LINK(server)->on_connect_send, &itocs);
@ -349,46 +260,31 @@ static int who_arg_to_ovmask(char *str)
}
/*
* Given the way irc nets disrespect the rfc, maybe we should completely forget
* Given the way irc nets disrespect the rfc, we completely forget
* about this damn ircmask...
:irc.iiens.net 352 pwet * ~a je.suis.t1r.net irc.iiens.net pwet H :0 d
*/
static int irc_352(struct link_server *server, struct line *line)
{
char *im;
(void)server;
if (line->elemc < 8)
return ERR_PROTOCOL;
if (strcmp(line->elemv[2], "*") == 0) {
if (server->irc_mask &&
strcmp(line->elemv[1], server->nick) == 0) {
im = malloc(strlen(server->nick) +
strlen(line->elemv[3]) +
strlen(line->elemv[4]) + 2 + 1);
strcpy(im, server->nick);
strcat(im, "!");
strcat(im, line->elemv[3]);
strcat(im, "@");
strcat(im, line->elemv[4]);
set_ircmask(server, im);
free(im);
return OK_FORGET;
}
} else {
if (!origin_is_me(line, server)) {
struct channel *channel;
struct nick *nick;
channel = hash_get(&server->channels, line->elemv[2]);
if (!channel)
return OK_COPY;
return OK_COPY_WHO;
nick = hash_get(&channel->nicks, line->elemv[6]);
if (!nick)
return OK_COPY;
return OK_COPY_WHO;
nick->ovmask = who_arg_to_ovmask(line->elemv[7]);
}
return OK_COPY_WHO;
}
@ -445,6 +341,8 @@ int irc_dispatch_server(struct link_server *server, struct line *line)
if (line->elemc == 0)
return ERR_PROTOCOL;
printf("coucou23: %s\n", line->elemv[0]);
if (strcmp(line->elemv[0], "PING") == 0) {
if (line->elemc < 2)
return ERR_PROTOCOL;
@ -515,6 +413,7 @@ int irc_dispatch_server(struct link_server *server, struct line *line)
if (LINK(server)->s_state == IRCS_CONNECTING) {
if (!list_is_empty(&LINK(server)->init_strings))
return ERR_PROTOCOL;
/* update the irc mask */
list_add_last(&LINK(server)->init_strings,
irc_line_dup(line));
}
@ -581,7 +480,7 @@ int irc_dispatch_server(struct link_server *server, struct line *line)
/* send join and related stuff to client */
static void irc_send_join(struct link_client *ic, struct channel *chan)
{
WRITE_LINE1(CONN(ic), LINK(ic)->l_server->irc_mask, "JOIN", chan->name);
WRITE_LINE1(CONN(ic), LINK(ic)->l_server->nick, "JOIN", chan->name);
if (chan->topic)
WRITE_LINE3(CONN(ic), P_SERV, "332", LINK(ic)->l_server->nick,
chan->name, chan->topic);
@ -760,7 +659,6 @@ static void irc_cli_make_join(struct link_client *ic)
static int irc_cli_startup(struct link_client *ic, struct line *line,
list_t *linkl)
{
char *initmask;
char *init_nick;
char *user, *pass, *connname;
(void)line;
@ -834,20 +732,8 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
return OK_CLOSE;
}
#if 0
TODO code this -- OR NOT!
if (!connection_check_source(ic, ic->client->src_ipl))
return ERR_AUTH;
#endif
TYPE(ic) = IRC_TYPE_CLIENT;
if (LINK(ic)->l_server)
initmask = make_irc_mask(init_nick,
LINK(ic)->l_server->irc_mask);
else
initmask = make_irc_mask(init_nick, LINK(ic)->prev_ircmask);
for (list_it_init(&LINK(ic)->init_strings, &it);
list_it_item(&it); list_it_next(&it))
write_init_string(CONN(ic), list_it_item(&it), init_nick);
@ -855,7 +741,7 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
/* we change nick on server */
if (LINK(ic)->l_server) {
struct link_server *server = LINK(ic)->l_server;
WRITE_LINE1(CONN(ic), initmask, "NICK", server->nick);
WRITE_LINE1(CONN(ic), init_nick, "NICK", server->nick);
if (!LINK(ic)->ignore_first_nick)
WRITE_LINE1(CONN(server), NULL, "NICK", init_nick);
@ -869,7 +755,6 @@ static int irc_cli_startup(struct link_client *ic, struct line *line,
WRITE_LINE0(CONN(server), NULL, "AWAY");
}
free(initmask);
if (!LINK(ic)->l_server) {
free(init_nick);
return OK_FORGET;
@ -1014,46 +899,12 @@ static int irc_cli_mode(struct link_client *ic, struct line *line)
return OK_COPY;
}
#if 0
static void unbind_to_server(struct link_client *ic)
{
struct irc_server *s = ic->client->server;
int i;
for (i = 0; i < s->clientc; i++)
if (s->clientv[i] == ic)
break;
if (i == s->clientc)
fatal("unbind_to_server");
for (i = i + 1; i < s->clientc; i++)
s->clientv[i - 1] = s->clientv[i];
s->clientc--;
s->clientv = realloc(s->clientv, s->clientc *
sizeof(struct irc_client *));
if (s->clientc == 0) { /* realloc was equiv to free() */
s->clientv = NULL;
return;
}
if (!s->clientv)
fatal("realloc");
}
static void bind_to_server(struct irc_client *ic)
{
struct irc_server *s = ic->client->server;
int i = s->clientc;
s->clientc++;
s->clientv = realloc(s->clientv, s->clientc *
sizeof(struct irc_client *));
if (!s->clientv)
fatal("realloc");
s->clientv[i] = ic;
}
#endif
static void irc_notify_disconnection(struct link_server *is)
{
int i;
LINK(is)->cli_nick = strdup(is->nick);
for (i = 0; i < LINK(is)->l_clientc; i++) {
struct link_client *ic = LINK(is)->l_clientv[i];
hash_iterator_t hi;
@ -1064,7 +915,7 @@ static void irc_notify_disconnection(struct link_server *is)
c->name, is->nick,
"Server disconnected, reconnecting");
}
WRITE_LINE2(CONN(ic), P_IRCMASK, "PRIVMSG", is->irc_mask,
WRITE_LINE2(CONN(ic), P_IRCMASK, "PRIVMSG", is->nick,
"Server disconnected, reconnecting");
}
}
@ -1213,11 +1064,11 @@ static int irc_dispatch_client(struct link_client *ic, struct line *line)
if (r == OK_COPY || r == OK_COPY_CLI) {
char *str = irc_line_to_string(line);
if (LINK(ic)->s_state == IRCS_CONNECTED &&
LINK(ic)->l_server->irc_mask)
LINK(ic)->l_server->nick)
write_line(CONN(LINK(ic)->l_server), str);
else if (LINK(ic)->l_server->irc_mask)
else if (LINK(ic)->l_server->nick)
WRITE_LINE2(CONN(ic), P_IRCMASK, "PRIVMSG",
LINK(ic)->l_server->irc_mask,
LINK(ic)->l_server->nick,
":Not connected please try again "
"later...\r\n");
@ -1248,7 +1099,7 @@ static void irc_copy_cli(struct link_client *src, struct link_client *dest,
}
if (ischannel(*line->elemv[1]) || LINK(src) != LINK(dest)) {
line->origin = LINK(src)->l_server->irc_mask;
line->origin = LINK(src)->l_server->nick;
str = irc_line_to_string(line);
line->origin = NULL;
write_line(CONN(dest), str);
@ -1270,7 +1121,7 @@ static void irc_copy_cli(struct link_client *src, struct link_client *dest,
line->origin = line->elemv[1];
/* tricky: */
line->elemv[1] = LINK(src)->l_server->irc_mask;
line->elemv[1] = LINK(src)->l_server->nick;
free(line->elemv[2]);
line->elemv[2] = tmp;
@ -1330,7 +1181,7 @@ static int origin_is_me(struct line *l, struct link_server *server)
if (!l->origin)
return 0;
nick = nick_from_ircmask(l->origin);
if (strcmp(nick, server->nick) == 0) {
if (strcasecmp(nick, server->nick) == 0) {
free(nick);
return 1;
}
@ -1862,7 +1713,6 @@ static int irc_nick(struct link_server *server, struct line *line)
struct channel *channel;
struct nick *nick;
hash_iterator_t hi;
char *s_nick;
if (line->elemc != 2)
return ERR_PROTOCOL;
@ -1870,19 +1720,9 @@ static int irc_nick(struct link_server *server, struct line *line)
if (!line->origin)
return ERR_PROTOCOL;
s_nick = nick_from_ircmask(line->origin);
if (strcmp(s_nick, server->nick) == 0) {
char *nim;
if (origin_is_me(line, server)) {
free(server->nick);
server->nick = strdup(line->elemv[1]);
/* How the hell do we handle that crap cleanly ? */
nim = make_irc_mask(line->elemv[1], server->irc_mask);
if (nim) {
free(server->irc_mask);
server->irc_mask = nim;
}
if (LINK(server)->follow_nick &&
(LINK(server)->away_nick == NULL ||
strcmp(server->nick, LINK(server)->away_nick))
@ -1895,18 +1735,17 @@ static int irc_nick(struct link_server *server, struct line *line)
for (hash_it_init(&server->channels, &hi); hash_it_item(&hi);
hash_it_next(&hi)) {
channel = hash_it_item(&hi);
nick = hash_get(&channel->nicks, s_nick);
nick = hash_get(&channel->nicks, server->nick);
if (!nick)
continue;
hash_remove(&channel->nicks, s_nick);
hash_remove(&channel->nicks, server->nick);
free(nick->name);
nick->name = strdup(line->elemv[1]);
hash_insert(&channel->nicks, nick->name, nick);
log_nick(LINK(server)->log, s_nick, channel->name,
log_nick(LINK(server)->log, server->nick, channel->name,
line->elemv[1]);
}
free(s_nick);
return OK_COPY;
}
@ -1996,10 +1835,6 @@ void server_cleanup(struct link_server *server)
free(server->nick);
server->nick = NULL;
}
if (server->irc_mask) {
free(server->irc_mask);
server->irc_mask = NULL;
}
if (LINK(server)->s_state == IRCS_CONNECTED) {
LINK(server)->s_state = IRCS_WAS_CONNECTED;
} else {
@ -2110,8 +1945,6 @@ void irc_server_free(struct link_server *s)
{
if (s->nick)
free(s->nick);
if (s->irc_mask)
free(s->irc_mask);
if (s->user_mode)
free(s->user_mode);
free(s);
@ -2172,13 +2005,6 @@ void irc_server_shutdown(struct link_server *s)
if (LINK(s)->prev_nick)
free(LINK(s)->prev_nick);
LINK(s)->prev_nick = strdup(s->nick);
if (LINK(s)->prev_ircmask) {
free(LINK(s)->prev_ircmask);
LINK(s)->prev_ircmask = NULL;
}
if (s->irc_mask)
LINK(s)->prev_ircmask = strdup(s->irc_mask);
}

View File

@ -78,8 +78,8 @@ struct link {
/* server related live stuff */
int s_state;
char *prev_nick;
char *prev_ircmask;
char *prev_nick; /* XXX del me */
char *cli_nick;
list_t init_strings;
/* connection state (reconnecting, was_connected ...) */
@ -182,8 +182,6 @@ struct link_server {
char *nick;
char *irc_mask;
/* channels we are in */
hash_t channels;