internal static MemoryStream GeneratePayload(NotificationPayload payload, ILogger logger) { try { //convert Devide token to HEX value. byte[] deviceToken = new byte[payload.DeviceToken.Length / 2]; for (int i = 0; i < deviceToken.Length; i++) { deviceToken[i] = byte.Parse(payload.DeviceToken.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); } var frameMemStream = new MemoryStream(); var endianWriter = new MiscUtil.IO.EndianBinaryWriter(MiscUtil.Conversion.EndianBitConverter.Big, frameMemStream); //item 1, device token endianWriter.Write((byte)1); endianWriter.Write((UInt16)32); frameMemStream.Write(deviceToken, 0, 32); //item 2, Payload string apnMessage = payload.ToJson(); endianWriter.Write((byte)2); endianWriter.Write((UInt16)apnMessage.Length); frameMemStream.Write(Encoding.UTF8.GetBytes(apnMessage), 0, apnMessage.Length); //item 3, Identifier endianWriter.Write((byte)3); endianWriter.Write((UInt16)4); endianWriter.Write((UInt32)payload.PayloadId); //item 4, Expiry date DateTime concreteExpireDateUtc = (DateTime.UtcNow.AddMonths(1)).ToUniversalTime(); TimeSpan epochTimeSpan = concreteExpireDateUtc - UNIX_EPOCH; var expiryTimeStamp = (int)epochTimeSpan.TotalSeconds; endianWriter.Write((byte)4); endianWriter.Write((UInt16)4); endianWriter.Write((UInt32)expiryTimeStamp); //item5 endianWriter.Write((byte)5); endianWriter.Write((UInt16)1); frameMemStream.WriteByte(5); return(frameMemStream); } catch (Exception ex) { logger.Error("Unable to generate payload - " + ex.Message); return(null); } }
private async Task <bool> ReadPossibleResponseAsync(NotificationPayload item) { var response = new byte[6]; var readCancelToken = new CancellationTokenSource(); // We are going to read from the stream, but the stream *may* not ever have any data for us to // read (in the case that all the messages sent successfully, apple will send us nothing // So, let's make our read timeout after a reasonable amount of time to wait for apple to tell // us of any errors that happened. readCancelToken.CancelAfter(750); int len = -1; while (!readCancelToken.IsCancellationRequested) { // See if there's data to read if (_connection.ApnsClient.Client.Available > 0) { len = await _connection.ApnsStream.ReadAsync(response, 0, 8).ConfigureAwait(false); break; } // Let's not tie up too much CPU waiting... await Task.Delay(50).ConfigureAwait(false); } if (len < 0) { //If we timed out waiting, but got no data to read, everything must be ok! _connection.Logger.Info("Notification successfully sent to APNS server for Device Token : " + item.DeviceToken); return(true); } else if (len == 0) { // If we got no data back, and we didn't end up canceling, the connection must have closed _connection.Logger.Info("APNS-Client: Server Closed Connection"); // Connection was closed _connection.Disconnect(); return(false); } // If we make it here, we did get data back, so we have errors var command = response[0]; if (command == 8) { var status = response[1]; var ID = new byte[4]; Array.Copy(response, 2, ID, 0, 4); var payLoadId = Encoding.ASCII.GetString(ID); var payLoadIndex = ((int.Parse(payLoadId)) - 1000); _connection.Logger.Error("Apple rejected palyload for device token : " + _notifications[payLoadIndex].DeviceToken); _connection.Logger.Error("Apple Error code : " + _errorList[status]); _connection.Logger.Error("Connection terminated by Apple."); _rejected.Add(_notifications[payLoadIndex].DeviceToken); _connection.Disconnect(); } return(false); }