C# iPhone push server?
Asked Answered
T

6

30

Im attempting to write a push server for the iPhone in C#. I have the following code:

        // Create a TCP/IP client socket.
        using (TcpClient client = new TcpClient())
        {
            client.Connect("gateway.sandbox.push.apple.com", 2195);
            using (NetworkStream networkStream = client.GetStream())
            {
                Console.WriteLine("Client connected.");

                X509Certificate clientCertificate = new X509Certificate(@"certfile.p12", passwordHere);
                X509CertificateCollection clientCertificateCollection = new X509CertificateCollection(new X509Certificate[1] { clientCertificate });

                // Create an SSL stream that will close the client's stream.
                SslStream sslStream = new SslStream(
                    client.GetStream(),
                    false,
                    new RemoteCertificateValidationCallback(ValidateServerCertificate),
                    null
                    );

                try
                {
                    sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com");
                }
                catch (AuthenticationException e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                    if (e.InnerException != null)
                    {
                        Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                    }
                    Console.WriteLine("Authentication failed - closing the connection.");
                    client.Close();
                    return;
                }
            }

ect....

Only I keep receiving a exception: "A call to SSPI failed, see Inner exception" Inner Exception -> "The message received was unexpected or badly formatted."

Does anyone have any idea whats going wrong here?

Transformer answered 28/6, 2009 at 23:57 Comment(5)
Figured it out. Replaced sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com"); with sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", clientCertificateCollection, SslProtocols.Default, false); And registered the certificates on the PC.Transformer
Yes, I have everything working and can push messages to my iPhone. Don't forget to register your .p12 file with windows.Transformer
Are you running mono on your iPhone?Alumina
you should answer your own question to close it.Calcicole
@Zenox - Is registering the .p12 file a necessary step? I thought since you were loading it from the file it wouldn't matter.Nickelson
T
8

Figured it out. Replaced sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com"); with sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", clientCertificateCollection, SslProtocols.Default, false); And registered the certificates on the PC.

Edit: Here is the code for creating a payload as requested:

    private static byte[] GeneratePayload(byte [] deviceToken, string message, string sound)
    {
        MemoryStream memoryStream = new MemoryStream();

        // Command
        memoryStream.WriteByte(0);

        byte[] tokenLength = BitConverter.GetBytes((Int16)32);
        Array.Reverse(tokenLength);
        // device token length
        memoryStream.Write(tokenLength, 0, 2);

        // Token
        memoryStream.Write(deviceToken, 0, 32);

        // String length
        string apnMessage = string.Format ( "{{\"aps\":{{\"alert\":{{\"body\":\"{0}\",\"action-loc-key\":null}},\"sound\":\"{1}\"}}}}",
            message,
            sound);

        byte [] apnMessageLength = BitConverter.GetBytes((Int16)apnMessage.Length);
        Array.Reverse ( apnMessageLength );
        // message length
        memoryStream.Write(apnMessageLength, 0, 2);

        // Write the message
        memoryStream.Write(System.Text.ASCIIEncoding.ASCII.GetBytes(apnMessage), 0, apnMessage.Length);

        return memoryStream.ToArray();
    } // End of GeneratePayload
Transformer answered 23/7, 2009 at 22:16 Comment(1)
What folder (Certificate Store) should I use to import to on Windows Server? Is it Personal or Trusted Publisher? I tried "Default select based on certificate type" but didnt work.Postaxial
W
5

From Zenox's comment: use a different version of AuthenticateAsClient

sslStream.AuthenticateAsClient("gateway.sandbox.push.apple.com", clientCertificateCollection, SslProtocols.Default, false);
Weir answered 16/7, 2009 at 19:42 Comment(0)
P
1

Other way is just to use X509Certificate2 and X509CertificateCollection2 classes.

Phanerogam answered 3/7, 2009 at 3:27 Comment(0)
H
1

I recently used Growl For Windows to push messages to the Prowl client on the IPhone from .Net code. So you might get your functionatlity without writing a push server yourself.

Heartsick answered 11/7, 2009 at 22:3 Comment(1)
That may work for pushing data to the apn, but what about handling the feedback though?Transformer
I
0

The "The message received was unexpected or badly formatted." error usually comes when you did not register the p12 certificate in Windows. (Under Vista, just double click on the p12 file and the import wizard will open)

Idyll answered 16/7, 2009 at 12:13 Comment(0)
E
0

In my case I had to delete all the certificate from my windows 8 and then re-install them in order to send push notifications to apple device.

I do not know why my certificates stop working, I am searching for the correct reason and will update here soon.

Ellett answered 28/11, 2013 at 7:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.