Skip to content

Instantly share code, notes, and snippets.

@icleversoft
Created April 26, 2012 07:22
Show Gist options
  • Save icleversoft/2497126 to your computer and use it in GitHub Desktop.
Save icleversoft/2497126 to your computer and use it in GitHub Desktop.
Sending Apple Push Notifications using C#
int port = 2195;
String hostname = "gateway.sandbox.push.apple.com";
//load certificate
string certificatePath = @"cert.p12";
string certificatePassword = "";
X509Certificate2 clientCertificate = new X509Certificate2(certificatePath, certificatePassword);
X509Certificate2Collection certificatesCollection = new X509Certificate2Collection(clientCertificate);
TcpClient client = new TcpClient(hostname, port);
SslStream sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
try
{
sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls, true);
}
catch (AuthenticationException ex)
{
client.Close();
return;
}
// Encode a test message into a byte array.
MemoryStream memoryStream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(memoryStream);
writer.Write((byte)0); //The command
writer.Write((byte)0); //The first byte of the deviceId length (big-endian first byte)
writer.Write((byte)32); //The deviceId length (big-endian second byte)
String deviceId = "DEVICEIDGOESHERE";
writer.Write(ToByteArray(deviceId.ToUpper()));
String payload = "{\"aps\":{\"alert\":\"I like spoons also\",\"badge\":14}}";
writer.Write((byte)0); //First byte of payload length; (big-endian first byte)
writer.Write((byte)payload.Length); //payload length (big-endian second byte)
byte[] b1 = System.Text.Encoding.UTF8.GetBytes(payload);
writer.Write(b1);
writer.Flush();
byte[] array = memoryStream.ToArray();
sslStream.Write(array);
sslStream.Flush();
// Close the client connection.
client.Close();
@MaDeRkAn
Copy link

Hello after sslStream.Write(array);
How can I understand notification is pushed successfully.

@RBische
Copy link

RBische commented Jul 16, 2015

Hello,
To send a bigger payload, it is necessary to write the first byte of payload length.
Like this :
writer.Write(Convert.ToByte(Math.Floor(utf8Bytes.Count() / 256)));
//First byte of payload length; (big-endian first byte)
writer.Write(Convert.ToByte(utf8Bytes.Count() % 256));

@dungnk
Copy link

dungnk commented Jul 18, 2015

I have used gistfile1.cs above. however, it returns error :" Authentication failed because the remote party has closed the transport stream" with function sslStream.AuthenticateAsClient(...)
Please help me!

@VictorZhang2014
Copy link

Thank you for your written code. It works for me.

@Vishwadeep-Sukhdeve
Copy link

Thank you
this work for me after finding below methods

`private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        // Do not allow this client to communicate with unauthenticated servers.
        return false;
    }


    public static byte[] ConvertToByteArray(string value)
    {
        byte[] bytes = null;
        if (String.IsNullOrEmpty(value))
            bytes = null;
        else
        {
            int string_length = value.Length;
            int character_index = (value.StartsWith("0x", StringComparison.Ordinal)) ? 2 : 0; // Does the string define leading HEX indicator '0x'. Adjust starting index accordingly.
            int number_of_characters = string_length - character_index;

            bool add_leading_zero = false;
            if (0 != (number_of_characters % 2))
            {
                add_leading_zero = true;

                number_of_characters += 1;  // Leading '0' has been striped from the string presentation.
            }

            bytes = new byte[number_of_characters / 2]; // Initialize our byte array to hold the converted string.

            int write_index = 0;
            if (add_leading_zero)
            {
                bytes[write_index++] = FromCharacterToByte(value[character_index], character_index);
                character_index += 1;
            }

            for (int read_index = character_index; read_index < value.Length; read_index += 2)
            {
                byte upper = FromCharacterToByte(value[read_index], read_index, 4);
                byte lower = FromCharacterToByte(value[read_index + 1], read_index + 1);

                bytes[write_index++] = (byte)(upper | lower);
            }
        }

        return bytes;
    }

    private static byte FromCharacterToByte(char character, int index, int shift = 0)
    {
        byte value = (byte)character;
        if (((0x40 < value) && (0x47 > value)) || ((0x60 < value) && (0x67 > value)))
        {
            if (0x40 == (0x40 & value))
            {
                if (0x20 == (0x20 & value))
                    value = (byte)(((value + 0xA) - 0x61) << shift);
                else
                    value = (byte)(((value + 0xA) - 0x41) << shift);
            }
        }
        else if ((0x29 < value) && (0x40 > value))
            value = (byte)((value - 0x30) << shift);
        else
            throw new InvalidOperationException(String.Format("Character '{0}' at index '{1}' is not valid alphanumeric character.", character, index));

        return value;
    }

    private byte[] HexString2Bytes(String hexString)
    {
        //check for null
        if (hexString == null) return null;
        //get length
        int len = hexString.Length;
        if (len % 2 == 1) return null;
        int len_half = len / 2;
        //create a byte array
        byte[] bs = new byte[len_half];
        try
        {
            //convert the hexstring to bytes
            for (int i = 0; i != len_half; i++)
            {
                bs[i] = (byte)Int32.Parse(hexString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
            }
        }
        catch (Exception ex)
        {
            //MessageBox.Show("Exception : " + ex.Message);
        }
        //return the byte array
        return bs;
    }`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment