iphone push function of C language implementation.
Directly on the source code:
IPPUSH.C//Compile under Linux: Gcc-o ippush ippush.c-lssl #ifdef _win32 # define Win32_lean_and_mean # include <windows.h&
Gt #else # include <sys/types.h> # include <sys/socket.h> # include <netinet/in.h> # include <netdb.h>
; # include <arpa/inet.h> # include <string.h> # include <unistd.h> # include <fcntl.h> # include &L t;errno.h> #endif #include <stdlib.h> #include <stdint.h> #include <assert.h> #include <openssl /ssl.h> #include <openssl/bio.h> #include <openssl/err.h> #define MAX_PAYLOAD_SIZE 256 #define Token_siz E void Devicetoken2binary (const char* SZ, const int len, unsigned char* const binary, const int size) {int I, Val
;
const char* PIN;
Char Buf[3] = {0};
ASSERT (size >= token_size);
for (i = 0;i < len;i++) {pin = sz + i * 2;
Buf[0] = pin[0];
BUF[1] = pin[1];
val = 0;
SSCANF (buf, "%x", &val);
Binary[i] = val;
} return; } void Devicebinary2toKen (const unsigned char* data, const int len, char* const token, const int size) {int i;
ASSERT (Size > Token_size * 2);
for (i = 0;i < len;i++) {sprintf (token + i * 2, "%02x", Data[i]);
} return; void closesocket (int socket) {#ifdef _WIN32 closesocket (socket); #else close (socket); #endif}//Initialize SSL library, Windows early
Start Winsock void Init_openssl () {#ifdef _win32 wsadata wsadata;
WSAStartup (Makeword (2, 2), &wsadata);
#endif ssl_library_init ();
Err_load_bio_strings ();
Ssl_load_error_strings ();
Openssl_add_all_algorithms (); } ssl_ctx* init_ssl_context (const char* Clientcert,/* Client's certificate/const char* Clientkey,/* Client key */const char* KEYPWD,/* Client key password, if any, */const char* CACert)/* Server CA certificate If any, *//Set up the SSL context ssl_ctx *ctx = Ssl_
Ctx_new (Sslv23_client_method ());
if (!ctx) {return NULL;
}//Certificate if (Ssl_ctx_use_certificate_file (CTX, Clientcert, Ssl_filetype_pem) <= 0) {return NULL; }//Key if (ssl_ctX_use_privatekey_file (CTX, Clientkey, Ssl_filetype_pem) <= 0) {return NULL;
}//Make sure the key and certificate file match if (Ssl_ctx_check_private_key (CTX) = = 0) {return NULL; }//Load CA if exist if (CACert) {if (!
Ssl_ctx_load_verify_locations (CTX, CACert, null)) {return null;
} return CTX;
///Establish TCP connection to server int tcp_connect (const char* host, int port) {struct hostent *hp;
struct sockaddr_in addr;
int sock =-1; Resolves the domain name if (!) (
HP = gethostbyname (host)) {return-1;
} memset (&addr, 0, sizeof (addr));
addr.sin_addr = * (struct in_addr*) hp->h_addr_list[0];
addr.sin_family = af_inet;
Addr.sin_port = htons (port);
if ((sock = socket (af_inet, Sock_stream, ipproto_tcp)) < 0) {return-1;
} if (Connect (sock, (struct sockaddr*) &addr, sizeof (addr))!= 0) {return-1;
Return sock;
//Implement SSL handshake, establish SSL connection ssl* Ssl_connect (ssl_ctx* CTX, int socket) {SSL *ssl = ssl_new (CTX);
BIO *bio = bio_new_socket (socket, bio_noclose);Ssl_set_bio (SSL, bio, bio);
if (Ssl_connect (SSL) <= 0) {return NULL;
} return SSL; //Verify server Certificate//First verify that the server's certificate is valid and that the CommonName (CN) of its secondary authentication server certificate is the same as our//actual server domain name int verify_connection (ssl* SSL, const char* p
eername) {int result = Ssl_get_verify_result (SSL); If (result!= x509_v_ok) {fprintf (stderr, "warning!
SSL Verify failed:%d ", result);
return-1;
} X509 *peer;
Char peer_cn[256] = {0};
Peer = ssl_get_peer_certificate (SSL);
X509_name_get_text_by_nid (X509_get_subject_name (peer), nid_commonname, PEER_CN, 255); if (strcmp (PEER_CN, PeerName)!= 0) {fprintf (stderr, "warning!
Server Name doesn ' t match, got:%s, required:%s, PEER_CN, peername);
return 0;
} void Json_escape (char* str) {int n;
Char buf[1024];
n = strlen (str) * sizeof (char) + 100;
ASSERT (N < sizeof (BUF));
strncpy (buf, str, n);
Buf[n] = ' the ';
char *found = BUF; while (*found!= ') {if (' \ ' = = = *found | | ' "' = = *found | | \ n ' = *found | | '/' = = *found) *str++ ='\\';
if (' \ n ' = = *found) *found = ' n ';
*str++ = *found++;
} *str= ';
Return }//Payload example//{"APS": {"alert": "You got your emails.", "badge": 9, "sound": "Default"} int build_payload (cha
r* buffer, int* Plen, char* msg, int badage, const char * sound) {int n;
Char buf[2048];
Char str[2048] = "{\ aps\": {\ "alert\": \ "";
n = strlen (str);
if (msg) {strcpy (buf, msg);
Json_escape (BUF);
n = n + sprintf (str+n, "%s", buf);
} n = n + sprintf (str+n, "%s%d", "\", \ "badge\": ", badage);
if (sound) {n = n + sprintf (str+n, "%s", ", \" sound\ ": \");
strcpy (buf, sound);
Json_escape (BUF);
n = n + sprintf (str+n, "%s%s", buf, "\");
} strcat (str, "}}");
n = strlen (str);
if (n > *plen) {*plen = n;
return-1;
} if (n < *plen) {strcpy (buffer, str);
else {strncpy (buffer, str, *plen);
} *plen = n;
return *plen; ///The first form of package int build_output_packet (char* buf, int buflen,//* Output buffer and length */const char* TOKENBInary,/* Binary token/char* MSG,/* message to send/int badage,/* Apply the number shown on the icon/const char * sound)/* The sound that is played when the device is received, can be null *
/{assert (Buflen >= 1 + 2 + token_size + 2 + max_payload_size);
char * pdata = BUF;
Command *pdata = 0;
Token length pdata++;
* (uint16_t*) pdata = htons (token_size);
Token binary pdata + 2;
memcpy (pdata, Tokenbinary, token_size);
pdata + = Token_size;
int payloadlen = max_payload_size; if (Build_payload (pdata + 2, &payloadlen, MSG, badage, sound) < 0) {Msg[strlen (msg)-(Payloadlen-max_payloa
d_size)] = ';
Payloadlen = max_payload_size;
if (Build_payload (pdata + 2, &payloadlen, MSG, badage, sound) <= 0) {return-1;
} * (uint16_t*) pdata = htons (Payloadlen);
Return 1 + 2 + token_size + 2 + payloadlen;
int Send_message (SSL *ssl, const char* token, char* msg, int badage, const char* sound) {int n;
Char buf[1 + 2 + token_size + 2 + max_payload_size];
unsigned char binary[token_size]; Int Buflen = sizeof (BUF);
n = strlen (token);
Devicetoken2binary (token, n, binary, token_size);
Buflen = Build_output_packet (buf, Buflen, (const char*) binary, MSG, badage, sound);
if (buflen <= 0) {return-1;
Return Ssl_write (SSL, buf, Buflen); int build_output_packet_2 (char* buf, int buflen,/* buffer and Length/uint32_t messageid,/* message number/uint32_t expiry,/* Expired Time/Const char* tokenbinary,/* Binary token/char* MSG,/* Message/INT badage,/* badage/const char * sound
)/* Sound/{assert (Buflen >= 1 + 4 + 4 + 2 + token_size + 2 + max_payload_size);
char * pdata = BUF;
Command *pdata = 1;
MessageID pdata++;
* (uint32_t*) pdata = MessageID;
Expiry time pdata = 4;
* (uint32_t*) pdata = htonl (expiry);
Token length pdata + 4;
* (uint16_t*) pdata = htons (token_size);
Token binary pdata + 2;
memcpy (pdata, Tokenbinary, token_size);
pdata + = Token_size;
int payloadlen = max_payload_size; if (Build_payload (pdata + 2, &Payloadlen, MSG, badage, sound) < 0) {Msg[strlen (msg)-(payloadlen-max_payload_size)] = ';
Payloadlen = max_payload_size;
if (Build_payload (pdata + 2, &payloadlen, MSG, badage, sound) <= 0) {return-1;
} * (uint16_t*) pdata = htons (Payloadlen);
Return 1 + 4 + 4 + 2 + token_size + 2 + payloadlen;
int send_message_2 (SSL *ssl, const char* token, uint32_t ID, uint32_t expire, char* msg, int badage, const char* sound)
{int i, n;
Char buf[1 + 4 + 4 + 2 + token_size + 2 + max_payload_size];
unsigned char binary[token_size];
int buflen = sizeof (BUF);
n = strlen (token);
printf ("Token length:%d, token_size =%d\n token =%s\n", n, token_size, token);
Devicetoken2binary (token, n, binary, token_size);
for (i = 0; i < token_size i++) printf ("%d", binary[i]);
printf ("\ n");
Buflen = Build_output_packet_2 (buf, Buflen, ID, expire, (const char*) binary, MSG, badage, sound);
if (buflen <= 0) {return-1; } n = ssl_write (SSL, buf, Buflen);
return n;
int main (int argc, char** argv) {int i, n;
Char buf[1024];
char * msg = NULL;
if (argc > 1) msg = argv[1];
Init_openssl (); Initialization context//DEVELOP.PEM is our certificate and key, in order to facilitate the use, we write the certificate and key to the same file//and take water key password protection//entrust_2048_ Ca.pem is the CA of Apple certificate, it is not in the root certificate of OpenSSL, so need us to specify manually, otherwise can not verify/detail: http://www.entrust.net/developer/index.cfm ssl_ctx *ctx =
Init_ssl_context ("Develop.pem", "Develop.pem", NULL, "Entrust_2048_ca.pem");
if (!ctx) {fprintf (stderr, "Init SSL context failed:%s\n", Err_reason_error_string (Err_get_error ()));
return-1;
//Connect to test server const char* host = "gateway.sandbox.push.apple.com";
const int port = 2195;
int socket = Tcp_connect (host, Port);
if (Socket < 0) {fprintf (stderr, "Failed to connect to host%s\n", Strerror (errno));
return-1;
}//SSL connection SSL *ssl = Ssl_connect (CTX, socket);
if (!SSL) {fprintf (stderr, "SSL Connect failed:%s\n", Err_reason_error_string (Err_get_error ())); Closesocket (SockeT);
return-1;
//Verify server certificate if (verify_connection (SSL, host)!= 0) {fprintf (stderr, "verify failed\n");
Closesocket (socket);
return 1;
} uint32_t msgid = 1; uint32_t expire = time (NULL) + 24 * 3600;
Expire 1 day printf ("main, expire =%d\n", expire);
if (!msg) {msg = "Hello\nthis is a test";
//Send a message to const char* token = "0a8b9e7cbe68616cd5470e4c8abb4c1a3f4ba2bee4ca113ff02ae2c325948b8a";
n = send_message_2 (SSL, token, msgid++, expire, MSG, 1, "Default");
printf ("after send_message_2, n =%d\n", n);
if (n <= 0) {fprintf (stderr, "Send failed:%s\n", Err_reason_error_string (Err_get_error ()));
}else {printf ("Send sucessfully.\n"); //Receive data from Apple Push server://n = recv (socket, buf, sizeof (BUF), msg_dontwait); Non-blocking mode receives n = read (socket, buf, sizeof (BUF));
Blocking mode receives printf ("from APNs, n =%d\n", n);
For (i=0 i<n; i++) printf ("%d", buf[i]);
printf ("\ n");
Turn off Connection Ssl_shutdown (SSL);
Closesocket (socket);
printf ("exit\n"); return 0; }