DtlsSocketContextソースコード分析

 

 

const char* DtlsSocketContext::DefaultSrtpProfile = "SRTP_AES128_CM_SHA1_80";

X509 *DtlsSocketContext::mCert = nullptr;
EVP_PKEY *DtlsSocketContext::privkey = nullptr;

  // 创建ssl 上下文,并设置证书和秘钥
  // memory is only valid for duration of callback; must be copied if queueing
  // is required
  DtlsSocketContext::DtlsSocketContext() {
    started = false;

    ELOG_DEBUG("Creating Dtls factory, Openssl v %s", OPENSSL_VERSION_TEXT);

    mContext = SSL_CTX_new(DTLS_method());
    assert(mContext);

    int r = SSL_CTX_use_certificate(mContext, mCert);
    assert(r == 1);

    r = SSL_CTX_use_PrivateKey(mContext, privkey);
    assert(r == 1);

    SSL_CTX_set_cipher_list(mContext, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");

    SSL_CTX_set_info_callback(mContext, SSLInfoCallback);

    SSL_CTX_set_verify(mContext, SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
      SSLVerifyCallback);

    SSL_CTX_set_options(mContext, SSL_OP_NO_QUERY_MTU);
      // SSL_CTX_set_session_cache_mode(mContext, SSL_SESS_CACHE_OFF);
      // SSL_CTX_set_options(mContext, SSL_OP_NO_TICKET);
      // Set SRTP profiles
    r = SSL_CTX_set_tlsext_use_srtp(mContext, DefaultSrtpProfile);
    assert(r == 0);

    SSL_CTX_set_verify_depth(mContext, 2);
    SSL_CTX_set_read_ahead(mContext, 1);

    ELOG_DEBUG("DtlsSocketContext created");
  }

    // 关闭mSocket,释放mContext
    DtlsSocketContext::~DtlsSocketContext() {
      mSocket->close();
      delete mSocket;
      mSocket = nullptr;
      SSL_CTX_free(mContext);
    }

    // 关闭mSocket
    void DtlsSocketContext::close() {
      mSocket->close();
    }

    // 当证书为空时,初始化openssl,但这个函数在程序没有被使用
    void DtlsSocketContext::Init() {
      ssl_thread_setup();
      if (DtlsSocketContext::mCert == nullptr) {
        OpenSSL_add_all_algorithms();
        SSL_library_init();
        SSL_load_error_strings();
        ERR_load_crypto_strings();
        createCert("sip:[email protected]", 365, 1024, DtlsSocketContext::mCert, DtlsSocketContext::privkey);
      }
    }

    // 清理ssl线程
    void DtlsSocketContext::Destroy() {
      ssl_thread_cleanup();
    }

    // 创建客户端的DtlsSocket
    DtlsSocket* DtlsSocketContext::createClient() {
      return new DtlsSocket(this, DtlsSocket::Client);
    }

    // 创建服务器的DtlsSocket
    DtlsSocket* DtlsSocketContext::createServer() {
      return new DtlsSocket(this, DtlsSocket::Server);
    }

    void DtlsSocketContext::getMyCertFingerprint(char *fingerprint) {
      DtlsSocket::computeFingerprint(DtlsSocketContext::mCert, fingerprint);
    }

    void DtlsSocketContext::setSrtpProfiles(const char *str) {
      int r = SSL_CTX_set_tlsext_use_srtp(mContext, str);
      assert(r == 0);
    }

    void DtlsSocketContext::setCipherSuites(const char *str) {
      int r = SSL_CTX_set_cipher_list(mContext, str);
      assert(r == 1);
    }

    // 获取ssl上下文
    SSL_CTX* DtlsSocketContext::getSSLContext() {
      return mContext;
    }

    // 解析包,并判断包的类型
    DtlsSocketContext::PacketType DtlsSocketContext::demuxPacket(const unsigned char *data, unsigned int len) {
      assert(len >= 1);

      if ((data[0] == 0)   || (data[0] == 1))
      return stun;
      if ((data[0] >= 128) && (data[0] <= 191))
      return rtp;
      if ((data[0] >= 20)  && (data[0] <= 64))
      return dtls;

      return unknown;
    }

    // 获取本地证书指纹
    std::string DtlsSocketContext::getFingerprint() const {
      char fprint[100] = {};
      mSocket->getMyCertFingerprint(fprint);
      return std::string(fprint);
    }
    
    // 开始握手过程
    void DtlsSocketContext::start() {
      started = true;
      mSocket->startClient();
    }
    
    // 处理接收的包数据
    void DtlsSocketContext::read(const unsigned char* data, unsigned int len) {
      mSocket->handlePacketMaybe(data, len);
    }

    // 设置接收对象
    void DtlsSocketContext::setDtlsReceiver(DtlsReceiver *recv) {
      receiver = recv;
    }
    
    // 将包发送到网络上
    void DtlsSocketContext::write(const unsigned char* data, unsigned int len) {
      if (receiver != NULL) {
        receiver->onDtlsPacket(this, data, len);
      }
    }

    // 超时处理
    void DtlsSocketContext::handleTimeout() {
      mSocket->handleTimeout();
    }

    // Dtls ssl握手完成,拿到srtp加解密所需的clientKey和serverKey秘钥
    void DtlsSocketContext::handshakeCompleted() {
      char fprint[100];
      SRTP_PROTECTION_PROFILE *srtp_profile;

      if (mSocket->getRemoteFingerprint(fprint)) {
        ELOG_TRACE("Remote fingerprint == %s", fprint);

        bool check = mSocket->checkFingerprint(fprint, strlen(fprint));
        ELOG_DEBUG("Fingerprint check == %d", check);

        SrtpSessionKeys* keys = mSocket->getSrtpSessionKeys();

        unsigned char* cKey = (unsigned char*)malloc(keys->clientMasterKeyLen + keys->clientMasterSaltLen);
        unsigned char* sKey = (unsigned char*)malloc(keys->serverMasterKeyLen + keys->serverMasterSaltLen);

        memcpy(cKey, keys->clientMasterKey, keys->clientMasterKeyLen);
        memcpy(cKey + keys->clientMasterKeyLen, keys->clientMasterSalt, keys->clientMasterSaltLen);

        memcpy(sKey, keys->serverMasterKey, keys->serverMasterKeyLen);
        memcpy(sKey + keys->serverMasterKeyLen, keys->serverMasterSalt, keys->serverMasterSaltLen);

        // g_base64_encode must be free'd with g_free.  Also, std::string's assignment operator does *not* take
        // ownership of the passed in ptr; under the hood it copies up to the first null character.
        gchar* temp = g_base64_encode((const guchar*)cKey, keys->clientMasterKeyLen + keys->clientMasterSaltLen);
        std::string clientKey = temp;
        g_free(temp); temp = NULL;

        temp = g_base64_encode((const guchar*)sKey, keys->serverMasterKeyLen + keys->serverMasterSaltLen);
        std::string serverKey = temp;
        g_free(temp); temp = NULL;

        ELOG_DEBUG("ClientKey: %s", clientKey.c_str());
        ELOG_DEBUG("ServerKey: %s", serverKey.c_str());

        free(cKey);
        free(sKey);
        delete keys;

        srtp_profile = mSocket->getSrtpProfile();

        if (srtp_profile) {
          ELOG_DEBUG("SRTP Extension negotiated profile=%s", srtp_profile->name);
        }

        if (receiver != NULL) {
          receiver->onHandshakeCompleted(this, clientKey, serverKey, srtp_profile->name);
        }
      } else {
        ELOG_DEBUG("Peer did not authenticate");
      }
    }
    
    //Dtls ssl对象握手失败
    void DtlsSocketContext::handshakeFailed(const char *err) {
      ELOG_WARN("DTLS Handshake Failure %s", err);
      receiver->onHandshakeFailed(this, std::string(err));
    }

 

おすすめ

転載: blog.csdn.net/tong5956/article/details/108362846