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

📄 lwld.c

📁 g729 coding ipaddressing
💻 C
📖 第 1 页 / 共 4 页
字号:
	}
    }
    *op = 0;

    /* Drop trailing blanks. */

    while (strlen(prune) > 0 && isspace(op[-1])) {
	*(--op) = 0;
    }

    l = strlen(prune);
    if (l == 0) {
	return TRUE;
    } else if (l > 48) {
	int n;

	/* String is too long.	Try to trim it at a word boundary,
	   but if that fails just brutally lop it off. */

	for (n = 47; n > 31; n--) {
	    if (isspace(prune[n])) {
		prune[n] = 0;
		n = 0;
		break;
	    }
	}
	if (n > 0) {
	    prune[47] = 0;
	}
    }

    *ap++ = item;

    *ap++ = l = strlen(prune);
    bcopy(prune, ap, l);
    ap += l;

    *app = ap;
}

/*  SERVICEPACKET  --  Process a packet from a connection.  */

static void servicePacket(csock, from)
  int csock;
  struct sockaddr_in from;	 /* Sending host address */
{
    int rll, forward, pvalid;
    char zp[1024];
    rtcp_t *rp;
    short srp;
    struct lwl *lw;		  /* Parsed packet */
    char *p, *pend;
    struct sockaddr_in fwdh;

    forward = FALSE;
    rll = recv(csock, zp, sizeof zp, 0);
#ifdef HEXDUMP
    if (hexdump) {
	fprintf(stderr, "%s: %d bytes read from socket.\n", prog, rll);
	xd(stderr, zp, rll, TRUE);
    }
#endif

    /* If packet was forwarded from another server, extract the
       embedded original source address and make the packet
       look like it came directly from the sender. */

    if (rll > 4 && (zp[0] & 0xC0) == 0xC0) {
	forward = TRUE;
	zp[0] &= ~0x40;
	bcopy(zp + (rll - 4), &fwdh.sin_addr, 4);
	rll -= 4;
	if (debugging) {
	    fprintf(stderr, "%s: received forwarded packet from %s.\n",
		prog, inet_ntoa(from.sin_addr));
	}
	from.sin_addr = fwdh.sin_addr ;
    }

    /* Some version of Speak Freely for Windows don't always
       pad request packets to a multiple of four bytes.  If
       this is the case, insert the pad ourselves. */

    while (((zp[1] & 0xFF) == RTCP_APP) && ((rll & 3) != 0)) {
	zp[rll++] = 0;
    }

    /* Validate this packet.  If it fails the validity check,
       ignore it do it can't crash the code below. */

    if (!gardol((unsigned char *) zp, rll)) {
	if (debugging) {
	    fprintf(stderr, "%s: discarded invalid RTCP packet from %s.\n",
		prog, inet_ntoa(from.sin_addr));
	}
	close(csock);
	return;
    }

    /* Walk through the individual items in a possibly composite
       packet until we locate an item we're interested in.  This
       allows us to accept packets that comply with the RTP standard
       that all RTCP packets begin with an SR or RR.  */

    p = zp;
    pend = p + rll;
    pvalid = FALSE;

    while ((p < pend) && (p[0] >> 6 & 3) == RTP_VERSION) {
	int pt = p[1] & 0xFF;

	if (pt == RTCP_SDES || pt == RTCP_BYE || pt == RTCP_APP) {
	    pvalid = TRUE;
	    break;
	}
	/* If not of interest to us, skip to next subpacket. */
	p += (ntohs(*((short *) (p + 2))) + 1) * 4;
    }

    if (!pvalid) {
	if (debugging) {
	    fprintf(stderr, "%s: discarded RTCP packet with unknown payload from %s.\n",
		prog, inet_ntoa(from.sin_addr));
	}
	close(csock);
	return;
    }

    /* Examine the packet to see what kind of request it is.
       Note that since all the packets we're interested in can
       be parsed without knowing their actual length in bytes, we
       can ignore the possible presence of padding. */

