static void connected(server *s) { /* Server successfully connected, send IRC init messages */ connection_thread *ct = s->connecting; if ((pthread_join(ct->tid, NULL))) fatal("pthread_join"); if (*ct->ipstr) newlinef(s->channel, 0, "--", "Connected to [%s]", ct->ipstr); else newlinef(s->channel, 0, "--", "Error determining server IP: %s", ct->error); s->soc = ct->socket; /* Set reconnect parameters to 0 in case this was an auto-reconnect */ s->reconnect_time = 0; s->reconnect_delta = 0; s->latency_time = time(NULL); s->latency_delta = 0; sendf(NULL, s, "NICK %s", s->nick); sendf(NULL, s, "USER %s 8 * :%s", config.username, config.realname); //FIXME: should the server send nick as is? compare the nick when it's received? //or should auto_nick take a server argument and write to a buffer of NICKSIZE length? }
//FIXME: move the stateful stuff to state.c, only the connection relavent stuff should be here void server_connect(char *host, char *port) { connection_thread *ct; server *tmp, *s = NULL; /* Check if server matching host:port already exists */ if ((tmp = server_head) != NULL) { do { if (!strcmp(tmp->host, host) && !strcmp(tmp->port, port)) { s = tmp; break; } } while ((tmp = tmp->next) != server_head); } /* Check if server is already connected */ if (s && s->soc >= 0) { channel_set_current(s->channel); newlinef(s->channel, 0, "-!!-", "Already connected to %s:%s", host, port); return; } if (s == NULL) s = new_server(host, port); channel_set_current(s->channel); if ((ct = calloc(1, sizeof(*ct))) == NULL) fatal("calloc"); ct->socket = -1; ct->socket_tmp = -1; ct->host = s->host; ct->port = s->port; s->connecting = ct; newlinef(s->channel, 0, "--", "Connecting to '%s' port %s", host, port); if ((pthread_create(&ct->tid, NULL, threaded_connect, ct))) fatal("pthread_create"); }
static int check_connect(server *s) { /* Check the server's connection thread status for success or failure */ if (!s->connecting) return 0; connection_thread *ct = (connection_thread*)s->connecting; /* Connection Success */ if (ct->socket >= 0) { connected(s); /* Connection failure */ } else if (*ct->error) { newline(s->channel, 0, "-!!-", ct->error); /* If server was auto-reconnecting, increase the backoff */ if (s->reconnect_time) { s->reconnect_delta *= 2; s->reconnect_time += s->reconnect_delta; newlinef(s->channel, 0, "--", "Attempting reconnect in %ds", s->reconnect_delta); } /* Connection in progress */ } else { return 1; } free(ct); s->connecting = NULL; return 1; }
//server_disconnect(server *s, char *mesg, int flags) void server_disconnect(server *s, int err, int kill, char *mesg) { /* When err flag is set: * Disconnect initiated by remote host * * When kill flag is set: * Free the server, update ccur */ /* Server connection in progress, cancel the connection attempt */ if (s->connecting) { connection_thread *ct = s->connecting; if ((pthread_cancel(ct->tid))) fatal("pthread_cancel"); /* There's a chance the thread is canceled with an open socket */ if (ct->socket_tmp) close(ct->socket_tmp); free(ct); s->connecting = NULL; newlinef(s->channel, 0, "--", "Connection to '%s' port %s canceled", s->host, s->port); } /* Server is/was connected, close socket, send quit message if non-erroneous disconnect */ else if (s->soc >= 0) { if (err) { /* If disconnecting due to error, attempt a reconnect */ newlinef(s->channel, 0, "ERROR", "%s", mesg); newlinef(s->channel, 0, "--", "Attempting reconnect in %ds", RECONNECT_DELTA); s->reconnect_time = time(NULL) + RECONNECT_DELTA; s->reconnect_delta = RECONNECT_DELTA; } else if (mesg) { sendf(NULL, s, "QUIT :%s", mesg); } close(s->soc); /* Set all server attributes back to default */ memset(s->usermodes, 0, MODE_SIZE); s->soc = -1; s->iptr = s->input; s->nptr = config.nicks; s->latency_delta = 0; /* Reset the nick that reconnects will attempt to register with */ auto_nick(&(s->nptr), s->nick); /* Print message to all open channels and reset their attributes */ channel *c = s->channel; do { newline(c, 0, "-!!-", "(disconnected)"); reset_channel(c); } while ((c = c->next) != s->channel); } /* Server was waiting to reconnect, cancel future attempt */ else if (s->reconnect_time) { newlinef(s->channel, 0, "--", "Auto reconnect attempt canceled"); s->reconnect_time = 0; s->reconnect_delta = 0; } if (kill) { DLL_DEL(server_head, s); free_server(s); } }