Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apns notification error: 'ConnectionError' System.NullReferenceException #672

Open
attilabicsko opened this issue Apr 1, 2016 · 27 comments

Comments

@attilabicsko
Copy link

I'm using PushSharp 4.0.4, installed from NuGet

In the OnNotificationFailed(ApnsNotification, AggregateException) event of the Apns broker, I often get this exception:

PushSharp.Apple.ApnsNotificationException: Apns notification error: 'ConnectionError'
---> System.NullReferenceException: Object reference not set to an instance of an object.

at PushSharp.Apple.ApnsConnection.createBatch(List`1 toSend)
at PushSharp.Apple.ApnsConnection.d__21.MoveNext()

--- End of inner exception stack trace ---
at PushSharp.Apple.ApnsServiceConnection.d__2.MoveNext()

It seems to happen randomly. I'm using PushSharp in a Windows Service, running multiple (>300) brokers in the same time stored in a singleton object's ConcurrentDictionary, if that helps.

Please advise how to troubleshoot this error.

@attilabicsko
Copy link
Author

Beside this, sometimes I get the following exception, also in OnNotificationFailed:

System.ArgumentException: Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
at System.Collections.Generic.Queue1.SetCapacity(Int32 capacity) at System.Collections.Generic.Queue1.Enqueue(T item)
at PushSharp.Apple.ApnsConnection.Send(CompletableApnsNotification notification)
at PushSharp.Apple.ApnsServiceConnection.d__2.MoveNext()

Am I doing something wrong or misunderstanding the concept, or could this happen due to a bug?

@iinke
Copy link

iinke commented Apr 4, 2016

Same happens for me.
It reproduces even with 1 broker, just not so often.

Looks like problem is in ApnsConnection class: notifications queue ( Queue<CompletableApnsNotification> notifications ) isn't thread-safe. I think this queue isn't thread-safe because of timerBatchWait timer: timer's callback executes on a new thread, not the broker thread.
If you for example place locks around all places where notifications.Enqueue/notifications.Dequeue is called (lock (notificationBatchQueueLock)), error doesn't seem to reproduce anymore. Should ConcurrentQueue be used instead of Queue here?

@mohammadjouhari
Copy link

any update on this. I am getting the same issue right here.

@mohammadjouhari
Copy link

@iinke I have a lock statement around the method that it is queening the device tokens. I am also creating batches and Queue device tokens in a timer. So in each 3 seconds I am queering 100 devices. But I am still getting this connection error.

iinke pushed a commit to iinke/PushSharp that referenced this issue Apr 13, 2016
@gabrieligbastos
Copy link

Didnt get it. Is it a bug or am I also doing something wrong?

@mohammadjouhari
Copy link

@gabrieligbastos it is a bug. Why this error is coming ?

@gabrieligbastos
Copy link

I have no clue why? It is just sometimes it just give me back this exception. Seems randomly, Could not find a situation that always happens.

Before update my NugetPackage to the new version, it was not getting this error.

@gabrieligbastos
Copy link

Any update to workaround this?

@sparity123
Copy link

I too have the same issue : Connection Error
I recently updated pushsharp library to 4.0.10, if i put thread.sleep(1000) in for loop notifications will be sent but it's getting late. Because I need to send notifications to thousands of device tokens. Even for 10 device tokens also not sending without thread.sleep(1000).
Please suggest me what's wrong with my code.
Here is my code snippet.

public static void SendNotifications(List currentBrandNotications, long brandId)
{
byte[] appleCert = null;

        string p12File = @"aps_production_brand" + brandId.ToString().Trim() + ".p12";
        try
        {
            appleCert = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "P12\\" + p12File));               
        }
        catch (Exception ex)
        {
            logger.Debug("P12 certificate is not avilable for BrandId: " + brandId);
        }

        try
        {
            logger.Debug(" Send PushNotifications To Apple :- ");

            if (appleCert != null)
            {
                // Configuration
                var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Production, appleCert, currentBrandNotications[0].P12Password);

                // Create a new broker
                var apnsBroker = new ApnsServiceBroker(config);
                var fbs = new FeedbackService(config);
                // Wire up events
                apnsBroker.OnNotificationFailed += (Notification, aggregateEx) =>
                {
                    //ScheduledNotification ScheduledNotification = new InstantPNScheduler.ScheduledNotification();

                    aggregateEx.Handle(ex =>
                    {
                        // See what kind of exception it was to further diagnose
                        if (ex is ApnsNotificationException)
                        {
                            var notificationException = (ApnsNotificationException)ex;

                            // Deal with the failed notification
                            var apnsNotification = notificationException.Notification;
                            var statusCode = notificationException.ErrorStatusCode;
                            logger.Debug("Apple Notification Failed: ID=" + apnsNotification.Identifier + " Code=" + statusCode);

                        }
                        else
                        {
                            // Inner exception might hold more useful information like an ApnsConnectionException           
                            logger.Debug(ex.InnerException.ToString());
                        }
                        // Mark it as handled
                        return true;
                    });
                };

                apnsBroker.OnNotificationSucceeded += (Notification) =>
                {
                    logger.Debug("Apple Notification Sent!");                  
                };

                // Start the broker
                apnsBroker.Start();  

                foreach (ScheduledNotification notification in currentBrandNotications)
                     {                      
                    try
                    {
                        //logger.Debug("iOS Device token=" + notification.DeviceToken);                                             apnsBroker.QueueNotification(new ApnsNotification
                        {
                               DeviceToken = notification.DeviceToken,
                               Payload = JObject.Parse("{\"aps\":{\"alert\":\"" + notification.Message + "\",\"badge\":1,\"sound\":\"sound.caf\",\"BrandId\":\"" + brandId.ToString() + "\",\"notificationType\":\"Basic\",\"DeviceType\":\"" + notification.DeviceType + "\",\"DeviceToken\":\"" + notification.DeviceToken + "\",\"NotificationId\":\"" + notification.NotificationId + "\"}}")

                            });
                        }
                        Thread.Sleep(800);
                    }
                    catch (Exception ex)
                    {

                        logger.Debug(" SendPushNotificationToApple :- " + ex.Message);
                    }
                }
                // Stop the broker, wait for it to finish   
                // This isn't done after every message, but after you're
                // done with the broker
                apnsBroker.Stop();
            }

        }
        catch (Exception ex)
        {
            logger.Debug("Error" + ex.Message);
        }
        finally
        {
            //apnsBroker = null;
        }

    }

Thanks in advance.

@lukaspechar
Copy link

@iinke any updates on this? I experienced this when dealing with a larger batch of notifications. I open the broker and send notification on a separate thread. Could this be the issue? Do you suggest I run the service on the main thread? The following are exceptions logged:

Initially one for every notification:

Source array was not long enough. Check srcIndex and length, and the array's lower bounds.

at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable) at System.Collections.Generic.Queue1.SetCapacity(Int32 capacity) at System.Collections.Generic.Queue1.Enqueue(T item) at PushSharp.Apple.ApnsConnection.Send(CompletableApnsNotification notification) at PushSharp.Apple.ApnsServiceConnection.<Send>d__2.MoveNext()

followed by a bunch of:

The ApnsNotificationErrorStatusCode: ConnectionError = 254,

@lukaspechar
Copy link

@Redth Just checking if there are any updates on this issue. I am experiencing this even with a single broker. Would be great to understand what is going on. Any help would be appreciated. Thanks

@dehaaneric
Copy link

I had this problem too. I solved it by checking the Push sharp (verbose) logging by setting:

        Log.ClearLoggers();
        Log.AddLogger(new PushLogger());

It showed the error "Missing Push Token". And because I had a device without a (valid) pushtoken on top of my queue, the APNS server disconnected (all) connection(s) without question.

@lukaspechar
Copy link

@tweek82 Thanks for your reply. How did you dequeue the device?

@dehaaneric
Copy link

I check the push token before I add it to the queue. When token is invalid I directly update the devive in my database by just deleting it.

@lukaspechar
Copy link

I am cleaning the expired devices using the FeedbackService class before I
add any to the queue. Is there an extra check I need to make? How do you
check the validity?

On 4 October 2016 at 16:22, tweek82 notifications@github.com wrote:

I check the push token before I add it to the queue. When token is invalid
I directly update the devive in my database by just deleting it.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#672 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAkJ3F2dvgRN-AUib61wbkhQYtXS9zh4ks5qwmE7gaJpZM4H9ixD
.

@dehaaneric
Copy link

Nothing fancy, just check IsNullOrWhitespace before queue'ing. Like this:

        foreach (var pushQueueItem in pushQueueItems.WithPrioSorting())
        {
            var pushServiceProviders = PushProviders.Single(x => x.DeviceType == pushQueueItem.AccountDeviceType);

            if (string.IsNullOrWhiteSpace(pushQueueItem.PushRegistrationId))
            {
                CurrentLogger.Logger.Info("Missing devicetoken for: "+JsonConvert.SerializeObject(pushQueueItem));
                PushResultIdCollectorService.AddFailedEntry(pushQueueItem.MessagePushRecipientId, DateTime.Now);

                _accountDeviceService.RemovePushDeviceForRecipient(pushQueueItem.MessagePushRecipientId);

                continue;
            }

            pushServiceProviders.Push(pushQueueItem);
        }

@lukaspechar
Copy link

Hmm, ok so you had an empty device token for the device. I guess I'll have to enable the log to monitor what the issue is in my case as I cannot see a reason why my token would be empty or null. I only insert them when the user registers for push notifications from the device. So you used the following to enable logging...

Log.ClearLoggers();
Log.AddLogger(new PushLogger());

I'll give it a go. Thanks for your help and swift replies 👍

@dehaaneric
Copy link

dehaaneric commented Oct 4, 2016

No problem. Please share any of your apns-troubles and solutions. It might help me and others too.

@lukaspechar
Copy link

Will do, once again thanks for your help @tweek82

@bidianqing
Copy link

Apns notification error: 'ConnectionError'

@bidianqing
Copy link

IIS Express is Succeeded and IIS is Failed

@faisalcse
Copy link

faisalcse commented Jul 11, 2017

I am getting frequently connection error while sending Push to iOS.

"Failed to Connect, check your firewall settings!

at PushSharp.Apple.ApnsConnection.d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at PushSharp.Apple.ApnsConnection.d__21.MoveNext()
"
Sometime it send and sometime it gives error.

Please advice on resolution.

Thanks in Advance.

@jimenaju
Copy link

Hello, I seem to be getting the same problem; I send 100 notifications and nothing is wrong, but when one of the tokens is wrong, Ialso get this exception often:
PushSharp.Apple.ApnsNotificationException: Apns notification error: 'ConnectionError'

Will insert code but keep in mind a lot of variables are useless, just using them to try to catch the problem...

`using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Web;
using System.Text;
//using JdSoft.Apple.Apns.Feedback;
using PushSharp.Apple;
//using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace PlaneSeats
{
public class APNS_Server
{ //doubts with Code, refer to:
//https://stackoverflow.com/questions/37045299/issue-with-pushsharp-apple-notification-from-version-4-0-10-0-to-testflight/37133379

    public void pushNotifiaction(String indicadores)
    {
        string outputString;
        string notificationToken;
        string certificatePath = @"D:\Certificados\Certificados 2.p12";
        string certificatePassword = "";
        var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Sandbox, certificatePath, certificatePassword);

        //----------------------------------get tokens arr START---------------------------------------------------------------

        String token_iPhone = "1d26e6aade3755f3e98c94421dfa77b7576f5c6d203aed03d4b09afeccc43dce";
        String token_iPad = "2268ce35a15ec46aeef3dd2820e227ea5d9e0eaa163ef2cc33197230cdf93866";
        String bad_token_1 = "e85583e571b7fc3b712ffd33085ca10b42c3691500b96151e95dbe9fab5bee80";
        String bad_token_2 = "75343d0295c6345fd1a6283e7bc6bd66c5";
        String bad_token_3 = "75343d0295c6345fd1a6283e7bc6bd66c55650e0cce06bf6c3bd4b7a368fc3c7";

        int arrSize = 5;
        String[] tokenArr = new String[arrSize]; // Initialize.
        tokenArr[0] = token_iPhone;           // Element 1.
        tokenArr[1] = token_iPad;             // Element 2.
        tokenArr[2] = bad_token_1;
        tokenArr[3] = bad_token_2;
        tokenArr[4] = bad_token_3;

        //----------------------------------get tokens arr END-----------------------------------------------------------------

        var apnsBroker = new ApnsServiceBroker(config);
        // Wire up events
            apnsBroker.OnNotificationFailed += (notification, aggregateEx) =>
            {
                outputString = String.Format("Apple Notification Failed Exception");
                aggregateEx.Handle(ex =>
                {
                    // See what kind of exception it was to further diagnose
                    if (ex is ApnsNotificationException)
                    {
                        notificationToken = "";
                        var notificationException = (ApnsNotificationException)ex;
                        ApnsNotificationErrorStatusCode errorCode = notificationException.ErrorStatusCode;
                        // Deal with the failed notification
                        var apnsNotification = notificationException.Notification;
                        var stCode = notificationException.ErrorStatusCode;
                        string statusCode = notificationException.ErrorStatusCode.ToString();
                        outputString = String.Format("Apple Notification Failed: ID={0}, Code=-{1}- Error code -{2}-.",
                        apnsNotification.Identifier, statusCode,errorCode);
                        outputString = statusCode;
                        outputString = notificationException.ErrorStatusCode.ToString();
                        notificationToken = apnsNotification.DeviceToken;
                        outputString = notificationToken;

                    }
                    else
                    {
                            // Inner exception might hold more useful information like an ApnsConnectionException           
                            outputString = String.Format("Apple Notification Failed for some unknown reason : {0}",
                            ex.InnerException);
                    }
                    // Mark it as handled
                    return true;
                });
            };
            
            apnsBroker.OnNotificationSucceeded += (notification) =>
            {
                notificationToken = "";
                notificationToken = notification.DeviceToken;
                outputString = String.Format("Apple Notification Sent: ID={0}.",
                notification.Identifier);
                outputString = "Apple Notification Sent!";

            };

//--------------------------------FOR LOOP. STARTS HERE--------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------#763

        apnsBroker.Start();
        foreach (String token in tokenArr)
            {
            //http://desarrolloalpha.inegi.org.mx/app/api/indicadores//interna_v1_1/IOSToken/1ds23/2/json/[TU TOKEN]
            try{
                        
                        // Queue a notification to send
                        ApnsNotification notification = new ApnsNotification
                        {       DeviceToken = token,
                                Payload = JObject.Parse("{\"aps\":{\"alert\":\"Jimena is testing apns feedback service!.\",\"badge\":\"1\"}}")
                                };
                         notification.Tag = token;
                         outputString = "Notification queue";
                         apnsBroker.QueueNotification(notification);
                         //apnsBroker.Stop();
      
            }
                catch (Exception e) {
                outputString = "Notification queue exception";
            }
            
        }
        apnsBroker.Stop();

//--------------------------------FOR LOOP. ENDS HERE--------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------------------------------------------------------------------------------
}
}

}
`
Also... if someone could tell me if the order is correct... I find it reaaally hard to understand as I´m new to... everything coding TT_TT

Thanks!

@andrei1152
Copy link

fixed this problem by setting config.internalBatchSize = int.MaxValue;
I think the notification queue is not thread safe and when notifications are divided into batches, adding them to the queue raises this exception

@andersemil
Copy link

andersemil commented Oct 13, 2017

Same issue here, I think I might have fixed it by locking notificationBatchQueueLock around the dequeueing, like this:

			lock (notificationBatchQueueLock) {
				while (notifications.Count > 0 && toSend.Count < Configuration.InternalBatchSize) {
					var n = notifications.Dequeue ();
					toSend.Add (n);
				}
			}

@EduardoKSibata
Copy link

Maybe this problem can occur when the token is in invalid format.
The token must be with Alphanumerics characters only, no white spaces or something else..
It works for me.

@fatim
Copy link

fatim commented Aug 23, 2018

I get the same error running the service in Azure WebApp. Same code works fine on my laptop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests