tokbox获取sessionId和tokenId for c++版本

本文介绍了一款基于TokBox API的C++实现方案,用于创建视频通话会话并生成会话ID及令牌ID。该方案通过HTTP请求与TokBox服务器交互,实现了密钥创建、令牌生成等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目中用到实时视频技术,我们使用tokbox来解决这个问题 ,官方没有C++版本.我写了一个qt c++版本的用于获取sessionId和tonkenId来进行视频通话


开发人员:Jason's.Alex   QQ:531401335

csdn博客:http://blog.youkuaiyun.com/RuShrooM

#ifndef TOKENSDK_H
#define TOKENSDK_H

#include <QObject>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkReply>


//http访问

class TokboxSDK : public QObject
{
    Q_OBJECT
public:
    explicit TokboxSDK(QObject *parent = 0);
    ~TokboxSDK();
    const QString &getSessionId()const{return sessionId;}
    const QString &getTokenId()const{return tokenId;}
    const QString &getKeyId()const{return keyId;}

    void createTokboxKeys(const QString &keyid,         //创建一个密钥
                          const QString &secret,
                          const QString &role="publisher",
                          const long &expireTime=0,
                          const QString &connectData="");//创建密钥

    QString generateToken(const QString &sessionId,const QString &role="publisher",  //生成token
                       const long &expireTime=0,const QString &connectData="");

    void loadRemoteXMLData(const QString &keyid,const QString &secret); //载入远程xml数据

signals:
    void error(const QString &s);//创建失败就返回错误信号
    void createFinish();//创建完成信号

private slots:
    void downRemoteXml(QNetworkReply *reply);
    void downRemoteXmlError(QNetworkReply::NetworkError);

private:
    QNetworkAccessManager *nkm;
    QNetworkReply *reply;

    QString repeatString(const QString &str,const int ×);

private:
    QString sessionId;
    QString tokenId;
    QString keyId;
    QString secret;
    QString role; //角色
    long expireTime;//有效时间
    QString connectData;//连接的用户数据

};

#endif // HTTPACCESS_H

#include "TokenSDK.h"
#include <QDebug>
#include <QSslConfiguration>
#include <QSsl>
#include <QtXml/QDomDocument>
#include <QDateTime>
#include <QMessageAuthenticationCode>


TokboxSDK::TokboxSDK(QObject *parent):
    QObject(parent)
{
    reply=0;
    nkm=new QNetworkAccessManager(this);
    connect(nkm,&QNetworkAccessManager::finished,this,&TokboxSDK::downRemoteXml);
}

TokboxSDK::~TokboxSDK()
{
    if(reply!=0)
    reply->deleteLater();
}


void TokboxSDK::loadRemoteXMLData(const QString &keyid,const QString &secret) //载入远程xml数据
{
    if(reply!=0)
        reply->deleteLater();

    QNetworkRequest reque(QUrl("https://api.opentok.com/hl/session/create"));

    reque.setRawHeader("X-TB-PARTNER-AUTH",QString("%1:%2").arg(keyid).arg(secret).toLatin1());
    reque.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");

   // QByteArray byte="location=127.0.0.1&p2p.preference=disabled";
   //reque.setHeader(QNetworkRequest::ContentLengthHeader,byte.length());

    reply=nkm->post(reque,"");
    connect(reply,static_cast<void (QNetworkReply::*)(QNetworkReply::NetworkError)>(&QNetworkReply::error),this,&TokboxSDK::downRemoteXmlError);
}


void TokboxSDK::createTokboxKeys(const QString &keyid,const QString &secret,const QString &role,
                                 const long &expireTime,const QString &connectData)//创建一个密钥创建密钥
{
    this->keyId=keyid;
    this->secret=secret;
    this->role=role;
    this->expireTime=expireTime;
    this->connectData=connectData;

    this->loadRemoteXMLData(keyid,secret); //下载远程数据
}



void TokboxSDK::downRemoteXml(QNetworkReply *)
{
    if(reply->bytesAvailable()<20)
    {
        emit error("download remote xml none");
        reply->deleteLater();
        reply=0;
        return;
    }

    QDomDocument doc;
    QString msgErrorStr;
    int line;
    int col;

    if(!doc.setContent(reply->readAll(),&msgErrorStr,&line,&col)) //载入xml数据
    {
        emit error(QString("parse tokbox session xml error:%1 line:%2 col:%3").arg(msgErrorStr).arg(line).arg(col));
        reply->deleteLater();
        reply=0;
        return;
    }

    QDomElement ele=doc.firstChildElement("sessions").firstChildElement("Session"); //解析session 字段
    this->sessionId=ele.firstChildElement("session_id").text();
    this->tokenId=generateToken(sessionId); //生成一个token

    reply->deleteLater();
    reply=0;

    emit createFinish();
}

