VoIP Faxing Notes

Large fix size jitter buffer

Don't use echo cancellation

Call starts out in either g711 or g729
Then if the switch hears the cng tones and t.38 is enabled on the mediatrix box, it switches over to t.38
If you are using g729, the switch might not detect the cng tones which is why g711 is better.
The preferred Clear channel codec is only for when t.38 is disabled, and it describes what codec to then use for when cng tones are detected.
T.38 is not a call setup protocol, thus the T.38 devices need to use standard call setup protocols to negotiate the T.38 call, e.g. H.323, SIP & MGCP.
For call waiting to work the user must have the call waiting feature in broadsoft, it must be turned on and call waiting must be enabled on the mediatrix box otherwise it returns a busy signal
Faxes Have to be set to the lowest baud rate 9,600. The default for most of the newer machines is 33,600.


Step 1: Reduce baud rate to 9600 or lowest possible (probably 2400)
Step 2: Disable error correction (ECM)
Step 3: Disable bandwidth saver by dialing *99 (countrycode-areacode-number)

The call path is a little confusing (why is there an INVITE from
196.38.232.2 -> 192.168.0.14 and then an INVITE back to the latter from
the former?), but the basic problem seems to be that you the default
voice codec set to G.729A.  This would explain why "training failed."

The way that T.38 setup works - at least, in the Cisco voice gateway
world - is that the call is first established using a voice codec.  The
DSPs on the receiving gateway analyze the acoustic content of the audio
stream for fax tones and/or modem preambles ("listen").  If they are
detected, the receiving gateway issues a re-INVITE and requests a switch
to T.38 in its new SDP offer.

In order for this to happen, the frequency response of the codec must be
sufficient to reconstruct the clear-channel PCM content of the bearer
channel.  This is only possible with G.711u/A, which is little more than
a packetised form of clear-channel 8 KHz PCM that carries the 3.1 KHz
(300 Hz to 3400 Hz) bearer spectrum of a digital DS0 and/or a
modem-grade analog line.

G.729A is a codec that uses some advanced compression techniques relying
on CELP (Code Excited Linear Prediction).  Like many other compression
schemes, it also shrinks the size of the data by referring via shorthand
to elements of a waveform table/model that approximate the quantised
value of a sample, but do not EQUAL it.  It's good enough for voice that
humans don't see too much of a difference vs. clear-channel PCM, but for
any sort of scheme reliant on the encoding of digital data into the
acoustic content of the bearer, it will positively not work.

As a result, G.729A cannot be used for either the conveyance or
detection of fax tones.  You need to switch this call to G.711u or
G.711A (in Cisco, "g711ulaw" or "g711alaw") before the appropriate
exchange can take place.  Hopefully, that should be all that is
necessary to effect a switch to T.38.  Make sure the default audio codec
for the call is G.711u/A END-TO-END (in all VoIP legs), so that no
transcoding to/from G.729A occurs anywhere.

Of course, there are a variety of other issues that can be brought to
bear on this scenario, but try that and see how it plays out.  One thing
at a time.

Vlans with Linksys SRW224G4P & Non-Cisco Router

Configuring the linksys switch to work with a non-cisco router was a bit of a pain. By default, all cisco interfaces are in vlan pvid 1, the native vlan and the packets are untagged. In order to separate the voice and data on my network, I set up two vlans on my router. VlanID 2 192.168.16.x  is used for voice and VlanID 3 192.168.15.x is used for data. I then configured one of the router's four switch ports to use 802.1Q tagging and enable both vlans on that port.

Each port on the linksys switch must be in one of the following three modes. Access is the default:

General — The port belongs to VLANs, and each VLAN is user-defined as tagged or
untagged (full 802.1Q mode).
– Access — The port belongs to a single untagged VLAN. When a port is in Access mode, the
packet types which are accepted on the port (packet type) cannot be designated. It is also not
possible to enable/disable ingress filtering on an access port.
– Trunk — The port belongs to VLANs in which all ports are tagged (except for an optional
single native VLAN).

To get the switch to work with my router, I first created two vlans to match those on my router.   I then made vlan 3 the management vlan for the switch and gave it an address on the 192.168.15.x network. I then designated port 24 (although you can use any port) to be my trunk port between the linksys switch and my router and to the switch to tag both vlans across that port. I then set the pvid to all of the other ports (1-23) to be 3. The PVID is the default vlan for which vlan traffic will be untagged on the port. Finally I set ports 1-23 to be in general mode, told them to exclude vlan 1, tag vlan 2, and leave vlan 3 untagged.

I then configured my phones to use vlan2 and gave them a 192.168.16.x address. Now any port on the linksys can be used for a phone or a computer, and the pc port on the back of cisco 7940's will also work.

In retrospect I realize I could have only created one additional vlan on the linksys switch and used the native vlan as my data vlan but this took me a little bit of playing around with to find where to configure everything in the gui, and it wasn't worth changing when I got it working.

Using PHP to Access Broadworks over SOAP

First off, this topic is embarrassingly under-documented. developer.broadsoft.com was of very little help.  This document was slightly helpful in its explanation regarding the session ID, JSESSIONID  and how a unique connection relates to them but other than that it wasn't much help.  To get this to work I had to download asocisoapclient_rel14.0, figure out how to get it work, then capture its transactions with a broadworks platform using wireshark, then mimic what it did in PHP.

