Monday, December 27, 2010

Delayed Push Notification Service for Windows Phone

This is a multi part blog post the other posts in this series are:

  • Overview – you’re reading this now.

  • The push notification service – how to implement the delayed push notification service

  • The client library – not yet written.

In this post I discuss push notifications, and share my web service which implements a delayed push notification.

Push notifications are a web service that MS provides that can send a message to the phone. There are 3 flavors of push notifications:

  1. Raw notification: Raw bytes - ignored if your app isn't running, sent to your app if it's running. 

  2. Tile notification: Manipulate application tile, worth it's own blog post. 

  3. Toast notifications: If your app isn't running pop up a toast giving a message to the user. 

An interesting detail about the push notification web service is how the web service is addressed, and how the phone is identified. I'd expected something like this: But instead you get the more elegant:



// doesn't work like this.
proxy = CreateProxy("http://well-known-push-notification-service")
proxy.push-toast(id-for-running-app-phone-taken-from-phone, "toast text")
proxy.push-toast(id-for-running-app-phone-taken-from-phone, "toast text2")
// works like this.
proxy = CreateProxy(id-for-running-app-phone-taken-from-phone-with-built-in-service-url)
proxy.push-toast("toast text") // no need to specify phone/app id
proxy.push-toast("toast text2") // no need to specify phone/app id
An annoying limitiation of push notifications is you can't schedule them at arbitrary times. From MSDN:

sendNotificationRequest.Headers.Add("X-NotificationClass", ""); 

// Possible batching interval values:
// 3: The message is delivered by the Push Notification Service immediately.
// 13: The message is delivered by the Push Notification Service within 450 seconds.
// 23: The message is delivered by the Push Notification Service within 900 seconds.
As a result I decided to write a simple web service which will allow you to send your app push notifications.  The sequence diagram for this service is:



The API for this web service is:

http://{root}/push-toast
POST a query string with the following parameters:
{'url:'push notification url',
'message':'text of the toast'
'seconds':'time delay in seconds'
}

RETURN: a json object with:
{
'key' : 'an opaque value used when requesting the toast be cancelled '
'secret' : 'an opaque value used when requesting the toast be cancelled '
}

http://{root}/cancel-push
POST a query string with the following parameters:
{
'key' : 'an opaque value returned from post'
'secret' : 'an opaque value returned from post'
}
RETURN: not defined
If you want to use this web service you can ping me and I'll give you access. In future blog posts I'll talk about the code for the web service as well as the client library.  Leave a comment if you'd like to use this service and we can talk about whatever features you require.

Tuesday, December 14, 2010

PsychicDebugging - You can browse to www.google.com, but you can't ping it.

In my last message to the world I though I'd fixed my networking, but turns out I hadn't. Here's the state of affairs:

  • IE; Chrome and Firefox work perfectly.

  • ping www.google.com fails instantly with hostname not found

  • nslookup www.google.com works

  • From python socket.gethostaddr ('www.google.com',80) fails instantly.

This had me stumped, I assumed the web browsers must be calling different apis from ping.  A few invocations of cdb, and I realized the apps that worked are all 32 bit. That was the trick, my 64 bit NSP catalog was also corrupted; and thus all 64bit apps couldn’t resolve networking.   Luckily from yesterdays shenanigans I had exported the catalog from the registry and re-loaded it. 

To look at the catalog use the powershell:

PS HKLM:\> dir HKLM:\SYSTEM\CurrentControlSet\services\WinSock2\Parameters\NameSpace_Catalog5\Catalog_Entries64 | % {$_.GetValue("LibraryPath")}
c:\Program Files (x86)\Microsoft Firewall Client 2004\FwcWsp64.dll
%SystemRoot%\system32\NLAapi.dll
%SystemRoot%\System32\mswsock.dll
%SystemRoot%\System32\winrnr.dll
%SystemRoot%\system32\napinsp.dll
%SystemRoot%\system32\pnrpnsp.dll
%SystemRoot%\system32\pnrpnsp.dll
%SystemRoot%\system32\wshbth.dll
C:\Program Files\Common Files\Microsoft Shared\Windows Live\WLIDNSP.DLL
C:\Program Files\Common Files\Microsoft Shared\Windows Live\WLIDNSP.DLL
In summary if someone asks how it’s possible the browser works but they can’t ping www.google.com – try checking their 64 bit NSP catalog.

Saturday, December 11, 2010

Set a System Restore Point

Start -> Create a  restore point -> Create

A few days ago my event viewer service failed to start, and I went on a crazy goose chase that was most unpleasant.  I suspect my life would have been better if I had a working restore point, so I'm sharing my wisdom with you: create a restore point now.

Some surprising things I found on my journey:

  • Eventlog not starting because The Authentication Service is Unknown (Error:1747) => Winsock Catalog corruption.
  • netsh winsock reset should fix said corruption but didn't in my case.
  • Rumor is when netsh winsock reset doesn't work and you need to get tcp to reinstall to rebuild the catalog.
  • Honestly I don't know how I got this fixed, but in theory a restore point would have fixed it.

