Properly handle broken up packets

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1129 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2003-06-28 18:35:58 +00:00
parent f5e13431a5
commit 9befc69684
3 changed files with 32 additions and 67 deletions

View File

@@ -1604,7 +1604,7 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
int portno=0; int portno=0;
int vportno=0; int vportno=0;
int peercapability, peernoncodeccapability; int peercapability, peernoncodeccapability;
int vpeercapability, vpeernoncodeccapability; int vpeercapability=0, vpeernoncodeccapability=0;
struct sockaddr_in sin; struct sockaddr_in sin;
char *codecs; char *codecs;
struct hostent *hp; struct hostent *hp;
@@ -1690,8 +1690,6 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
sdpLineNum_iterator_init(&iterator); sdpLineNum_iterator_init(&iterator);
while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') { while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
char* mimeSubtype = ast_strdupa(a); // ensures we have enough space char* mimeSubtype = ast_strdupa(a); // ensures we have enough space
if (sipdebug)
ast_verbose("Pre-Found description format %s\n", mimeSubtype);
if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue; if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) != 2) continue;
if (sipdebug) if (sipdebug)
ast_verbose("Found description format %s\n", mimeSubtype); ast_verbose("Found description format %s\n", mimeSubtype);
@@ -1704,7 +1702,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req)
// Now gather all of the codecs that were asked for: // Now gather all of the codecs that were asked for:
ast_rtp_get_current_formats(p->rtp, ast_rtp_get_current_formats(p->rtp,
&peercapability, &peernoncodeccapability); &peercapability, &peernoncodeccapability);
ast_rtp_get_current_formats(p->vrtp, if (p->vrtp)
ast_rtp_get_current_formats(p->vrtp,
&vpeercapability, &vpeernoncodeccapability); &vpeercapability, &vpeernoncodeccapability);
p->capability = capability & (peercapability | vpeercapability); p->capability = capability & (peercapability | vpeercapability);
p->noncodeccapability = noncodeccapability & (peernoncodeccapability | vpeernoncodeccapability); p->noncodeccapability = noncodeccapability & (peernoncodeccapability | vpeernoncodeccapability);

2
file.c
View File

