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

来源:互联网 发布:高斯键盘知乎 编辑:程序博客网 时间:2024/04/30 15:15
//SSLComm.h
#ifndef SSLCOMM_H#define SSLCOMM_H #ifdef linux#include <assert.h>#include "openssl/pem.h"#include "openssl/rsa.h"#include "openssl/crypto.h"#include "openssl/x509.h"#include "openssl/ssl.h"#include "openssl/err.h"#include "openssl/rand.h" #include "errno.h"#include "sys/socket.h"#include "netinet/in.h"#include "unistd.h"#include <arpa/inet.h>#include <netdb.h> #include "Utility.h" #define APNS_DEV#if defined(APNS_DEV) #define CA_CERT_PATH    "./pem"#define RSA_CLIENT_CERT     "./pem/a.pem"#define RSA_CLIENT_KEY      "./pem/a.pem"/* Development Connection Infos */#define APPLE_HOST          "gateway.sandbox.push.apple.com"#define APPLE_PORT          2195 #define APPLE_FEEDBACK_HOST "feedback.sandbox.push.apple.com"#define APPLE_FEEDBACK_PORT 2196 #else#define CA_CERT_PATH    "./pem"#define RSA_CLIENT_CERT     "./pem/b.pem"#define RSA_CLIENT_KEY      "./pem/b.pem"#define APPLE_HOST          "gateway.push.apple.com"#define APPLE_PORT          2195#define APPLE_FEEDBACK_HOST "feedback.push.apple.com"#define APPLE_FEEDBACK_PORT 2196#endif  class CSSLComm{ public:    CSSLComm();    ~CSSLComm();     bool connected();    bool ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath);    void PushNotification(const char *pToken,const char *pMsg);     void GenPushData(const char *pToken);    int GenPayloadData(int badgeNum,const char *pMsg = NULL);     private:    void Reset();     private:     SSL_CTX         *m_pctx;    SSL             *m_pssl;    const SSL_METHOD      *m_pmeth;    X509            *m_pserver_cert;    EVP_PKEY        *m_pkey;     /* Socket Communications */    struct sockaddr_in   m_server_addr;    struct hostent      *m_phost_info;     int                  m_sockfd;    uint16 m_tokenLen;    struct PUSHDATA    {        char szToken[1+2+32];        char szPayload[2+256];    }m_data;     CSyncCritical m_lock;}; #endif #endif // SSLCOMM_H


//SSLComm.cpp