QString TokboxSDK::generateToken(const QString &sessionId,const QString &role,  //生成token
                   const long &expireTime,const QString &connectData)
{
    if(sessionId.isEmpty())
    {
        emit error("Null or empty session ID are not valid");
        return "";
    }

    QString subSessionId=sessionId.mid(2);//从第二个字符串开始截取
    QString decodeSessionId; //解码的sessionid
    for(int i=0;i<3;++i)
    {
        QString newSessionId=subSessionId+repeatString("=",i);
        decodeSessionId=QByteArray::fromBase64(newSessionId.replace('-','+').replace('_','/').toLatin1());

        if(decodeSessionId.contains("~"))
        {
            if(decodeSessionId.split("~")[1]!=keyId)
            {
                emit error("An invalid session ID was passed");
                return "";
            }
            break;
        }
    }


    long createTime=QDateTime::currentMSecsSinceEpoch()/1000;//获取当前的系统时间
    qsrand(QDateTime::currentMSecsSinceEpoch());
    int nonce=qrand();

    QString dataStringBuilder=QString("session_id=%1&create_time=%2&nonce=%3&role=%4")
                                .arg(sessionId).arg(createTime).arg(nonce).arg(role);

    if("subscriber"!=role&&"publisher"!=role&&"moderator"!=role&&!role.isEmpty())
    {
        emit error(role+" is not a recognized role");
        return "";
    }


    if(expireTime!=0)
    {
        if(expireTime<QDateTime::currentMSecsSinceEpoch()/1000-1)
        {
            emit error("Expire time must be in the future");
            return "";
        }

        if(expireTime>QDateTime::currentMSecsSinceEpoch()/1000+2592000)
        {
            emit error("Expire time must be in the next 30 days");
            return "";
        }

        dataStringBuilder.append("&expire_time=");
        dataStringBuilder.append(QString::number(expireTime));
     }

    if(!connectData.isEmpty())
    {
        if(connectData.length()>1000)
        {
            emit error("Connection data must be less than 1000 characters");
            return "";
        }

        dataStringBuilder.append("&connection_data=");
        dataStringBuilder.append(connectData);
    }

    QString tokenStringBuiler="T1==";
                                                                        //添加hmac密钥
    QString innerBuilder=QString("partner_id=%1&sig=%2:%3").arg(keyId)
            .arg(QString(QMessageAuthenticationCode::hash(dataStringBuilder.toLatin1(),
                                                          secret.toLatin1(),QCryptographicHash::Sha1).toHex()))
            .arg(dataStringBuilder);

    return tokenStringBuiler.append(innerBuilder.toLatin1().toBase64());
}

QString TokboxSDK::repeatString(const QString &str,const int ×)
{
    QString ret;
    for(int i=0;i<times;++i)
        ret+=str;

    return ret;
}

void TokboxSDK::downRemoteXmlError(QNetworkReply::NetworkError )
{
    emit error(reply->errorString());

    if(reply!=0)
    {
      reply->deleteLater();
      reply=0;
    }
}


MICROSOFT FOUNDATION CLASS LIBRARY : ZSCPascal AppWizard has created this ZSCPascal application for you. This application not only demonstrates the basics of using the Microsoft Foundation classes but is also a starting point for writing your application. This file contains a summary of what you will find in each of the files that make up your ZSCPascal application. ZSCPascal.h This is the main header file for the application. It includes other project specific headers (including Resource.h) and declares the CZSCPascalApp application class. ZSCPascal.cpp This is the main application source file that contains the application class CZSCPascalApp. ZSCPascal.rc This is a listing of all of the Microsoft Windows resources that the program uses. It includes the icons, bitmaps, and cursors that are stored in the RES subdirectory. This file can be directly edited in Microsoft Developer Studio. resSCPascal.ico This is an icon file, which is used as the application s icon. This icon is included by the main resource file ZSCPascal.rc. resSCPascal.rc2 This file contains resources that are not edited by Microsoft Developer Studio. You should place all resources not editable by the resource editor in this file. ZSCPascal.reg This is an example .REG file that shows you the kind of registration settings the framework will set for you. You can use this as a .REG file to go along with your application or just delete it and rely on the default RegisterShellFileTypes registration. ZSCPascal.clw This file contains information used by ClassWizard to edit existing classes or add new classes. ClassWizard also uses this file to store information needed to create and edit message maps and dialog data maps and to create prototype member functions. For the main frame window: MainFrm.h, MainFrm.cpp These files contain the frame class CMainFrame, which is derived from CMDIFrameWnd and controls all MDI frame features. resToolbar.bmp This bitmap file is used to create tiled images for the toolbar. The initial toolbar and status bar are constructed in the CMainFrame class. Edit this toolbar bitmap along with the array in MainFrm.cpp to add more toolbar buttons. AppWizard creates one document type and one view: ZSCPascalDoc.h, ZSCPascalDoc.cpp - the document These files contain your CZSCPascalDoc class. Edit these files to add your special document data and to implement file saving and loading (via CZSCPascalDoc::Serialize). ZSCPascalView.h, ZSCPascalView.cpp - the view of the document These files contain your CZSCPascalView class. CZSCPascalView objects are used to view CZSCPascalDoc objects. resSCPascalDoc.ico This is an icon file, which is used as the icon for MDI child windows for the CZSCPascalDoc class. This icon is included by the main resource file ZSCPascal.rc. Other standard files: StdAfx.h, StdAfx.cpp These files are used to build a precompiled header (PCH) file named ZSCPascal.pch and a precompiled types file named StdAfx.obj. Resource.h This is the standard header file, which defines new resource IDs. Microsoft Developer Studio reads and updates this file. Other notes: AppWizard uses "TODO:" to indicate parts of the source code you should add to or customize. If your application uses MFC in a shared DLL, and your application is in a language other than the operating system s current language, you will need to copy the corresponding localized resources MFC40XXX.DLL from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. For example, MFC40DEU.DLL contains resources translated to German.) If you don t do this, some of the UI elements of your application will remain in the language of the operating system.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值