chiark / gitweb /
Debianisation (initial cut)
[innduct.git] / innduct.h
index 1033ac79875ec2c54fc4d17f780e81e4d790897a..231524d04b0fdaaa54d5687fe10d474a66f71904 100644 (file)
--- a/innduct.h
+++ b/innduct.h
@@ -59,6 +59,7 @@
 #include <time.h>
 #include <math.h>
 #include <ctype.h>
+#include <limits.h>
 
 #include <oop.h>
 #include <oop-read.h>
@@ -71,7 +72,7 @@
 #define INNDCOMMCHILD_ESTATUS_FAIL     26
 #define INNDCOMMCHILD_ESTATUS_NONESUCH 27
 
-#define MAX_LINE_FEEDFILE (NNTP_MSGID_MAXLEN + sizeof(TOKEN)*2 + 10)
+#define MAX_LINE_FEEDFILE (NNTP_MAXLEN_MSGID + sizeof(TOKEN)*2 + 10)
 #define MAX_CLI_COMMAND 1000
 
 #define VA                va_list al;  va_start(al,fmt)
 
 #define DUMPV(fmt,pfx,v) fprintf(f, " " #v "=" fmt, pfx v);
 
-#define FOR_CONN(conn) \
-  for ((conn)=LIST_HEAD(conns); (conn); (conn)=LIST_NEXT((conn)))
+#define FOR_LIST_NODE(nodevar, list) \
+  for ((nodevar)=LIST_HEAD(list); (nodevar); (nodevar)=LIST_NEXT((nodevar)))
+
+#define FOR_CONN(conn) FOR_LIST_NODE(conn, conns)
 
 /*----- doubly linked lists -----*/
 
@@ -155,47 +158,36 @@ DEFLIST(Article);
 
 
 /*----- configuration options -----*/
-/* when changing defaults, remember to update the manpage */
-
-static const char *sitename, *remote_host;
-static const char *feedfile, *path_run, *path_cli, *path_cli_dir;
-static int quiet_multiple=0;
-static int interactive=0, try_filemon=1;
-static int try_stream=1;
-static int port=119;
-static const char *inndconffile;
 
-static int max_connections=10;
-static int max_queue_per_conn=200;
-static int target_max_feedfile_size=100000;
-static int period_seconds=30;
-static int filepoll_seconds=5;
-static int max_queue_per_ipf=-1;
+extern const char *sitename, *remote_host;
+extern const char *feedfile, *path_run, *path_cli, *path_cli_dir;
+extern int quiet_multiple, interactive, try_filemon, try_stream, port;
+extern const char *inndconffile;
 
-static int connection_setup_timeout=200;
-static int inndcomm_flush_timeout=100;
+extern int max_connections, max_queue_per_conn, target_max_feedfile_size;
+extern int period_seconds, filepoll_seconds, max_queue_per_ipf;
+extern int connection_setup_timeout, inndcomm_flush_timeout;
 
-static double nocheck_thresh= 95.0; /* converted from percentage by main */
-static double nocheck_decay= 100; /* conv'd from articles to lambda by main */
+extern double nocheck_thresh;
+extern double nocheck_decay;
 
 /* all these are initialised to seconds, and converted to periods in main */
-static int reconnect_delay_periods=1000;
-static int flushfail_retry_periods=1000;
-static int backlog_retry_minperiods=100;
-static int backlog_spontrescan_periods=300;
-static int spontaneous_flush_periods=100000;
-static int max_separated_periods=2000;
-static int need_activity_periods=1000;
-static int lowvol_thresh=3;
-static int lowvol_periods=1000;
+extern int reconnect_delay_periods;
+extern int flushfail_retry_periods;
+extern int backlog_retry_minperiods;
+extern int backlog_spontrescan_periods;
+extern int spontaneous_flush_periods;
+extern int max_separated_periods;
+extern int need_activity_periods;
+extern int stats_log_periods;
+extern int lowvol_thresh;
+extern int lowvol_periods;
 
