C++服务器的push推送通知的代码,SSL链接

来源:互联网 发布:合肥唯米淘宝培训 编辑:程序博客网 时间:2024/05/01 04:07
  1. #ifndef SSLCOMM_H  
  2. #define SSLCOMM_H  
  3.    
  4. #ifdef linux  
  5. #include <assert.h>  
  6. #include "openssl/pem.h"  
  7. #include "openssl/rsa.h"  
  8. #include "openssl/crypto.h"  
  9. #include "openssl/x509.h"  
  10. #include "openssl/ssl.h"  
  11. #include "openssl/err.h"  
  12. #include "openssl/rand.h"  
  13.    
  14. #include "errno.h"  
  15. #include "sys/socket.h"  
  16. #include "netinet/in.h"  
  17. #include "unistd.h"  
  18. #include <arpa/inet.h>  
  19. #include <netdb.h>  
  20.    
  21. #include "Utility.h"  
  22.    
  23. #define APNS_DEV  
  24. #if defined(APNS_DEV)  
  25.    
  26. #define CA_CERT_PATH    "./pem"  
  27. #define RSA_CLIENT_CERT     "./pem/a.pem"  
  28. #define RSA_CLIENT_KEY      "./pem/a.pem"  
  29. /* Development Connection Infos */  
  30. #define APPLE_HOST          "gateway.sandbox.push.apple.com"  
  31. #define APPLE_PORT          2195  
  32.    
  33. #define APPLE_FEEDBACK_HOST "feedback.sandbox.push.apple.com"  
  34. #define APPLE_FEEDBACK_PORT 2196  
  35.    
  36. #else  
  37. #define CA_CERT_PATH    "./pem"  
  38. #define RSA_CLIENT_CERT     "./pem/b.pem"  
  39. #define RSA_CLIENT_KEY      "./pem/b.pem"  
  40. #define APPLE_HOST          "gateway.push.apple.com"  
  41. #define APPLE_PORT          2195  
  42. #define APPLE_FEEDBACK_HOST "feedback.push.apple.com"  
  43. #define APPLE_FEEDBACK_PORT 2196  
  44. #endif  
  45.    
  46.    
  47. class CSSLComm  
  48. {  
  49.  public:  
  50.     CSSLComm();  
  51.     ~CSSLComm();  
  52.    
  53.     bool connected();  
  54.     bool ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath);  
  55.     void PushNotification(const char *pToken,const char *pMsg);  
  56.    
  57.     void GenPushData(const char *pToken);  
  58.     int GenPayloadData(int badgeNum,const char *pMsg = NULL);  
  59.    
  60.     private:  
  61.     void Reset();  
  62.    
  63.     private:  
  64.    
  65.     SSL_CTX         *m_pctx;  
  66.     SSL             *m_pssl;  
  67.     const SSL_METHOD      *m_pmeth;  
  68.     X509            *m_pserver_cert;  
  69.     EVP_PKEY        *m_pkey;  
  70.    
  71.     /* Socket Communications */  
  72.     struct sockaddr_in   m_server_addr;  
  73.     struct hostent      *m_phost_info;  
  74.    
  75.     int                  m_sockfd;  
  76.     uint16 m_tokenLen;  
  77.     struct PUSHDATA  
  78.     {  
  79.         char szToken[1+2+32];  
  80.         char szPayload[2+256];  
  81.     }m_data;  
  82.    
  83.     CSyncCritical m_lock;  
  84. };  
  85.    
  86. #endif  
  87.    
  88. #endif // SSLCOMM_H  


//SSLComm.cpp

