使用PJLIB库实现SSL加密的TCP服务器和客户端

附一个PJSIP库的基础介绍链接:
http://www.zhimax.com/article/tcp/pjlib.html

PJLIB的测试源码链接:
https://trac.pjsip.org/repos/browser/pjproject/tags/2.9/pjlib/src?order=name#pjlib-test

基于测试源码,自己动手写了一个SSL加密的TCP服务器和客户端。开发环境是centos7.

服务端代码:

#include <pjlib.h>
#include <iostream>
#include <netinet/in.h>
#include "PQTEL.pb.h"       

using namespace std;
using namespace pqtel_msg;

#define CERT_CA_FILE            "./ca.crt"
#define CERT_FILE               "./server.crt"
#define CERT_PRIVKEY_FILE       "./server.pem"
#define CERT_PRIVKEY_PASS       ""

#define SVR_IP                  "127.0.0.1"
#define SVR_PORT                14789

//全局变量
pj_caching_pool         cachingPool;
pj_pool_factory         *mem;

struct send_key {
   
    pj_ioqueue_op_key_t op_key;
};

struct PJ_Data
{
   
    pj_pool_t      *pool;       
    pj_ioqueue_t   *ioqueue;        
    pj_bool_t       is_server;     
    pj_bool_t       is_verbose;          
    pj_bool_t       is_done;      
    struct send_key send_key;  
};

struct pqtel_head
{
   
    short                   type;
    short                   msglen;
};

static void dump_ssl_info(const pj_ssl_sock_info *si)
{
   
    const char *tmp_st;

    /* Print cipher name */
    tmp_st = pj_ssl_cipher_name(si->cipher);
    if (tmp_st == NULL)
        tmp_st = "[Unknown]";
    PJ_LOG(3, ("", ".....Cipher: %s", tmp_st));

    /* Print remote certificate info and verification result */
    if (si->remote_cert_info && si->remote_cert_info->subject.info.slen) 
    {
   
        char buf[2048];
        const char *verif_msgs[32];
        unsigned verif_msg_cnt;

        /* Dump remote TLS certificate info */
        PJ_LOG(3, ("", ".....Remote certificate info:"));
        pj_ssl_cert_info_dump(si->remote_cert_info, "  ", buf, sizeof(buf));
        PJ_LOG(3,("", "\n%s", buf));

        /* Dump remote TLS certificate verification result */
        verif_msg_cnt = PJ_ARRAY_SIZE(verif_msgs);
        pj_ssl_cert_get_verify_status_strings(si->verify_status, verif_msgs, &verif_msg_cnt);
        PJ_LOG(3,("", ".....Remote certificate verification result: %s",(verif_msg_cnt == 1? verif_msgs[0]:"")));
        if (verif_msg_cnt > 1) {
   
            unsigned i;
            for (i = 0; i < verif_msg_cnt; ++i)
                PJ_LOG(3,("", "..... - %s", verif_msgs[i]));
        }
    }
} 

const char* SVR_MakeHead(char* output, char *sendbuf, int length)
{
   
    //拼接应用层协议头
    pqtel_head *head = (pqtel_head *)sendbuf;
    head->type = htons(0x5051);
    head->msglen = htons(length + 2);
    short ncrc = htons(0x2022);
    memcpy(sendbuf, head, sizeof(pqtel_head));
    memcpy(sendbuf + sizeof(pqtel_head), output, length);
    memcpy(sendbuf + sizeof(pqtel_head) + length, (char*)&ncrc, sizeof(short));
    return sendbuf;
}

int SVR_SendRep(pj_ssl_sock_t *ssock)
{
   
    pj_status_t status;
    char output[256] = {
   0};
    char sendbuf[512] = {
   0};
    int length;
    bool flag;
    pj_ssize_t size;
    
    PqtelMsg msg;
    Response *rep = msg.mutable_response();
    rep->set_result(200);
    rep->set_error_describe("login   OK ");

    length = msg.ByteSize();
    flag = msg.SerializeToArray(output,length);
    if(!flag)
    {
   
        printf("SendRep SerializeToArray is wrong \n");
        return -1;
    }
    SVR_MakeHead(output,sendbuf,length);
    size = length + 6;
    struct PJ_Data *st = (struct PJ_Data*) pj_ssl_sock_get_user_data(ssock);
    status = pj_ssl_sock_send(ssock, (pj_ioqueue_op_key_t*)&st->send_key, sendbuf, &size, 0);
    if(status == PJ_SUCCESS)
        printf("Send login rep OK,size---%d \n",(int)size);
    
    return 0;
}

int SVR_RecvData(pj_ssl_sock_t *ssock, char *data, pj_size_t size)
{
   
    short ncrc;
    int proto_len;
    char proto_msg[512] = {
   0};
    pqtel_head *head = (pqtel_head *)data;
    if (ntohs(head->type) != 0x5051)
    {
   
        printf("SVR_RecvData  Get type is wrong \n");
        return -1;
    }
    proto_len = ntohs(head->msglen) - 2;
    memcpy((char*)&ncrc, data + sizeof(pqtel_head) + proto_len, sizeof(short));
    memcpy(proto_msg, data + sizeof(pqtel_head), proto_len);

    //反序列化protobuf数据
    PqtelMsg msg;
    bool flag = msg.ParseFromArray(proto_msg, proto_len);
    if (!flag)
    {
   
        printf("SVR_RecvData  ParseFromArray is wrong \n");
        return -2;
    }

    if (msg.type() == Login_Request)
    {
   
        string uuid = msg.request().login().uuid();
        printf("SVR_RecvData  Get Login_Req uuid --- [%s] \n", uuid.c_str());

        //发送回应
        SVR_SendRep(ssock);
    }    

    return 0;
}

pj_bool_t SVR_DataRead(pj_ssl_sock_t 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值