项目中用到实时视频技术,我们使用tokbox来解决这个问题 ,官方没有C++版本.我写了一个qt c++版本的用于获取sessionId和tonkenId来进行视频通话
开发人员:Jason's.Alex QQ:531401335
csdn博客:http://blog.csdn.net/RuShrooM
#ifndef TOKENSDK_H
#define TOKENSDK_H
#include
#include
#include
#include
//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
#include
#include
#include
#include
#include
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(&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(expireTimeQDateTime::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;ierrorString());
if(reply!=0)
{
reply->deleteLater();
reply=0;
}
}