Ejemplo n.º 1
0
        ApnsServerNotification Parse(List <byte> data)
        {
            // COMMAND          FRAME LENGTH    FRAME
            // 1 byte (0x02)    4 bytes         ITEM ... ITEM ... ITEM ...

            // ITEM ID          ITEM LENGTH     ITEM DATA
            // 1 byte           2 bytes         variable length

            // ITEMS:
            // 1: 32 bytes                      Device Token
            // 2: 2048 bytes (up to)            Payload
            // 3: 4 bytes                       Notification identifier
            // 4: 4 bytes                       Expiration
            // 5: 1 byte                        Priority (10 - immediate, or 5 - normal)

            var notification = new ApnsServerNotification();

            ApnsNotificationException exception = null;

            // If there aren't even 5 bytes, we can't even check if the length of notification is correct
            if (data.Count < 5)
            {
                return(null);
            }

            // Let's check to see if the notification is all here in the buffer
            var apnsCmd         = data [0];
            var apnsFrameLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.GetRange(1, 4).ToArray(), 0));

            // If we don't have all of the notification's frame data that we should have, we need to keep waiting
            if (data.Count - 5 < apnsFrameLength)
            {
                return(null);
            }

            var frameData = data.GetRange(5, apnsFrameLength);

            // Remove the data we are processing
            data.RemoveRange(0, apnsFrameLength + 5);

            // Now process each item from the frame
            while (frameData.Count > 0)
            {
                // We need at least 4 bytes to count as a full item (1 byte id + 2 bytes length + at least 1 byte data)
                if (frameData.Count < 4)
                {
                    exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.ProcessingError, "Invalid Frame Data");
                    break;
                }

                var itemId     = frameData [0];
                var itemLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt16(frameData.GetRange(1, 2).ToArray(), 0));

                // Make sure the item data is all there
                if (frameData.Count - 3 < itemLength)
                {
                    exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.ProcessingError, "Invalid Item Data");
                    break;
                }

                var itemData = frameData.GetRange(3, itemLength);
                frameData.RemoveRange(0, itemLength + 3);

                if (itemId == 1)   // Device Token

                {
                    notification.DeviceToken = BitConverter.ToString(itemData.ToArray()).Replace("-", "");
                    if (notification.DeviceToken.Length != 64)
                    {
                        exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.InvalidTokenSize, "Invalid Token Size");
                    }
                }
                else if (itemId == 2)     // Payload

                {
                    notification.Payload = BitConverter.ToString(itemData.ToArray());
                    if (notification.Payload.Length > 2048)
                    {
                        exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.InvalidPayloadSize, "Invalid Payload Size");
                    }
                }
                else if (itemId == 3)     // Identifier

                {
                    if (itemData.Count > 4)
                    {
                        exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.ProcessingError, "Identifier too long");
                    }
                    else
                    {
                        notification.Identifier = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(itemData.ToArray(), 0));
                    }
                }
                else if (itemId == 4)     // Expiration

                {
                    int secondsSinceEpoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(itemData.ToArray(), 0));

                    var expire = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(secondsSinceEpoch);
                    notification.Expiration = expire;
                }
                else if (itemId == 5)     // Priority
                {
                    notification.Priority = itemData [0];
                }
            }

            if (exception == null && string.IsNullOrEmpty(notification.DeviceToken))
            {
                exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.MissingDeviceToken, "Missing Device Token");
            }
            if (exception == null && string.IsNullOrEmpty(notification.Payload))
            {
                exception = new ApnsNotificationException(ApnsNotificationErrorStatusCode.MissingPayload, "Missing Payload");
            }

            // See if there was an error and we can assign an ID to it
            if (exception != null)
            {
                exception.NotificationId = notification.Identifier;

                throw exception;
            }

            return(notification);
        }
Ejemplo n.º 2
0
        ApnsServerNotification Parse (List<byte> data)
        {            
            // COMMAND          FRAME LENGTH    FRAME
            // 1 byte (0x02)    4 bytes         ITEM ... ITEM ... ITEM ...

            // ITEM ID          ITEM LENGTH     ITEM DATA
            // 1 byte           2 bytes         variable length

            // ITEMS:
            // 1: 32 bytes                      Device Token
            // 2: 2048 bytes (up to)            Payload
            // 3: 4 bytes                       Notification identifier
            // 4: 4 bytes                       Expiration
            // 5: 1 byte                        Priority (10 - immediate, or 5 - normal)

            var notification = new ApnsServerNotification ();

            ApnsNotificationException exception = null;

            // If there aren't even 5 bytes, we can't even check if the length of notification is correct
            if (data.Count < 5)
                return null;

            // Let's check to see if the notification is all here in the buffer
            var apnsCmd = data [0];
            var apnsFrameLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(data.GetRange (1, 4).ToArray (), 0));

            // If we don't have all of the notification's frame data that we should have, we need to keep waiting
            if (data.Count - 5 < apnsFrameLength)
                return null;
       
            var frameData = data.GetRange (5, apnsFrameLength);

            // Remove the data we are processing
            data.RemoveRange (0, apnsFrameLength + 5);

            // Now process each item from the frame
            while (frameData.Count > 0) {

                // We need at least 4 bytes to count as a full item (1 byte id + 2 bytes length + at least 1 byte data)
                if (frameData.Count < 4) {
                    exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.ProcessingError, "Invalid Frame Data");
                    break;
                }
                    
                var itemId = frameData [0];
                var itemLength = IPAddress.NetworkToHostOrder (BitConverter.ToInt16 (frameData.GetRange (1, 2).ToArray (), 0));

                // Make sure the item data is all there
                if (frameData.Count - 3 < itemLength) {
                    exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.ProcessingError, "Invalid Item Data");
                    break;
                }

                var itemData = frameData.GetRange (3, itemLength);
                frameData.RemoveRange (0, itemLength + 3);

                if (itemId == 1) { // Device Token

                    notification.DeviceToken = BitConverter.ToString(itemData.ToArray()).Replace("-", "");
                    if (notification.DeviceToken.Length != 64)
                        exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.InvalidTokenSize, "Invalid Token Size");

                } else if (itemId == 2) { // Payload

                    notification.Payload = BitConverter.ToString(itemData.ToArray());
                    if (notification.Payload.Length > 2048)
                        exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.InvalidPayloadSize, "Invalid Payload Size");

                } else if (itemId == 3) { // Identifier

                    if (itemData.Count > 4)
                        exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.ProcessingError, "Identifier too long");
                    else
                        notification.Identifier = IPAddress.NetworkToHostOrder (BitConverter.ToInt32 (itemData.ToArray (), 0));

                } else if (itemId == 4) { // Expiration

                    int secondsSinceEpoch = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(itemData.ToArray (), 0));

                    var expire = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (secondsSinceEpoch);
                    notification.Expiration = expire;

                } else if (itemId == 5) { // Priority
                    notification.Priority = itemData [0];
                }
            }

            if (exception == null && string.IsNullOrEmpty (notification.DeviceToken))
                exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.MissingDeviceToken, "Missing Device Token");
            if (exception == null && string.IsNullOrEmpty (notification.Payload))
                exception = new ApnsNotificationException (ApnsNotificationErrorStatusCode.MissingPayload, "Missing Payload");

            // See if there was an error and we can assign an ID to it
            if (exception != null) {
                exception.NotificationId = notification.Identifier;

                throw exception;
            }

            return notification;
        }