    rp = (rtcp_t *) p;
    srp = ntohs(*((short *) p));
    if (
#ifdef RationalWorld
	rp->common.version == RTP_VERSION && /* Version ID correct */
	rp->common.count == 1
#else
	(((srp >> 14) & 3) == RTP_VERSION) &&
	(((srp >> 8) & 0x1F) == 1)
#endif
       ) {

	switch (
#ifdef RationalWorld
		rp->common.pt
#else
		srp & 0xFF
#endif
	       ) {

	    /*	SDES packet.  This is a notification by a listening
			      that it's just started or is still
			      listening.  If the host was previously
			      active we replace the old parameters
			      with the new in case something has
			      changed.	The timeout is reset.  Identity
			      of host is by canonical name, not SSRC,
			      since the host may have restarted with
			      a new SSRC without having sent us a BYE.	*/

	    case RTCP_SDES:

		/* Parse the fields out of the SDES packet. */

		{
		    char *cp = (char *) rp->r.sdes.item,
			 *lp = cp + (ntohs(rp->common.length) * 4);
		    struct lwl *lr, *llr;

		    lw = (struct lwl *) malloc(sizeof(struct lwl));
		    if (lw != NULL) {
			bzero((char *) lw, sizeof(struct lwl));

			lw->ssrc = rp->r.sdes.src;
			lw->naddr = from.sin_addr.s_addr;
			lw->port = from.sin_port;
			lw->ltime = time(NULL);
			if (prolix) {
			    printf("%s: %s SDES %08X\n", prog,
				inet_ntoa(from.sin_addr), lw->ssrc);
			}
			while (cp < lp) {
			    switch ((*cp) & 0xFF) {

				case RTCP_SDES_CNAME:
				    lw->cname = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_NAME:
				    lw->name = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_EMAIL:
				    lw->email = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_PHONE:
				    lw->phone = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_LOC:
				    lw->loc = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_TOOL:
				    lw->tool = dupSdesItem(&cp);
				    break;

				case RTCP_SDES_PRIV:
				    {
					char *zp = dupSdesItem(&cp);

					if (zp != NULL) {
					    if (zp[0] == 1 &&
						zp[1] == 'P') {
						lw->port = atoi(zp + 2);
					    }
					    free(zp);
					}
				    }
				    break;

				case RTCP_SDES_END:
				    cp = lp;
				    break;

				default:
				    {
					char *zp = dupSdesItem(&cp);

					if (zp != NULL) {
					    free(zp);
					}
				    }
				    break;
			    }
			}
			if (debugging) {
			    dumpLwl(stderr, lw);
			}

			/* Search chain and see if a user with this
			   name is already know.  If so, replace the
			   entry with this one. */

			if (lw->cname != NULL) {
			    lr = conn;
			    llr = NULL;

			    while (lr != NULL) {
				char *p = lw->cname, *q = lr->cname;

				if (*p == '*') {
				    p++;
				}
				if (*q == '*') {
				    q++;
				}
				if (strcmp(p, q) == 0) {
				    lw->next = lr->next;
				    if (llr == NULL) {
					conn = lw;
				    } else {
					llr->next = lw;
				    }
				    destroyLwl(lr);
				    lw = NULL;
				    break;
				}
				llr = lr;
				lr = lr->next;
			    }

			    /* If we didn't find an entry already in the
			       chain, link in the new entry.  */

			    if (lw != NULL) {
				lw->next = conn;
				conn = lw;
				if (verbose) {
				    logLwl(lw, "Connect: ");
				}
				changed();
			    }
			    if (!forward && lwl_nsites > 0) {
				forwardLwlMessage(zp, rll, from.sin_addr);
			    }
			} else {
			    /* Bogus item with no CNAME -- discard. */
			    if (debugging || verbose) {
				fprintf(stderr, "Bogus SDES with no CNAME.\n");
				if (!debugging) {
				    dumpLwl(stderr, lw);
				}
			    }
			    destroyLwl(lw);
			}
		    }
		}
		break;

	    /*	BYE packet.  This is sent when a listening host is
			     ceasing to listen in an orderly manner.
			     Identity here is by SSRC, since the
			     host is assumed to have properly announced
			     itself.  Besides, that's the only ID in
			     the RTCP BYE packet, so it had darned
			     well be sufficient.  */

	    case RTCP_BYE:
		{
		    struct lwl *lr = conn, *llr = NULL;

		    if (prolix) {
			printf("%s: %s BYE %08X\n", prog,
			    inet_ntoa(from.sin_addr), rp->r.bye.src[0]);
		    }
		    while (lr != NULL) {
			if (rp->r.bye.src[0] == lr->ssrc) {
			    if (llr == NULL) {
				conn = lr->next;
			    } else {
				llr->next = lr->next;
			    }
			    if (debugging) {
				fprintf(stderr, "Releasing:\n");
				dumpLwl(stderr, lr);
			    }
			    if (verbose) {
				logLwl(lr, "Bye:     ");
			    }
			    changed();
			    destroyLwl(lr);
			    break;
			}
			llr = lr;
			lr = lr->next;
		    }
		    if (!forward && lwl_nsites > 0) {
			forwardLwlMessage(zp, rll, from.sin_addr);
		    }
		}
		break;

	    /*	Application request packets.  The following application
		extensions implement the various queries a client can make
		regarding the current state of the listening host list.  */

	    case RTCP_APP:
		if (prolix) {
		    printf("%s: %s APP %.4s\n", prog,
			inet_ntoa(from.sin_addr), p + 8);
		}

		/*  SFlq  --  Pattern match in cname and name and
			      return matches, up to the maximum
			      packet size.  If either the query string
			      or the canonical name begins with an
			      asterisk, the asterisk(s) is(/are) ignored
			      and a precise match with the canonical
			      name is required.  */

		if (bcmp(p + 8, "SFlq", 4) == 0) {
		    struct lwl *lr = conn;
		    char b[1500];
		    rtcp_t *rp = (rtcp_t *) b;
		    char *ap, *pap;
		    int l, scandex = 0;

#ifdef RationalWorld
		    rp->common.version = RTP_VERSION;
		    rp->common.p = 0;
		    rp->common.count = 0;
		    rp->common.pt = RTCP_SDES;
#else
		    *((short *) rp) = htons((RTP_VERSION << 14) |
					     RTCP_SDES | (0 << 8));
#endif

		    ap = (char *) &(rp->r.sdes.src);

		    if (prolix) {
			printf("%s: %s query \"%s\"\n", prog, inet_ntoa(from.sin_addr), p + 12);
		    }
		    lcase(p + 12);
		    while (lr != NULL) {
			if (queryMatch(p + 12, lr)) {
			    char s[20];

			    pap = ap;
			    *((unsigned long *) ap) = lr->ssrc;
			    ap += sizeof(unsigned long);
			    addSDES(RTCP_SDES_CNAME, lr->cname +
				(lr->cname[0] == '*' ? 1 : 0));

			    if (lr->name != NULL) {
				addSDES(RTCP_SDES_NAME, lr->name);
			    }

			    if (lr->email != NULL) {
				addSDES(RTCP_SDES_EMAIL, lr->email +
				  (lr->email[0] == '*' ? 1 : 0));
			    }

			    if (lr->phone != NULL) {
				addSDES(RTCP_SDES_PHONE, lr->phone);
			    }

			    if (lr->loc != NULL) {
				addSDES(RTCP_SDES_LOC, lr->loc);
			    }

			    if (lr->tool != NULL) {
				addSDES(RTCP_SDES_TOOL, lr->tool);
			    }

			    sprintf(s, "\001P%d", lr->port);
			    addSDES(RTCP_SDES_PRIV, s);

			    {
				struct sockaddr_in u;

				u.sin_addr.s_addr = lr->naddr;
				sprintf(s, "\001I%s", inet_ntoa(u.sin_addr));
				addSDES(RTCP_SDES_PRIV, s);
			    }

			    sprintf(s, "\001T%lu", lr->ltime);
			    addSDES(RTCP_SDES_PRIV, s);

#ifdef NEEDED
			    /* If we're over the packet size limit,
			       let the user know there's more to be
			       retrieved starting at the given offset. */

			    if ((ap - b) > MaxReplyPacket) {
				sprintf(s, "\001M%d", scandex);
				addSDES(RTCP_SDES_PRIV, s);
			    }
#endif
			    *ap++ = RTCP_SDES_END;

			    /* Pad to next 32 bit boundary. */

			    while (((ap - b) & 3) != 0) {
				*ap++ = RTCP_SDES_END;
			    }
			    if ((ap - b) > MaxReplyPacket) {
				ap = pap;
				break;
			    }
#ifdef RationalWorld
			    rp->common.count++;
#else
			    (((unsigned char *) rp)[0])++;
#endif
			}
			lr = lr->next;
			scandex++;
		    }

		    l = ap - b;

		    rp->common.length = htons(((l + 3) / 4) - 1);
		    l = (ntohs(rp->common.length) + 1) * 4;
#ifdef HEXDUMP
		    if (hexdump) {
			fprintf(stderr, "%s: %d bytes sent to socket.\n", prog, l);
			xd(stderr, b, l, TRUE);
		    }
#endif
		    if (send(csock, b, l, 0) < 0) {
			perror("sending query match reply");
		    }
		}

		/*  SFms  --  Retrieve the server's information
			      message, if any.	If the server doesn't
			      publish a message, a null string is
			      returned in the reply packet.  */

⌨️ 快捷键说明

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