@@ -1,4 +1,4 @@
/*m /*
* Asterisk -- A telephony toolkit for Linux. * Asterisk -- A telephony toolkit for Linux.
* *
* Generic File Format Support. * Generic File Format Support.

90
rtp.c
View File

@@ -60,7 +60,6 @@ struct ast_rtp {
char resp; char resp;
struct ast_frame f; struct ast_frame f;
unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET]; unsigned char rawdata[8192 + AST_FRIENDLY_OFFSET];
int readsofar;
unsigned int ssrc; unsigned int ssrc;
unsigned int lastts; unsigned int lastts;
unsigned int lastrxts; unsigned int lastrxts;
@@ -335,19 +334,17 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
int mark; int mark;
unsigned int timestamp; unsigned int timestamp;
unsigned int *rtpheader; unsigned int *rtpheader;
unsigned char cache[12];
static struct ast_frame *f, null_frame = { AST_FRAME_NULL, }; static struct ast_frame *f, null_frame = { AST_FRAME_NULL, };
struct rtpPayloadType rtpPT; struct rtpPayloadType rtpPT;
len = sizeof(sin); len = sizeof(sin);
/* Cache where the header will go */ /* Cache where the header will go */
memcpy(cache, rtp->rawdata + AST_FRIENDLY_OFFSET + rtp->readsofar, 12); res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET,
res = recvfrom(rtp->s, rtp->rawdata + AST_FRIENDLY_OFFSET + rtp->readsofar, sizeof(rtp->rawdata) - AST_FRIENDLY_OFFSET - rtp->readsofar,
0, (struct sockaddr *)&sin, &len); 0, (struct sockaddr *)&sin, &len);
rtpheader = (unsigned int *)(rtp->rawdata + rtp->readsofar + AST_FRIENDLY_OFFSET); rtpheader = (unsigned int *)(rtp->rawdata + AST_FRIENDLY_OFFSET);
if (res < 0) { if (res < 0) {
ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno)); ast_log(LOG_WARNING, "RTP Read error: %s\n", strerror(errno));
if (errno == EBADF) if (errno == EBADF)
@@ -373,18 +370,11 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
seqno &= 0xffff; seqno &= 0xffff;
timestamp = ntohl(rtpheader[1]); timestamp = ntohl(rtpheader[1]);
/* Restore original data if important */
if (rtp->readsofar)
memcpy(rtp->rawdata + AST_FRIENDLY_OFFSET + rtp->readsofar, cache, 12);
rtpheader = NULL;
rtp->readsofar += (res - hdrlen);
#if 0 #if 0
printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen); printf("Got RTP packet from %s:%d (type %d, seq %d, ts %d, len = %d)\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), payloadtype, seqno, timestamp,res - hdrlen);
#endif #endif
rtpPT = ast_rtp_lookup_pt(rtp, payloadtype); rtpPT = ast_rtp_lookup_pt(rtp, payloadtype);
if (!rtpPT.isAstFormat) { if (!rtpPT.isAstFormat) {
rtp->readsofar = 0;
// This is special in-band data that's not one of our codecs // This is special in-band data that's not one of our codecs
if (rtpPT.code == AST_RTP_DTMF) { if (rtpPT.code == AST_RTP_DTMF) {
/* It's special -- rfc2833 process it */ /* It's special -- rfc2833 process it */
@@ -429,16 +419,14 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
/* Send any pending DTMF */ /* Send any pending DTMF */
if (rtp->resp && !rtp->dtmfcount) { if (rtp->resp && !rtp->dtmfcount) {
rtp->readsofar = 0;
ast_log(LOG_DEBUG, "Sending pending DTMF\n"); ast_log(LOG_DEBUG, "Sending pending DTMF\n");
return send_dtmf(rtp); return send_dtmf(rtp);
} }
rtp->f.mallocd = 0; rtp->f.mallocd = 0;
rtp->f.datalen = rtp->readsofar; rtp->f.datalen = res - hdrlen;
rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET; rtp->f.data = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET; rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) { if (rtp->f.subclass < AST_FORMAT_MAX_AUDIO) {
rtp->readsofar = 0;
switch(rtp->f.subclass) { switch(rtp->f.subclass) {
case AST_FORMAT_ULAW: case AST_FORMAT_ULAW:
case AST_FORMAT_ALAW: case AST_FORMAT_ALAW:
@@ -474,11 +462,9 @@ struct ast_frame *ast_rtp_read(struct ast_rtp *rtp)
/* Video -- samples is # of samples vs. 90000 */ /* Video -- samples is # of samples vs. 90000 */
rtp->f.samples = timestamp - rtp->lastividtimestamp; rtp->f.samples = timestamp - rtp->lastividtimestamp;
rtp->lastividtimestamp = timestamp; rtp->lastividtimestamp = timestamp;
/* Return now if it's not the whole frame */ if (mark)
if (!mark) { rtp->f.subclass |= 0x1;
return &null_frame;
}
rtp->readsofar = 0;
} }
rtp->f.src = "RTP"; rtp->f.src = "RTP";
return &rtp->f; return &rtp->f;
@@ -887,7 +873,6 @@ static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec
int ms; int ms;
int pred; int pred;
int mark = 0; int mark = 0;
int pos, len;
ms = calc_txstamp(rtp); ms = calc_txstamp(rtp);
/* Default prediction */ /* Default prediction */
@@ -928,20 +913,8 @@ static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec
rtp->lastts = pred; rtp->lastts = pred;
else else
ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
/* Get a pointer to the header */
rtpheader = (unsigned int *)(f->data - hdrlen);
rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++) | (mark << 23));
rtpheader[1] = htonl(rtp->lastts);
rtpheader[2] = htonl(rtp->ssrc);
if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, &rtp->them, sizeof(rtp->them));
if (res <0)
ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
#if 0
printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
#endif
}
} else { } else {
mark = f->subclass & 0x1;
pred = rtp->lastovidtimestamp + f->samples; pred = rtp->lastovidtimestamp + f->samples;
/* Re-calculate last TS */ /* Re-calculate last TS */
rtp->lastts = rtp->lastts + ms * 90; rtp->lastts = rtp->lastts + ms * 90;
@@ -953,30 +926,19 @@ static int ast_rtp_raw_write(struct ast_rtp *rtp, struct ast_frame *f, int codec
ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms); ast_log(LOG_DEBUG, "Difference is %d, ms is %d\n", abs(rtp->lastts - pred), ms);
rtp->lastovidtimestamp = rtp->lastts; rtp->lastovidtimestamp = rtp->lastts;
} }
pos = 0; }
while(pos < f->datalen) { /* Get a pointer to the header */
/* Split packets up if necessary */ rtpheader = (unsigned int *)(f->data - hdrlen);
mark = 0; rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++) | (mark << 23));
len = f->datalen; rtpheader[1] = htonl(rtp->lastts);
if (len > RTP_MTU) rtpheader[2] = htonl(rtp->ssrc);
len = RTP_MTU; if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
if ((pos + len) >= f->datalen) res = sendto(rtp->s, (void *)rtpheader, f->datalen + hdrlen, 0, &rtp->them, sizeof(rtp->them));
mark = 1; if (res <0)
/* Get a pointer to the header */ ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
rtpheader = (unsigned int *)(f->data + pos - hdrlen);
rtpheader[0] = htonl((2 << 30) | (codec << 16) | (rtp->seqno++) | (mark << 23));
rtpheader[1] = htonl(rtp->lastts);
rtpheader[2] = htonl(rtp->ssrc);
if (rtp->them.sin_port && rtp->them.sin_addr.s_addr) {
res = sendto(rtp->s, (void *)rtpheader, len + hdrlen, 0, &rtp->them, sizeof(rtp->them));
if (res <0)
ast_log(LOG_NOTICE, "RTP Transmission error to %s:%d: %s\n", inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port), strerror(errno));
#if 0 #if 0
printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port)); printf("Sent %d bytes of RTP data to %s:%d\n", res, inet_ntoa(rtp->them.sin_addr), ntohs(rtp->them.sin_port));
#endif #endif
}
pos += len;
}
} }
return 0; return 0;
} }
@@ -986,6 +948,7 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
struct ast_frame *f; struct ast_frame *f;
int codec; int codec;
int hdrlen = 12; int hdrlen = 12;
int subclass;
/* If we have no peer, return immediately */ /* If we have no peer, return immediately */
@@ -1002,24 +965,27 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
return -1; return -1;
} }
subclass = _f->subclass;
if (_f->frametype == AST_FRAME_VIDEO)
subclass &= ~0x1;
codec = ast_rtp_lookup_code(rtp, 1, _f->subclass); codec = ast_rtp_lookup_code(rtp, 1, subclass);
if (codec < 0) { if (codec < 0) {
ast_log(LOG_WARNING, "Don't know how to send format %d packets with RTP\n", _f->subclass); ast_log(LOG_WARNING, "Don't know how to send format %d packets with RTP\n", _f->subclass);
return -1; return -1;
} }
if (rtp->lasttxformat != _f->subclass) { if (rtp->lasttxformat != subclass) {
/* New format, reset the smoother */ /* New format, reset the smoother */
ast_log(LOG_DEBUG, "Ooh, format changed from %d to %d\n", rtp->lasttxformat, _f->subclass); ast_log(LOG_DEBUG, "Ooh, format changed from %d to %d\n", rtp->lasttxformat, subclass);
rtp->lasttxformat = _f->subclass; rtp->lasttxformat = subclass;
if (rtp->smoother) if (rtp->smoother)
ast_smoother_free(rtp->smoother); ast_smoother_free(rtp->smoother);
rtp->smoother = NULL; rtp->smoother = NULL;
} }
switch(_f->subclass) { switch(subclass) {
case AST_FORMAT_ULAW: case AST_FORMAT_ULAW:
case AST_FORMAT_ALAW: case AST_FORMAT_ALAW:
if (!rtp->smoother) { if (!rtp->smoother) {
@@ -1072,7 +1038,7 @@ int ast_rtp_write(struct ast_rtp *rtp, struct ast_frame *_f)
ast_rtp_raw_write(rtp, f, codec); ast_rtp_raw_write(rtp, f, codec);
break; break;
default: default:
ast_log(LOG_WARNING, "Not sure about sending format %d packets\n", _f->subclass); ast_log(LOG_WARNING, "Not sure about sending format %d packets\n", subclass);
// fall through to... // fall through to...
case AST_FORMAT_H261: case AST_FORMAT_H261:
case AST_FORMAT_H263: case AST_FORMAT_H263: