In previous blog posts on Microsoft SIP Processing Language (MSPL), I’ve explained how to essentially intercept SIP requests, such as the INVITE message that initiates a call, and pass them along to a UCMA application for handling by passing a parameter to the ProxyRequest method. In this post, I want to discuss what you can do if you want to “fork” a request, which means you are sending it to multiple endpoints simultaneously.

Generally, an application forks a request because one of a number of endpoints may need or choose to answer it, and the application doing the routing (in this case, your MSPL script) does not have a way of knowing in advance which one it is. Now, in the vast majority of cases where you would want to fork a request, Lync already takes care of it for you. The routing behavior built into Lync forks new SIP INVITEs sent to a user among all the active endpoints for that user. For load balancing and resiliency, you don’t need to create your own forking behavior; instead, you should create a trusted application pool with multiple computers. However, occasionally you may run into a situation where your MSPL script needs to send a request to multiple endpoints, and let the endpoints themselves decide who accepts.

To fork a request in MSPL, you basically need to replace the call to ProxyRequest (which you would normally use to proxy the message to a single destination) with three things, in order:

BeginFork

Fork (repeated once for each destination)

EndFork

It’s a sort of triple-decker sandwich of Fork commands. Here’s an example of what this looks like:

You’ll notice that the BeginFork command takes two parameters, and you may be wondering what these do. The answer is a mystery; according to the official documentation, both parameters are “reserved,” and they must be set to false and 0, respectively. I haven’t tested to see what happens if you set them to, say, true and 98, and I’m not responsible for any painful consequences if you try it yourself.

You have to call BeginFork first, to start the forking operation. Once you’ve done so, you can then call Fork as many times as you want to, passing in a destination URI each time. In the example above, I’ve used two UCMA application GRUUs.

Last but not least, you need to call EndFork to finish the forking. EndFork does not take any parameters, reserved or otherwise.

As with ProxyRequest, when you fork messages you need to be careful and have at least a general understanding of what you are doing. Usually forking makes the most sense with INVITE requests. What you don’t want to do, for the most part, is fork a message within a SIP dialog that has already been established with the INVITE / 200 OK / ACK handshake. Once the session is established, it’s understood that messages within the session (such as MESSAGE requests that carry IM text) will continue to be routed to the same endpoints, so changing this can lead to some pretty weird reactions. You also shouldn’t be messing with the routing for requests that have a Route header (a so-called “strict route”) pre-defining where the request should go; this is naughty behavior and against the rules, and from what I understand Lync will not allow you to do this in your script.

I’ve only come across a very few cases where forking in an MSPL script was necessary, but in those cases it was the only way to solve the problem. If anyone has any interesting use cases for forking to share, I’d be very curious to hear about them. Feel free to comment also if you have questions about implementation.

10 Comments on “Forking SIP requests in an MSPL script”

Hello Michael,
You wrote that “What you don’t want to do, for the most part, is fork a message within a SIP dialog that has already been established with the INVITE / 200 OK / ACK handshake”. How to determine that “INVITE” message is from established session? By analyzing “Session-Expires” and searching a “refresher” in it?

If you want to exclude re-INVITEs (INVITEs that are sent to renegotiate media in an established session), what I usually do is check the CSEQ header. If the value is greater than 1, it’s a re-INVITE.
Does that answer your question?

I am trying to perform the Fork operation using two sip addresses. I can call each of these addresses through my Lync client fine, but as soon as I try to Fork the message I get an error, “Peer server pool is out of service”.

I am sure I am missing something as I am new to Lync and UCMA, but any help would be appreciated.

8Michael said at 2:08 pm on February 16th, 2014:

Hi Jon,

You can’t fork to an address of record (AOR) like you are trying to do. The destination has to represent a unique endpoint and is the actual location to which the message will be routed (i.e., a request URI).

I was able to figure this out after a few days of experimenting. The key to this was to enable the “IsDefaultRoutingEndpoint” option on the Application Endpoint Settings.

On another note, I attended both of your sessions last week at Lync Conf ’14, and I had 2 requests…

1. Could you please post the code from your “Advanced UCMA” session?
2. You had mentioned during your “MSPL/Routing” session that there were PowerShell commands that you could use to publish your script-only .am file to your frontend server – are you able to provide some guidance on where to find these?