Summary:ASTERISK-21448: New SIP Channel Driver - basic fax support
Reporter:Matt Jordan (mjordan)Labels:Asterisk12 NewSIP
Date Opened:2013-04-16 09:14:33Date Closed:2014-01-06 11:57:16.000-0600
Versions:Frequency of
Description:Ew, fax. :-(

Unfortunately, reality is a harsh mistress, and some level of fax support in {{chan_gulp}} would be nice. This doesn't mean we have to do everything that {{chan_sip}} does, but basic pass-through and store/forward fax support will be needed.

This still entails quite a bit of work. This can be broken down into four 'stages' - although each of these is quite big and will most likely overlap. Normally I'd create this as four issues, but I have a feeling that as one area is worked on other areas will naturally progress - but it still helps to break this up a bit to scope out the work accurately.

h3. Add configuration support for Fax and integrate the UDPTL stack into {{chan_gulp}}

* People need to be able to configure fax support for an endpoint. These may or may not be parameters on the actual endpoint object. At a minimum, the following needs to be configurable:
** Error correction - FEC, redundancy, or none
** T38MaxDatagram - this overrides whatever is offered to a set value. (Needed for compatibility with some devices)
** FaxDetect - CNG and/or T.38. Determines how we bounce out to the {{fax}} extension.
* Add a UDPTL object to the possible channel driver's media objects. This shouldn't be initialized until Asterisk detects that a fax is desired. This occurs either on an inbound INVITE request negotiating T.38; a CNG tone; or a control frame indicating that a fax should start.
* Add the necessary read/write hooks to read/write to the UDPTL stack.

h3. Add CNG detection and {{fax}} extension redirection

This is simpler then all of the T.38 shenanigans, and relatively independent of them. If we're configured to support CNG fax detection, and the DSP detects a CNG, redirect the Asterisk channel to the fax extension.

h3. Parse T.38 parameters/provide T.38 parameters

* If we receive an inbound (re-)INVITE request or a response with T.38 parameters, parse them out and store them as appropriate.
* On outbound INVITE requests, if the inbound call leg already supports T.38 and the endpoint we're communicating with can support fax, then pass the parameters over as appropriate

Note that Asterisk initiating a fax request is handled in the next step...

h3. Implement the T.38 state machine

* Implement a state machine for the T.38 states. The T.38 state machine consists of states that the T.38 negotiation can be in, as well as what the appropriate responses should be. Whenever the state machine changes to a particular state, a {{AST_CONTROL_T38_PARAMETERS}} frame should be queued on the channel. States are:
*** Valid response is AST_T38_REQUEST_NEGOTIATE
*** Valid response is AST_T38_NEGOTIATED
*** Valid response is AST_T38_TERMINATED if previous state was T38_ENABLED
*** Valid response is AST_T38_REFUSED if previous state was T38_LOCAL_REINVITE
*** No response is performed
* Implement a handler for the {{AST_CONTROL_T38_PARAMETERS}} control frame. When we receive such a frame, initialize the UDPTL object if needed. This should handle the processing for each of the T.38 state machine's response codes.
*** Perform error checking and deny if in error, *ELSE*
*** If in state T38_PEER_REINVITE, switch to T38_ENABLED and respond with 200 OK, *ELSE*
*** If not in state T38_ENABLED, send an INVITE request
*** If state is T38_PEER_REINVITE, reject; *ELSE*
*** If state is T38_ENABLED, send re-INVITE
*** Queue up a new control frame with a response type AST_T38_REQUEST_NEGOTIATE

It would be wise to study the T.38 implementation in {{chan_sip}} when tackling this task. While we can all bash {{chan_sip}} for it's peculiarities, T.38 is no joke and trying to perform this task without first understanding how it's been implemented before is bound to cause a lot of heartburn. There's a lot of error detection, off nominal path handling, and other bug fixing that has been done that is not included in this issue, and missing those critical items would be 'bad'.