[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