AudioVideoMcuSession.EndTransfer() raises FailureResponseException “400 Bad request”

If your UCMA application tries to transfer an already established PSTN call to conference by invoking AudioVideoMcuSession.EndTransfer() and it receives FailureResponseException with the magical Message property set toA 400 (Bad request) response was received from the network and the operation failed …”  then most probably you are facing the same issue I have spent weeks before.

First of all let me summarize how AudioVideoMcuSession.EndTransfer() works in the background: while transferring an established call to conference UCMA stack sends a SIP INFO message to Lync Front End. This INFO message conveys a C3P request in the body including the SIP address of the remote party on the call you are trying to transfer to the conference. Normally, Front End adds this URI to the focus and then dials out the URI with SIP Replaces header in the INVITE message. Thus Front End replaces the call between the remote party and the UCMA application with a new call between the remote party and the conference focus. Actually, Front End and MCU do a lot of other things but those are completely irrelevant now …

Why does Lync Front End raise this exception?

If you are facing the same issue I was facing before then it is because your UCMA application tries to add a tel URI to the conference focus (you can run OCSLogger on Front End to confirm this) but only SIP URI is allowed. See the document “[MS-CONFBAS]: Centralized Conference Control Protocol: Basic Architecture and Signaling Specification” for more details. It clearly states that the user entity in the C3P xml document must be specified by a SIP URI:

The entity attribute of the user element MUST be a SIP URI

If Front End receives a C3P addUser request with a tel UI in the user entity attribute then it rejects the request with response code 400 ("Bad request") and ms-diagnostics header: "Failed to parse the C3P request".

Why does UCMA application send C3P request with tel URI if it is invalid?

Because it simply picks up the SIP P-Asserted-Identity header from the signalling channel of the PSTN call (or the SIP From header if no P-Asserted-Identity header exists) and uses that in the C3P request when it tries to to transfer the PSTN call to conference .

Why does UCMA application receive tel URI as P-Asserted-Identity on PSTN call?

This is another story …. It would worth its own blog entry. But now let me just say that it is closely related to the way Mediation Server and Front End works together if caller id is not normalized to E.164 on PSTN gateway (more precisely, if plus sign is missing from the beginning of the PSTN caller id digits).

What can I do to overcome this issue?

You can configure PSTN gateway to ensure that PSTN caller ids are always normalized to E.164. However, there are cases when this is simply not possible either because you have no influence on gateway settings or you want to have a solution which leaves other parts of the Lync environment unaffected. In this case you can do the following: change your code to pass McuTransferOptions to AudioVideoMcuSession.BeginTransfer(). Using McuTransferOptions you can tell UCMA what SIP URI you want to appear in conference focus. If it is specified then UCMA uses this URI in the C3P request instead of the URI extracted from SIP signaling of the PSTN call. You can easily construct a SIP URI based on the PSTN caller id (tel URI in our case) you have received.

string pstnUri = pstnCall.RemoteEndpoint.Participant.Uri;

McuTransferOptions mto = new McuTransferOptions();
mto.ParticipantDisplayName = ConstructDisplayNameFromPstnCallerID(pstnUri);
mto.ParticipantUri = ConstructSipUriFromPstnCallerID(pstnUri);

mcu.BeginTransfer(pstnCall, mto, …);

If you use McuTransferOptions then your application will always work regardless how normalization on PSTN gateway is configured.