The asoscisoapclient is a valuable tool when attempting to get OCI over SOAP to work. Once you go through the painful process of getting it to work, you can take a capture while its executing and look at the communication between it and the webserver. To get asoscisoapclient to work i had to:
  1. Update JRE to 1.6.x
  2. Make sure the JAVA_HOME environment variable is set to something like "C:\Program Files\Java\jre6" (quotes included). This can be set by right clicking on "My Computer"->Properties->Advanced->Environemnt Variables. Look under system variables and make sure it is there. If it is not, add it. From a command line you can check to make sure it has been set properly by typing echo %JAVA_HOME% and seeing the path displayed. That path must have the java "bin" folder in it.
  3. Download asoscisoapclient
  4. Unzip it
  5. Open asoci soapclient_rel14.0\ASOCISoapClient\ociclient.config
    1. set userId
    2. set password
    3. set url to be http://theserver/webservice/services/ProvisioningService
    4. set runMode = Single
    5. set singleInputFile = input.xml
    6. set singleOutputFile = response.xml
  6.  Open a comand prompt
    1. change directory to where you unzipped the download. cd "C:\Documents and Settings\WIN_USERNAME\My Documents\Downloads\asoci
      soapclient_rel14.0\ASOCISoapClient"
    2. execute startociclient.bat ociclient.config
    3. The program will not be able to authenticate because the request it uses to login (LoginRequest) is depreciated. The LoginRequest14sp4 should now be used. I didn't bother editing and recompiling their code to make this change because I was able to see what I needed to without doing so.
    4. The program will show use the OCI commands but not the SOAP headers.

Now open wireshark, start a capture and execute the program. You should see http/xml packets go across your screen. The important thing that I learned from this is:
  1. What the soap envelope looks like. (I just copied it.)
  2. That unlike the soap envelop, the OCI command must be html encoded.
  3. HTTP POSTs must be used
  4. The server is capable of using HTTP/1.1 even though the program uses HTTP/1.0 because the server responds using the HTTP/1.1 protocol (which is important because it allows for persistent connections)
  5. The SOAPAction: "" header must be defined
Finally, to replicate this in PHP I tried and confirmed that both PEAR's Http_Request class and PHP's extension php_curl.dll will do the trick. Http_Request seemed to be a little neater while curl seemed to be a bit more configurable. I've heard that Http_Request is just a wrapper for curl although I haven't confirmed that. The important thing to remember is to use Http/1.1. If you don't and plan on ...say.. retrieving 1192 user records, your connection will close in the middle of things and you'll get only about the first 30. Another important thing to remember is that all transactions have to be done across the same connection. Just because you have a valid Session ID and JSESSIONID doesn't mean that you can drop the connection and then open up another using the same Sesseion ID and JSESSIONID and pick up where you left off. I've read that a single Session ID and JSESSIONID are valid for hours, maybe even days, so it sounds like the trick is just keeping the connection open. Finally and most importantly understand this... OCI over SOAP is very strict and rigid. The ErrorResponses often times are not helpful and in my case were down right misleading. I kept getting a response that said "REQUEST_TIMEOUT – The OCS, or the Provisioning Server through the
OCS, did not respond in a timely manner; the service may have received a RequestTimeoutException" which according to the little documentation that exists told me to "Verify that the Provisioning Server is running and
Verify that the OCS is communicating with the Provisioning Server". This sent me on a diagnostic tangent wondering if PHP was using multiple HTTP connections during a single script execution, leaving my requests that weren't on the initial connection to timeout. The real problem turned out to be a misplaced "&" in the OCI command. Somewhere in the process of html encoding and decoding the requests it got added where it shouldn't have been and caused about 3 hours of unnecessary, discouraging pain.

I will post my PHP class for accessing the broadworks platform when I finish it up. You can email blake.mckeeby@gmail.com and I can see if I can help although I am definitely no pro at this sort of thing.

Note:
Apparently you can put more than one OCI request inside a SOAP envelope but I haven't tried this yet. It isn't recommended to put more than 15 OCI requests in a single envelope.

Edgemarc Sip Registrion Control

 
When the phone registers it tells the server how long its registration should be good for. If you want the edgemarc to intercept and replace this value, enable and edit the "Softswitch/IP-PBX expires Overides (s)" field. The softswitch then responds to the registration expire value with either what the phone sent of what it is configured for. If you want this value to be overridden enable and edit the  "Phone Expires Override (s)" field. Finally the edgmarc prevents the softswitch from being flooded with registration attempts. The "Rate-Pacing interval (s)" determines how often the edgemarc will allow a phone's registration to be sent through it. 
Note: when the edgemarc was configured as pictued above, summit-broadband said it was seeing reregistrations every 15 seconds excatly.

Summit-broad uses the reregistrations to keep the session alive in their session border controllers.

Edgemarc Keepalive Messages

If you tell the edgemarc to send keepalive messages it sends SIP Option Request "pings" (messages that ask the Sip Server what it is capable of). Some providers like Summit Broadband don't respond to these requests unless a phone is registered. Because the service provider doesn't respond the edgemarc thinks their service is down and goes into local mode. When the edgemarc is in local mode it doesn't forward the registration requests from the phone to the provider.

Problem:
If the edgemarc is started and the "Number of missed messages to declare alarm" is reached before the phone sends the registration request, the edgemarc goes to local only mode and the edgemarc will then never leave local only mode because the service provider will not respond to the Sip Option Request "pings"