📄 lwld.c
字号:
if (cstat >= 0) {
if (send(sock, q->q_pkt, q->q_rll, 0) < 0) {
perror("forwarding look who's listening source ID message");
break;
} else {
Lock(fwdlistLock);
f->head = q->next;
if (f->head == NULL) {
f->tail = NULL;
}
free(q);
f->queuelen--;
if (f->queuelen < 0) {
fprintf(stderr, "%s: forward queue underflow to %s.\n",
prog, f->sitename);
f->queuelen = 0;
}
Unlock(fwdlistLock);
if (debugging) {
fprintf(stderr, "%s: forwarded packet to server %s. Queue length now %d.\n",
prog, f->sitename, f->queuelen);
}
}
} else {
/* As LWL servers go up and down, failures to connect
to forwarding destinations are not uncommon. Further,
while a server is down, we get here on every packet
we attempt to forward. To avoid blithering all
over the log, we only note such failure if in
prolix or debugging mode. */
if (prolix || debugging) {
perror("connecting forwarding socket");
}
break;
}
close(sock);
sock = -1;
}
/* If we bailed out of the above loop due to an error in
forwarding the packet, make sure the socket is closed. */
if (sock >= 0) {
close(sock);
sock = -1;
}
sleep(ForwarderSleep);
}
#ifdef DBTHREAD
fprintf(stderr, "Exited forwarder thread for %s\n", f->sitename);
#endif
f->status = -1; /* Forwarder terminated */
return NULL;
}
#endif
/* FORWARDLIST -- Parse a list of servers to forward packets to. */
static void forwardList(cp)
char *cp;
{
#ifdef THREADS
struct forwarder *f;
char *ep, *np;
while (TRUE) {
while (*cp != 0 && isspace(*cp)) {
cp++;
}
if (*cp == 0) {
break;
}
if ((np = strchr(cp, ',')) != NULL) {
*np++ = 0;
}
f = (struct forwarder *) malloc(sizeof(struct forwarder));
if (f != NULL) {
bzero(f, sizeof(struct forwarder));
f->status = 1;
f->sitename = cp;
f->port = Internet_Port + 2;
if ((ep = strchr(cp, ':')) != NULL) {
*ep = 0;
f->port = atoi(ep + 1);
}
f->next = fwdlist;
fwdlist = f;
if (pthread_create(&(f->thread), &detached, forwarder_thread, f) != 0) {
fprintf(stderr, "%s: Cannot launch forwarder thread for %s: %s",
prog, cp, strerror(errno));
free(f);
}
} else {
fprintf(stderr, "%s: out of memory allocating forwarder for %s\n",
prog, cp);
break;
}
if (np == NULL) {
break;
}
cp = np;
}
#else
struct hostent *h;
char *ep, *np;
long iadr;
int n;
lookhost.sin_family = AF_INET;
while (lwl_nsites < LWL_MAX_SITES) {
n = lwl_nsites;
while (*cp != 0 && isspace(*cp)) {
cp++;
}
if (*cp == 0) {
break;
}
if ((np = strchr(cp, ',')) != NULL) {
*np++ = 0;
}
lwl_ports[lwl_nsites] = Internet_Port + 2;
if ((ep = strchr(cp, ':')) != NULL) {
*ep = 0;
lwl_ports[lwl_nsites] = atoi(ep + 1);
}
if (isdigit(*cp) && (iadr = inet_addr(cp)) != -1) {
bcopy((char *) &iadr, (char *) (&lwl_sites[lwl_nsites]),
sizeof iadr);
lwl_nsites++;
} else {
h = gethostbyname(cp);
if (h != NULL) {
bcopy((char *) (h->h_addr),
(char *) (&lwl_sites[lwl_nsites]),
sizeof(unsigned long));
lwl_nsites++;
} else {
fprintf(stderr, "%s: warning, forward destination %s unknown.\n",
prog, cp);
}
}
if (debugging && lwl_nsites > n) {
fprintf(stderr, "%s: forwarding to LWL server %s: %s.\n", prog,
inet_ntoa(lwl_sites[n]), cp);
}
if (np == NULL) {
break;
}
cp = np;
}
#endif
}
/* FORWARDLWLMESSAGE -- If forwarding is enabled, pass this message
on to hosts in our forward list, changing the
packet protocol header to indicate the packet
was forwarded and appending the IP address
of the originating host to the end of the packet. */
static void forwardLwlMessage(zp, rll, addr)
char *zp; /* Packet address */
int rll; /* Total packet length (starting at zp) */
struct in_addr addr; /* IP address of originator of this packet */
{
int i, sock, wasfwd = FALSE;
zp[0] |= 0x40; /* Set forwarded packet flag bit */
bcopy(&addr, zp + rll, sizeof(struct in_addr));
rll += sizeof(struct in_addr);
#ifdef THREADS
{
struct forwarder *f = fwdlist;
while (f != NULL) {
if (f->status == 0) {
if (f->queuelen > ForwarderMaxQ) {
fprintf(stderr, "%s: %s queue too long; forward message discarded.\n",
prog, f->sitename);
} else {
struct lwl_queueitem *q = (struct lwl_queueitem *) malloc(
sizeof(struct lwl_queueitem) + rll);
if (q != NULL) {
q->next = NULL;
q->q_rll = rll;
bcopy(zp, q->q_pkt, rll);
Lock(fwdlistLock);
f->queuelen++;
if (f->head == NULL) {
f->head = f->tail = q;
} else {
f->tail->next = q;
f->tail = q;
}
Unlock(fwdlistLock);
}
}
}
f = f->next;
}
}
#else
for (i = 0; i < lwl_nsites; i++) {
if (lwl_ports[i] >= 0) {
int cstat;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening forwarding socket");
continue;
}
lookhost.sin_port = htons(lwl_ports[i]);
bcopy((char *) (&lwl_sites[i]), (char *) &lookhost.sin_addr.s_addr,
sizeof lookhost.sin_addr.s_addr);
errno = 0;
do {
cstat = connect(sock, (struct sockaddr *) &(lookhost), sizeof lookhost);
if (cstat >= 0) {
break;
}
} while (errno == EINTR);
if (cstat >= 0) {
if (send(sock, zp, rll, 0) < 0) {
perror("forwarding look who's listening source ID message");
} else {
if (debugging) {
fprintf(stderr, "%s: forwarded packet to server %s.\n",
prog, inet_ntoa(lookhost.sin_addr));
}
}
} else {
/* As LWL servers go up and down, failures to connect
to forwarding destinations are not uncommon. Further,
while a server is down, we get here on every packet
we attempt to forward. To avoid blithering all
over the log, we only note such failure if in
prolix or debugging mode. */
if (prolix || debugging) {
perror("connecting forwarding socket");
}
}
close(sock);
}
}
#endif
}
/* QUERYMATCH -- Determing if query matches a given item. */
static int queryMatch(q, l)
char *q;
struct lwl *l;
{
char ts[1024];
int exact = FALSE;
char *s;
s = ts;
/* We give preference to an E-mail address, if given, to a
canonical address since it's the user's best known published
identity on the net. This, of course, runs the risk of
spoofing, but since anybody can send us an RTCP packet with
whatever cname they like, there's no added security in insisting
on using it. */
strcpy(s, (l->email == NULL) ? l->cname : l->email);
lcase(s);
if (*q == '*') {
exact = TRUE;
q++;
}
if (*s == '*') {
exact = TRUE;
s++;
}
/* Even if we're using the E-mail name, allow an asterisk on the
canonical name to require an exact match. */
if (l->cname[0] == '*') {
exact = TRUE;
}
if (exact) {
return strcmp(s, q) == 0;
}
if (strstr(s, q)) {
return TRUE;
}
if (l->name != NULL) {
strcpy(s, l->name);
lcase(s);
if (strstr(s, q)) {
return TRUE;
}
}
return FALSE;
}
/* RELEASE -- Check for connections who haven't send us an update
once in the timeout interval and close them. They
probably went away without having the courtesy to
say good-bye. */
static void release()
{
struct lwl *lw, *llr = NULL, *lf;
time_t now = time(NULL);
LockConn();
lw = conn;
while (lw != NULL) {
if ((now - lw->ltime) > TimeoutTime) {
lf = lw;
if (llr == NULL) {
conn = lw->next;
lw = conn;
} else {
llr->next = lw->next;
lw = lw->next;
}
/*
fprintf(stderr, "\nTiming out:\n");
dumpLwl(stderr, lf);
*/
if (verbose) {
logLwl(lf, "Timeout: ");
}
htmlChange = TRUE;
destroyLwl(lf);
} else {
llr = lw;
lw = lw->next;
}
}
UnlockConn();
#ifndef THREADS
updHTML(); /* Update HTML if something's changed recently */
signal(SIGALRM, release); /* Reset signal to handle timeout (Sys V) */
alarm(TockTock); /* Reset the timer */
#endif
}
/* PLUMBER -- Catch SIGPIPE signal which occurs when remote user
disconnects before we try to send the reply. */
static void plumber()
{
#ifdef DBTHREAD
fprintf(stderr, "Caught SIGPIPE--continuing.\n");
#endif
signal(SIGPIPE, plumber); /* Reset signal just in case */
}
/* EXITING -- Release socket in case of termination. */
static void exiting()
{
#ifdef DBTHREAD
fprintf(stderr, "Exiting.\n");
#endif
shutdown(sock, 2);
close(sock);
exit(0);
}
/* PROG_NAME -- Extract program name from argv[0]. */
static char *prog_name(arg)
char *arg;
{
char *cp = strrchr(arg, '/');
return (cp != NULL) ? cp + 1 : arg;
}
/* USAGE -- Print how-to-call information. */
static void usage()
{
V fprintf(stderr, "%s -- Speak Freely: Look Who's Listening Server.\n", prog);
#ifdef THREADS
V fprintf(stderr, " (Multi-threaded version)\n");
#endif
V fprintf(stderr, " %s.\n", Relno);
V fprintf(stderr, "\n");
V fprintf(stderr, "Usage: %s [options]\n", prog);
V fprintf(stderr, "Options:\n");
V fprintf(stderr, " -D Debugging output on stderr\n");
V fprintf(stderr, " -Fserv,... Forward to listed servers\n");
V fprintf(stderr, " -Hpath Write HTML status on base path\n");
V fprintf(stderr, " -Insec Interval between HTML updates\n");
V fprintf(stderr, " -Mfile Load server message from file\n");
V fprintf(stderr, " -Pport Listen on given port\n");
V fprintf(stderr, " -U Print this message\n");
V fprintf(stderr, " -V[V] List connections and disconnects [-VV: all packets]\n");
#ifdef HEXDUMP
V fprintf(stderr, " -X Dump packets in hex\n");
#endif
V fprintf(stderr, " -Zpath Write HTML private directory on base path\n");
V fprintf(stderr, "\n");
V fprintf(stderr, "by John Walker\n");
V fprintf(stderr, " WWW: http://www.fourmilab.ch/\n");
}
/* ADD_SDES_ITEM -- Include an SDES item in a reply packet,
pruning illegal characters and content,
checking for packet overflow, and updating
the packet pointer. */
#define addSDES(item, text) add_sdes_item(item, text, &ap)
static int add_sdes_item(item, text, app)
int item;
char *text;
char **app;
{
int l, state;
char prune[258];
char *ap = *app, *hp, *op = prune;
/* Copy the text to the "prune" buffer using a simple
state machine parser, filtering extraneous
information. */
state = 0;
while (*text) {
unsigned char ch = (unsigned char) *text++;
if (item == RTCP_SDES_PRIV && op == prune) {
/* Allow PRIV item binary prefix field to pass. */
*op++ = (char) ch;
continue;
}
/* Discard non-graphic characters (ISO 8859 standard). */
if (!isspace(ch) && (ch < ' ' || (ch > '~' && ch < 161))) {
continue;
}
switch (state) {
case 0: /* Skipping initial white space */
if (!isspace(ch)) {
state = 1;
} else {
break;
}
/* Note fall-through */
case 1: /* Transcribing to output */
s1: if (ch == '<') {
if ((hp = strchr(text, '>')) != NULL) {
text = hp + 1;
if (op > prune && isspace(op[-1])) {
state = 2;
}
continue;
}
}
if (isspace(ch)) {
ch = ' '; /* Convert all white space into blanks */
state = 2;
}
*op++ = (char) ch;
break;
case 2: /* Collapsing multiple white space */
if (!isspace(ch)) {
state = 1;
goto s1;
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -