[asterisk-dev] res_fax_spandsp segfaults during fax detection

Pavel Troller patrol at sinus.cz
Tue Jan 28 22:52:49 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

Hi!
 So, wouldn't it be possible that the whole problem occurs, because something
(RTP engine ?) forgets to convert the A-law to linear in some special case?
In such a case, datalen would equal to samples...
  With regards,
    Pavel



More information about the asterisk-dev mailing list