2

I am trying to send a push notification to IOS device via PushSharp. For android, it works. For IOS, the call to StopAllServices() hangs forever, without calling any exception handlers.

Could the problem be that I was given a .pem certificate file, and pushsharp requires a .p12 file?

The code is the following:

var br = new PushBroker();
br.OnNotificationSent += br_OnNotificationSent;
br.OnNotificationFailed += br_OnNotificationFailed;
br.OnChannelException += br_OnChannelException;
br.OnServiceException += br_OnServiceException;
br.OnDeviceSubscriptionChanged += br_OnDeviceSubscriptionChanged;
br.OnDeviceSubscriptionExpired += br_OnDeviceSubscriptionExpired;
br.OnChannelCreated += br_OnChannelCreated;
br.OnChannelDestroyed += br_OnChannelDestroyed;

var appleCert = Resource1.ck; // this is a pem file, not a p12 file!!! could this be the problem?
var sandbox = true;
br.RegisterAppleService(new ApplePushChannelSettings(!sandbox, appleCert, "223684"));
// password given to me by ios developer

var deviceIds = new string[] { "09eddcb8b89494adf802a0caf97d5daaa789a53f52d8c544dbdcf39f2c0b619a" };

foreach (var did in deviceIds)
{
    br.QueueNotification(
         new AppleNotification()
               .ForDeviceToken(did)//the recipient device id
               .WithAlert("test: " + DateTime.Now.ToString())//the message
               .WithBadge(1)
               .WithSound("sound.caf"));
}
br.StopAllServices(waitForQueuesToFinish: true); // hangs forever, no callbacks are called

I am using PushSharp taken via Git, and compiled by myself with Visual Studio 2013, as of yesterday.

The hang happens both if the code is in a console application and in an asp.net application.

I am using the sandbox, because I was told to. If I use the production server, I get an exception telling me that the certificate is for the sandbox.

Thanks for any hint as to the cause of the freeze.

Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
seguso
  • 2,024
  • 2
  • 18
  • 20
  • Could you wait few seconds for `br_OnNotificationFailed` or any other event? It should contain some error description. – Konrad Kokosa Jul 02 '14 at 18:51
  • Sorry, what do you mean by "wait few seconds for br_onnotificationfailed"? That is a callback, not something to wait for. And it is not being called. – seguso Jul 03 '14 at 06:44
  • PushSharp callbacks are usually called after few seconds. I am not also sure how it can be possible to receive callback when you block your thread with `waitForQueuesToFinish` - isn't it deadlock? By waiting I was thinking about letting the program to run normally and see if you receive any callback. Nevertheless, I would investigate certificates issue - it made me a lot of headache one day. – Konrad Kokosa Jul 03 '14 at 07:08

4 Answers4

4

We spent a whole day trying to guess the problem! In the end it was in the wrong Newtonsoft.Json version Some of the projects in our solution were dependant on the older version of this library as a result we had bad luck to get wrong version in the /bin folder of the Web project.

Andrew
  • 73
  • 1
  • 7
1

You can wait few seconds for br_OnNotificationFailed or any other event probably. It should contain some error description.

Nevertheless, I've found out PushSharp has strict requirements about certificates usage. PEM should be OK but it is not enough, even if you import it from file - you should have all necessary certificates in Windows certificates store (pem itself and its dependecies):

  1. Import your PEM to Local Machine\Root storage and give read access rights of its private key to the user of your running application

  2. Import from Apple site certificates Apple Worldwide Developer Relations Certification Authority and Apple Root CA into Local Machine\Trusted Root Certification Authorities

  3. Import Entrust Secure CA certificate (for SSL as described in iOS Developer Library) into Local Machine\Trusted Root Certification Authorities

Konrad Kokosa
  • 16,563
  • 2
  • 36
  • 58
  • "Import your PEM to Local Machine\Root storage": I can't find a guide to do that. Pageant.exe cannot import it. The right-click menu does not show anything. I am in Windows 8. – seguso Jul 03 '14 at 09:02
  • 1
    @seguso, [here](http://www.sqlservermart.com/HowTo/Windows_Import_Certificate.aspx) you have a small tutorial. But you probably need to convert this pem into pfx, like described [here](http://www.sslshopper.com/article-most-common-openssl-commands.html). – Konrad Kokosa Jul 03 '14 at 09:05
  • Thanks. I cannot convert the pem to p12 because I need two pems for that, and the ios developer won't give both to me. I asked him for a p12, he made one and gave it to me, and now I get a different error. This time an exception is thrown: CryptographicExcepion, thrown by new ApplePushChannelSettings(!sandbox, appleCert, "223684") . I guess I need to open a new question for that... could the p12 be invalid or created incorrectly ? – seguso Jul 03 '14 at 12:00
1

In the end it was a certificate problem. The .pem I was given is not accepted by PushSharp. Only when I was given a .p12 created with this guide

https://code.google.com/p/apns-sharp/wiki/HowToCreatePKCS12Certificate

, the problem was solved.

However, PushSharp should have raised an exception instead of hanging.

seguso
  • 2,024
  • 2
  • 18
  • 20
1

An ASP.NET application is NOT the ideal place to use PushSharp. You'd be better off using a Windows Service, or some other infrastructure if at all possible. The reason is that in an ASP.NET application, the Application Pool (AppPool) can be restarted on you and is usually not under your direct control, which means all the Queued notifications that PushSharp may be in the process of sending could be lost if PushSharp is not cleaned up gracefully.

If you MUST run PushSharp in an ASP.NET application, the best way is to create a singleton PushBroker instance in your Global.asax file. You should keep this singleton instance around for the lifespan of your web application, including a call to pushBroker.StopAllServices() when your Application is ending (Application_End in global.asax).

You can help mitigate losing messages due to unforeseen App Pool terminations or restarts by persisting notifications you want to send in some other way, and only removing them from that persistent storage once the OnNotificationSent event has fired. This is still not perfect (you may risk multiple notification deliveries), but it's probably adequate for most.

You should not be creating and destroying instances of PushBroker each time you send a notification, as this uses unnecessary resources and if you're using Apple APNS, they require you to keep the connection to their servers open as long as possible when sending notifications. You should also call pushBroker.StopAllServices() in your Application_Ended event in your Global.asax. Keep in mind that PushSharp works.

Ref: https://github.com/Redth/PushSharp/issues/240

Vijay Singh Rana
  • 1,060
  • 14
  • 32