[cpp] view plaincopy
  1. #ifdef linux  
  2.    
  3. #include "SSLComm.h"  
  4.    
  5. CSSLComm::CSSLComm()  
  6. {  
  7.     //ctor  
  8.     m_sockfd = -1;  
  9.     m_pctx = NULL;  
  10.     m_pssl = NULL;  
  11.     m_pmeth = NULL;  
  12.     m_pserver_cert = NULL;  
  13.     m_pkey = NULL;  
  14.    
  15.     m_tokenLen = htons(32);  
  16.     memset((void*)&m_data,0,sizeof(m_data));  
  17.    
  18. }  
  19.    
  20. CSSLComm::~CSSLComm()  
  21. {  
  22.     //dtor  
  23.     Reset();  
  24.    
  25. }  
  26. void CSSLComm::Reset()  
  27. {  
  28.    
  29.     if(m_pssl)  
  30.     {  
  31.         SSL_shutdown(m_pssl);  
  32.         SSL_free(m_pssl);  
  33.         m_pssl = NULL;  
  34.     }  
  35.     if(m_pctx)  
  36.     {  
  37.         SSL_CTX_free(m_pctx);  
  38.         m_pctx = NULL;  
  39.     }  
  40.     if(m_sockfd > 2)  
  41.     {  
  42.         close(m_sockfd);  
  43.         m_sockfd = -1;  
  44.     }  
  45.    
  46. }  
  47.    
  48.    
  49. bool CSSLComm::connected()  
  50. {  
  51.     if(m_sockfd < 2) return false;  
  52.    
  53.     struct timeval timeout;  
  54.     timeout.tv_sec = 0;  
  55.     timeout.tv_usec = 0;  
  56.     fd_set fdwrite;  
  57.     fd_set fdexcept;  
  58.     FD_ZERO(&fdwrite);  
  59.     FD_ZERO(&fdexcept);  
  60.     FD_SET(m_sockfd,&fdwrite);  
  61.     FD_SET(m_sockfd,&fdexcept);  
  62.     int ret = select(m_sockfd+1,NULL,&fdwrite,&fdexcept,&timeout);  
  63.     if(ret == -1)  
  64.         return false;  
  65.     if(ret > 0)  
  66.     {  
  67.         if(FD_ISSET(m_sockfd,&fdexcept))  
  68.             return false;  
  69.         else if(FD_ISSET(m_sockfd,&fdwrite))  
  70.         {  
  71.             int err = 0;  
  72.             socklen_t len = sizeof(err);  
  73.             int result = getsockopt(m_sockfd,SOL_SOCKET,SO_ERROR,(char*)&err,&len);  
  74.             if(result < 0 || err != 0)  
  75.                 return false;  
  76.             return true;  
  77.         }  
  78.     }  
  79.     return false;  
  80. }  
  81.    
  82.    
  83. bool CSSLComm::ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath)  
  84. {  
  85.     Reset();  
  86.    
  87.     int err;  
  88.    
  89.     /* Load encryption & hashing algorithms for the SSL program */  
  90.     SSL_library_init();  
  91.    
  92.     /* Load the error strings for SSL & CRYPTO APIs */  
  93.     SSL_load_error_strings();  
  94.    
  95.     /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */  
  96.     m_pmeth = SSLv3_method();  
  97.    
  98.     /* Create an SSL_CTX structure */  
  99.     m_pctx = SSL_CTX_new(m_pmeth);  
  100.     if(!m_pctx)  
  101.     {  
  102.         printf("Could not get SSL Context\n");  
  103.         return false;  
  104.     }  
  105.    
  106.     /* Load the CA from the Path */  
  107.     if(SSL_CTX_load_verify_locations(m_pctx, NULL, capath) <= 0)  
  108.     {  
  109.         /* Handle failed load here */  
  110.         printf("Failed to set CA location...\n");  
  111.         ERR_print_errors_fp(stderr);  
  112.         return false;  
  113.     }  
  114.    
  115.     /* Load the client certificate into the SSL_CTX structure */  
  116.     if (SSL_CTX_use_certificate_file(m_pctx, certfile, SSL_FILETYPE_PEM) <= 0)  
  117.     {  
  118.         printf("Cannot use Certificate File\n");  
  119.         ERR_print_errors_fp(stderr);  
  120.         return false;  
  121.     }  
  122.    
  123.     /* Load the private-key corresponding to the client certificate */  
  124.     if (SSL_CTX_use_PrivateKey_file(m_pctx, keyfile, SSL_FILETYPE_PEM) <= 0)  
  125.     {  
  126.         printf("Cannot use Private Key\n");  
  127.         ERR_print_errors_fp(stderr);  
  128.         return false;  
  129.     }  
  130.    
  131.     /* Check if the client certificate and private-key matches */  
  132.     if (!SSL_CTX_check_private_key(m_pctx))  
  133.     {  
  134.         printf("Private key does not match the certificate public key\n");  
  135.         return false;  
  136.     }  
  137.    
  138.     /* Set up a TCP socket */  
  139.     m_sockfd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);  
  140.     if(m_sockfd == -1)  
  141.     {  
  142.         printf("Could not get Socket\n");  
  143.         return false;  
  144.     }  
  145.    
  146.     memset (&m_server_addr, '\0'sizeof(m_server_addr));  
  147.     m_server_addr.sin_family      = AF_INET;  
  148.     m_server_addr.sin_port        = htons(port);       /* Server Port number */  
  149.     m_phost_info = gethostbyname(host);  
  150.     if(m_phost_info)  
  151.     {  
  152.         /* Take the first IP */  
  153.         struct in_addr *address = (struct in_addr*)m_phost_info->h_addr_list[0];  
  154.         m_server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */  
  155.    
  156.     }  
  157.     else  
  158.     {  
  159.         printf("Could not resolve hostname %s\n", host);  
  160.         return false;  
  161.     }  
  162.    
  163.     /* Establish a TCP/IP connection to the SSL client */  
  164.     err = connect(m_sockfd, (struct sockaddr*) &m_server_addr, sizeof(m_server_addr));  
  165.     if(err == -1)  
  166.     {  
  167.         printf("Could not connect\n");  
  168.         return false;  
  169.     }  
  170.    
  171.     /* An SSL structure is created */  
  172.     m_pssl = SSL_new(m_pctx);  
  173.     if(!m_pssl)  
  174.     {  
  175.         printf("Could not get SSL Socket\n");  
  176.         return false;  
  177.     }  
  178.    
  179.     /* Assign the socket into the SSL structure (SSL and socket without BIO) */  
  180.     SSL_set_fd(m_pssl, m_sockfd);  
  181.    
  182.     /* Perform SSL Handshake on the SSL client */  
  183.     err = SSL_connect(m_pssl);  
  184.     if(err == -1)  
  185.     {  
  186.         printf("Could not connect to SSL Server\n");  
  187.         return false;  
  188.     }  
  189.     return true;  
  190.    
  191. }  
  192.    
  193. void CSSLComm::PushNotification(const char *pToken,const char *pMsg)  
  194. {  
  195.     CMyLock lock(&m_lock);  
  196.     if(!connected())  
  197.     {  
  198.         ssl_connect(APPLE_HOST, APPLE_PORT, RSA_CLIENT_CERT, RSA_CLIENT_KEY, CA_CERT_PATH);  
  199.     }  
  200.     int paylen = GenPayloadData(1,pMsg);  
  201.     GenPushData(pToken);  
  202.     int ret = SSL_write(m_pssl, (void*)&m_data, 35 + paylen);  
  203.     //printf("ret = %d \n",ret);  
  204. }  
  205.    
  206. void CSSLComm::GenPushData(const char *pToken)  
  207. {  
  208.     char *ptr = m_data.szToken;  
  209.     *ptr++ = 0;  
  210.     memcpy(ptr,&m_tokenLen,2);  
  211.     ptr += 2;  
  212.     memcpy(ptr,pToken,32);  
  213. }  
  214.    
  215. int CSSLComm::GenPayloadData(int badgeNum,const char *pMsg)  
  216. {  
  217.     char buf[256] = {0};  
  218.     char badgeBuf[3] = {0};  
  219.     strcpy(&m_data.szPayload[2], "{\"aps\":{");  
  220.     if(pMsg != NULL)  
  221.     {  
  222.         strcat(&m_data.szPayload[2], "\"alert\":");  
  223.         snprintf(buf, sizeof(buf)-1,"\"%s\",", pMsg);  
  224.         strcat(&m_data.szPayload[2],buf);  
  225.     }  
  226.     if(badgeNum > 99 || badgeNum < 0) badgeNum = 1;  
  227.     snprintf(badgeBuf, sizeof(badgeBuf)-1,"%d", badgeNum);  
  228.     strcat(&m_data.szPayload[2], "\"badge\":");  
  229.     strcat(&m_data.szPayload[2], badgeBuf);  
  230.     strcat(&m_data.szPayload[2], ",\"sound\":\"msg.wav\"}");  
  231.     /* 
  232.         int i = 0; 
  233.         while(payload->dictKey<i> != NULL && i < 5) 
  234.         { 
  235.             sprintf(tmpBuff, "\"%s\":\"%s\"", payload->dictKey<i>, payload->dictValue<i>); 
  236.             strcat(messageBuff, tmpBuff); 
  237.             if(i < 4 && payload->dictKey[i + 1] != NULL) 
  238.             { 
  239.                 strcat(messageBuff, ","); 
  240.             } 
  241.             i++; 
  242.         } 
  243.     */  
  244.    
  245.     snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"""forum_id",88);  
  246.     strcat(&m_data.szPayload[2],buf);  
  247.    
  248.     snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"""topic_id",999);  
  249.     strcat(&m_data.szPayload[2],buf);  
  250.    
  251.     strcat(&m_data.szPayload[2],"}");  
  252.     int len = strlen(&m_data.szPayload[2]);  
  253.     assert(len <= 256);  
  254.     uint16_t payload_len = htons(len);  
  255.     memcpy(m_data.szPayload,&payload_len,sizeof(payload_len));  
  256.     return len + 2;  
  257. }  
  258.    
  259. #endif  
0 0
原创粉丝点击