X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=innduct.git;a=blobdiff_plain;f=conn.c;h=36f554f1a6e422ca34e3de52540bea7157750dc4;hp=301d0258d81e8746c5b4f2a28bc85d7afe7318e0;hb=e3812169fa785d9f7632bf8a82b4e9775fb7fbd6;hpb=f4aee95c41a0d6231d115386b8fbb23f6b8e349a diff --git a/conn.c b/conn.c index 301d025..36f554f 100644 --- a/conn.c +++ b/conn.c @@ -1,3 +1,31 @@ +/* + * innduct + * tailing reliable realtime streaming feeder for inn + * conn.c - connection establishment and teardown + * + * Copyright (C) 2010 Ian Jackson + * + * 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 . + * + * (I believe that when you compile and link this as part of the inn2 + * build, with the Makefile runes I have provided, all the libraries + * and files which end up included in innduct are licence-compatible + * with GPLv3. If not then please let me know. -Ian Jackson.) + */ + +#include "innduct.h" + /*========== management of connections ==========*/ static void reconnect_blocking_event(void) { @@ -10,7 +38,7 @@ void conn_closefd(Conn *conn, const char *msgprefix) { conn->fd, msgprefix, strerror(errno)); } -static int conn_busy(Conn *conn) { +int conn_busy(Conn *conn) { return conn->waiting.count || conn->priority.count || @@ -18,7 +46,7 @@ static int conn_busy(Conn *conn) { conn->xmitu; } -static void conn_dispose(Conn *conn) { +void conn_dispose(Conn *conn) { if (!conn) return; if (conn->rd) { oop_rd_cancel(conn->rd); @@ -46,7 +74,7 @@ static void *conn_exception(oop_source *lp, int fd, return OOP_CONTINUE; } -static void vconnfail(Conn *conn, const char *fmt, va_list al) { +void vconnfail(Conn *conn, const char *fmt, va_list al) { int requeue[art_MaxState]; memset(requeue,0,sizeof(requeue)); @@ -72,8 +100,9 @@ static void vconnfail(Conn *conn, const char *fmt, va_list al) { LIST_REMOVE(conns,conn); - char *m= xvasprintf(fmt,al); - warn("C%d (now %d) connection failed requeueing " RCI_TRIPLE_FMT_BASE ": %s", + char *m= mvasprintf(fmt,al); + warn("C%d (now %d) connection failed " + "(requeueing " RCI_TRIPLE_FMT_BASE "): %s", conn->fd, conns.count, RCI_TRIPLE_VALS_BASE(requeue, /*nothing*/), m); free(m); @@ -82,7 +111,7 @@ static void vconnfail(Conn *conn, const char *fmt, va_list al) { check_assign_articles(); } -static void connfail(Conn *conn, const char *fmt, ...) { +void connfail(Conn *conn, const char *fmt, ...) { va_list al; va_start(al,fmt); vconnfail(conn,fmt,al); @@ -118,7 +147,7 @@ static void conn_idle_close(Conn *conn, const char *why) { * For our last connection, we also shut it down if we have had * less than K in the last L */ -static void check_idle_conns(void) { +void check_idle_conns(void) { Conn *conn; int volthisperiod= lowvol_perperiod[lowvol_circptr]; @@ -160,9 +189,33 @@ static void check_idle_conns(void) { conn_idle_close(conn, "low volume"); } +/*---------- reporting numbers of connections ----------*/ + +static int conns_max_reported, conns_idle_reported; + +void notice_conns_more(const char *new_kind) { + if (conns.count > conns_max_reported) { + notice("up to %d connection(s) (%s)", conns.count, new_kind); + conns_max_reported= conns.count; + } +} + +void notice_conns_fewer(void) { + if (!conns.count && !conns_idle_reported) { + notice("low volume, using intermittent connection"); + conns_idle_reported= 1; + } +} + +void notice_conns_stats(void) { + notice("currently %d connection(s)", conns.count); + conns_max_reported= conns.count; + conns_idle_reported= 0; +} + /*---------- making new connections ----------*/ -static pid_t connecting_child; +pid_t connecting_child; int connecting_fdpass_sock; static void connect_attempt_discard(void) { @@ -274,14 +327,15 @@ static void *connchild_event(oop_source *lp, int fd, oop_event e, void *u) { loop->on_fd(loop, conn->fd, OOP_EXCEPTION, conn_exception, conn); conn->rd= oop_rd_new_fd(loop,conn->fd, 0, 0); /* sets nonblocking, too */ if (!conn->fd) crash("oop_rd_new_fd conn failed (fd=%d)",conn->fd); - int r= oop_rd_read(conn->rd, &peer_rd_style, NNTP_STRLEN, + int r= oop_rd_read(conn->rd, &peer_rd_style, NNTP_MAXLEN_COMMAND+1, &peer_rd_ok, conn, &peer_rd_err, conn); if (r) syscrash("oop_rd_read for peer (fd=%d)",conn->fd); LIST_ADDHEAD(conns, conn); - notice("C%d (now %d) connected %s", - conn->fd, conns.count, conn->stream ? "streaming" : "plain"); + const char *streamdesc= conn->stream ? "streaming" : "plain"; + info("C%d (now %d) connected %s", conn->fd, conns.count, streamdesc); + notice_conns_more(streamdesc); connect_attempt_discard(); check_assign_articles(); @@ -294,13 +348,13 @@ static void *connchild_event(oop_source *lp, int fd, oop_event e, void *u) { return OOP_CONTINUE; } -static int allow_connect_start(void) { +int allow_connect_start(void) { return conns.count < max_connections && !connecting_child && !until_connect; } -static void connect_start(void) { +void connect_start(void) { assert(!connecting_child); assert(!connecting_fdpass_sock); @@ -316,13 +370,15 @@ static void connect_start(void) { if (!connecting_child) { FILE *cn_from, *cn_to; - char buf[NNTP_STRLEN+100]; + char buf[NNTP_MAXLEN_COMMAND+100]; int exitstatus= CONNCHILD_ESTATUS_NOSTREAM; xclose(socks[0], "(in child) parent's connection fdpass socket",0); alarm(connection_setup_timeout); - if (NNTPconnect((char*)remote_host, port, &cn_from, &cn_to, buf) < 0) { + buf[sizeof(buf)-1] = 0; + if (NNTPconnect(remote_host, port, &cn_from, &cn_to, + buf, sizeof(buf)-1) < 0) { int l= strlen(buf); int stripped=0; while (l>0) { @@ -374,7 +430,7 @@ static void connect_start(void) { default: warn("connect: unexpected response to MODE STREAM: %.50s", sanitise(buf,-1)); - exitstatus= 2; + exitstatus= CONNCHILD_ESTATUS_NOSTREAM; break; } }