Quantcast
Channel: Clarity UC » Unified Communications Web API (UCWA)
Viewing all 16 articles
Browse latest View live

UCWA – Unified Communications Web-pal

$
0
0

I first heard about Unified Communications (UC) when I was investigating Clarity for my initial job interview. I had used Lync at a previous job, but never thought it would be a technology that needed any additional features or coding support as it functioned well enough as a person connector and meeting provider (as the company choose it to replace AT&T conferencing). Writing managed code for it via UCMA can produce some interesting products (shameless plug – Clarity Connect). Boiling down the technology to a few key points it has: people, audio, video, and connector pieces that join those people together into a meeting/conference (in my closed exposure to UCMA).

The current API has platform limitations in that to develop a for a non-.NET platform results in creating web services for your clients to connect (OCS and Android, Lync and iOS and Android). While this is can be seen as a common workaround for connecting disparate systems together it can feel like a misstep on the technology provider’s part. If only there is a way Microsoft could create such a service that any platform could access…

Web API and HTTP

During the Build 2012 Building Services for Any Client with ASP.NET Web API session it was hard not to see how Microsoft desires to loop in more platforms and developers with ASP.NET Web API. By designing web service logic as a Web API it means any platform that can talk HTTP will have a method to access your service. The simple case is the web browser: can it create HTTP requests and receive response (sure can…)? Now think of the native platform be it desktop or mobile device and if in its native language create and receive HTTP requests it can interact with a Web API. If only UC would get a taste of Web API…

Lync and UCWA

The demo highlighted the power of Web API with a mini-preview hosted by members of the Lync Server Team starting at 00:02:35 (ending at 00:10:56). The demo included sneak peeks of a Windows Phone 8 Lync application and Lync Web App. Unified Communications Web API (UCWA) is built on top of the ASP.NET Web API meaning each of those demo applications were making the same requests for data with the only differences existing in how the platform needed to interpret that data for UI presentation (I’m grossly over simplifying this…). Prior to UCWA, Lync Web App was a Silverlight application which could pose some limitations on which platforms had access. This is a step forward, but not a complete step as media (audio/video – a crucial piece) was delegated through a plugin. All hope is not lost as technologies like WebRTC may pave the way for plugin-less audio/video.

Even more UCWA act now!

I’ll admit this was not the first time I heard of UCWA… back on August 9th I attended a Lync Developer Roundtable titled: UCWA Overview. The general (vague) timeline for UCWA is that sometime after Lync Server 2013 RTM, UCWA will be released as an update, and with Office 2013 hitting RTM on October 24, it is safe to believe this may be on the calendar for 2013. Their mini-road map also lists additional modalities with planned support VoIP, Video Sharing, and Anonymous Access as part of a Futures. The demo showed off tasks such as getting/setting presence/note as well as instant messaging. The API has 2 channels through which data is sent: Command and Event. The Command channel appears to map directly to the basic HTTP verbs of GET, POST, PUT, and DELETE allowing the application to make a request and receive the response. The Event channel is a bit more complex as the server will be using this to relay events as they happen back to the application (via GET most likely). Resources are the object data received in requests that may a collection of web links (need to retrieve data), embedded resource (data is present), property bag (key value pairs defining the request).

Wait there’s more…

Doing a bit of searching on UCWA brought up a blog post by Matt Landis about Lync Server 2013 and UCWA highlighting UCWA’s features and current limitations. Matt also links to a set of Lync 2013 training videos on UCWA featuring George Durzi, Module 3 to be exact (Using the Unified Communications Web API). George goes through 2 samples: User Presence and Instant Messaging. He launches up a sample site (similar to the previous demo) and shows the task executing as well as covering how the JavaScript achieves the request and shows the request/response in Fiddler traces. The demos shown are more in depth than shown during the Lync Developer Roundtable.

Wrap-up

UCWA could shape up to be an interesting technology going forward, I’m waiting to see how Microsoft will handle audio/video streams without a plugin. From watching both demo series it appears UCWA will play a role in UC-related technologies. While seeing demo videos can be fun it is always better to get your hands dirty in new technology and I asked around a bit as was able to get information on how to get involved with Lync-related technologies (such as UCWA). If you are interested in getting the inside scoop on UCWA before it hits release consider joining the Microsoft Technology Adoption Program (TAP) by contacting LyncISV@microsoft.com.

UCWA Related Links


UCWA – It’s here and you should be too

$
0
0

After many months of hit/miss details on UCWA (Unified Communications Web-API) it is finally time to start creating with UCWA. With the Lync 2013 Conference in the recent past, there have been small glimpses of UCWA sprinkled throughout demos for the lucky attendees some during sessions and for the casual speculator during the Opening Keynote itself. I say speculation as you would need to corner a Lync Team member or two and get confirmation (good luck with this one…). In reality it is highly possibly that a good portion of Lync now or going forward will be UCWA-based. Its reach has the potential to be far greater than a platform-dedicated API such as UCMA (quick note: UCMA is not going away). Enough with the casual speculation, UCWA enables Lync capabilities on any device and with UCWA the designer/developers are free to present Lync in a paradigm-appropriate fashion.

UC-What-API?

No time to explain, read these: UCWA – Unified Communications Web-pal and What is Lync UCWA API

What can I do right now…

You should stop reading right this second and point your favorite web-browsing device to the Lync Web Developer Site and check out the Interactive Demo if you missed it at the conference or jump right into Code. A side-task could be bugging IT to upgrade to Lync Server 2013 CU1 (this is where UCWA arrived): Email. Read this MSDN Forum Topic for an additional step in UCWA deployment.

If you are interested in jumping right into code, make sure to download the UCWA Helper Libraries.

If you want a more advanced look at what is going on look at the network traffic in Fiddler or your favorite browser-based debugging tools while viewing the Interactive Demo. From a raw-HTTP standpoint those are the commands that is making all that UCWA magic. Before jumping the gun and hand-crafting URLs and web-requests it would be good to dive into the documentation specifically Hypermedia.

Using those OAuth Tokens

If you had a chance to step through the demo above you are mere web requests away from creating a UCWA application. The typical process of UCWA starts with AutoDiscovery, Authentication, Creating Application, and Log-in. With the OAuth Tokens technically we can skip to Creating Application, but without some important links it is impossible to create an application and in general it is bad practice to hard-code links as per the principles of Hypermedia. For a quick-start check out KeyTask – Create an Application and think of replacing contoso.com with gotuc.net for the initial Auto-discovery step:

Compare that with the response found on the key task page (highlighted below) shows the slight differences making it difficult to depend on hard-coded links:

Continuing on with key task by jumping to step 7, since 3 OAuth Tokens are already available, it is possible to attach one into an Authorization header as such:

Once you have reached the end of the key task you should have a response similar to:

communication, me, onlineMeeting, people are what can be considered the available Lync capabilities for this application. For more information on these and other resources look at the Dynamic API Graph.

Tools of the trade

With a new technology it is always best to gather a few tools to make learning that much easier.

  • Fiddler – For Windows this is an exceptional web traffic tool. The fun part about it is that it can display the requests being made as well as allow a mechanism for hand-crafting requests (when the need arises). I’ve also have planned a Fiddler Inspector specifically for UCWA development and hope to do a follow-up post containing the goodies and usage.
  • Web Debugging – The most modern browsers have developer tools built-in (F-12/Menus) or expanded via add-ons (FireBug) and they are pretty solid when it comes to needing to debug html/JS/Net traffic.

Check out Tracing and Debugging Tools for Browser-Based Applications for more details on debugging.

What’s next

There is so much more UCWA concepts and ideas that I plan on elaborating in the coming days with the possibility of a sample application to demonstrate the key concepts of UCWA. In the interim read up on the documentation, play around with Fiddler, and wait patiently for the upcoming UCWA Developer Roundtable later this month or early next.

UCWA – Troubleshooting the Launch

$
0
0

