mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-05 12:16:00 +00:00
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:
@@ -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
2
file.c
@@ -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
90
rtp.c
@@ -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:
|
||||||
|
Reference in New Issue
Block a user