[asterisk-dev] res_fax_spandsp segfaults during fax detection
Michal Rybárik
michal at rybarik.sk
Tue Jan 28 15:31:18 CST 2014
Hi Matthew,
On 01/28/2014 01:00 AM, Matthew Jordan wrote:
> In res_rtp_asterisk, the packet is read from the socket in
> ast_rtp_read. This is also the place where the read data is converted
> into a frame of the appropriate type. The payload for the voice frame
> is obtained in the actual RTP packet itself:
>
> rtp->f.src = "RTP";
> rtp->f.mallocd = 0;
> rtp->f.datalen = res - hdrlen;
> rtp->f.data.ptr = rtp->rawdata + hdrlen + AST_FRIENDLY_OFFSET;
> rtp->f.offset = hdrlen + AST_FRIENDLY_OFFSET;
> rtp->f.seqno = seqno;
>
> Later on, an ast_frdup most likely pulled the frame off of the rtp
> engine and re-malloc'd it; however, this is code that happens all the
> time and wouldn't have perturbed the datalen. Your problem is most
> likely coming from whatever RTP packet was sent to Asterisk. You may
> want to look at a pcap of the message traffic that caused the problem
> to determine what about the packet is causing the issue.
>
> It may be necessary for something either in res_rtp_asterisk or
> res_fax_spandsp to verify that the number of samples in the RTP packet
> (or what the voice frame has in it before it gets handed off) matches
> what is expected.
>
Thank you very much for explanation. I'm not very familiar with RTP
source code, this makes things more clear to me (but there is still lot
of code, which I don't understand). Please be so kind, and look at this:
In my setup, I should have 20ms A-law frames from RTP, and 20ms A-law
frames from DAHDI (alawtosln). With sampling frequency 8000 Hz, I should
have 50 frames per second, and every frame should have (8000/50)=160
samples inside. A-law samples are stored as 16bit integers, so all
samples int he frame should be 320 bytes long.
Now please look at the values, which are stored inside ast_frame
structure. I dump contents of structure in res_fax_spandsp, just before
frame pointer is passed to modem_connect_tones_rx(). Following sequence
of frames is RTP part of a call, just after call was answered:
{ frametype=2, datalen=160, samples=160, mallocd=1, mallocd_hdr_len=562,
offset=64, src=RTP, flags=1, ts=10300, len=20, seqno=55975,
data.ptr=0x82cfcb8 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10320, len=20, seqno=55976,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10340, len=20, seqno=55977,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10360, len=20, seqno=55978,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10380, len=20, seqno=55979,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10400, len=20, seqno=55980,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10420, len=20, seqno=55981,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10440, len=20, seqno=55982,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10460, len=20, seqno=55983,
data.ptr=0xb54013c0 }
{ frametype=2, datalen=160, samples=160, mallocd=0, mallocd_hdr_len=0,
offset=76, src=RTP, flags=1, ts=10480, len=20, seqno=55984,
data.ptr=0xb54013c0 }
And now, look at the A-law frames coming from DAHDI:
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
{ frametype=2, datalen=320, samples=160, mallocd=1, mallocd_hdr_len=722,
offset=64, src=alawtolin, flags=0, ts=0, len=0, seqno=0,
data.ptr=0x84d1138 }
In file include/asterisk/frame.h there is struct ast_frame defined, and
I see that:
int datalen; /*! Length of data */
int samples; /*! Number of samples in this frame */
int mallocd; /*! Was the data malloc'd? i.e.
should we free it when we discard the frame? */
I think that if in both cases we have A-law samples, we have also 320
bytes of data in both cases, and so we should have "datalen" set to 320
in both cases. But for RTP frames, "datalen" is set to 160. It is
impossible to store 320 bytes into 160bytes space. Datalen should be 320
also for RTP frame. "Datalen" is set probably somewehere in frame.c, I
don't know yet where it is exactly (for this frame). But I see in
frame.c that "datalen" and also "samples" are used when allocating
memory and copying data, and if have bad value there, I expect that bad
things may happen. I think this could be the problem what we are looking
for, but maybe I am completely wrong... I'm not sure. What do you think?
Also I don't understand other difference. Frames coming from DAHDI has
mallocd=1 and data.ptr points always to the same address, for all
frames. But frames from RTP are different - first frame (which sometimes
causes segfault) has very different data.ptr address, and has mallocd=1.
Next RTP frames has mallocd=0, and data.ptr is now different as at the
first frame, but remains the same for all next frames. Is it the correct
behavior, or is there something wrong? Why first RTP frame in the call
is stored on the other memory address, than all other RTP frames?
Thank you very much
--
Michal Rybarik
More information about the asterisk-dev
mailing list