It has been a week since the launch of UCWA at http://ucwa.lync.com and users have run into a few minor issues in getting up and running. The purpose of this post is to give a an overview of how to debug through these issues and provide detailed information to UCWA Forum questions. Debugging UCWA has two distinct routes: Network Traffic and JavaScript (or other languages making web requests). The best tools I have found to achieve this in a PC environment is Fiddler2 paired with a online hosting tool (ala Dropbox) for network traffic. JavaScript will be covered later!

Fiddler2

Fiddler2 and web-traffic debugging go hand in hand especially since Fiddler2 can decrypt HTTPS traffic (most of UCWA). Fiddler2 by default will attempt to read all web traffic from all processes which can be a bit overwhelming and unnecessary. It is possible to limit it by choosing Web Browsers in the lower right as seen below:

Another neat feature of fiddler is specifically targeting a process by clicking and dragging Any Process as seen in the two pictures below:

Once the correct filtering is in place it is easy to capture network traffic and capturing can be started/stopped by pressing F-12. Once the network traffic has been capture it is possible to save the session data for later debugging or sharing with other users. A sample Fiddler2 Archive (.saz) can be loaded up a viewed by selecting a specific call and browsing headers, JSON, raw for both requests and responses. It is a good idea to filter out requests from any saved archive that contain sensitive information such as usernames and passwords. The simple route is to directly delete that web request from the archive prior to saving. Subsequent requests with OAuth Tokens (Authorization Headers) can still be considered somewhat sensitive, but the lifetime of an OAuth Token is ~8 hours.

Hosting Fiddler2 Traces

I’m not sure I have a great answer to this question, but temporarily Dropbox is sufficient. I know there are many hosting options available and don’t really care want to invest the time arguing for one over another. The point of hosting these traces online is to prevent posting walls of text when asking a question when possible. Also as the complexity of a UCWA application increases it becomes more important to capture network traffic in order to understand what occurred when the first sign(s) trouble manifested.

Update to CU1 Already…

If you have not upgraded to CU1 I’m not sure how you intended to develop with UCWA. Also take the time to run the bootstrapper in the Lync Server Management Shell.

Issue #1: Service does not allow a cross domain request from this origin.

The hosting location needs to be added to the Lync Server’s white-list as described in ITAdmin-Configuration. As stated in the article it is imperative that the domain matches the expected domain and as such http://localhost:1234 != http://localhost. After your specified hosting location has been added to the white-list it can be checked by using a simple Fiddler2 trace with minor modifications. Open the Fiddler2 trace and drag the second request (403 response) into the Composer tab as this will copy that requests data. At this point you will want to change the request to point to your specific Lync Server (https://lyncdiscover.mydomain.com/) and change Request Headers value of X-Ms-Origin to the correct hosting domain (be sure to include port number!):

Issue the request after making the modifications and check the Response to see if it resulted in a 200 (OK) or 403 with an X-Ms-dianostics header. If you receive another 403 you should verify in the hosting environment (IIS, Apache, etc) and check the port against what is stored in the white-list (Get-CsWebServiceConfiguration | select CrossDomainAuthorizationList).

Follow Up

As more issues arise I will attempt to highlight debugging solutions and continue providing suggestions and information on the UCWA Forum. I will also provide more Fiddler2 traces when they are relevant to the issue/debugging.

UCWA – Fiddler and Firefox

$
0
0

Using Fiddler2 to decrypt HTTPS traffic aids in determining what responses are received from various requests. One thing I have noticed while debugging in Firefox with Fiddler2 active is the initial Autodiscovery fails (trace) rather rapidly and all I can see in the trace is a CONNECT request to http://lyncdiscover.domain.com:443. First off, it is good to verify that Fiddler2 is setup to decrypt HTTPS traffic, but not Ignore server certificate errors as seen below:

Fiddler2 is acting as a man in the middle of the HTTPS conversation and presenting the response decrypted and it achieves this by installing a Root Certificate. I’ve noticed most browsers do not have a security problem with Fiddler2′s Root certificate with the exception of Firefox.

To fix up Autodiscovery it is possible that two security exceptions will need to be added depending on the Lync Server configuration. To achieve this in Firefox navigate Tools -> Options -> Advanced -> Encryption tab -> View Certificates -> Servers tab and choose Add Exception.

Based on Lync Server configuration it is possible that Autodiscovery exposes an internal location (lyncdiscoverinternal.domain.com) and/or an external location (lyncdiscover.domain.com). Test out both address types to see which exist and add the appropriate exception. Each exception will be stored under DO_NO_TRUST (Fiddler2 certificate) as shown below for gotuc.net:

At this point it is possible to re-test Autodiscovery and track how far Firefox can get before the next hurdle. The hurdle (trace) in the case of gotuc.net is that Autodiscovery changes domain from lyncdiscover.gotuc.net to ocsrp.gotuc.net. This can be seen by viewing a Fiddler2 trace after Autodiscovery and see the CONNECT request against http://ocsrp.gotuc.net:443. Adding another exception for this domain should enable Firefox and Fiddler2 to play nice while debugging network traffic.

This process can be repeated for any domains where you plan on testing UCWA with Firefox and Fiddler2. It should be noted that the Autodiscovery process should be similar on each Lync Server 2013 system (with CU1), but the domain returned by Autodiscovery can vary due to Lync Server configurations. In the case of gotuc.net it is http://ocsrp.gotuc.net where as a few other domains I have poked at have varied from http://lync.domain.com to http://lync2k13.domain.com (so no hard-coding links…).

Happy Debugging…

UCWA – Issue #2 Help my browser wants to download /xframe

$
0
0

A fair number of developers have run into an issue while attempting to run the samples (contained in the UCWA Helper Libraries). Originally I thought it might have been something quirky about the setup I have locally as I already had IIS setup with a MIME type for .json. After further examination I found the root cause to be a missed step in the enabling of UCWA on a Lync Server 2013.

Quick Install Guide

  1. Upgrade to CU1
  2. Read ITAdmin-Configuration and for your sanity run bootstrapper!
  3. Determine what domain you plan on hosting samples and put it on the allowed list (previous ITAdmin-Configuration link provides steps)
  4. Host the samples / UCWA code and test it out

But I’ve done all that…

If you believe you have done all of the above and it is still not working it is time to jump into some web requests. A normal request on a Lync Server 2013 (with CU1) to https://lyncdiscover.domain.com/xframe (or https://lyncdiscoverinternal.domain.com/xframe depends on configuration…) should yield the result below:

In the case where bootstrapper was not run you may see results similar to the following:

One of the neat things to note about this server state is that any request to https://lyncdiscover.domain.com/xx will return application/json and this conflicts with the text/html request resulting in a 406 (Not Acceptable). What running bootstrapper after upgrading to CU1 achieves is enabling IIS routing rules to allow the download of /xframe instead of a redirect. If all goes well the request should result in the /xframe html downloaded and you can continue running the samples.

UCWA – Obscuring confidential data in Fiddler traces

$
0
0

When posting Fiddler traces online it can be hard to avoid sharing confidential information. To get a better piece of mind in the security of confidential data it may be necessary to obscure parts of the data shared online or in demo situations. A few quick ways that come to mind are taking a screenshot of the Fiddler trace and manually blacking (or removing) portions,

posting an edited raw version of the HTTP command,

POST https://lync.domain.com/webticket/oauthtoken HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded;charset='utf-8'
X-Ms-Origin: http://domain.com
X-Requested-With: XMLHttpRequest
Referer: https://lync.domain.com/Autodiscover/XFrame/XFrame.html
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: lync.domain.com
Content-Length: 73
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
Authorization: NTLM user_ntlm_token

grant_type=password&username=shagman@domain.com&password=**************

or sharing nothing at all (most secure, but least useful when trying to get support). I have spent a good deal of thinking on how to achieve this in Fiddler and came up with a solution that allows an obscuring of data for sessions that prompts for saving the result leaving the original sessions unmodified. This magic is achieved with the help of FiddlerScript (part of Fiddler) and use of the Fiddler Google Group.

FiddlerScript

