534 lines
21 KiB
C
534 lines
21 KiB
C
/*
|
|
* aprsc
|
|
*
|
|
* (c) Heikki Hannikainen, OH7LZB <hessu@hes.iki.fi>
|
|
*
|
|
* This program is licensed under the BSD license, which can be found
|
|
* in the file LICENSE.
|
|
*
|
|
*/
|
|
|
|
#ifndef WORKER_H
|
|
#define WORKER_H
|
|
|
|
#define _GNU_SOURCE
|
|
#ifndef __USE_UNIX98
|
|
#define __USE_UNIX98 /* to get PTHREAD_MUTEX_RECURSIVE on Linux */
|
|
#endif
|
|
|
|
#include <pthread.h>
|
|
#include <semaphore.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <time.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
|
|
#include "xpoll.h"
|
|
#include "rwlock.h"
|
|
#include "cJSON.h"
|
|
#include "errno_aprsc.h"
|
|
#include "tls.h"
|
|
|
|
extern time_t now; /* current wallclock time */
|
|
extern time_t tick; /* clocktick - monotonously increasing for timers, not affected by NTP et al */
|
|
|
|
extern void pthreads_profiling_reset(const char *name);
|
|
|
|
extern pthread_attr_t pthr_attrs; /* used to setup new threads */
|
|
|
|
/* minimum and maximum length of a callsign on APRS-IS */
|
|
#define CALLSIGNLEN_MIN 3
|
|
#define CALLSIGNLEN_MAX 9
|
|
|
|
/* packet length limiters and buffer sizes */
|
|
#define PACKETLEN_MIN 10 /* minimum length for a valid APRS-IS packet: "A1A>B1B:\r\n" */
|
|
#define PACKETLEN_MAX 512 /* maximum length for a valid APRS-IS packet (incl. CRLF) */
|
|
|
|
/*
|
|
* Packet length statistics:
|
|
*
|
|
* <= 80: about 25%
|
|
* <= 90: about 36%
|
|
* <= 100: about 73%
|
|
* <= 110: about 89%
|
|
* <= 120: about 94%
|
|
* <= 130: about 97%
|
|
* <= 140: about 98.7%
|
|
* <= 150: about 99.4%
|
|
*/
|
|
|
|
#define PACKETLEN_MAX_SMALL 100
|
|
#define PACKETLEN_MAX_MEDIUM 180 /* about 99.5% are smaller than this */
|
|
#define PACKETLEN_MAX_LARGE PACKETLEN_MAX
|
|
|
|
/* number of pbuf_t structures to allocate at a time */
|
|
#define PBUF_ALLOCATE_BUNCH_SMALL 2000 /* grow to 2000 in production use */
|
|
#define PBUF_ALLOCATE_BUNCH_MEDIUM 2000 /* grow to 2000 in production use */
|
|
#define PBUF_ALLOCATE_BUNCH_LARGE 50 /* grow to 50 in production use */
|
|
|
|
/* a packet buffer */
|
|
/* Type flags -- some can happen in combinations: T_CWOP + T_WX / T_CWOP + T_POSITION ... */
|
|
#define T_POSITION (1 << 0) // Packet is of position type
|
|
#define T_OBJECT (1 << 1) // packet is an object
|
|
#define T_ITEM (1 << 2) // packet is an item
|
|
#define T_MESSAGE (1 << 3) // packet is a message
|
|
#define T_NWS (1 << 4) // packet is a NWS message
|
|
#define T_WX (1 << 5) // packet is WX data
|
|
#define T_TELEMETRY (1 << 6) // packet is telemetry
|
|
#define T_QUERY (1 << 7) // packet is a query
|
|
#define T_STATUS (1 << 8) // packet is status
|
|
#define T_USERDEF (1 << 9) // packet is userdefined
|
|
#define T_CWOP (1 << 10) // packet is recognized as CWOP
|
|
#define T_STATCAPA (1 << 11) // packet is station capability response
|
|
#define T_3RDPARTY (1 << 12) // packet is a 3rd-party } packet
|
|
#define T_ALL (1 << 15) // set on _all_ packets
|
|
|
|
#define F_DUPE (1 << 0) /* Duplicate of a previously seen packet */
|
|
#define F_HASPOS (1 << 1) /* This packet has valid parsed position */
|
|
#define F_HAS_TCPIP (1 << 2) /* There is a TCPIP* in the path */
|
|
#define F_FROM_UPSTR (1 << 3) /* Packet is from an upstream server */
|
|
#define F_FROM_DOWNSTR (1 << 4) /* Packet is from a downstream server */
|
|
|
|
struct client_t; /* forward declarator */
|
|
|
|
struct pbuf_t {
|
|
struct pbuf_t *next;
|
|
struct client_t *origin;
|
|
/* where did we get it from (don't send it back)
|
|
NOTE: This pointer is NOT guaranteed to be valid!
|
|
It does get invalidated by originating connection close,
|
|
but it is only used as read-only comparison reference
|
|
against output client connection pointer. It may
|
|
point to reused connection entry, but even that does
|
|
not matter much -- a few packets may be left unrelayed
|
|
to the a client in some situations, but packets sent
|
|
a few seconds latter will go through just fine.
|
|
In case of "dump history" (if we ever do) this pointer
|
|
is ignored while history dumping is being done.
|
|
*/
|
|
|
|
uint32_t srcname_hash; /* source name hash */
|
|
uint32_t srccall_hash; /* srccall hash */
|
|
uint32_t dstname_hash; /* srccall hash */
|
|
uint16_t packettype; /* bitmask: one or more of T_* */
|
|
uint16_t flags; /* bitmask: one or more of F_* */
|
|
uint16_t srcname_len; /* parsed length of source (object, item, srcall) name 3..9 */
|
|
uint16_t dstcall_len; /* parsed length of destination callsign *including* SSID */
|
|
uint16_t dstname_len; /* parsed length of message destination including SSID */
|
|
uint16_t entrycall_len;
|
|
uint32_t seqnum; /* ever increasing counter, dupecheck sets */
|
|
time_t t; /* when the packet was received */
|
|
|
|
int packet_len; /* the actual length of the packet, including CRLF */
|
|
int buf_len; /* the length of this buffer */
|
|
|
|
const char *srccall_end; /* source callsign with SSID */
|
|
const char *dstcall_end_or_ssid; /* end of dest callsign (without SSID) */
|
|
const char *dstcall_end; /* end of dest callsign with SSID */
|
|
const char *qconst_start; /* "qAX,incomingSSID:" -- for q and e filters */
|
|
const char *info_start; /* pointer to start of info field */
|
|
const char *srcname; /* source's name (either srccall or object/item name) */
|
|
const char *dstname; /* message destination callsign */
|
|
|
|
float lat; /* if the packet is PT_POSITION, latitude and longitude go here */
|
|
float lng; /* .. in RADIAN */
|
|
float cos_lat; /* cache of COS of LATitude for radial distance filter */
|
|
|
|
char symbol[3]; /* 2(+1) chars of symbol, if any, NUL for not found */
|
|
char is_free; /* 1: in global free list, 0: not in global free list */
|
|
|
|
char data[1]; /* contains the whole packet, including CRLF, ready to transmit */
|
|
};
|
|
|
|
/* global packet buffer */
|
|
extern rwlock_t pbuf_global_rwlock;
|
|
extern struct pbuf_t *pbuf_global;
|
|
extern struct pbuf_t **pbuf_global_prevp;
|
|
extern struct pbuf_t *pbuf_global_dupe;
|
|
extern struct pbuf_t **pbuf_global_dupe_prevp;
|
|
|
|
/* a network client */
|
|
typedef enum {
|
|
CSTATE_INIT,
|
|
CSTATE_UDP,
|
|
CSTATE_LOGIN,
|
|
CSTATE_LOGRESP,
|
|
CSTATE_CONNECTED,
|
|
CSTATE_COREPEER
|
|
} CStateEnum;
|
|
|
|
struct worker_t; /* used in client_t, but introduced later */
|
|
struct filter_t; /* used in client_t, but introduced later */
|
|
|
|
union sockaddr_u {
|
|
struct sockaddr sa;
|
|
struct sockaddr_in si;
|
|
struct sockaddr_in6 si6;
|
|
};
|
|
|
|
/* list of message recipient callsigns heard on a client port */
|
|
#define CLIENT_HEARD_BUCKETS 32 /* up to ~300 calls in heard list per client */
|
|
struct client_heard_t {
|
|
struct client_heard_t *next;
|
|
struct client_heard_t **prevp;
|
|
|
|
uint32_t hash;
|
|
|
|
int call_len;
|
|
time_t last_heard;
|
|
|
|
char callsign[CALLSIGNLEN_MAX+1];
|
|
};
|
|
|
|
#define WBUF_ADJUSTER 0 /* Client WBUF adjustment can be usefull -- but code is infant.. */
|
|
|
|
/* error codes for incoming packet drop reasons */
|
|
#define INERR_UNKNOWN 0
|
|
#define INERR_NO_COLON -1 /* no : in packet */
|
|
#define INERR_NO_DST -2 /* no > in packet to mark beginning of dstcall */
|
|
#define INERR_NO_PATH -3 /* no path found between srccall and : */
|
|
#define INERR_INV_SRCCALL -4 /* invalid or too long srccall */
|
|
#define INERR_NO_BODY -5 /* no packet body/data after : */
|
|
#define INERR_INV_DSTCALL -6 /* invalid or too long dstcall */
|
|
#define INERR_DISALLOW_UNVERIFIED -7 /* disallow_unverified = 1, unverified client */
|
|
#define INERR_DISALLOW_UNVERIFIED_PATH -8 /* disallow_unverified = 1, TCPXX path */
|
|
#define INERR_NOGATE -9 /* packet path has NOGATE/RFONLY */
|
|
#define INERR_3RD_PARTY_IP -10 /* 3rd-party packet dropped due to TCPIP/TCPXX in path */
|
|
#define INERR_INV_3RD_PARTY -11 /* invalid 3rd-party packet header */
|
|
#define INERR_GENERAL_QUERY -12 /* general query ?APRS? dropped */
|
|
#define INERR_OUT_OF_PBUFS -13 /* aprsc ran out of packet buffers */
|
|
#define INERR_CLASS_FAIL -14 /* aprsc failed to classify packet */
|
|
#define INERR_Q_BUG -15 /* aprsc q construct code bugging */
|
|
#define INERR_Q_DROP -16 /* q construct drop */
|
|
#define INERR_SHORT_PACKET -17 /* too short packet */
|
|
#define INERR_LONG_PACKET -18 /* too long packet */
|
|
#define INERR_INV_PATH_CALL -19 /* invalid callsign in path */
|
|
#define INERR_Q_QAX -20
|
|
#define INERR_Q_QAZ -21
|
|
#define INERR_Q_QPATH_MYCALL -22
|
|
#define INERR_Q_QPATH_CALL_TWICE -23
|
|
#define INERR_Q_PATH_LOGIN_NOT_LAST -24
|
|
#define INERR_Q_PATH_CALL_IS_LOCAL_CLIENT -25
|
|
#define INERR_Q_PATH_CALL_IS_INVALID -26
|
|
#define INERR_Q_QAU_PATH_CALL_IS_SRCCALL -27
|
|
#define INERR_Q_NEWQ_BUFFER_SMALL -28
|
|
#define INERR_Q_NONVAL_MULTI_Q_CALLS -29
|
|
#define INERR_Q_I_NO_VIACALL -30
|
|
#define INERR_Q_DISALLOW_PROTOCOL -31
|
|
#define INERR_EMPTY -32
|
|
#define INERR_DIS_SRCCALL -33
|
|
#define INERR_DIS_DX -34
|
|
#define INERR_DIS_MSG_DST -35
|
|
|
|
#define INERR_MIN -35 /* MINIMUM VALUE FOR INERR, GROW WHEN NEEDED! */
|
|
/* WHEN ADDING STUFF HERE, REMEMBER TO UPDATE inerr_labels IN incoming.c. Thanks! */
|
|
#define INERR_BUCKETS (INERR_MIN*-1 + 1)
|
|
|
|
struct portaccount_t { /* Port accounter tracks port usage, and traffic
|
|
Reporting looks up these via listener list. */
|
|
pthread_mutex_t mutex; /* mutex to protect counters, refcount especially */
|
|
|
|
long counter; /* New arriving connects count */
|
|
long gauge; /* Number of current connects */
|
|
long gauge_max; /* Maximum of the current connects */
|
|
|
|
long long rxbytes, txbytes;
|
|
long long rxpackets, txpackets;
|
|
long long rxdrops, rxdupes;
|
|
long long rxerrs[INERR_BUCKETS];
|
|
|
|
/* record usage references */
|
|
int refcount; /* listener = 1, clients ++ */
|
|
};
|
|
|
|
extern struct portaccount_t client_connects_tcp;
|
|
extern struct portaccount_t client_connects_sctp;
|
|
extern struct portaccount_t client_connects_udp;
|
|
extern struct portaccount_t inbound_connects;
|
|
|
|
struct client_udp_t { /* UDP services can be available at multiple
|
|
client ports. This is shared refcounted
|
|
file descriptor for them. */
|
|
struct client_udp_t *next;
|
|
struct client_udp_t **prevp;
|
|
struct portaccount_t *portaccount;
|
|
int fd; /* file descriptor */
|
|
int refcount; /* Reference count */
|
|
int polled; /* Is there a thread polling this? */
|
|
uint16_t af; /* Address family */
|
|
uint16_t portnum; /* Server UDP port */
|
|
};
|
|
|
|
|
|
#define FILTER_S_SIZE 256 /* how many bytes of filter to store for status display */
|
|
|
|
/* These are the currently used buffer sizes.
|
|
* Do not increase them too much - we wish to disconnect stuck sockets pretty
|
|
* quickly, so that hanging servers will not cause data to overflow
|
|
* the 30-second dupe check window. The current APRS-IS rate is somewhere around
|
|
* 3-4 Kbytes/second, and then we have the operating system TCP socket buffers too.
|
|
*/
|
|
#define FIXED_IOBUFS 0
|
|
#ifdef FIXED_IOBUFS
|
|
#define OBUF_SIZE 8000
|
|
#define IBUF_SIZE 8000
|
|
#endif
|
|
|
|
struct client_t {
|
|
struct client_t *next;
|
|
struct client_t **prevp;
|
|
|
|
struct client_t *class_next;
|
|
struct client_t **class_prevp;
|
|
|
|
union sockaddr_u addr;
|
|
struct portaccount_t *portaccount; /* port specific global account accumulator */
|
|
struct portaccount_t localaccount; /* client connection specific account accumulator */
|
|
|
|
int ai_protocol; /* IPPROTO_SCTP, UDP, TCP */
|
|
|
|
struct client_udp_t *udpclient; /* pointer to udp service socket, if available */
|
|
int udp_port; /* client udp port - if client has requested it */
|
|
int udpaddrlen; /* ready to use sockaddr length */
|
|
union sockaddr_u udpaddr; /* ready to use sockaddr data */
|
|
|
|
int fd;
|
|
|
|
int portnum;
|
|
int listener_id; /* which listener is this client connected to */
|
|
time_t connect_time;/* Time of connection, wallclock real time */
|
|
time_t connect_tick;/* Time of connection, monotonous */
|
|
time_t last_read; /* Time of last read - not necessarily last packet... */
|
|
time_t keepalive; /* Time of next keepalive chime */
|
|
time_t cleanup; /* Time of next cleanup */
|
|
|
|
struct xpoll_fd_t *xfd; /* poll()/select() structure as defined in xpoll.h */
|
|
|
|
#ifdef USE_SSL
|
|
struct ssl_connection_t *ssl_con;
|
|
#endif
|
|
|
|
/* first stage read buffer - used to crunch out lines to packet buffers */
|
|
#ifndef FIXED_IOBUFS
|
|
char *ibuf;
|
|
#endif
|
|
int ibuf_size; /* size of buffer */
|
|
int ibuf_end; /* where data in buffer ends */
|
|
|
|
/* output buffer */
|
|
#ifndef FIXED_IOBUFS
|
|
char *obuf;
|
|
#endif
|
|
int obuf_size; /* size of buffer */
|
|
int obuf_start; /* where data in buffer starts */
|
|
int obuf_end; /* where data in buffer ends */
|
|
int obuf_flushsize; /* how much data in buf before forced write() at adding ? */
|
|
int obuf_writes; /* how many times (since last check) the socket has been written ? */
|
|
int obuf_wtime; /* when was last write? */
|
|
#if WBUF_ADJUSTER
|
|
int wbuf_size; /* socket wbuf size */
|
|
#endif
|
|
int32_t flags; /* bit flags on what kind of client this is */
|
|
|
|
#define CLFLAGS_INPORT 0x001
|
|
#define CLFLAGS_UPLINKPORT 0x002
|
|
#define CLFLAGS_UDPSUBMIT 0x004
|
|
#define CLFLAGS_PORT_RO 0x008
|
|
#define CLFLAGS_USERFILTEROK 0x010 /* Permits entry of user defined filters */
|
|
#define CLFLAGS_FULLFEED 0x100 /* Together with filter t/c* -- which really implements it */
|
|
#define CLFLAGS_DUPEFEED 0x200 /* Duplicates are also sent to client */
|
|
#define CLFLAGS_MESSAGEONLY 0x400 /* Together with filter t/m -- which really implements it */
|
|
#define CLFLAGS_CLIENTONLY 0x800 /* Client connected on client-only port */
|
|
#define CLFLAGS_IGATE 0x1000 /* Igate port */
|
|
#define CLFLAGS_UPLINKMULTI 0x2000 /* Allow multiple parallel outgoing connections */
|
|
|
|
#define VALIDATED_WEAK 1 /* client validated with passcode */
|
|
#define VALIDATED_STRONG 3 /* client validated with SSL certificate */
|
|
|
|
CStateEnum state; /* state of the client... one of CSTATE_* */
|
|
char warned; /* the client has been warned that it has bad filter definition */
|
|
char validated; /* did the client provide a valid passcode */
|
|
char username_len; /* length of user name */
|
|
char hidden; /* is the user on a hidden listener socket, not shown on status */
|
|
char failed_cmds; /* how many login commands have failed */
|
|
char quirks_mode; /* is this a known buggy-and-unmaintained application on our blacklist */
|
|
char no_tx; /* is the TX igate implementation broken and on our blacklist */
|
|
char loc_known; /* have we received a position packet from this client */
|
|
|
|
/* the current handler function for incoming lines */
|
|
int (*handler_line_in) (struct worker_t *self, struct client_t *c, int l4proto, char *s, int len);
|
|
int (*handler_consume_input) (struct worker_t *self, struct client_t *c);
|
|
int (*write) (struct worker_t *self, struct client_t *c, char *p, int len);
|
|
|
|
int (*handler_client_readable) (struct worker_t *self, struct client_t *c);
|
|
int (*handler_client_writable) (struct worker_t *self, struct client_t *c);
|
|
|
|
/* outbound filter chain head */
|
|
struct filter_t *posdefaultfilters;
|
|
struct filter_t *negdefaultfilters;
|
|
struct filter_t *posuserfilters;
|
|
struct filter_t *neguserfilters;
|
|
|
|
/* List of station callsigns (not objects/items!) which have been
|
|
* heard by this client. Only collected for filtered ports!
|
|
* Used for deciding if messages should be routed here.
|
|
*
|
|
* client_courtesy lists the srccalls which have originated messages
|
|
* on this filtered ports, and should have a courtesy position sent.
|
|
*/
|
|
struct client_heard_t* client_heard[CLIENT_HEARD_BUCKETS];
|
|
struct client_heard_t* client_courtesy[CLIENT_HEARD_BUCKETS];
|
|
int client_heard_count; /* number of 'heard' list entries for clients */
|
|
int client_courtesy_count; /* number of 'courtesy' list entries for clients */
|
|
|
|
/* coordinates of client, if transmitted */
|
|
float lat, lng, cos_lat;
|
|
|
|
// Maybe we use these four items, or maybe not.
|
|
// They are there for experimenting with outgoing queue processing algorithms.
|
|
/* Pointer to last pointer in pbuf_global(_dupe) */
|
|
//struct pbuf_t **pbuf_global_prevp;
|
|
//struct pbuf_t **pbuf_global_dupe_prevp;
|
|
//uint32_t last_pbuf_seqnum;
|
|
//uint32_t last_pbuf_dupe_seqnum;
|
|
|
|
char username[16]; /* The callsign */
|
|
char app_name[32]; /* application name, from 'user' command */
|
|
char app_version[32]; /* application version, from 'user' command */
|
|
|
|
char addr_rem[80]; /* client IP address in text format */
|
|
char addr_hex[36]; /* client IP address in hex format */
|
|
char addr_loc[80]; /* server IP address in text format */
|
|
|
|
#ifdef USE_SSL
|
|
/* for SSL cert auth, store SSL certificate subject and issuer */
|
|
char cert_subject[256];
|
|
char cert_issuer[256];
|
|
#endif
|
|
|
|
#ifdef FIXED_IOBUFS
|
|
char ibuf[IBUF_SIZE];
|
|
char obuf[OBUF_SIZE];
|
|
#endif
|
|
char filter_s[FILTER_S_SIZE];
|
|
};
|
|
|
|
extern struct client_t *client_alloc(void);
|
|
extern void client_free(struct client_t *c);
|
|
extern int set_client_sockopt(struct client_t *c);
|
|
extern int pass_client_to_worker(struct worker_t *wc, struct client_t *c);
|
|
extern void worker_mark_client_connected(struct worker_t *self, struct client_t *c);
|
|
extern struct client_t *pseudoclient_setup(int portnum);
|
|
|
|
|
|
/* worker thread structure */
|
|
struct worker_t {
|
|
struct worker_t *next;
|
|
struct worker_t **prevp;
|
|
|
|
int id; /* sequential id for thread */
|
|
pthread_t th; /* the thread itself */
|
|
|
|
int shutting_down; /* should I shut down? */
|
|
|
|
struct client_t *clients; /* all clients handled by this thread */
|
|
/* c->class_next lists, classified clients for optimized outbound */
|
|
struct client_t *clients_dupe; /* dupeclient port clients */
|
|
struct client_t *clients_ro; /* read-only clients */
|
|
struct client_t *clients_ups; /* upstreams and peers */
|
|
struct client_t *clients_other; /* other clients (unoptimized) */
|
|
pthread_mutex_t clients_mutex; /* mutex to protect access to the client list by the status dumps */
|
|
|
|
struct client_t *new_clients; /* new clients which passed in by accept */
|
|
struct client_t *new_clients_last; /* last client in the list, to support FIFO queuing */
|
|
pthread_mutex_t new_clients_mutex; /* mutex to protect *new_clients */
|
|
int client_count; /* modified by worker thread only! */
|
|
|
|
struct xpoll_t xp; /* poll/epoll/select wrapper */
|
|
|
|
/* thread-local packet buffer freelist */
|
|
struct pbuf_t *pbuf_free_small; /* <= 130 bytes */
|
|
struct pbuf_t *pbuf_free_medium; /* 131 >= x <= 300 */
|
|
struct pbuf_t *pbuf_free_large; /* 301 >= x <= 600 */
|
|
|
|
/* packets which have been parsed, waiting to be moved into
|
|
* pbuf_incoming
|
|
*/
|
|
struct pbuf_t *pbuf_incoming_local;
|
|
struct pbuf_t **pbuf_incoming_local_last;
|
|
|
|
/* packets which have been parsed, waiting for dupe check */
|
|
struct pbuf_t *pbuf_incoming;
|
|
struct pbuf_t **pbuf_incoming_last;
|
|
pthread_mutex_t pbuf_incoming_mutex;
|
|
|
|
int pbuf_incoming_local_count; /* number of packets parsed, not yet in dupecheck's inbox */
|
|
int pbuf_incoming_count; /* number of packets waiting for dupecheck thread to get */
|
|
|
|
/* Pointer to last pointer in pbuf_global(_dupe) */
|
|
struct pbuf_t **pbuf_global_prevp;
|
|
struct pbuf_t **pbuf_global_dupe_prevp;
|
|
|
|
uint32_t last_pbuf_seqnum;
|
|
uint32_t last_pbuf_dupe_seqnum;
|
|
|
|
/* how many packets were dropped internally within this worker
|
|
* (process hangs and time jumps)
|
|
*/
|
|
unsigned int internal_packet_drops;
|
|
};
|
|
|
|
extern cJSON *worker_shutdown_clients;
|
|
|
|
extern int workers_running;
|
|
|
|
extern void pbuf_init(void);
|
|
extern void pbuf_free(struct worker_t *self, struct pbuf_t *p);
|
|
extern void pbuf_free_many(struct pbuf_t **array, int numbufs);
|
|
extern void pbuf_dump(FILE *fp);
|
|
extern void pbuf_dupe_dump(FILE *fp);
|
|
|
|
extern int client_postread(struct worker_t *self, struct client_t *c, int r);
|
|
extern int client_buffer_outgoing_data(struct worker_t *self, struct client_t *c, char *p, int len);
|
|
|
|
extern int client_printf(struct worker_t *self, struct client_t *c, const char *fmt, ...);
|
|
extern int client_write(struct worker_t *self, struct client_t *c, char *p, int len);
|
|
extern int client_bad_filter_notify(struct worker_t *self, struct client_t *c, const char *filt);
|
|
extern void client_close(struct worker_t *self, struct client_t *c, int errnum);
|
|
extern void client_init(void);
|
|
|
|
extern struct worker_t *worker_threads;
|
|
extern struct worker_t *worker_alloc(void);
|
|
extern void worker_free_buffers(struct worker_t *self);
|
|
extern void workers_stop(int stop_all);
|
|
extern void workers_start(void);
|
|
|
|
extern int keepalive_interval;
|
|
extern int fileno_limit;
|
|
|
|
extern int obuf_writes_threshold;
|
|
|
|
extern struct client_udp_t *udpclients;
|
|
extern struct client_udp_t *udppeers;
|
|
extern void client_udp_free(struct client_udp_t *u);
|
|
extern struct client_udp_t *client_udp_alloc(struct client_udp_t **root, int fd, int portnum);
|
|
extern struct client_udp_t *client_udp_find(struct client_udp_t *root, int af, int portnum);
|
|
|
|
extern void inbound_connects_account(const int add, struct portaccount_t *p);
|
|
|
|
extern struct portaccount_t *port_accounter_alloc(void);
|
|
extern void port_accounter_drop(struct portaccount_t *p);
|
|
|
|
extern char *strsockaddr(const struct sockaddr *sa, const int addr_len);
|
|
extern char *hexsockaddr(const struct sockaddr *sa, const int addr_len);
|
|
extern void clientaccount_add_rx(struct client_t *c, int l4proto, int rxbytes, int rxpackets, int rxerr, int rxdupes);
|
|
extern void clientaccount_add_tx(struct client_t *c, int l4proto, int txbytes, int txpackets);
|
|
|
|
extern void json_add_rxerrs(cJSON *root, const char *key, long long vals[]);
|
|
extern int worker_client_list(cJSON *workers, cJSON *clients, cJSON *uplinks, cJSON *peers, cJSON *totals, cJSON *memory);
|
|
|
|
#endif
|