-static double max_bad_data_ratio= 1; /* conv'd from percentage by main */
-static int max_bad_data_initial= 30;
-  /* in one corrupt 4096-byte block the number of newlines has
-   * mean 16 and standard deviation 3.99.  30 corresponds to z=+3.5 */
+extern double max_bad_data_ratio;
+extern int max_bad_data_initial;
 
 
-/*----- statistics -----*/
+/*----- article states, and statistics -----*/
 
 typedef enum {      /* in queue                 in conn->sent             */
   art_Unchecked,    /*   not checked, not sent    checking                */
@@ -203,9 +195,7 @@ typedef enum {      /* in queue                 in conn->sent             */
   art_Unsolicited,  /*   -                        sent body without check */
   art_MaxState,
 } ArtState;
-
-static const char *const artstate_names[]=
-  { "Unchecked", "Wanted", "Unsolicited", 0 };
+extern const char *const artstate_names[]; /* xmit.c */
 
 #define RESULT_COUNTS(RCS,RCN)                 \
   RCS(sent)                                    \
@@ -231,6 +221,10 @@ typedef enum {
   RCI_max
 } ResultCountIndex;
 
+typedef enum {
+  read_ok, read_blank, read_err, nooffer_missing,
+  ECI_max
+} EventCountIndex;
 
 /*----- transmission buffers -----*/
 
@@ -250,6 +244,11 @@ struct XmitDetails {
 
 /*----- core operational data structure types -----*/
 
+typedef struct {
+  int results[art_MaxState][RCI_max];
+  int events[ECI_max];
+} Counts;
+
 struct InputFile {
   /* This is also an instance of struct oop_readable */
   struct oop_readable readable; /* first */
@@ -267,8 +266,7 @@ struct InputFile {
   long inprogress; /* includes queue.count and also articles in conns */
   long autodefer; /* -1 means not doing autodefer */
 
-  int counts[art_MaxState][RCI_max];
-  int readcount_ok, readcount_blank, readcount_err, count_nooffer_missing;
+  Counts counts;
   char path[];
 };
 
@@ -283,6 +281,22 @@ struct Article {
   char messageid[1];
 };
 
+struct Conn {
+  ISNODE(Conn);
+  int fd; /* may be 0, meaning closed (during construction/destruction) */
+  oop_read *rd; /* likewise */
+  int oopwriting; /* since on_fd is not idempotent */
+  int max_queue, stream;
+  const char *quitting;
+  int since_activity; /* periods */
+  ArticleList waiting; /* not yet told peer */
+  ArticleList priority; /* peer says send it now */
+  ArticleList sent; /* offered/transmitted - in xmit or waiting reply */
+  struct iovec xmit[CONNIOVS];
+  XmitDetails xmitd[CONNIOVS];
+  int xmitu;
+};
+
 #define SMS_LIST(X)                            \
   X(NORMAL)                                    \
   X(FLUSHING)                                  \
@@ -302,23 +316,24 @@ extern const char *sms_names[];
 
 /*----- help.c -----*/
 
-static void syscrash(const char *fmt, ...) NORET_PRINTF(1,2);
-static void crash(const char *fmt, ...) NORET_PRINTF(1,2);
-static void info(const char *fmt, ...) PRINTF(1,2);
-static void dbg(const char *fmt, ...) PRINTF(1,2);
+void syscrash(const char *fmt, ...) NORET_PRINTF(1,2);
+void crash(const char *fmt, ...) NORET_PRINTF(1,2);
+void info(const char *fmt, ...) PRINTF(1,2);
+void dbg(const char *fmt, ...) PRINTF(1,2);
 
 void logv(int sysloglevel, const char *pfx, int errnoval,
          const char *fmt, va_list al) PRINTF(5,0);
 
-char *xvasprintf(const char *fmt, va_list al) PRINTF(1,0);
-char *xasprintf(const char *fmt, ...) PRINTF(1,2);
+char *mvasprintf(const char *fmt, va_list al) PRINTF(1,0);
+char *masprintf(const char *fmt, ...) PRINTF(1,2);
 
 int close_perhaps(int *fd);
 void xclose(int fd, const char *what, const char *what2);
 void xclose_perhaps(int *fd, const char *what, const char *what2);
-pid_t xfork(const char *what);
+pid_t xfork(const char *what); /* also runs postfork in child */
+pid_t xfork_bare(const char *what);
 
-static void on_fd_read_except(int fd, oop_call_fd callback);
+void on_fd_read_except(int fd, oop_call_fd callback);
 void cancel_fd_read_except(int fd);
 
 void report_child_status(const char *what, int status);
@@ -329,6 +344,7 @@ void xunlink(const char *path, const char *what);
 time_t xtime(void);
 void xsigaction(int signo, const struct sigaction *sa);
 void xsigsetdefault(int signo);
+void raise_default(int signo) NORET;
 
 void xgettimeofday(struct timeval *tv_r);
 void xsetnonblock(int fd, int nonb);
@@ -349,38 +365,132 @@ static inline int isewouldblock(int errnoval) {
   return errnoval==EWOULDBLOCK || errnoval==EAGAIN;
 }
 
-/*----- innduct.c -----*/
+#define INNLOGSETS(INNLOGSET)                  \
+  INNLOGSET(die,      "fatal",    LOG_ERR)     \
+  INNLOGSET(warn,     "warning",  LOG_WARNING) \
+  INNLOGSET(notice,   "notice",   LOG_NOTICE)  \
+  INNLOGSET(debug,    "debug",    LOG_DEBUG)
+#define INNLOGSET_DECLARE(fn, pfx, sysloglevel)                                \
+  void duct_log_##fn(int l, const char *fmt, va_list al, int errval)   \
+    PRINTF(3,0);
+INNLOGSETS(INNLOGSET_DECLARE)
+
+/*----- duct.c -----*/
 
 void postfork(void);
+void period(void);
+
+/*----- cli.c -----*/
+
+void cli_init(void);
+void cli_stdio(void);
 
 /*----- conn.c -----*/
 
 void conn_closefd(Conn *conn, const char *msgprefix);
+void check_idle_conns(void);
+int conn_busy(Conn *conn);
+void conn_dispose(Conn *conn);
+
+void vconnfail(Conn *conn, const char *fmt, va_list al) PRINTF(2,0);
+void connfail(Conn *conn, const char *fmt, ...)         PRINTF(2,3);
+
+void notice_conns_more(const char *new_kind);
+void notice_conns_fewer(void);
+void notice_conns_stats(void);
+
+int allow_connect_start(void);
+void connect_start(void);
 
 /*----- defer.c -----*/
 
 void poll_backlog_file(void);
+void search_backlog_file(void);
+void open_defer(void);
+void close_defer(void);
+
+/*----- filemon.c -----*/
+
+int filemon_method_init(void);
+void filemon_method_dump_info(FILE *f);
+
+void filemon_start(InputFile *ipf);
+void filemon_stop(InputFile *ipf);
 
 /*----- infile.c -----*/
 
 void filepoll(void);
 
+void inputfile_reading_start(InputFile *ipf);
+void inputfile_reading_stop(InputFile *ipf);
+void inputfile_reading_pause(InputFile *ipf);
+void inputfile_reading_resume(InputFile *ipf);
+  /* pause and resume are idempotent, and no-op if not done _reading_start */
+
+InputFile *open_input_file(const char *path);
+void close_input_file(InputFile *ipf); /* does not free */
+char *dbg_report_ipf(InputFile *ipf);
+
+void tailing_make_readable(InputFile *ipf);
+
+/*----- recv.c -----*/
+
+extern const oop_rd_style peer_rd_style;
+oop_rd_call peer_rd_ok, peer_rd_err;
+
+void article_done(Article *art, int whichcount);
+
 /*----- statemc.c -----*/
 
-sig_atomic_t terminate_sig_flag;
+void statemc_check_flushing_done(void);
+void statemc_check_backlog_done(void);
+
+extern sig_atomic_t terminate_sig_flag;
+void statemc_period_poll(void);
+void statemc_lock(void);
+void init_signals(void);
+void statemc_init(void);
+void showstats(void);
+
+#define SMS(newstate, periods, why) \
+   (statemc_setstate(sm_##newstate,(periods),#newstate,(why)))
+void statemc_setstate(StateMachineState newsms, int periods,
+                            const char *forlog, const char *why);
+
+void statemc_start_flush(const char *why); /* Normal => Flushing */
+void spawn_inndcomm_flush(const char *why); /* Moved => Flushing */
+int trigger_flush_ok(const char *why /* 0 means timeout */);
+                                  /* => Flushing,FLUSHING, ret 1; or ret 0 */
+
+void preterminate(void);
 
 /*----- xmit.c -----*/
 
 void inputfile_queue_check_expired(InputFile *ipf);
+void check_assign_articles(void);
+void queue_check_input_done(void);
+void check_reading_pause_resume(InputFile *ipf);
+
+void conn_maybe_write(Conn *conn);
+void conn_make_some_xmits(Conn *conn);
+void *conn_write_some_xmits(Conn *conn);
+
+void xmit_free(XmitDetails *d);
+
+int article_check_expired(Article *art /* must be queued, not conn */);
+void article_autodefer(InputFile *ipf, Article *art);
+void article_defer(Article *art /* not on a queue */, int whichcount);
+void autodefer_input_file(InputFile *ipf);
 
 /*----- external linkage for debug/dump only -----*/
 
-pid_t connecting_child;
-pid_t inndcomm_child;
+extern pid_t connecting_child;
+extern int connecting_fdpass_sock;
+extern pid_t inndcomm_child;
 
 /*========== general operational variables ==========*/
 
-/* innduct.c */
+/* duct.c */
 extern oop_source *loop;
 extern ConnList conns;
 extern char *path_lock, *path_flushing, *path_defer, *path_dump;
@@ -389,11 +499,14 @@ extern pid_t self_pid;
 extern int *lowvol_perperiod;
 extern int lowvol_circptr;
 extern int lowvol_total; /* does not include current period */
+extern int until_stats_log;
 
 /* statemc.c */
 extern StateMachineState sms;
 extern int until_flush;
 extern InputFile *main_input_file, *flushing_input_file, *backlog_input_file;
+extern Counts backlog_counts;
+extern int backlog_counts_report;
 extern FILE *defer;
 extern int until_connect, until_backlog_nextscan;
 extern double accept_proportion;