#ifdef linux #include "SSLComm.h" CSSLComm::CSSLComm(){    //ctor    m_sockfd = -1;    m_pctx = NULL;    m_pssl = NULL;    m_pmeth = NULL;    m_pserver_cert = NULL;    m_pkey = NULL;     m_tokenLen = htons(32);    memset((void*)&m_data,0,sizeof(m_data)); } CSSLComm::~CSSLComm(){    //dtor    Reset(); }void CSSLComm::Reset(){     if(m_pssl)    {        SSL_shutdown(m_pssl);        SSL_free(m_pssl);        m_pssl = NULL;    }    if(m_pctx)    {        SSL_CTX_free(m_pctx);        m_pctx = NULL;    }    if(m_sockfd > 2)    {        close(m_sockfd);        m_sockfd = -1;    } }  bool CSSLComm::connected(){    if(m_sockfd < 2) return false;     struct timeval timeout;    timeout.tv_sec = 0;    timeout.tv_usec = 0;    fd_set fdwrite;    fd_set fdexcept;    FD_ZERO(&fdwrite);    FD_ZERO(&fdexcept);    FD_SET(m_sockfd,&fdwrite);    FD_SET(m_sockfd,&fdexcept);    int ret = select(m_sockfd+1,NULL,&fdwrite,&fdexcept,&timeout);    if(ret == -1)        return false;    if(ret > 0)    {        if(FD_ISSET(m_sockfd,&fdexcept))            return false;        else if(FD_ISSET(m_sockfd,&fdwrite))        {            int err = 0;            socklen_t len = sizeof(err);            int result = getsockopt(m_sockfd,SOL_SOCKET,SO_ERROR,(char*)&err,&len);            if(result < 0 || err != 0)                return false;            return true;        }    }    return false;}  bool CSSLComm::ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath){    Reset();     int err;     /* Load encryption & hashing algorithms for the SSL program */    SSL_library_init();     /* Load the error strings for SSL & CRYPTO APIs */    SSL_load_error_strings();     /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */    m_pmeth = SSLv3_method();     /* Create an SSL_CTX structure */    m_pctx = SSL_CTX_new(m_pmeth);    if(!m_pctx)    {        printf("Could not get SSL Context\n");        return false;    }     /* Load the CA from the Path */    if(SSL_CTX_load_verify_locations(m_pctx, NULL, capath) <= 0)    {        /* Handle failed load here */        printf("Failed to set CA location...\n");        ERR_print_errors_fp(stderr);        return false;    }     /* Load the client certificate into the SSL_CTX structure */    if (SSL_CTX_use_certificate_file(m_pctx, certfile, SSL_FILETYPE_PEM) <= 0)    {        printf("Cannot use Certificate File\n");        ERR_print_errors_fp(stderr);        return false;    }     /* Load the private-key corresponding to the client certificate */    if (SSL_CTX_use_PrivateKey_file(m_pctx, keyfile, SSL_FILETYPE_PEM) <= 0)    {        printf("Cannot use Private Key\n");        ERR_print_errors_fp(stderr);        return false;    }     /* Check if the client certificate and private-key matches */    if (!SSL_CTX_check_private_key(m_pctx))    {        printf("Private key does not match the certificate public key\n");        return false;    }     /* Set up a TCP socket */    m_sockfd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);    if(m_sockfd == -1)    {        printf("Could not get Socket\n");        return false;    }     memset (&m_server_addr, '\0', sizeof(m_server_addr));    m_server_addr.sin_family      = AF_INET;    m_server_addr.sin_port        = htons(port);       /* Server Port number */    m_phost_info = gethostbyname(host);    if(m_phost_info)    {        /* Take the first IP */        struct in_addr *address = (struct in_addr*)m_phost_info->h_addr_list[0];        m_server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */     }    else    {        printf("Could not resolve hostname %s\n", host);        return false;    }     /* Establish a TCP/IP connection to the SSL client */    err = connect(m_sockfd, (struct sockaddr*) &m_server_addr, sizeof(m_server_addr));    if(err == -1)    {        printf("Could not connect\n");        return false;    }     /* An SSL structure is created */    m_pssl = SSL_new(m_pctx);    if(!m_pssl)    {        printf("Could not get SSL Socket\n");        return false;    }     /* Assign the socket into the SSL structure (SSL and socket without BIO) */    SSL_set_fd(m_pssl, m_sockfd);     /* Perform SSL Handshake on the SSL client */    err = SSL_connect(m_pssl);    if(err == -1)    {        printf("Could not connect to SSL Server\n");        return false;    }    return true; } void CSSLComm::PushNotification(const char *pToken,const char *pMsg){    CMyLock lock(&m_lock);    if(!connected())    {        ssl_connect(APPLE_HOST, APPLE_PORT, RSA_CLIENT_CERT, RSA_CLIENT_KEY, CA_CERT_PATH);    }    int paylen = GenPayloadData(1,pMsg);    GenPushData(pToken);    int ret = SSL_write(m_pssl, (void*)&m_data, 35 + paylen);    //printf("ret = %d \n",ret);} void CSSLComm::GenPushData(const char *pToken){    char *ptr = m_data.szToken;    *ptr++ = 0;    memcpy(ptr,&m_tokenLen,2);    ptr += 2;    memcpy(ptr,pToken,32);} int CSSLComm::GenPayloadData(int badgeNum,const char *pMsg){    char buf[256] = {0};    char badgeBuf[3] = {0};    strcpy(&m_data.szPayload[2], "{\"aps\":{");    if(pMsg != NULL)    {        strcat(&m_data.szPayload[2], "\"alert\":");        snprintf(buf, sizeof(buf)-1,"\"%s\",", pMsg);        strcat(&m_data.szPayload[2],buf);    }    if(badgeNum > 99 || badgeNum < 0) badgeNum = 1;    snprintf(badgeBuf, sizeof(badgeBuf)-1,"%d", badgeNum);    strcat(&m_data.szPayload[2], "\"badge\":");    strcat(&m_data.szPayload[2], badgeBuf);    strcat(&m_data.szPayload[2], ",\"sound\":\"msg.wav\"}");    /*        int i = 0;        while(payload->dictKey<i> != NULL && i < 5)        {            sprintf(tmpBuff, "\"%s\":\"%s\"", payload->dictKey<i>, payload->dictValue<i>);            strcat(messageBuff, tmpBuff);            if(i < 4 && payload->dictKey[i + 1] != NULL)            {                strcat(messageBuff, ",");            }            i++;        }    */     snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"", "forum_id",88);    strcat(&m_data.szPayload[2],buf);     snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"", "topic_id",999);    strcat(&m_data.szPayload[2],buf);     strcat(&m_data.szPayload[2],"}");    int len = strlen(&m_data.szPayload[2]);    assert(len <= 256);    uint16_t payload_len = htons(len);    memcpy(m_data.szPayload,&payload_len,sizeof(payload_len));    return len + 2;} #endif