⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lwld.c

📁 g729 coding ipaddressing
💻 C
📖 第 1 页 / 共 4 页
字号:
/*

			 Speak Freely for Win32
		     Look Who's Listening Server

  This is the Win32 of the LWL daemon.
*/

#include "speakfree.h"

#ifdef THREADS
#include <pthread.h>
#define Lock(x) pthread_mutex_lock(&(x))
#define Unlock(x) pthread_mutex_unlock(&(x))
#define LockConn()  Lock(connLock)
#define UnlockConn() Unlock(connLock)
#else
#define LockConn()
#define UnlockConn()
#endif

#define TockTock    120 	      /* Timeout check frequency, seconds */
#define TimeoutTime 15 * 60	      /* No-response timeout interval, seconds */
#define ServiceThreadTimeout	60    /* Service thread timeout interval, seconds  */

#define MaxReplyPacket 512	      /* Maximum length of reply data */

static int sock;		      /* Our socket */
static char *prog;		      /* Program name */ 

static int lwlport = Internet_Port + 2; /* Look Who's Listening port */
static int debugging = FALSE;	      /* Debug mode enabled */
static int verbose = FALSE;	      /* Show connections/disconnects */
static int prolix = FALSE;	      /* Extremely verbose (show queries) */
#ifdef HEXDUMP
static int hexdump = FALSE;	      /* Dump received packets in hex ? */
#endif
static char *htmlFile = NULL;	      /* HTML file name base */
static char *htmlPrivateFile = NULL;  /* HTML private directory file name base */
static int htmlTime = 1 * 60;	      /* HTML file update time */
static time_t htmlLast = 0;	      /* HTML last update time */
static int htmlChange = TRUE;	      /* Change since last HTML update ? */
static char *message = NULL;	      /* Server information message */
static int messagel;		      /* Length of server information message */

#ifdef THREADS

#define ForwarderSleep	30	      /* How often to update forwarded hosts */
#define ForwarderMaxQ	15	      /* Maximum items in forward queue */

struct lwl_queueitem {
    struct lwl_queueitem *next;       /* Next item in LWL queue */
    int q_rll;			      /* Length of message */
    char q_pkt[2];		      /* Message body */
};

struct forwarder {
    struct forwarder *next;	      /* Next forwarder in chain */
    int status; 		      /* Site status (0 = normal) */
    char *sitename;		      /* Site name specification */
    struct in_addr site;	      /* Internet address of target host */
    long port;			      /* Destination port on that host */
    pthread_t thread;		      /* ID of forwarder thread */
    int queuelen;		      /* Length of queue for forwarder */
    struct lwl_queueitem *head, *tail;/* Queue of messages to be forwarded */
};

static pthread_attr_t detached;       /* Attributes for our detached threads */
static pthread_mutex_t fwdlistLock = PTHREAD_MUTEX_INITIALIZER;
static struct forwarder *fwdlist = NULL; /* List of forwarding destinations */

#define lwl_nsites 1		      /* Threaded version driven from list */

struct ballOstring {
    struct ballOstring *next, *prev;  /* Forward and back queue links */
    pthread_t thread;		      /* Service thread ID */
    time_t startTime;		      /* When did thread start ? */
    struct in_addr site;	      /* Internet address of requesting site */
    struct service_arg *sa;	      /* Service thread argument */
};

static struct ballOstring bshead;     /* Ball of string queue head */
static pthread_mutex_t bsLock = PTHREAD_MUTEX_INITIALIZER;

#else
static struct sockaddr_in lookhost;   /* Look who's listening host, if any */
static struct in_addr lwl_sites[LWL_MAX_SITES]; /* LWL site addresses */
static long lwl_ports[LWL_MAX_SITES]; /* Ports for LWL hosts */
static int lwl_nsites = 0;	      /* Number of LWL sites published on */
#endif

struct lwl {
    struct lwl *next;		      /* Next connection */
    time_t ltime;		      /* Time of last update */
    unsigned long ssrc; 	      /* Session source descriptor */
    long naddr; 		      /* Internet address */
    short port; 		      /* Port address */
    char *cname;		      /* Canonical name */ 
    char *name; 		      /* User name */
    char *email;		      /* Electronic mail address */
    char *phone;		      /* Telephone number */
    char *loc;			      /* Geographic location */
    char *tool; 		      /* Application name */
};

#ifdef THREADS
				      /* Connection chain critical section */
static pthread_mutex_t connLock = PTHREAD_MUTEX_INITIALIZER;
#endif
static struct lwl *conn = NULL;       /* Chain of current connections */

/*  ETIME  --  Edit time and date for log messages.  */

static char *etime(gmt)
  int gmt;
{
    struct tm *t;
    time_t clock;
    static char s[20];

    time(&clock);
    if (gmt) {
	t = gmtime(&clock);
    } else {
	t = localtime(&clock);
    }
    sprintf(s, "%02d-%02d %02d:%02d", t->tm_mon + 1, t->tm_mday,
	       t->tm_hour, t->tm_min);
    return s;
}

/*  ESTIME  --	Edit short time.  */

