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

//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
 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值