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

9 篇文章 1 订阅

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


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

csdn博客:http://blog.csdn.net/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;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值