Forking SIP requests in an MSPL script

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:

[csharp] BeginFork(false, 0); Fork("sip:appserver.domain.local@domain.local;gruu;opaque=srvr:fork:saLA7P02gZi2Ho78Ix_w2AA"); Fork("sip:appserver.domain.local@domain.local;gruu;opaque=srvr:spoon:saLA7P02gZi2Ho78Ix_w2AA"); EndFork(); [/csharp]

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.