FiddlerScript is an extension to Fiddler using JScript allowing it to be edited and applied without re-launching the application. It is also possible to Extend FiddlerScript with .NET, but I went for the route of creating a few JScript functions to provide methods for obscuring Fiddler traces.

Quick Requirements

Before I get too far into this, I may as well state that in order to make use of the FiddlerScript it is necessary to be using one of the following versions (or later) of Fiddler: v2.4.3.6 beta (.NET 2.x) or v4.4.3.0 beta (.NET 4.x).

Editing FiddlerScript

Getting to FiddlerScript from inside Fiddler is as simple as Ctrl+R or Rules -> Customize Rules…

Each time you Save in the Fiddler2 ScriptEditor it either reports errors (via a MessageBox) or loads the new features. In the case of what I wanted to achieve with obscuring it was to add a contextual menu item, Obscure Selected Sessions, and a menu item (found in the Tools menu under Hosts… / Reset Script), Obscure All Sessions. To add a contextual menu item and menu item it is as simple as:

public static ContextAction("Obscure Selected Sessions")
function DoObscureSelected(...)

public static ToolsAction("Obscure All Sessions")
function DoObscureAll()

The logic of the script prompts the user (yes/no) about obscuring sessions and in the case of a yes it will begin processing sessions. In each of the functions the script will iterate over the sessions and make necessary changes and in the case of this script the changes are as follows:

  • Host – Change host name to domain.com
  • Request
    • Replace domain in the following headers: Referer, X-Ms-Origin, Host, and WWW-Authenticate with domain.com
    • Replace Authorization header with Bearer cwt=user_oauth_token
    • Replace password in grant_type=password with **************
    • Replace domain in Body with domain.com
  • Response
    • Replace X-MS-Server-fqdn header with fqdn.domain.com
    • Replace Set-Cookie header with cwt_user_cookie
    • Replace Authorization header with domain.com or NTLM user_ntlm_token
    • Replace access_token (body data) with cwt=user_ouath_token
    • Replace domain in Body with domain.com

After completing the loop iterations the script will attempt to save the now obscured sessions to a file, which can be loaded to see the changes that were made, leaving the original sessions preserved. I have done a bit of testing to see that ~90% of the domain-specific-data is obscured, but there may be cases where it misses a piece. It does not obscure user names as I didn’t really see a good use case for it. If all users became users@domain.com it would be near impossible to determine which user was actually performing an action (in the trace).

Before and After

A quick dog and pony show of modifications to expect:

Request Headers Before

Request Headers After

Response Body Before

Response Body After

Just give me the code already…

I have placed the code online here: Fiddler2 Obscure.js. It contains 5 methods that need to be pasted into the Fiddler ScriptEditor. In my instance I pasted the code below the definition of DoRemoveEncoding(…)

Save (Ctrl+S) in the editor and with luck you should have no errors. If you do you will want to upgrade to a later version of Fiddler with the alternative learning some JScript!

UCWA by the numbers – #1 Autodiscovery

$
0
0

With most UCWA applications you have to start somewhere and where better to start than Autodiscovery (or AutoDiscovery). By contacting the Autodiscover service in your Lync Server topology, it is possible to locate the user and xframe hrefs which are needed to begin the initial steps of UCWA. Depending on the Lync Server 2013 setup it is possible to see the Autodiscover service from a few locations:

  • http://lyncdiscoverinternal.domain.com
  • https://lyncdiscoverinternal.domain.com
  • http://lyncdiscover.domain.com
  • https://lyncdiscover.domain.com

In most typical setups you can ignore the http variants leaving just https://lyncdiscoverinternal.domain.com (internal) and https://lyncdiscover.domain.com (external). The general idea being try the internal location first (in the event that the application is running within the hosted environment) with a fallback the external location. A typical successful response appears as follows:

user

The user href leads to Authentication (which is a topic for another time) in the response headers that are returned on a request as follows:

Reading the WWW-Authenticate headers it is possible to determine that the previous Lync Server has an OAuth Token service at https://lync.domain.com/WebTicket/oauthtoken supporting the following grant types: urn:microsoft.rtc:windows (Windows Login), urn:microsoft.rtc:anonmeeting, and password.

xframe

The xframe href leads to XFrame which is the conduit for cross-domain requests. The general intention is to embedded this into the Html page via an iframe and this can be achieved using the UCWA Helper libraries, specifically Transport.js -> injectFrame(…). Once the iframe is properly loaded making cross-domain requests is much simpler using Transport.js. A savvy user from creating their own stringified Json and doing a postMessage directly on the iframe, but it would require handling the onmessage for the host page.

One more thing…

If you happen to be doing Autodiscovery and run into a response that looks like the following:

You should really upgrade to Lync Server 2013 CU1!

Next up

Next in line is a look at Authentication including how to use each grant type.

UCWA by the numbers – #2 Authentication

$
0
0

After Autodiscovery the next step in UCWA is Authentication. In UCWA Authentication has a few possible routes based on grant type:

  • urn:microsoft.rtc:windows – windows-based credentials
  • password – typical user name and password
  • urn:microsoft.rtc:anonmeeting – anonymous meeting join
  • urn:microsoft.rtc:passive – ADFS / two-factor authentication

Documentation on Authentication can be found on the Lync Web Developer Portal at GettingStarted-Authentication

To see which grant types are available it is possible to make a request on the user href from Autodiscovery to get a 401 (Unauthorized) containing WWW-Authenticate headers listing possible grant types:

In this case the WWW-Authenticate header lists the MsRtcOAuth service at https://lync.domain.com/WebTicket/oauthtoken and supports urn:microsoft.rtc:windows, urn:microsoft.rtc:anonmeeting, and password.

urn:microsoft.rtc:windows

This type of authentication will use IWA, Integrated Windows Authentication, which can be thought of as the familiar Windows Login prompt. On a Windows system that is authenticated on the same domain as a Lync Server it is possible (browser depending) that the dialog box will not show up and credentials will magically flow through to UCWA. This can sometime be a pain when you want to control the user that is logging in.

To see this grant type in action by using the UCWA helper libraries and hosting them in your favorite web server (IIS/Apache) assuming you have it on the allowed list! Browse to the samples and choose My own topology and provide the Sign-in Address and attempt to login.

Sample Trace

password

This type of authentication provides more control over who is logging in, but requires user name and password sent. It functions similar to urn:microsoft.rtc:windows with the except of requiring user name and password in the request.

To see this grant type in action by using the UCWA helper libraries and hosting them in your favorite web server (IIS/Apache) assuming you have it on the allowed list! Browse to the samples and choose My own topology and provide the Sign-in Address and Password and attempt to login.

Sample Trace

Shared code

Both urn:microsoft.rtc:windows and password grant types follow the same next steps in authentication:

  • Make a GET request on user href from initial Autodiscovery with new OAuth token
  • Make a POST request on applications href with userAgent, endpointId, culture
  • Make a GET request on makeMeAvailable href with SupportedModalities (Messaging)
  • Make a GET request on applications href to get updated capabilities

Sample Trace

urn:microsoft.rtc:anonmeeting

This type of authentication provides a mechanism for anonymous users to join online meetings with authenticated users. The first step is acquiring a meeting Uri and the easiest way I have found is to start a Meet Now via the settings wheel in the Lync 2013 Client. Once the meeting has loaded up, click the ellipses in the lower right choosing Meeting Entry Info and click Copy All Info. Paste this information into a text editor and grab the meeting href which should look like: https://meet.domain.com/user_name/unique_id.

The idea is to take this information and constructor a meeting Uri for anonymous authentication in the form of: grant_type=urn:microsoft.rtc:anonmeeting&password=unique_id&
ms_rtc_conferenceuri=sip:user_name@domain.com;gruu;opaque=app:conf:focus:id:unique_id

After successfully authenticating using the anonymous meeting grant type the follow steps are recommended:

  • Make a GET request on user href from initial Autodiscovery with new OAuth token
  • Make a POST request on applications href with userAgent, endpointId, culture
  • Make a GET request on applications href to get capabilities
  • Make a GET request on events href to start listening to events (messaging at the very least)
  • Make a POST request on joinOnlineMeeting href with anonymousDisplayName and onlineMeetingUri
  • In the first burst of event data you will see a messaging event with a state of Disconnected and you can make a POST request on addMessaging href with operationId to enable the messaging modality

