struct Timer i_reconn_timer; /**< when to reconnect the connection */
struct Timer i_request_timer; /**< when the current request times out */
struct IAuthFlags i_flags; /**< connection state/status/flags */
- struct DNSQuery i_query; /**< DNS lookup for iauth server */
unsigned int i_recvM; /**< messages received */
unsigned int i_sendM; /**< messages sent */
unsigned int i_recvK; /**< kilobytes received */
memset(&i_addr(iauth), 0, sizeof(i_addr(iauth)));
i_port(iauth) = port;
iauth_active = iauth;
+ timer_init(&i_reconn_timer(iauth));
i_reconnect(iauth) = reconnect;
iauth_reconnect(iauth);
}
if (t_active(&i_request_timer(iauth)))
timer_del(&i_request_timer(iauth));
/* Disconnect from the server. */
- if (s_fd(&i_socket(iauth)) != -1)
+ if (i_GetConnected(iauth))
iauth_disconnect(iauth);
/* Free memory. */
MyFree(iauth);
assert(format != 0);
vd.vd_format = format;
va_start(vd.vd_args, format);
- sendwallto_group_butone(&me, WALL_DESYNCH, NULL, "IAuth protocol violation: %v", &vd);
+ sendto_opmask_butone(NULL, SNO_CONNEXIT, "IAuth protocol violation: %v", &vd);
va_end(vd.vd_args);
}
{
close(s_fd(&i_socket(iauth)));
socket_del(&i_socket(iauth));
- s_fd(&i_socket(iauth)) = -1;
+ i_ClrConnected(iauth);
}
/** DNS completion callback for an %IAuth connection.
* @param[in] vptr Pointer to the IAuth struct.
* @param[in] he DNS reply parameters.
*/
-static void iauth_dns_callback(void *vptr, struct DNSReply *he)
+static void iauth_dns_callback(void *vptr, const struct irc_in_addr *addr, const char *h_name)
{
struct IAuth *iauth = vptr;
- if (!he) {
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth connection to %s failed: host lookup failed", i_host(iauth));
+ if (!addr) {
+ log_write(LS_IAUTH, L_NOTICE, 0, "IAuth connection to %s failed: host lookup failed", i_host(iauth));
} else {
- memcpy(&i_addr(iauth).addr, &he->addr, sizeof(i_addr(iauth).addr));
+ memcpy(&i_addr(iauth).addr, addr, sizeof(i_addr(iauth).addr));
if (!irc_in_addr_valid(&i_addr(iauth).addr)) {
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth connection to %s failed: host came back as unresolved", i_host(iauth));
+ log_write(LS_IAUTH, L_NOTICE, 0, "IAuth connection to %s failed: host came back as unresolved", i_host(iauth));
return;
}
iauth_reconnect(iauth);
static void iauth_schedule_reconnect(struct IAuth *iauth)
{
struct Timer *timer;
- assert(!t_active(&i_reconn_timer(iauth)));
- timer = timer_init(&i_reconn_timer(iauth));
- timer_add(timer, iauth_reconnect_ev, iauth, TT_RELATIVE, i_reconnect(iauth));
+ timer = &i_reconn_timer(iauth);
+ if (t_onqueue(timer))
+ timer_chg(timer, TT_RELATIVE, i_reconnect(iauth));
+ else
+ timer_add(&i_reconn_timer(iauth), iauth_reconnect_ev,
+ iauth, TT_RELATIVE, i_reconnect(iauth));
}
/** Initiate a (re-)connection to \a iauth.
IOResult result;
int fd;
- Debug((DEBUG_INFO, "IAuth attempt connection to %s port %p.", i_host(iauth), i_port(iauth)));
+ if (i_GetConnected(iauth)) {
+ iauth_disconnect(iauth);
+ iauth_schedule_reconnect(iauth);
+ return;
+ }
+ log_write(LS_IAUTH, L_DEBUG, 0, "IAuth attempt connection to %s port %p.", i_host(iauth), i_port(iauth));
if (!irc_in_addr_valid(&i_addr(iauth).addr)
&& !ircd_aton(&i_addr(iauth).addr, i_host(iauth))) {
- i_query(iauth).vptr = iauth;
- i_query(iauth).callback = iauth_dns_callback;
- gethost_byname(i_host(iauth), &i_query(iauth));
+ gethost_byname(i_host(iauth), iauth_dns_callback, iauth);
return;
}
local = irc_in_addr_is_ipv4(&i_addr(iauth).addr) ? &VirtualHost_v4 : &VirtualHost_v6;
fd = os_socket(local, SOCK_STREAM, "IAuth");
- if (fd < 0)
+ if (fd < 0) {
+ iauth_schedule_reconnect(iauth);
return;
+ }
if (!os_set_sockbufs(fd, SERVER_TCP_WINDOW, SERVER_TCP_WINDOW)) {
- close(fd);
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth reconnect unable to set socket buffers: %s", strerror(errno));
- return;
+ log_write(LS_IAUTH, L_WARNING, 0, "IAuth reconnect unable to set socket buffers: %s", strerror(errno));
+ goto failure;
}
+ s_fd(&i_socket(iauth)) = fd;
result = os_connect_nonb(fd, &i_addr(iauth));
if (result == IO_FAILURE) {
- close(fd);
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth reconnect unable to initiate connection: %s", strerror(errno));
- return;
+ log_write(LS_IAUTH, L_NOTICE, 0, "IAuth reconnect unable to initiate connection: %s", strerror(errno));
+ goto failure;
}
if (!socket_add(&i_socket(iauth), iauth_sock_callback, iauth,
(result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING,
SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE, fd)) {
- close(fd);
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth reconnect unable to add socket: %s", strerror(errno));
- return;
+ log_write(LS_IAUTH, L_WARNING, 0, "IAuth reconnect unable to add socket: %s", strerror(errno));
+ goto failure;
}
+ return;
+failure:
+ close(fd);
+ i_ClrConnected(iauth);
+ iauth_schedule_reconnect(iauth);
+ return;
}
/** Read input from \a iauth.
char readbuf[SERVER_TCP_WINDOW];
length = 0;
- if (IO_FAILURE == os_recv_nonb(s_fd(&i_socket(iauth)), readbuf, sizeof(readbuf), &length))
- return;
+ if (IO_FAILURE == os_recv_nonb(s_fd(&i_socket(iauth)), readbuf, sizeof(readbuf), &length)
+ || length == 0) {
+ iauth_reconnect(iauth);
+ return;
+ }
i_recvB(iauth) += length;
if (i_recvB(iauth) > 1023) {
i_recvK(iauth) += i_recvB(iauth) >> 10;
i_ClrBlocked(iauth);
iauth_write(iauth);
break;
- case ET_EOF:
- iauth_disconnect(iauth);
- break;
case ET_ERROR:
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth socket error: %s", strerror(ev_data(ev)));
- log_write(LS_SOCKET, L_ERROR, 0, "IAuth socket error: %s", strerror(ev_data(ev)));
+ log_write(LS_IAUTH, L_ERROR, 0, "IAuth socket error: %s", strerror(ev_data(ev)));
+ /* and fall through to the ET_EOF case */
+ case ET_EOF:
iauth_disconnect(iauth);
+ iauth_schedule_reconnect(iauth);
break;
default:
assert(0 && "Unrecognized event type");
{
/* TODO: this could probably be more intelligent */
if (ev_type(ev) == ET_EXPIRE) {
- sendto_opmask_butone(0, SNO_OLDSNO, "IAuth request timed out; reconnecting");
+ log_write(LS_IAUTH, L_NOTICE, 0, "IAuth request timed out; reconnecting");
iauth_reconnect(t_data(ev_timer(ev)));
}
}
/* Allocate and initialize IAuthRequest struct. */
if (!(iar = MyCalloc(1, sizeof(*iar))))
return exit_client(cptr, cptr, &me, "IAuth memory allocation failed");
+ cli_iauth(cptr) = iar;
iar->iar_next = &i_list_head(iauth);
iar->iar_prev = i_list_head(iauth).iar_prev;
iar->iar_client = cptr;
if (cli_iauth(cptr)) {
iauth_dispose_request(iauth_active, cli_iauth(cptr));
cli_iauth(cptr) = NULL;
- } else if (IsIAuthed(cptr) && i_GetIClass(iauth_active)) {
- /* TODO: report quit to iauth */
+ }
+ if (iauth_active && i_GetConnected(iauth_active)) {
+ iauth_send(iauth_active, "ExitUser %x", cptr);
+ iauth_write(iauth_active);
}
}
static void iauth_dispose_request(struct IAuth *iauth, struct IAuthRequest *iar)
{
assert(iar->iar_client != NULL);
- if (iar->iar_timed)
+ if (iar->iar_timed && t_active(&i_request_timer(iauth)))
timer_del(&i_request_timer(iauth));
cli_iauth(iar->iar_client) = NULL;
iar->iar_prev->iar_next = iar->iar_next;