static char *estime()
{
    struct tm *t;
    time_t clock;
    static char s[20];

    time(&clock);
    t = localtime(&clock);
    sprintf(s, "%02d:%02d", t->tm_hour, t->tm_min);
    return s;
}

/*  DUPSDESITEM  --  Make a copy of an SDES item and advance the pointer
		     past it.  */

static char *dupSdesItem(cp)
  char **cp;
{
    char *ip = *cp, *bp;
    int l = ip[1] & 0xFF;

    bp = malloc(l + 1);
    if (bp != NULL) {
	bcopy(ip + 2, bp, l);
	bp[l] = 0;
    }
    *cp = ip + l + 2;
    return bp;
}

/*  DESTROYLWL	--  Release storage associated with an LWL list item.  */

static void destroyLwl(lw)
  struct lwl *lw;
{
    if (lw->cname != NULL) {
	free(lw->cname);
    }
    if (lw->name != NULL) {
	free(lw->name);
    }
    if (lw->email != NULL) {
	free(lw->email);
    }
    if (lw->phone != NULL) {
	free(lw->phone);
    }
    if (lw->loc != NULL) {
	free(lw->loc);
    }
    if (lw->tool != NULL) {
	free(lw->tool);
    }
    free(lw);
}

/*  DUMPLWL  --  Dump an LWL on the specified stream.  */

static void dumpLwl(fo, lw)
  FILE *fo;
  struct lwl *lw;
{
    struct sockaddr_in s;

    s.sin_addr.s_addr = lw->naddr;
    fprintf(fo, "SSRC = %X IP = %s Port %d %s", lw->ssrc, inet_ntoa(s.sin_addr),
		lw->port, ctime(&(lw->ltime)));
    if (lw->cname != NULL) {
	fprintf(fo, "	 CNAME = %s\n", lw->cname);
    }
    if (lw->name != NULL) {
	fprintf(fo, "	  NAME = %s\n", lw->name);
    }
    if (lw->email != NULL) {
	fprintf(fo, "	 EMAIL = %s\n", lw->email);
    }
    if (lw->phone != NULL) {
	fprintf(fo, "	 PHONE = %s\n", lw->phone);
    }
    if (lw->loc != NULL) {
	fprintf(fo, "	   LOC = %s\n", lw->loc);
    }
    if (lw->tool != NULL) {
	fprintf(fo, "	  TOOL = %s\n", lw->tool);
    }
}

#ifdef NEEDED

/*  DUMPLWLCHAIN  --  Dump all current connections.  */

static void dumpLwlChain(fo)
  FILE *fo;
{
    struct lwl *lw;

    LockConn();
    lw = conn;
    fprintf(fo, "\n==========  %s  ==========\n", etime(FALSE));
    while (lw != NULL) {
	fprintf(fo, "\n");
	dumpLwl(fo, lw);
	lw = lw->next;
    }
    UnlockConn();
}
#endif

/*  LOGLWL  --	Generate log entry for LWL event.  */

static void logLwl(lw, event)
  struct lwl *lw;
  char *event;
{
    char ipport[40], deef[256];
    struct sockaddr_in u;

    u.sin_addr.s_addr = lw->naddr;
    sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
    sprintf(deef, "%s %s", ipport, lw->email ? lw->email : lw->cname);
    if (lw->name) {
	sprintf(deef + strlen(deef), " (%s)", lw->name);
    }
    printf("%s %s%s\n", estime(), event, deef);
}

/*  GARDOL  -- Validity-check an RTCP packet to make sure we don't
	       crash if some bozo sends us garbage.  */

static int gardol(p, len)
  unsigned char *p;
  int len;
{
    unsigned char *end;

    if ((((p[0] >> 6) & 3) != RTP_VERSION) ||	   /* Version incorrect ? */
	((p[0] & 0x20) != 0) || 		   /* Padding in first packet ? */
	((p[1] != RTCP_SR) && (p[1] != RTCP_RR) &&
	 (p[1] != RTCP_SDES) && (p[1] != RTCP_BYE) &&
	 (p[1] != RTCP_APP))) { 		   /* Item type valid ? */
	return FALSE;
    }
    end = p + len;

    do {
	/* Advance to next subpacket */
	p += (ntohs(*((short *) (p + 2))) + 1) * 4;
    } while (p < end && (((p[0] >> 6) & 3) == RTP_VERSION));

    return p == end;
}

/*  MAKEHTML  --  Create an HTML file showing current connections.  If
		  "private" is set, exact-match names are included
		  in the HTML file; this allows creation of a non-exported
		  active site file for the system manager's use.  */