Summary: Go set a restore point now :)

Tuesday, November 23, 2010

The Scunthorpe problem

I ran across an obscure reference to Scunthorpe problem and had to investigate what this “problem” is.  It turns out Scunthorpe is a town in England, as are the following towns which share the same problem: Penistone, Lightwater.

No idea? Perhaps this interview question will make it clear: Design a simple system that can determine if a user name is obscene.

Friday, October 15, 2010

Facebook, OpenID and Decrypting SSL

I was excited to see Facebook (FB) supporting login via OpenID (FB is a relying party), and I decided to give it a whirl. Here I list the results of my investigation, which describe the odd use of OpenID, as well as my wire level analysis which I hope you find informative. This post doesn't go into details of how OpenID works, if you're interested in that leave a comment and I'll put up such a post.

FB uses OpenID in a way I've never seen before. In the "common" OpenID login model, you get a login page that shows you some sort of login via OpenID buttons. When you go to the FB login page there is no login via OpenID.   This confused me, but I went to my FB account settings and linked my google account to my FB account. (Attempts to link my MyOpenID account failed with a strange error message). 

After some trial and error I realized that if I was logged into my Google account and went to the FB page than I'd automatically get logged into FB.

Debugging SSL via Charles

I needed to look at the network layer to see what is going on. Some of you may want to investigate this with tshark, but much of the traffic runs over SSL, since we don't have the server certs that's a dead end.  Instead you should fire up Charles, an http(s) debugging proxy.  Charles can sit in the middle of your SSL connections, and relay SSL traffic by presenting ‘untrusted certs’. Visually it looks like this:

 

image

 

How Facebook OpenID login works at a high level:

  1. Facebook login page contains javascript that tells your browser to login to Yahoo and Google via OpenID
  2. Your browser tries to connect to Yahoo and Google OpenID Endpoints, which post results back to FB
  3. If the login via OpenID succeeds, and you have a linked account you get logged into FB.
  4. If the request fails or there is no linked account you see nothing.

The Facebook OpenID approach:

If you’re logged into your Google account, and then go to the FB page, you’ll be automatically logged into FB, otherwise nothing happens. This is by design as mentioned here.

This is an interesting implementation of login via OpenID. It has the following advantages:

  • It’s immune to phishing
  • It requires no UI when you’re logged into your OpenID provider

At the same time there are some big disadvantages:

  • There is a privacy leak as all OpenID providers supported by FB now know you’re trying to access FB and at what frequency and from what client
  • FB needs to connect to every OpenID provider that exists on login.
  • FB doesn’t allow you to specify which account you want to use to login if you have multiple.
  • You can’t link your FB account to OpenID by logging into OpenID
  • It’s hard to discover login is failing because you aren’t signed into an OpenID account.

I look forward to seeing how FB moves this forward.

How Facebook OpenID login works at a protocol level:

This is probably too geeky for most but I find it interesting so I’ll share it. Comment if you’d like to see more of this sort of analysis.

The first column is the return code 200 is success, 302 is a redirect. Second column is the DNS name, and third column is truncated request.

1) Facebook login page contains javascript that tells your browser to login to Yahoo and Google via OpenID

// Connect to FB
200    GET    www.facebook.com   

// JavaScript connects to FB Analytics system telling them what we're trying.
200    GET    pixel.facebook.com    /ajax/openid/metrics.php?metric=requestSent&immediate=true&context=background_login&openid_url=http%3A%2F%2Fyahoo.com%2F&asyncSignal=779    
200    GET    pixel.facebook.com    /ajax/openid/metrics.php?metric=requestSent&immediate=true&context=background_login&openid_url=http%3A%2F%2Fgmail.com&asyncSignal=9380    

// 2) Javascript tries to connect to Yahoo and Google OpenID Endpoints, which post results to: www.facebook.com/openeid/receiver

// 2.1) HTTPS connection to Google OpenID
302    GET    www.google.com    /accounts/o8/ud?openid.claimed_id=…

// 2.2) HTTPS connection to Yahoo OpenID
302    GET    open.login.yahooapis.com    /openid/op/auth?openid.claimed_id=…

// 2.3) Yahoo OpenID telling FB it failed.
302    GET    www.facebook.com    /openid/receiver.php?provider_id=1923581983856&openid.mode=setup_needed&…

// 2.4) Google OpenID telling FB it succeeded.
302    GET    www.facebook.com    /openid/receiver.php?provider_id=1010459756371&…openid.sig=…

// FB telling itself the Yahoo login failed (this gives FB the chance to add new paramters server side, which it does)
200    GET    www.facebook.com    /openid/receiver.php?provider_id=1923581983856&…

// FB recording stats that the yahoo login failed.
200    GET    pixel.facebook.com    /ajax/openid/metrics.php?metric=requestCanceled&immediate=true&context=background_login&openid_url=http%3A%2F%2Fyahoo.com…

// FB telling itself the Google Login Succeeded (this gives FB the chance to add new paramters server side, which it does)
200    GET    www.facebook.com    /openid/receiver.php?provider_id=1010459756371 …

