Open attilabicsko opened 8 years ago
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.Queue
1.Enqueue(T item)
at PushSharp.Apple.ApnsConnection.Send(CompletableApnsNotification notification)
at PushSharp.Apple.ApnsServiceConnection.
Am I doing something wrong or misunderstanding the concept, or could this happen due to a bug?
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?
any update on this. I am getting the same issue right here.
@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.
Didnt get it. Is it a bug or am I also doing something wrong?
@gabrieligbastos it is a bug. Why this error is coming ?
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.
Any update to workaround this?
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
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.
@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.Queue
1.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,
@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
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.
@tweek82 Thanks for your reply. How did you dequeue the device?
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.
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 https://github.com/Redth/PushSharp/issues/672#issuecomment-251402577, or mute the thread https://github.com/notifications/unsubscribe-auth/AAkJ3F2dvgRN-AUib61wbkhQYtXS9zh4ks5qwmE7gaJpZM4H9ixD .
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);
}
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 👍
No problem. Please share any of your apns-troubles and solutions. It might help me and others too.
Will do, once again thanks for your help @tweek82
Apns notification error: 'ConnectionError'
IIS Express is Succeeded and IIS is Failed
I am getting frequently connection error while sending Push to iOS.
"Failed to Connect, check your firewall settings!
at PushSharp.Apple.ApnsConnection.d25.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.d21.MoveNext() " Sometime it send and sometime it gives error.
Please advice on resolution.
Thanks in Advance.
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-------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------https://github.com/Redth/PushSharp/issues/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!
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
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);
}
}
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.
I get the same error running the service in Azure WebApp. Same code works fine on my laptop.
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)d__21.MoveNext()
at PushSharp.Apple.ApnsConnection.
--- End of inner exception stack trace ---d__2.MoveNext()
at PushSharp.Apple.ApnsServiceConnection.
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.