2

I am trying to develop my own Apple Push Notification Server application to send push notification to iOS devices. I download the source code for Moon-APNS from GitHub and modified it to fit with my Web API application.

The following line of code is causing IIS to throw an unhandled win32 exception:

apnsStream.BeginRead(response, 0, 6, new AsyncCallback(ReadResponse), new MyAsyncInfo(response, apnsStream));

Went I look in my computer applications windows log in event viewer, the unhandled exception comes from the ReadResponse method. I have the code with the ReadResponse method and apnsStream.BeginRead call contained within a try-catch statements and it still throws an unhandled exception.

Message: Safe handle has been closed

Stack Trace: at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.ContextAwareResult.Complete(IntPtr userToken) at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

Here is the complete section of source when I open the TcpClient to the Apple Push Notification Server:

using(TcpClient apnsClient = new TcpClient())
{
    //open connection to the Apple Push Notification service a TCP client connection
    apnsClient.Connect("gateway.sandbox.push.apple.com", 2195);

    //open an SSL Stream
    using(SslStream apnsStream = new SslStream(apnsClient.GetStream(), false, ValidateServerCertificate, SelectLocalCertificate))
    {
        apnsStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", certificates, System.Security.Authentication.SslProtocols.Default, false);

        _CanReadStream = apnsStream.CanRead;
        _IsConnected = true;

        var response = new byte[6];

        apnsStream.BeginRead(response, 0, 6, new AsyncCallback(ReadResponse), new MyAsyncInfo(response, apnsStream));

        //put code to generate payload here           
    }
}

Source code from ReadResponse method

private void ReadResponse(IAsyncResult ar)
{
    if (_IsConnected) return;

    int payLoadIndex = 0;
    string payLoadId = string.Empty;

    try
    {
        var info = ar.AsyncState as MyAsyncInfo;
        info.Stream.ReadTimeout = 100;

        if (_CanReadStream)
        {
            var command = Convert.ToInt16(info.ByteArray[0]);
            var status = Convert.ToInt16(info.ByteArray[1]);
            var id = new byte[4];
            Array.Copy(info.ByteArray, 2, id, 0, 4);

            payLoadId = Encoding.Default.GetString(id);
            payLoadIndex = int.Parse(payLoadId) - 1000;

            _RejectedDevices.Add(_NotificationPayload[payLoadIndex].DeviceToken);

             _IsConnected = false;
         }
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

What can do to resolve this issue?

Michael Kniskern
  • 24,792
  • 68
  • 164
  • 231
  • Your code doesn't make sense. You are attempting to read error responses from a socket that you just opened. That would never return anything. You should only attempt to read error responses from a socket to which you already sent push notifications. – Eran Aug 21 '14 at 18:08
  • @Eran - so is the problem my use of the `using` statements or the `apnsStream.BeginRead` call itself? Which part of my code is trying to read error responses? I tried to follow the same pattern in the PushNotification.cs on Moon-APNS https://github.com/arashnorouzi/Moon-APNS/blob/master/Application/MoonApns/PushNotification.cs This is pretty foreign territory for me, so please excuse my lack of understanding. – Michael Kniskern Aug 21 '14 at 19:08
  • The entire code you posted attempts to read error responses. Error responses are the only responses Apple send. If the code you posted comes from `ReadResponse` method, then this method is useless, and you shouldn't use it. It only makes sense to read error responses from the same sockets to which you previously wrote push notifications. – Eran Aug 21 '14 at 19:15
  • @Eran - This code does not come from the `ReadResponse` method. This code is me trying to establish a connection to the APNS server. I will update the question with the `ReadResponse` method source code. – Michael Kniskern Aug 21 '14 at 19:17
  • In that case, just remove the `apnsStream.BeginRead` call. Or put it after you write a push notification to the Stream. – Eran Aug 21 '14 at 19:19
  • @Eran - Did you happen to look at the source code for the PushNotification.cs for Moon-APNS? He is doing the same thing when he establishes his connection via `TcpClient` https://github.com/arashnorouzi/Moon-APNS/blob/master/Application/MoonApns/PushNotification.cs#L124 – Michael Kniskern Aug 21 '14 at 19:27

0 Answers0