// 3. If the login via OpenID succeeds, and you have a linked account you get logged into FB. (FB Logging in)
302    POST    www.facebook.com    /login.php    
200    GET    www.facebook.com    /     

The actual request if you’re feeling really geeky:

// More Details 2.1) HTTPS connection to Google OpenID

openid.claimed_id    http://specs.openid.net/auth/2.0/identifier_select
openid.ext0.mode    fetch_request
openid.ext0.required    email,first_name,last_name,country,language,dob
openid.ext0.type.country    http://axschema.org/contact/country/home
openid.ext0.type.dob    http://axschema.org/birthDate
openid.ext0.type.email    http://axschema.org/contact/email
openid.ext0.type.first_name    http://axschema.org/namePerson/first
openid.ext0.type.language    http://axschema.org/pref/language
openid.ext0.type.last_name    http://axschema.org/namePerson/last
openid.identity    http://specs.openid.net/auth/2.0/identifier_select
openid.mode    checkid_immediate
openid.ns    http://specs.openid.net/auth/2.0
openid.ns.ext0    http://openid.net/srv/ax/1.0
openid.ns.oauth    http://specs.openid.net/extensions/oauth/1.0
openid.ns.ui    http://specs.openid.net/extensions/ui/1.0
openid.oauth.consumer    www.facebook.com
openid.oauth.scope    http://www.google.com/m8/feeds/contacts/
openid.realm    https://www.facebook.com/
openid.return_to    https://www.facebook.com/openid/receiver.php?provider_id=1010459756371&protocol=http&context=background_login&request_id=1
openid.ui.icon    true
openid.ui.mode    popup

// More Details 2.4) Google OpenID telling FB it succeeded.
provider_id    1010459756371
protocol    http
context    background_login
request_id    1
openid.ns    http://specs.openid.net/auth/2.0
openid.mode    id_res
openid.op_endpoint    https://www.google.com/accounts/o8/ud
openid.response_nonce    2010-10-14T06:07:08ZPY_ztwISRBSIzA
openid.return_to    https://www.facebook.com/openid/receiver.php?provider_id=1010459756371&protocol=http&context=background_login&request_id=1
openid.assoc_handle    ...
openid.signed    op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle,ns.ext1,ns.ext2,ext1.mode,ext1.type.first_name,ext1.value.first_name,ext1.type.email,ext1.value.email,ext1.type.language,ext1.value.language,ext1.type.last_name,ext1.value.last_name,ext2.scope,ext2.request_token
openid.sig    oCFFt53s1j4rD7kGOE8x1ycZMfU=
openid.identity    https://www.google.com/accounts/o8/id?id=...
openid.claimed_id    https://www.google.com/accounts/o8/id?id=...
openid.ns.ext1    http://openid.net/srv/ax/1.0
openid.ext1.mode    fetch_response
openid.ext1.type.first_name    http://axschema.org/namePerson/first
openid.ext1.value.first_name    Igor
openid.ext1.type.email    http://axschema.org/contact/email
openid.ext1.value.email    ...
openid.ext1.type.language    http://axschema.org/pref/language
openid.ext1.value.language    en
openid.ext1.type.last_name    http://axschema.org/namePerson/last
openid.ext1.value.last_name    ...
openid.ns.ext2    http://specs.openid.net/extensions/oauth/1.0
openid.ext2.scope    http://www.google.com/m8/feeds/contacts/
openid.ext2.request_token    4/bv0-X57lya6ESvrvYG3pQiAGuSzn
openid.ns.ext3    http://specs.openid.net/extensions/ui/1.0
openid.ext3.mode    popup

Friday, October 8, 2010

Taskmgr to PowerShell: Kill A Process

You know the drill, some app freezes. You try to close it, that doesn’t work.  You fire up taskmgr, sort by name, type in the name, and then hit the delete key to kill the process.  Easy with powershell:

Get-Process | ? {$_.Name -eq "firefox"} | kill


The real power here is the composability of powershell, for example you could also debug the process.



Get-Process | ? {$_.Name -eq "firefox"} | Debug-Process


Or if you’re not sure what’s going to happen you can always pass the –whatif qualifier:



PS C:\Users\igord\Downloads> Get-Process | ? {$_.Name -eq "firefox"} | Debug-Process -whatif
What if: Performing operation "Debug-Process" on Target "firefox (8204)"


Happy Powershelling

Wednesday, October 6, 2010

Photo Fusing in Windows Live Photo Gallery

On my camera, I can make the self timer take 8 photos 2 seconds apart. This leaves me with a 1 in 8  chance of getting a good picture. However, using the photo fuse tool in Windows Live Photogallery, I can do a visual merge of the photos to pick my favorite part of each photo.  For example, I used the following source photos:

IMG_1349IMG_1352IMG_1353IMG_1354

IMG_1355IMG_1356IMG_1357

To created this composite photo, (To which I also applied straiten and auto fix)

StaceyDaveAndFamFuse

That’s seriously cool!