Sample Trace

urn:microsoft.rtc:passive

I cannot speak much to this grant type as it is not enable in the environment I test with.

Bugs

I found 2 bugs in the FiddlerScript I wrote a few posts back (UCWA – Obscuring confidential data in Fiddler traces). I had not handled any Windows-based Authentication in UCWA for awhile and thus did not have any traces locally where I would see headers containing an NTLM token. Now checks are in place to check the Authorization header (requests) and WWW-Authenticate header (responses) and replace the value with “NTLM user_ntlm_token”.

The second bug related to Request Urls and not checking to see if they contained a domain that could be obscured. If you look at the user href it will be something like: https://lync.domain.com/Autodiscover/AutodiscoverService.svc/root?originalDomain=domain.com. In the response data this was handled properly, but not in when it came to the Request Url (oops!).

In any sense both have been addressed and the update can be found here: Fiddler2 Obscure

Next Up

Next in line is a look at Conversation and/or Conferencing.


UCWA by the numbers – #3 Communication

$
0
0

After (with a small detour to makeMeAvailable) UCWA is ready for an important task, Communication and more specifically Conversation and Conferencing. I felt the need to combine discussion on the two topics as it allows me to cover some of the differences that will need to be handled depending on how the UCWA user participates in communication.

Many of these traces were created with the UCWA helper libraries (specifically the Instant Messaging task).

Some base documentation on how to send an outgoing IM can be found at: KeyTasks-Communication-OutgoingIMCall

Two Routes, well really four paths…

Using the umbrella, Communication, to describe Conversation and Conferencing, it is possible to identify the two routes as either incoming or outgoing.

Incoming communication is a scenario where a messagingInvitation or onlineMeetingInvitation will appear in the event channel allowing UCWA to either accept or decline the request similar to below:

Outgoing communication is a scenario where the UCWA user makes a request to startMessaging or startOnlineMeeting. These links can be found under the communication resource as seen below:

This gives the following as a map of communications:

  • Incoming
    • messagingInvitation – Conversation
    • onlineMeetingInvitation – Conference
  • Outgoing
    • startMessaging – Conversation
    • startOnlineMeeting – Conference

messagingInvitation

The messagingInvitation as seen above contains basic information about who invited (messagingInvitation._embedded.from) and a series of links to accept, decline, and view the invite message. Following the accept href will join the user into the Conversation and cause the event channel to propagate more conversation and messaging events.

onlineMeetingInvitation

Similar to a messagingInvitation, an onlineMeetingInvitation contains information about invited, but since it is a conference it also contains conference information (onlineMeetingUri and supported modalities). To join the Conference just follow the accept href, but be warned that unlike a Conversation it will not have messaging as a default modality. Instead the event channel will indicate that messaging is in a Disconnected state:

A POST request on the addMessaging href will add the UCWA user to the messaging modality of the Conference and the event channel will propagate a messaging event with a Connected state. How retrieve these links in the event this information was missed will be described in the following sections.

startMessaging

This is how a UCWA user initiates a messaging Conversation as seen in KeyTasks-Communication-OutgoingIMCall. Starting this process will create a messagingInvitation for the other user (could be UCWA, Lync, etc).

startOnlineMeeting

This is how a UCWA user initiates a Conference and will have to wait until a later time to discuss it further (sadly).

So I’ve joined a Conversation/Conference… now what?

Joining either a Conversation or Conference the event channel with propagate many conversation-related events. The most important (for me at least) is what I tend to call the messaging links which is an event containing sendMessage, setIsTyping, and stopMessaging among others. It should be noted that you will want to see the event containing this data has a state of Connected:

If somehow this information does not show up in the event channel it is possible to start at applications and get to the links as follows:

  1. GET request on the root applications href
  2. GET request on _embedded.communication._links.conversations.href to get the active conversations
  3. GET request on the correct conversation under ._links.conversation
  4. GET request on _links.messaging.href
  5. Cache the important links in the response

Another important link to cache is addParticipant and can be found in event channel data for the conversation or in the above description in step 3 response data. With the set of links it is possible send messages, indicate UCWA user is typing, end the conversation, and add more participants (which may escalate the Conversation to a Conference!).

Sending and Receiving Messages

With the sendMessage href it is possible to POST a message to the conversation/conference and afterwards observe the message hit the event channel:

On the flip side of things, a message event in the event channel may contain a plainMessage encoded as data Url (The “data” URL scheme) which means decoding in some form to turn “href=data:text/plain;charset=utf-8,words+with+spaces” into “words with spaces”:

Are you typing or not?

Using the setIsTyping href it indicates to the conversation/conference that the user is currently typing a message. Some rudimentary testing seems to lean toward the indication being active for about 10-15 seconds before it is no longer displayed. To continuously indicate a user is typing it should make subsequent posts when nearing the 15 second mark. An interesting side is that user typing will not pass through the event channel as a result of making the request on setIsTyping.

When another user is typing the event channel will provide two notifications: the user being added to the list of typing participants and the user being deleted from the list of typing participants.

Is it over yet?

It is possible to end communication by making a POST request on stopMessaging which will trigger event channel data to notify that the user has disconnected any connected modalities (messaging, audio, etc) and deleted from participant/participantMessaging, conversation/conference, and related pieces:

The events seen above can help in understanding what happens when a conversation is terminated: messaging transitions to the disconnected state, localParticipant (Our user) deleted, participantMessaging (Our/other users) deleted and participant (other users) deleted. Tracking participant and participantMessaging for added/deleted can indicate when users are entering/leaving the conversation.

Adding Participants

Making a POST request on addParticipant with the sip of the user to add will trigger a participantInvitation and update to the conversation:

In the event that the conversation has not already been escalated to a Conference the state of the conversation will change to Conferencing and become Conferenced when the user accepts the invitation. As stated above in onlineMeetingInvitation, a UCWA user will see messaging in a Disconnected state and need to make a POST request on addMessaging to participate. In the cases where a Lync Client user is the third user added to the Conversation the preexisting UCWA users will still have valid messaging links.

Wrap-up

Communication in UCWA covers a good portion of the interesting pieces of the API (Conversation and Conferencing) and is typically where event channel processing becomes important. Being able to send/receive messages, indicate typing, invite other users, and stop communication are the basics of chatting in Lync. With these basic it would be rather simple to work toward an anonymous chat client (using the anonymous meeting grant type) assuming access to a service providing meeting Uri(s).

Next Up

I’ll look at incorporating the information from this posting into an anonymous meeting join and visit a topic from Authentication I skipped, renewing OAuth tokens. I’ll plan on providing a full trace and work from there as opposed to all the screenshots this run (mostly due to needing to look at both Conversation and Conference).

UCWA by the numbers – #4 Anonymous Meeting Join

$
0
0

It has been some time since the overview of Communication (Conversation/Conferencing) which gave information on some of the basic tasks: sendMessage, setIsTyping, stopMessaging, and addParticipant. One of the big features of UCWA (as of CU1) is Anonymous Meeting Join as it can provide plugin-less web chat between an authenticated Lync User and a user browsing your website. In this journey through Anonymous Meetings I plan to cover authenticating to UCWA via a meeting Uri, handling some of the more interesting meeting events, and renewing the anonymous user’s OAuth token.

What is a meeting Uri?

To me a meeting Uri appears in two distinctive forms:

  • joinUrl = https://meet.domain.com/user_name/unique_id – This can be found in meetings joined via the Lync Client via Meeting Entry Info -> Meeting Link or contained in a onlineMeeting created in UCWA
  • onlineMeetingUri = user_name@domain.com;gruu;opaque=app:conf:focus:id:unique_id – This can be found in an onlineMeeting created in UCWA

