/// <summary>
        /// Given the raw packet data, converts the data back into a <see cref="RegistrationPacket"/>
        /// </summary>
        /// <param name="bytes">The raw packet data</param>
        /// <param name="passwordManager">The list of client passwords</param>
        /// <param name="passwordRequired">Indicates if the request must supply a valid password</param>
        /// <returns><see cref="RegistrationPacket"/></returns>
        /// <remarks>
        /// If the client password does not match the password used to validate the sent notification,
        /// or if the packet is malformed in any way, a <c>null</c> object will be returned.
        /// </remarks>
        public static RegistrationPacket FromPacket(byte[] bytes, PasswordManager passwordManager, bool passwordRequired)
        {
            RegistrationPacket rp = null;

            // parse the packet
            if (bytes != null && bytes.Length > 18)
            {
                // check md5 hash first
                string password = null;
                bool   valid    = BasePacket.IsPasswordValid(bytes, passwordManager, passwordRequired, out password);
                if (!valid)
                {
                    return(rp);
                }

                int        protocolVersion = (int)bytes[0];
                PacketType packetType      = (PacketType)bytes[1];

                if (packetType == PacketType.Registration)
                {
                    int index = 6;
                    List <NotificationType> notificationTypes = new List <NotificationType>();
                    short  applicationNameLength    = BitConverter.ToInt16(new byte[] { bytes[3], bytes[2] }, 0);
                    int    notificationCount        = (int)bytes[4];
                    int    defaultNotificationCount = (int)bytes[5];
                    string applicationName          = Encoding.UTF8.GetString(bytes, index, applicationNameLength);
                    index += applicationNameLength;
                    for (int n = 0; n < notificationCount; n++)
                    {
                        short  notificationNameLength = BitConverter.ToInt16(new byte[] { bytes[index + 1], bytes[index] }, 0);
                        string notificationName       = Encoding.UTF8.GetString(bytes, index + 2, notificationNameLength);
                        index += 2 + notificationNameLength;
                        NotificationType nt = new NotificationType(notificationName, false);
                        notificationTypes.Add(nt);
                    }
                    for (int d = 0; d < defaultNotificationCount; d++)
                    {
                        int notificationIndex = (int)bytes[index++];
                        notificationTypes[notificationIndex].Enabled = true;
                    }

                    rp = new RegistrationPacket(protocolVersion, applicationName, password, notificationTypes);
                }
            }

            return(rp);
        }
        /// <summary>
        /// Given the raw packet data, converts the data back into a <see cref="NotificationPacket"/>
        /// </summary>
        /// <param name="bytes">The raw packet data</param>
        /// <param name="passwordManager">The list of client passwords</param>
        /// <param name="passwordRequired">Indicates if the request must supply a valid password</param>
        /// <returns><see cref="NotificationPacket"/></returns>
        /// <remarks>
        /// If the client password does not match the password used to validate the sent notification,
        /// or if the packet is malformed in any way, a <c>null</c> object will be returned.
        /// </remarks>
        public static NotificationPacket FromPacket(byte[] bytes, PasswordManager passwordManager, bool passwordRequired)
        {
            NotificationPacket np = null;

            // parse the packet
            if (bytes != null && bytes.Length > 18)
            {
                // check md5 hash first
                string password = null;
                bool   valid    = BasePacket.IsPasswordValid(bytes, passwordManager, passwordRequired, out password);
                if (!valid)
                {
                    return(np);
                }

                int        protocolVersion = (int)bytes[0];
                PacketType packetType      = (PacketType)bytes[1];

                if (packetType == PacketType.Notification)
                {
                    short    flags    = BitConverter.ToInt16(new byte[] { bytes[3], bytes[2] }, 0);
                    bool     sticky   = ((flags & 1) == 1 ? true : false);
                    Priority priority = ConvertFlagToPriority(flags);

                    short notificationNameLength = BitConverter.ToInt16(new byte[] { bytes[5], bytes[4] }, 0);
                    short titleLength            = BitConverter.ToInt16(new byte[] { bytes[7], bytes[6] }, 0);
                    short descriptionLength      = BitConverter.ToInt16(new byte[] { bytes[9], bytes[8] }, 0);
                    short applicationNameLength  = BitConverter.ToInt16(new byte[] { bytes[11], bytes[10] }, 0);

                    int    index            = 12;
                    string notificationName = Encoding.UTF8.GetString(bytes, index, notificationNameLength);
                    index += notificationNameLength;
                    string title = Encoding.UTF8.GetString(bytes, index, titleLength);
                    index += titleLength;
                    string description = Encoding.UTF8.GetString(bytes, index, descriptionLength);
                    index += descriptionLength;
                    string applicationName = Encoding.UTF8.GetString(bytes, index, applicationNameLength);

                    NotificationType nt = NotificationType.GetByName(notificationName); //TODO:
                    np = new NotificationPacket(protocolVersion, applicationName, password, nt, title, description, priority, sticky);
                }
            }

            return(np);
        }