static int makeHTML(fname, private)
  char *fname;
  int private;
{
    FILE *of;
    char f[132], fn[132];

    strcpy(f, fname);
    strcat(f, ".new");
    of = fopen(f, "w");
    if (of != NULL) {
	struct lwl *lw;

#define P(x) fprintf(of, x)

	LockConn();
	lw = conn;
	P("<html>\n<head>\n<title>\nSpeak Freely: Active Sites\n");
	P("</title>\n</head>\n\n<body>\n<center>\n<h1>");
	P("Speak Freely: Active Sites</h1>\n<h2>");
	fprintf(of, "As of %s UTC</h2>\n</center>\n<p>\n", etime(TRUE));

	if (lw == NULL) {
	    P("<h2>No sites active.</h2>\n");
	} else {
	    int i = 0;

	    while (lw != NULL) {
		if (private || ((lw->email == NULL || lw->email[0] != '*') &&
		    (lw->cname[0] != '*'))) {
		    i++;
		}
		lw = lw->next;
	    }
	    lw = conn;
	    if (i == 0) {
		/* Fib about number of sites active if all active sites
		   don't want a directory listing. */
		P("<h2>No sites active.</h2>\n");
	    } else {
		fprintf(of, "<h2>%d site%s active.</h2>\n",
		    i, i == 1 ? "" : "s");
		P("<pre>\n");
		while (lw != NULL) {
		    if (private || ((lw->email == NULL || lw->email[0] != '*') &&
			(lw->cname[0] != '*'))) {
			char ipport[40];
			struct tm *lt;
			struct sockaddr_in u;

			lt = localtime(&lw->ltime);
			u.sin_addr.s_addr = lw->naddr;
			sprintf(ipport, "%s:%d", inet_ntoa(u.sin_addr), lw->port);
			fprintf(of, "\n%-24s %-48s %02d:%02d\n", ipport, lw->cname,
			    lt->tm_hour, lt->tm_min);
			if (lw->name != NULL) {
			    fprintf(of, "%25s%s\n", "", lw->name);
			}
			if (lw->loc != NULL) {
			    fprintf(of, "%25s%s\n", "", lw->loc);
			}
			if (lw->phone != NULL) {
			    fprintf(of, "%25sPhone:  %s\n", "", lw->phone);
			}
			if (lw->email != NULL) {
			    fprintf(of, "%25sE-mail: %s\n", "", lw->email);
			}
		    }
		    lw = lw->next;
		}
		P("</pre>\n");
	    }
	}
	UnlockConn();

	P("</body>\n</html>\n");
	fclose(of);
	strcpy(fn, fname);
	strcat(fn, ".html");
	rename(f, fn);
	if (debugging) {
	    fprintf(stderr, "%s: updated %s\n", prog, fn);
	}
	return TRUE;
    }
    return FALSE;
}

/*  UPDHTML  --  Update HTML if necessary.  */

static void updHTML()
{
    time_t now;

    if (((htmlFile != NULL) || (htmlPrivateFile != NULL)) && htmlChange && 
	((htmlTime <= 0) || (((now = time(NULL)) - htmlLast) > htmlTime))) {
	htmlLast = now;
	htmlChange = FALSE;
	if (htmlFile != NULL) {
	    makeHTML(htmlFile, FALSE);
	}
	if (htmlPrivateFile != NULL) {
	    makeHTML(htmlPrivateFile, TRUE);
	}
    }
}

/*  CHANGED  --  Indicate a change which may require updating
		 the HTML file.  */

static void changed()
{
    htmlChange = TRUE;
#ifndef THREADS
    updHTML();
#endif
}

/*  LCASE  --  Convert a string to lower case.	*/

static void lcase(s)
  char *s;
{
    while (*s) {
	if (isupper(*s)) {
	    *s = tolower(*s);
	}
	s++;
    }
}

#ifdef THREADS

/*  FORWARDER_THREAD  --  Thread which manages forwarding to a given
			  destination.	*/

static void *forwarder_thread(arg)
  void *arg;
{
    struct forwarder *f = (struct forwarder *) arg;
    struct hostent *h;
    long iadr;

#ifdef DBTHREAD
fprintf(stderr, "Started forwarder thread for %s\n", f->sitename);
#endif
    if (isdigit(f->sitename[0]) && (iadr = inet_addr(f->sitename)) != -1) {
	bcopy((char *) &iadr, (char *) (&(f->site)),
	      sizeof iadr);
	f->status = 0;
    } else {
	h = gethostbyname(f->sitename);
	if (h != NULL) {
	    bcopy((char *) (h->h_addr), 
		  (char *) (&(f->site)),
		  sizeof(unsigned long));
	    f->status = 0;
	} else {
	    fprintf(stderr, "%s: warning, forward destination %s unknown.\n",
		prog, f->sitename);
	    f->status = -2;
	    return NULL;
	}
    }
    if (debugging && f->status == 0) {
	fprintf(stderr, "%s: forwarding to LWL server %s: %s.\n", prog,
	    inet_ntoa(f->site), f->sitename);
    }

    while (f->status == 0) {
	struct lwl_queueitem *q;
	int sock = -1;

	while ((q = f->head) != NULL) {
	    int cstat;
	    struct sockaddr_in lookhost;

	    sock = socket(AF_INET, SOCK_STREAM, 0);
	    if (sock < 0) {
		perror("opening forwarding socket");
		break;
	    }

	    lookhost.sin_port = htons(f->port);
	    bcopy((char *) (&(f->site)), (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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -