Created
April 26, 2012 07:22
-
-
Save icleversoft/2497126 to your computer and use it in GitHub Desktop.
Sending Apple Push Notifications using C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
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!
Thank you for your written code. It works for me.
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
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));