The idea is to take one of these (preferably onlineMeetingUri) and construct the Anonymous Meeting Grant Type (as seen at GettingStarted-Authentication). In the case where you only have a joinUrl bit of extra work is necessary and when crafting code to go along with this topic I created two functions to handle this as follows:

// UcwaObject.js
function determineDomain() {
    var domain = "";

    if(meeting.joinUrl) {
        var temp = meeting.joinUrl.match(/*WordPress hates this regex...*/);

        if(temp.length !== 0) {
            temp = temp[0];

            domain = temp.slice(temp.indexOf(".") + 1);
        }
    }
    else if(meeting.onlineMeetingUri) {
        var temp = meeting.onlineMeetingUri.split("@");

        if(temp.length >= 2) {
            temp = temp[1];

            domain = temp.split(";")[0];
        }
    }

    return domain;
}

obj.prototype.getOnlineMeetingUri = function() {
    if(meeting.onlineMeetingUri) {
        return meeting.onlineMeetingUri;
    }
    else if(meeting.joinUrl) {
        var domain = determineDomain();
        var temp = meeting.joinUrl.split(domain);

        if(temp.length >= 2) {
            temp = temp[1];
            temp = temp.split("/");

            return "sip:" + temp[1] + "@" + domain + ";gruu;opaque=app:conf:focus:id:" + temp[2];
        }
    }
}

WordPress is eating my regex above, but it can be viewed in the UcwaObject.js file later.

