首页 > 代码库 > 【转】Extending Lync Server routing with MSPL
【转】Extending Lync Server routing with MSPL
【原文地址:http://blog.greenl.ee/2011/07/08/extending-lync-server-routing-with-mspl-part-1/】
Recently I’ve taken a number of questions about customizing the routing of messages in Lync Server, which is possible with the Lync Server 2010 SDK. Since most of the how-to material out there is about either UCMA or the Lync 2010 (client) SDK, I thought I would write up a few articles on the basics of what you can do with the Lync Server 2010 SDK, and particularly with Microsoft SIP Processing Language, a.k.a. MSPL.
I’ll start by explaining a bit about the SDK: what it is, what you can do with it, and how it differs from the other ones that are available for Lync.
At a high level, there are three elements to the Lync Server SDK:
- Application manifest files
- Microsoft SIP Processing Language (MSPL)
- Managed SIP Application API
Application manifest files are XML files that give Lync Server details on an application it should load when starting up. They are stored on the server where Lync Server is running, and have a .am extension (short for “application manifest”).
Microsoft SIP Processing Language, or MSPL, is a scripting language that you can use to customize how Lync Server handles and routes SIP messages. Unlike UCMA applications, MSPL scripts run in the context of the Lync Server process itself, so they can intercept messages between users, filter messages, reroute messages, and so forth. Also, again unlike UCMA applications, they don’t run as a separate process, nor do they create endpoints of their own. Consequently, they aren’t limited to controlling messages to and from a single endpoint, like UCMA applications.
Here are a couple diagrams to illustrate the differences. First, here’s a UCMA application:
The application runs on a separate server from Lync Server, and creates an endpoint which communicates with other Lync endpoints via the Lync Front End Server. This means that it can participate in and control a conversation between, for instance, Endpoint 2 and itself, but it can’t do anything with a conversation between Endpoint 2 and Endpoint 3.
The MSPL script, by contrast, simply modifies the behavior of the Lync Server Front End. It has visibility to and control over every message that is proxied through the Front End Server, regardless of where it comes from or where it goes.
The MSPL code itself is included directly in the application manifest.
The concept is basically the same for the Managed SIP Application API. With this API, you can write managed code to manipulate SIP messages, instead of using MSPL. This opens up many more possibilities for things like data storage and complex message modifications, but there are many more performance and scalability issues to consider.
Let’s take a look at a very simple MSPL script. Now, since the MSPL script goes inside an application manifest, the first step is to create the manifest file, which we can call Simple.am.
The application manifest is an ordinary XML file. You can edit it in Visual Studio, or in another text editor; it doesn’t make much difference since there is no Intellisense available. At the very beginning of the manifest file, along with the xml declaration, is the root element, <lc:applicationManifest>. The only thing you need to change in here is the appUri attribute, which is basically a unique identifier for your application. You’ll need this later in order to install the application.
<?xml version="1.0" ?><lc:applicationManifest appUri="http://blog.greenl.ee/Application" xmlns:lc="http://schemas.microsoft.com/lcs/2006/05">
Next, we can specify what types of messages this application should handle, using the <lc:requestFilter> and <lc:responseFilter> elements. As you might have guessed, these control the types of requests and responses, respectively, that are passed through the application. Here’s an example of a <lc:requestFilter> element:
<lc:requestFilter methodNames="ALL" strictRoute="false" registrarGenerated="true" domainSupported="true"/ >
The methodNames attribute can have one of the following:
- ALL
- NONE
- a list of SIP method names separated by commas
The strictRoute attribute, which defaults to false, controls whether the application sees requests for which explicit routing details have already been specified. If this is set to true, these messages that have a “strict” route will also go through the application.
There are a few other attributes that can go in this element, but I’ll skip them for now since they are not necessary for most situations.
The <lc:responseFilter> element works similarly:
<lc:responseFilter reasonCodes="ALL" />
The reasonCodes attribute holds a comma-delimited list of SIP response codes, or ALL, or NONE.
Another important setting is controlled by the <lc:proxyByDefault> element, which looks like this:
<lc:proxyByDefault action="false" />
If this is set to false, any messages that are not proxied, responded to, or otherwise handled by the application are simply dropped. If it’s true, messages that are not handled are proxied to their destination by Lync Server, just as they would were the application not installed.
Since this application will consist only of an MSPL script, and will not use any managed code, we can add the following element as well:
<lc:scriptOnly />
So here’s what the manifest looks like now, with those elements added:
<?xml version="1.0" ?><lc:applicationManifest appUri="http://blog.greenl.ee/Application" xmlns:lc="http://schemas.microsoft.com/lcs/2006/05"><lc:requestFilter methodNames="ALL" strictRoute="false" registrarGenerated="true" domainSupported="true"/ ><lc:responseFilter reasonCodes="ALL" /><lc:proxyByDefault action="false" /><lc:scriptOnly />
We have an application manifest, but now we need to add the script. The MSPL script is included in the manifest within the <lc:splScript> element, like so:
<lc:splScript> <![CDATA[ /* script goes here */ ]]></lc:splScript>
Besides lacking Intellisense and compile-time syntax checks (since the script is not compiled), MSPL is not that difficult to write. The syntax looks more or less like a pared-down version of C#. While I can’t possibly cover everything you can do with MSPL in this post, I’ll go over some of the basics, and leave the rest to future posts. You can also find the full documentation on MSDN at http://msdn.microsoft.com/en-us/library/gg425301.aspx.
To start, most scripts will need to access the message. The sipMessage variable provides access to a class that contains the message details. However, in many cases, the application’s behavior will depend on whether it is handling a request or a response; and the data available will depend on which type of message it is. The application can use something like the following to do this:
if (sipRequest) { /* do something */}if (sipResponse) { /* do something else */}
It can then look at the properties on the request or response and take action appropriately. Here’s an example that blocks all messages from a certain SIP URI:
if (sipRequest) { if (ContainsString(sipRequest.From, "sip:disgruntled_employee@ourcompany.biz", true)) { Log("Debugr", false, "Blocked message to ", sipRequest.To); Respond(403, "Forbidden"); }}
What we’re doing here is looking at the From header on the SIP request, checking to see whether it contains a particular SIP header (the true in the third parameter tells the function to ignore case), and if there is a match, responding with a 403 Forbidden response. Because we have proxyByDefault set to true, any other request will simply be proxied by Lync Server as usual.
If we changed proxyByDefault to false, we’d need to add a bit of code:
if (sipRequest) { if (ContainsString(sipRequest.From, "sip:disgruntled_employee@ourcompany.biz", true)) { Log("Debugr", false, "Blocked message to ", sipRequest.To); Respond(403, "Forbidden"); } else { ProxyRequest(); }}
ProxyRequest tells Lync to go ahead and proxy the request as it normally would. You can also (as long as the message does not have a strict route, as described above) add a string parameter to ProxyRequest, which tells Lync specifically where to send the message. One possible reason you might do this is if you want to send certain requests to a PBX, a UCMA application, or some other specific destination.
There is also a ProxyResponse method, which does the same thing with responses. It can’t take any parameters since the response always goes back to where the request came from.
The Log method allows you to write messages to the log while your script is running. The first parameter must be “Event”, “Error”, or “Debugr”. The r in Debugr is not a typo. The second parameter can be true (to log the entire message except the Content) or false to log only some basic details. Finally, you can specify as many string parameters as you want to add notes to the log message.
So here’s a complete, although very rudimentary, MSPL script in an application manifest:
<?xml version="1.0" ?><lc:applicationManifest appUri="http://blog.greenl.ee/Application" xmlns:lc="http://schemas.microsoft.com/lcs/2006/05"> <lc:requestFilter methodNames="ALL" strictRoute="false" registrarGenerated="true" domainSupported="true"/ > <lc:responseFilter reasonCodes="ALL" /> <lc:proxyByDefault action="false" /> <lc:scriptOnly /> <lc:splScript><![CDATA[ if (sipRequest) { if (ContainsString(sipRequest.From, "sip:disgruntled_employee@ourcompany.biz", true)) { Log("Debugr", false, "Blocked message to ", sipRequest.To); Respond(403, "Forbidden"); } else { ProxyRequest(); } } ]]></lc:splScript></lc:applicationManifest>
So far, you’ve seen how MSPL works and how to create a very basic MSPL application. There is quite a lot more to learn about MSPL. In my next post, in a few days, I’ll explain how to install the script on Lync Server using the New-CsServerApplication PowerShell command (http://technet.microsoft.com/en-us/library/gg398096.aspx). Meanwhile, if you have specific questions, feel free to comment or send me an email!
【转】Extending Lync Server routing with MSPL