It is not defined in the above code but the meeting object can have a joinUrl and/or a onlineMeetingUri. The function determineDomain() will be used first by AutoDiscovery for xframe injection followed by cross-domain messaging. The idea of the function is to pull out the domain portion of either meeting piece either by regex matching (should match https://meet.domain.com above) with trimming or splitting on “@” followed by “;”. The function getOnlineMeetingUri() will either return the meeting object’s onlineMeetingUri or using determineDomain() with splitting to generate an onlineMeetingUri.

Authenticating Anonymously

I’m going to skip over AutoDiscovery as determineDomain() is used to get the domain from the supplied meeting object and it is the same as any other UCWA application. Authentication required a bit of change as the current samples (UCWA helper libraries) do not have a mechanism for handling an Anonymous Meeting Grant Type. By adding additional library variables, modifying the start() method to take and additional parameter, onlineMeetingUri, minor changes to requestAccessToken(), avoiding the request to makeMeAvailable, and exposing a method to get an authorization link (will be used later to renew authentication) it was possible to authenticate to the meeting.

// Authentication.js
...
// Link to the OAuth service
this.authorizationLink = null;
// The link to a meeting to authenticate to
this.onlineMeetingUri = null;
...

obj.prototype.start = function(link, application, callback, onlineMeetingUri) {
    ...
    this.onlineMeetingUri = onlineMeetingUri;
    ...
}

this.requestAccessToken = function(link, grantType, data) {
    this.authorizationLink = link;
    ...
    else if(this.onlineMeetingUri) {
        data = "grant_type=urn:microsoft.rtc:anonmeeting&password=" + this.onlineMeetingUri.slice(this.onlineMeetingUri.lastIndexOf(":") + 1) + "&ms_rtc_conferenceuri=" + this.onlineMeetingUri
    }
    ...
}

// this.handleState()
case 4:
    if(!scope.onlineMeetingUri) {
        scope.makeMeAvailable();
    }
    else {
        scope.currentState++;
        scope.handleState();
    }

obj.prototype.getAuthorizationLink = function() {
    return this.authorizationLink;
}

Renewing Anonymous User

An anonymous user can participate in the meeting for about one hour before needing to renew their OAuth token. Renewing the OAuth token is handled by making a POST request to the OAuth token service and is why it made sense to store that authorization link. The one missing piece from the puzzle is a small update to Transport.js to provide a mechanism to get the accessToken. I created a method, getAuthorization(), to return both the accessToken and the tokenType.

// Transport.js
obj.prototype.getAuthorization = function() {
    return {
        accessToken: this.accessToken,
        tokenType: this.tokenType
    };
}

Creating an Anonymous Meeting Grant Type line and appending “&ms_rtc_renew=accessToken”, it is possible to renew the existing OAuth token. I wrapped the code in an interval timer that should fire every 55 minutes extending that anonymous users OAuth token.

// UcwaObject.js
...
var onlineMeetingUri = _scope.getOnlineMeetingUri();
var grantLine = "grant_type=urn:microsoft.rtc:anonmeeting&password=" + onlineMeetingUri.slice(onlineMeetingUri.lastIndexOf(":") + 1) + "&ms_rtc_conferenceuri=" + onlineMeetingUri;

// Every 55 min we should attempt to extend our meeting lease...
_timerId = window.setInterval(function() {
    _scope.Transport.clientRequest({
        url: _scope.Authentication.getAuthorizationLink(),
        type: "post",
        contentType: "application/x-www-form-urlencoded;charset=UTF-8",
        data: grantLine += "&ms_rtc_renew=" + _scope.Transport.getAuthorization().accessToken
    });
}, 3300000);

Let’s talk Events

Assuming everything worked for Authentication it is a good time to start listening to Events, but not without another modification to ensure all event data flows through to handlers.

// Events.js
// this.processEvents(data)
    ...
    scope.checkHrefOrOperationListeners(cachedData, data);
    ...

// this.checkHrefOrOperationListeners(cachedData, data)
    ...
    for(var i = 0; i < localHandlers.length; i++){
        if(localHandlers[i] && localHandlers[i][normalizedEventType]){
            var handler = localHandlers[i][normalizedEventType];
            handler(cachedData, data);
        }
    }

The change in processEvents() is to allow more than just cacheData to flow through to checkHrefOrOperationListeners(). In checkHrefOrOperationListeners() I removed the check against data._embedded and the request going outbound to force the user to handle event processing on their own and because it was making a request for data when I really want to view the non-embedded data.

With those changes in place it was time to add event handlers for messaging, participant, localParticipant, and message. messaging events in the updated state help are used to know when to add modalities (messaging in this case) and when that modality has connected which in turn enables sendMessage, stopMessaging, and setIsTyping for the anonymous user. participant events are used to determine when users are typing (by checking data.in.rel === “typingParticipants”) and when they are added to the meeting for the started handler while those same events in the completed state indicate a user has finished typing or has left the meeting. localParticipant events in the started state indicate joining the meeting and when in the completed state it means leaving the meeting. message events in the completed state indicate a user has successfully posted a message to the meeting and it can be processed.

I have to join the meeting too?

Authenticating to the meeting anonymously does not actually place the user into the meeting. The additional step is to make a POST request to joinOnlineMeeting with: anonymousDisplayName and onlineMeetingUri. After joining the meeting a torrent of events will flow containing who is currently in the meeting, who is typing, and other meeting vitals. Processing those events should put the UCWA application in a state where the anonymous user should be able to communicate to the meeting and see updates.

And now for something different…

I have not provided any code previously in postings because the topics were building up to something and I think that Anonymous Meeting Join is as good time as any to provide a sample application bringing together the UCWA helper libraries and user-generated code. Without further ado, presenting the mess, Anonymous Meeting Join Sample (I save CSS/Html pretties for other projects):

The sample code allows a user to provide either a joinUrl or an onlineMeetingUri to join the meeting. Filling out either field and a name followed by clicking the Join Meeting button will attempt to anonymously join that meeting. I have noticed that sometimes users will get placed into a lobby and it will be the organizer’s job to admit these users in. Upon join the interface will change to add the connected users below the user’s Display Name and an messages will be placed in the section above the input/Send button area with a typing notification appearing slightly above the pair as seen below:

The code is structured as follows:

  • AnonMeeting.js – Logic for handling buttons (join online meeting, send message) and event handling
  • Authentication.js – Version based on Feb 2013 Samples with updates
  • AutoDiscovery.js – Version based on Feb 2013 Samples
  • Cache.js – Version based on Feb 2013 Samples
  • Events.js – Version based on Feb 2013 Samples with updates
  • GeneralHelper.js – Version based on Feb 2013 Samples
  • index.html – Main site
  • Transport.js – Version based on Feb 2013 Samples awith updates
  • UcwaObject.js – Logic for handling AutoDiscovery, Authentcation, and renewing Authentication

Sample code: AnonMeeting.7z
Sample Fiddler Trace: AnonMeeting.saz

Next Up

The next steps are to create more sample UCWA applications and explain their workings.

UCWA and fun with .NET/Mono

$
0
0

I had some time to take a break from working on JavaScript/HTML and decided to revisit .NET languages to gauge how difficult it would be to create a basic UCWA application. My initial thoughts were to create a simple Console application to ignore UI and focus on how to UCWA in a .NET. This proceeded to balloon into creating a set of helper classes mimicking the JavaScript version, creating a WPF version of the Console application, and finally creating a version that would work on my PS Vita.

Console.WriteLine(“UCWA are you out there?”);

It did not take long until I had felt I was writing too many BeginX/EndX code that I should consider writing up a few helper classes, combined with Program.cs ballooning out of control. I chose Json.NET as the library with which I would process the response body (mostly due to the list of framework support which becomes important when I attempted to bring UCWA to PS Vita).

Transport was the first helper class to work on as I originally wanted to start AutoDiscovery, but lacked the means to send requests (without duplicating some Transport code of course). The JavaScript Transport library was an adequate starting point as the .NET equivalent should be able to take in a set of request data (url, Http method, Headers, and data) and in turn execute a web request returning a set of response data (HttpWebResponse, Json, and raw data). Transport contained the basics of executing a request, setting authorization credentials (Bearer cwt=xxx), basic request validation, and checking for domain changes (xframe in response Json).

This early in development I was not considering sharing source to enable older frameworks resulting in a fair amount of specialized web request code, but it was sufficient enough for me to attempt replicating AutoDiscovery. Without the need to inject an xframe for cross-domain communication I was able to boil AutoDiscovery down to requesting lyncdiscoverinternal followed by lyncdiscover when needed.

With how easy I found AutoDiscovery I had high hopes that Authentication. Authentication is a bit odd in that the application needs to make a failed request to get the location of the authentication service and use that to get the credentials to make a successful request. In other words Make auth request -> read WWW-Authenticate response header -> Make request to OAuth service -> Make auth request. It was at this point that I neglected to url encode part of my Json response when creating an application resulting in a failure. After rectifying that and making a request to makeMeAvailable I had successfully created a UCWA application using .NET.

At this point I should have considered the concept proven, but I wanted to see something simple like meDashboard replicated on the Console:

The crowning achievement for me was option #7 where I get the photo and display it on the commandline via Ascii:

I did run into one fun issue as a result of using Fiddler so heavily during testing in that when I went to demo it without Fiddler running I would occasionally run into issues where a request would appear to hang. It was after a few searches that I came across: Help! Running Fiddler Fixes My App??? and had to add some clean up code for streams, requests, and responses resulting in a much happier Console application.

WPF and remembering how to data bind properly

With a bit of extra time I decided to tackle a WPF application and attempt to consolidate the helper classes into a helper library. With the helper library in place (aptly named UCWA.Sharp as it was written in C#, but thinking about it now it could have been UCWA.NET…) it was time to re-learn data binding and Mvvm. I do not feel much changed in the helper classes beyond experimenting with creating Batch and Events classes, but I did not reach a point where they became necessary. I took the time to implement a meDashboard and Contacts which included searching for contacts. I did have a bit of fun and tried styling it similar to the samples site included in the helper libraries with some effect. I’d say I was a bit ambitious to put most of the tasks in place with a post for Call Via Work:



PS Vita and struggling against the PS Mobile SDK

I’ve had a PS Vita for awhile now and rather recently the cost of the license to publish applications has been removed. The PS Mobile SDK (found at PSM Dev Portal) is based on Mono using C# and provides a brand-enhanced (or however you want to think of it) version of Mono-Develop. I created a fork on my helper libraries as I knew I would be making changes to accommodate Mono which resulted in the mass exodus of async/await to be replaced with wrapping most methods in Task.Factory.StartNew(…) among other minor changes.

I did run into the situation that I need to use Json.net, but there really is not a version built for PS Mobile SDK and as far as I could manage it would not let me just pull .NET built version into my project and run with it. Not to be detoured too long I decided to use the source and create a library built against the supplied version on Mono. After much trimming I had a version that would work with application I built using the PS Mobile SDK.

With changes and Json.net in place I attempted to run AutoDiscovery as that should be the simplest bit of UCWA, but I noticed I was failing each request (internal/external). Reading about the exception it seemed that I was having certificate failure in that the PS Vita did not want to accept the certificates presented. With a bit of looking I found that I could correct it by using the ServicePointManager and providing a ServerCertificateValidationCallback. As this was a proof of concept I went with a rather blunt solution:

ServicePointManager.ServerCertificateValidationCallback = delegate
{
    return true;
};

With the fix in place I was seeing the responses I was looking hoping for and so I began to work with PS Mobile SDK’s provided UIComposer to create WinForm-like interfaces for logging in and displaying a meDashboard-like contact card. After composing and including the layouts into my project I was able to make changes to the class and add appropriate handlers similar to WinForms. I did have some assets for default user image and presence indicators that had to be included in the output to get them to display properly.


It would not be complete without a demo of it actually running on a PS Vita. In the demo I was changing the user’s presence/note via both the PS Vita and Lync Client: UCWA & PS Vita

And that’s all folks

For now the proof of concepts will continue to live on my desktop and have time to figure out what to do with a .NET UCWA helper library. It proved (to me at least) that UCWA is not just a technology that can be used in web-based applications.

UCWA & Deciphering multipart/batching with Fiddler

$
0
0

When I was first working with UCWA I had trouble processing Batch messages (multipart/batching) as I would be constantly coping each individual message from Fiddler and dumping it into a JSON parser to see a prettier display of results. While a few batch messages might not seem to daunting, it is possible to wrap 20 requests into a single batch message. At this point I began to read up on creating Custom Inspectors Fiddler.

What is an Inspector

Fiddler includes a set of Inspectors by default and the ones I find myself readily using when debugging UCWA tend to include: Headers, TextView, Raw, and JSON. Inspectors implement an interface that provides the component with the Header/Body data for the message and from there the component can choose how to display. In the case of the Headers Inspector it separates the message headers into bold categories.

When it comes to processing Batch messages either TextView (view Body data) or Raw (Header & Body) is the place to grab the individual message. According to RFC 2046 each message in a multipart entry is separated by a boundary and in the example below the boundary is 07b2d3f3-9a8f-416c-a006-c489726f0660. It is possible to see that both responses in this Batch message have a Content-Type of application/json.

Custom Inspector at a Glance

Similar to extending Fiddler via FiddlerScript, it is possible to create a Custom Inspector for Request/Responses and this time with C#! Basic documentation exists on how to Build a Custom Inspector. When creating this extension there is a choice to make: support .NET 2.0 or .NET 4.0 (directly related to which Fiddler version is installed and the extension is built against). In my case I chose to support .NET 2.0 as it is compatible with the .NET 4.0 version (and potentially newer versions).

Typically a Custom Inspector would implement Inspector2 and IResponseInspector (Response handler) or IRequestInspector (Request handler), but with Batch messaging both the request and response are of type multipart/batching and it would be ideal to visually represent both in some readable fashion.

Request messages will be wrapping Content-Type of application/http; msgtype=request which should contain the following:

  • Verb – GET, POST, PUT, DELETE
  • Url – what data is being accessed
  • Headers
  • Body – Optional

Response messages will be wrapping Content-Type of application/http; msgtype=response which should contain the following:

  • Status code – 200, 301, 418 (if only)
  • Status – text description of code
  • Headers
  • Body – Optional

JsonViewer

I had a good idea of what the data might look like, but was unsure how I wanted to visually present it to the user. A colleague of mine pointed me at JSON Viewer as it had a standalone control for displaying JSON. Another lucky feature is that it included a Custom Inspector and I was able to use that as a base for the creation of a new Custom Inspector. I would reuse the code that made use of the JsonViewer control and provide it with a JSON-formatted Batch message. JSON Viewer also has dependencies on Json.NET, so came along for the ride as well.

I browsed Fiddler reference in my project and discovered that IRequestInspector and IResponseInspector would only give me access to headers and I wanted to be able to process both headers and body. By having my main class (MimeInspector also implements Inspector2) implement IBaseInspector I was able to process body data. With a fair amount of string manipulation I was able to transform the header/body into a fairly readable JSON object rendered in a JSON Viewer control. All that was left to do was define classes implementing IRequestInspector2 and IResponseInspector2 inheriting from MimeInspector (to benefit from the header/body processing and display via a JSON Viewer control).

Request

Response

Using a Custom Inspector

Using a Custom Inspector is as simple as navigating to Fiddler’s install location and placing the necessary files into the Inspectors folder (Fiddler should not be running if you are adding/removing Inspectors). The end result is a new tab in Fiddler, multipart/batching, that can render Batch messages into an easier to read/navigate JSON display.

Fiddler Custom Inspector: MimeParser.7z
Sample Fiddler Trace: Batch.saz
Sample Fiddler Trace: Batch 2.saz

UCWA – Messing with SignalR and NodeJS

$
0
0

I have been thinking about other transport mechanisms (other than iframe) that would be interesting to see working with UCWA and two immediately came to mind: SignalR and NodeJS. Each can be used to work around the issue of cross-domain requests and provide additional pathways to access UCWA in the event that iframe communication is not feasible.

SignalR

I choose to go the self-hosted route and found great use out of Tutorial: SignalR Self-Host and ASP.NET SignalR Hubs API Guide – JavaScript Client (C#). I felt that by self-hosting it would allow me to run it via a Console application (short-term) and delay the decisions about where it would make the most sense to have it hosted.

I was able to reuse a subset of the helper libraries I made in my previous .NET efforts, specifically Transport and some helper functions. The only modifications that seemed necessary were changes to the Response object as this would be directly used by the other sample libraries. I also wanted to avoid making modifications to the sample libraries beyond choosing between using iframe or SignalR.

The samples libraries’ Transport.js needed modifications to support using SignalR over iframe. Modifications were made to allow Transport to take a hub Url (location of the hub proxy) upon construction. Presence of a hub Url is used to determine if Transport should create/connect to the hub proxy (injectFrame(…)) and how to send the request (clientRequest(…)). Similar to how event handlers for onmessage/message were attached/removed a function for handling the response callback was added to attach/remove handler per clientRequest(…) call.

The SignalR hub consists of one method, Request(…), that takes a request object (generated by Transport.js) and execute the request using the .NET Transport library notifying the caller by a response callback. The response object relatively close to the object return by the sample libraries. Running with the UCWA samples was as simple as starting the console application hosting the SignalR hub and loading up the modified samples code (inspecting the JavaScript console to see if the hub connected correctly).

One issue I did run into was that requesting images became a bit of difficulty as the POST on applications returns an HttpOnly cookie that is rather impossible to set from JavaScript. With much deliberation I was able to reason out that image requests could go through clientRequest(…) (the request uses the Authorization header in place of the cookie) and take the raw (I call it base64 below, but it is really just a C# byte[]) response data and stick that into a data Uri for the src property of the image (data:image/png;base64,base64_encoded_string).

One downside of using this SignalR proxy (at least for WebSockets transport) is that network traffic reachable via Fiddler/Network tab becomes nothing more than the initial negotiate/connect calls to the hub proxy. I have not played around to check out other transport types it might use to see what may/may not show up in Fiddler/Network tab.

NodeJS

NodeJS took a bit of time to wrap my head around what exactly I was intending to accomplish. The end desire boiled down to issuing a request containing data similar to what Transport.js would be sending along via postMessage. I created an Http server listening on port 8889 that would take Http request data, filter it, and issue an Https request to UCWA. When the response comes back for the Https request, write out the status code, headers, body, and respond as if it was the intended Http request. Initially it worked very well for GET requests as there wasn’t any complicated body data. For POST (and PUT) requests recalculate the content-length headers based on the inner data (data actually being sent in the request and not the data containing url, type, etc).

Debugging NodeJS was actually a bit interesting from Fiddler/Network tab point of view as the request originates from http://localhost:8889 and the end result is determined by the Url provided in the request body. The request headers are relatively close to the end result with a bit of fixing depending on the request type.

Samples containing GET/POST requests: NodeJS.saz

The many faces of Transport

Currently Transport in the sample libraries makes exclusive use of a cross-domain iframe for communication and it works for most situations. If new transport mechanism were to be added, I could see them being added as part of the Lync Server and started as services (of some sort). Perhaps information would be offered similar to how the iframe is currently offered during AutoDiscovery and based on the option chosen by user/code it could load use the appropriate transport. It would be interesting to take this idea further and see how many supported browsers UCWA could reach by utilizing more transport mechanisms like Socket.IO, etc.

UCWA by the numbers – #5 Re-join Conversations

$
0
0

I have been a bit lax on finding aspects of UCWA that could use a bit of demystification, but it is not to say that there are not things I do not understand rather that I have not spent time thinking about some of the more unique scenarios. One of those scenarios is needing to re-join an in-progress conversation that the UCWA dropped out of. This can be achieved by utilizing the threadId parameter provided either when making the initial POST request to startMessaging or as part of event channel data included in messagingInvitation / conversation events.

I’m re-purposing work done for UCWA by the numbers – #4 Anonymous Meeting Join and creating a sample that allows user sign-in (username and password) and starts a conversation with a specified user. Additional buttons will be present to leave and re-join the conversation. Refreshing the page will attempt to clean up the UCWA application similar to how anonymous meeting join cleaned up.

The sample I have in mind will make use of startMessaging providing operationId (required), to (required), threadId (optional). It is possible to not provide threadId and parse messagingInvitation or conversation event data to retrieve a generated threadId (as seen below).

Differences between Conversations and Meetings

One interesting situation I encountered when transitioning the code from meeting to conversation is how event data related to typingParticipants and message (other events exhibit this behavior, but are less important to this sample). Meeting events will contain a participant object that has a populated title property whereas conversation events do not. This immediately posed a problem due to the code structure of expecting to find this value to indicate who is typing or sent a message.

Meeting – typingParticipants

Conversation typingParticipants

Meeting – message

Conversation – message

While this property value may not be available in certain circumstances it is possible to follow the participant href to get data stored in the meeting or conversation about the participant. This however had similar problems that a name property was not available to conversation, but by following the contact href it is possible to finally reach the name (or title).

participant

contact

I created an array of titles/names indexed by URI to track what users I had already executed the additional requests (as opposed to getting new contact information every new typingParticipants / message event). It was also important to track completed messagingInvitation and conversation events to determine if/when a remote participant declined the invitation or a failure occurred and when the conversation has ended.

Re-join a Conversation

After authenticating and starting a conversation with a remote participant it is possible to leave the conversation via Leave Conversation button. What I did notice is that after making the request to startMessaging with the original threadId is the UCWA joins a conversation while the remote user can take a short while before they re-join the conversation. I have actually seen two distinct behaviors surrounding this as follows:

  • Lync Client is in background – Upon re-join request a popup message indicating that UCWA user is adding IM appears and both users appears in sample site under participants list
  • Lync Client is in foreground – Upon re-join Lync conversation window blinks and only UCWA user appears in sample site under participants list

Eventually the remote participant appears in both situations, but it is a bit odd at first glance.

Traces and Code

Traces containing the differences between Meetings and Conversations are as follows:

The code is structured as follows:

  • Authentication.js – Version identical to AnonMeeting.7z
  • AutoDiscovery.js – Version identical to AnonMeeting.7z
  • Cache.js – Version identical to AnonMeeting.7z
  • Events.js – Version identical to AnonMeeting.7z
  • GeneralHelper.js – Version identical to AnonMeeting.7z
  • index.html – Main site with modifications for Conversations
  • RejoinConversation.js – Re-purposed logic from AnonMeeting.7z for handling buttons (start/leave/rejoin conversation, send message) and event handling
  • Transport.js – Version identical to AnonMeeting.7z
  • UcwaObject.js – Re-purposed logic from AnonMeeting.7z for handling AutoDiscovery, Authentication, and reportMyActivity

Sample code: RejoinConversation.7z

Next Up

I am thinking about doing a short excerpt on how to parse HTTP links posted into a conversation from Lync/LWA as they can appear funky.

UCWA – Handling Hyperlinks and Other Mini-Updates

$
0
0

One quirky behavior of Lync users is that they will sometimes send other users hyperlinks and it seems rather straightforward in how handling should happen, but I wouldn’t be writing about it if that was the case. The first time I sent a hyperlink (http://ucwa.lync.com) from Lync Client I noticed that the result was a bit different than what appeared in the conversation window: http://ucwa.lync.com &lt;http://ucwa.lync.com&gt;. With a bit of substitution it was possible to see that the result: http://ucwa.lync.com <http://ucwa.lync.com>. While it is possible to do some transformations to remove the repeated value and turn the first into a usable hyperlink it will be easier to act the problem at the source and by that I’m referring to MessageFormat.

Enabling Html Formatted Messages

Inspecting the Communication resource it is possible to see a supportedMessageFormats property and by default UCWA has this collection set to Plain.

Communication

Executing a PUT request on the Communication resource would allow Html formatted messages to come across containing Html tags and CSS styles relating to the content the user sent, meaning the original hyperlink should come across as an anchor tag. My first few attempts at structuring a PUT resulted in 400 (Bad Request). I felt I had everything in place with the addition of Html under supportedMessageFormats and could not determine why it would not accept the request.

Communication PUT

Since Communication provides an ETag value we should provide the If-Match header with the supplied ETag value. In the event that the If-Match value does not match the ETag it will respond with a 412 (Precondition Failed). Assuming the PUT request succeeds with a 204 response it is now possible to see Html formatted messages. In the original example the message would come across as: <span style=”margin-bottom:0pt;font-size:10pt;line-height:normal;”><a href=”http://ucwa.lync.com/” title=”http://ucwa.lync.com/”><span style=”color:black;”>http://ucwa.lync.com</span></a></span>. It would be possible to put this into a message container and have a functional hyperlink (hopefully).

Fiddler Traces: UCWA Html Messaging and LWA Html Messaging

Side Effects

One side effect of enabling Html formatted messaging is that all messages will come across as Html formatted. I looked into LWA (Lync Web App) and found the behavior to be that both Plain and Html formatted messages were returned for each message. I played around with changing Content-Type headers, but have not come to a conclusion why UCWA is only returning Html formatted messages when both MessageFormats are enabled.

Fiddler MimeParser Updates

I had not intended on doing too much additional work on the original Mime-Parser I wrote about back in August (UCWA & Deciphering multipart/batching with Fiddler), but while doing some debugging I noticed it had a few issues:

  • Navigating between request/response items that were not multipart/batch after previously displaying could lead the misconception that the current response was being processed.
  • Transfer-Encoding: Chunked messages would attempt processing and fail because the body would not decode.
  • No support for multipart/related or multipart/alternative.

I figured based on the changes I had working locally there was no reason not to clean it up a bit and put out a newer version. If nothing else to have a publicly accessible location point people I work with at when they ask me about how I read some of the more complex UCWA traffic.

Latest MimeParser: MimeParser 1.0.1.7z

Next Up

I may have some material ready on simplifying configuration of UCWA and the cross-domain authorization otherwise I’ll find more information and a possible solution to getting Plain and Html formatted messages when using UCWA.


UCWA March 2014 Samples SDK Overview

$
0
0

I had a deeper look into Events planned, but I felt it would be easier to put together information on the latest release of the samples, UCWA March 2014 Samples. It has been a bit since the last update to the samples (May/June 2013), but we have not seen new features added in any recent cumulative updates, but that does not mean that there is no room for improvement in the available samples.

Stated Changes

As per the CHANGELOG.TXT the changes since last release are as follows:

  1. Add Call Via Work sample [works in sandbox only] (site)
  2. Add Anonymous Meeting Join sample (site)
  3. Add timer query parameters and method to update values (Events.js)
  4. Add method to parse header string into JSON-like object (GeneralHelper.js)
  5. Change Cache to provide interface for implementations and updates to support deferred access (Cache.js)
  6. Add in-memory storage and localStorage implementations of new Cache interface (MemoryStorage.js/LocalStorage.js)
  7. Remove isDefined(…) usage (All)
  8. Add method for default value fallback (GeneralHelper.js)
  9. Updating frameInjection to wait for injection prior to executing callback (Transport.js)

And now for comments regarding these changes:

  1. This has been features of UCWA at the start of release, but finally have samples demonstrating their function. There has been information on Anonymous Meeting Join (via a previous posting) and Call-Via-Work has always existed as part of the Interactive Demo.
  2. See comment above.
  3. Event query parameters should allow fine-tuned control over how the event channel handles events with differing priorities, prioritizing requests, and a general purpose timeout. I have not spent any time seeing how this functionality works, but I plan on covering parts of this for the deeper look into Events.
  4. Parsing the response header string was a bit of a mess or it felt like it anyways and having a method to turn that string into a JSON object definitely makes it easier to find the specific header values. It even handles the WWW-Authenticate header!
  5. The new interface of the Cache should resemble the Facade pattern and it will allow developers to create their own mechanisms to store UCWA application data. The interface exposes iCRUD (where i is Init()) and returns promise objects via jQuery, $.deferred(), to allow deferred object processing.
  6. These two implementations provide the real basics of how in-memory and localStorage work with the new interface. It would not be too hard to create additional implementations like IndexedDB.
  7. GeneralHelper’s isDefined(…) function had some uses, but it was not generally needed.
  8. I have run into a few issues where I think the callback function I wrote is flawless to find out that it had an error and caused the next code segments to never run.
  9. Frame injection logic in general is weird and improvements to how it functions are welcome. In this case after the new frame is injected into the DOM the supplied callback should be executed.

Overall it looks like a solid set of changes to the existing helper libraries and in the following sections. Let us briefly look at the two new samples and some other features.

Call-Via-Work

For Call-Via-Work to function properly the Lync Server you are running against needs a PSTN gateway as the request to startPhoneAudio will need to establish a call between a Lync User and a supplied phone number. The sample is setup to call sip:CallViaWorkBot@gotuc.net which happens be on the same domain as the users provide by the Lync Web Developer Portal. Using the provided credentials from the portal allows for easy testing of this feature.

Anonymous Meeting Join

Anonymous Meeting Join was added to this samples release as a new authentication method (preexisting are My own topology and The developer sandbox) that requires an Online Meeting Uri and Display Name. The best way to get an Online Meeting Uri is to use to Schedule a Meeting and copy the onlineMeetingUri output which is now displayed after the meeting is created. The sample code is very similar to Instant Messaging as both are interacting with the Messaging modality with the differences being a conversation versus a conference.

Other Features

Now for some of the more minor changes seen across the samples as a whole by sifting through folder diffs:

  • Any code using the old cache has been updated to use the new version.
  • Fixes to some of the usage logic files.
  • Fixes were made to incoming/outgoing conversation samples.
  • Scheduling a meeting was changed to provide accessLevel and output onlineMeetingUri.
  • Events no longer makes a request if the _embedded property is not present.
  • Index.js alerts if it has a problem loading jQuery.
  • Transport alerts the reason why it failed for cross-domain issues and attempts to not make the second request if going from internal to external discovery.
  • Transport maintains a list of outstanding methods attached to windows’s (on)message function and attempts to cleanup better to avoid dangling event handlers.
  • There is a License Terms file.

Closing

It will be interesting to see this sample set continue to grow as new functionality is added to Lync Server 2013 and what areas UCWA will move into next. If you haven’t tried UCWA or the new samples consider taking a look today!

UCWA March 2014 Samples

Viewing all 16 articles
Browse latest View live