Initial commit

This commit is contained in:
talksik
2021-12-29 01:57:42 -08:00
commit ce39a60b42
4634 changed files with 997667 additions and 0 deletions
+258
View File
@@ -0,0 +1,258 @@
var crypto = require('crypto');
var crc32 = require('crc-32');
var UINT32 = require('cuint').UINT32;
var version = "006";
var randomInt = Math.floor(Math.random() * 0xFFFFFFFF);
const VERSION_LENGTH = 3;
const APP_ID_LENGTH = 32;
var AccessToken = function (appID, appCertificate, channelName, uid) {
let token = this;
this.appID = appID;
this.appCertificate = appCertificate;
this.channelName = channelName;
this.messages = {};
this.salt = randomInt;
this.ts = Math.floor(new Date() / 1000) + (24 * 3600);
if (uid === 0) {
this.uid = "";
} else {
this.uid = `${uid}`;
}
this.build = function () {
var m = Message({
salt: token.salt
, ts: token.ts
, messages: token.messages
}).pack();
var toSign = Buffer.concat(
[Buffer.from(token.appID, 'utf8'),
Buffer.from(token.channelName, 'utf8'),
Buffer.from(token.uid, 'utf8'),
m]);
var signature = encodeHMac(token.appCertificate, toSign);
var crc_channel = UINT32(crc32.str(token.channelName)).and(UINT32(0xffffffff)).toNumber();
var crc_uid = UINT32(crc32.str(token.uid)).and(UINT32(0xffffffff)).toNumber();
var content = AccessTokenContent({
signature: signature,
crc_channel: crc_channel,
crc_uid: crc_uid,
m: m
}).pack();
return (version + token.appID + content.toString('base64'));
}
this.addPriviledge = function (priviledge, expireTimestamp) {
token.messages[priviledge] = expireTimestamp;
};
this.fromString = function (originToken) {
try {
originVersion = originToken.substr(0, VERSION_LENGTH);
if(originVersion != version) {
return false;
}
var originAppID = originToken.substr(VERSION_LENGTH, (VERSION_LENGTH + APP_ID_LENGTH));
var originContent = originToken.substr((VERSION_LENGTH + APP_ID_LENGTH));
var originContentDecodedBuf = Buffer.from(originContent, 'base64');
var content = unPackContent(originContentDecodedBuf);
this.signature = content.signature;
this.crc_channel_name = content.crc_channel_name;
this.crc_uid = content.crc_uid;
this.m = content.m;
var msgs = unPackMessages(this.m);
this.salt = msgs.salt;
this.ts = msgs.ts;
this.messages = msgs.messages;
} catch (err) {
console.log(err);
return false;
}
return true;
};
};
module.exports.version = version;
module.exports.AccessToken = AccessToken;
module.exports.priviledges = {
kJoinChannel: 1,
kPublishAudioStream: 2,
kPublishVideoStream: 3,
kPublishDataStream: 4,
kPublishAudiocdn: 5,
kPublishVideoCdn: 6,
kRequestPublishAudioStream: 7,
kRequestPublishVideoStream: 8,
kRequestPublishDataStream: 9,
kInvitePublishAudioStream: 10,
kInvitePublishVideoStream: 11,
kInvitePublishDataStream: 12,
kAdministrateChannel: 101,
kRtmLogin: 1000
};
var encodeHMac = function (key, message) {
return crypto.createHmac('sha256', key).update(message).digest();
};
var ByteBuf = function () {
var that = {
buffer: Buffer.alloc(1024)
, position: 0
};
that.buffer.fill(0);
that.pack = function () {
var out = Buffer.alloc(that.position);
that.buffer.copy(out, 0, 0, out.length);
return out;
};
that.putUint16 = function (v) {
that.buffer.writeUInt16LE(v, that.position);
that.position += 2;
return that;
};
that.putUint32 = function (v) {
that.buffer.writeUInt32LE(v, that.position);
that.position += 4;
return that;
};
that.putBytes = function (bytes) {
that.putUint16(bytes.length);
bytes.copy(that.buffer, that.position);
that.position += bytes.length;
return that;
};
that.putString = function (str) {
return that.putBytes(Buffer.from(str));
};
that.putTreeMap = function (map) {
if (!map) {
that.putUint16(0);
return that;
}
that.putUint16(Object.keys(map).length);
for (var key in map) {
that.putUint16(key);
that.putString(map[key]);
}
return that;
};
that.putTreeMapUInt32 = function (map) {
if (!map) {
that.putUint16(0);
return that;
}
that.putUint16(Object.keys(map).length);
for (var key in map) {
that.putUint16(key);
that.putUint32(map[key]);
}
return that;
};
return that;
}
var ReadByteBuf = function(bytes) {
var that = {
buffer: bytes
, position: 0
};
that.getUint16 = function () {
var ret = that.buffer.readUInt16LE(that.position);
that.position += 2;
return ret;
};
that.getUint32 = function () {
var ret = that.buffer.readUInt32LE(that.position);
that.position += 4;
return ret;
};
that.getString = function () {
var len = that.getUint16();
var out = Buffer.alloc(len);
that.buffer.copy(out, 0, that.position, (that.position + len));
that.position += len;
return out;
};
that.getTreeMapUInt32 = function () {
var map = {};
var len = that.getUint16();
for( var i = 0; i < len; i++) {
var key = that.getUint16();
var value = that.getUint32();
map[key] = value;
}
return map;
};
return that;
}
var AccessTokenContent = function (options) {
options.pack = function () {
var out = new ByteBuf();
return out.putString(options.signature)
.putUint32(options.crc_channel)
.putUint32(options.crc_uid)
.putString(options.m).pack();
}
return options;
}
var Message = function (options) {
options.pack = function () {
var out = new ByteBuf();
var val = out
.putUint32(options.salt)
.putUint32(options.ts)
.putTreeMapUInt32(options.messages).pack();
return val;
}
return options;
}
var unPackContent = function(bytes) {
var readbuf = new ReadByteBuf(bytes);
return AccessTokenContent({
signature: readbuf.getString(),
crc_channel_name: readbuf.getUint32(),
crc_uid: readbuf.getUint32(),
m: readbuf.getString()
});
}
var unPackMessages = function(bytes) {
var readbuf = new ReadByteBuf(bytes);
return Message({
salt: readbuf.getUint32(),
ts: readbuf.getUint32(),
messages: readbuf.getTreeMapUInt32()
});
}
+173
View File
@@ -0,0 +1,173 @@
var crypto = require('crypto');
var version = "005";
var noUpload = "0";
var audioVideoUpload = "3";
var generatePublicSharingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, PUBLIC_SHARING_SERVICE);
};
var generateRecordingKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, RECORDING_SERVICE);
};
var generateMediaChannelKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs) {
channelName=channelName.toString();
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, null, MEDIA_CHANNEL_SERVICE);
};
var generateInChannelPermissionKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, permission) {
var extra = {};
extra[ALLOW_UPLOAD_IN_CHANNEL] = permission;
return generateDynamicKey(appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, IN_CHANNEL_PERMISSION);
};
var generateDynamicKey = function (appID, appCertificate, channelName, unixTs, randomInt, uid, expiredTs, extra, serviceType) {
var signature = generateSignature5(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra);
var content = DynamicKey5Content({
serviceType: serviceType
, signature: signature
, appID: hexDecode(appID)
, unixTs: unixTs
, salt: randomInt
, expiredTs: expiredTs
, extra: extra}).pack();
return version + content.toString('base64');
};
module.exports.version = version;
module.exports.noUpload = noUpload;
module.exports.audioVideoUpload = audioVideoUpload;
module.exports.generatePublicSharingKey = generatePublicSharingKey;
module.exports.generateRecordingKey = generateRecordingKey;
module.exports.generateMediaChannelKey = generateMediaChannelKey;
module.exports.generateInChannelPermissionKey = generateInChannelPermissionKey;
module.exports.generateDynamicKey = generateDynamicKey;
var generateSignature5 = function(appCertificate, serviceType, appID, unixTs, randomInt, channelName, uid, expiredTs, extra) {
// decode hex to avoid case problem
var rawAppID = hexDecode(appID);
var rawAppCertificate = hexDecode(appCertificate);
var m = Message({
serviceType: serviceType
, appID: rawAppID
, unixTs: unixTs
, salt: randomInt
, channelName: channelName
, uid: uid
, expiredTs: expiredTs
, extra: extra
});
var toSign = m.pack();
return encodeHMac(rawAppCertificate, toSign);
};
var encodeHMac = function(key, message) {
return crypto.createHmac('sha1', key).update(message).digest('hex').toUpperCase();
};
var hexDecode = function(str) {
return Buffer.from(str, 'hex');
};
var ByteBuf = function() {
var that = {
buffer: Buffer.alloc(1024)
, position: 0
};
that.buffer.fill(0);
that.pack = function() {
var out = Buffer.alloc(that.position);
that.buffer.copy(out, 0, 0, out.length);
return out;
};
that.putUint16 = function(v) {
that.buffer.writeUInt16LE(v, that.position);
that.position += 2;
return that;
};
that.putUint32 = function(v) {
that.buffer.writeUInt32LE(v, that.position);
that.position += 4;
return that;
};
that.putBytes = function(bytes) {
that.putUint16(bytes.length);
bytes.copy(that.buffer, that.position);
that.position += bytes.length;
return that;
};
that.putString = function(str) {
return that.putBytes(Buffer.from(str));
};
that.putTreeMap = function(map) {
if (!map) {
that.putUint16(0);
return that;
}
that.putUint16(Object.keys(map).length);
for (var key in map) {
that.putUint16(key);
that.putString(map[key]);
}
return that;
};
return that;
}
var DynamicKey5Content = function(options) {
options.pack = function() {
var out = ByteBuf();
return out.putUint16(options.serviceType)
.putString(options.signature)
.putBytes(options.appID)
.putUint32(options.unixTs)
.putUint32(options.salt)
.putUint32(options.expiredTs)
.putTreeMap(options.extra)
.pack();
}
return options;
}
var Message = function(options) {
options.pack = function() {
var out = ByteBuf();
return out.putUint16(options.serviceType)
.putBytes(options.appID)
.putUint32(options.unixTs)
.putUint32(options.salt)
.putString(options.channelName)
.putUint32(options.uid)
.putUint32(options.expiredTs)
.putTreeMap(options.extra)
.pack();
}
return options;
}
// InChannelPermissionKey
var ALLOW_UPLOAD_IN_CHANNEL = 1;
// Service Type
var MEDIA_CHANNEL_SERVICE = 1;
var RECORDING_SERVICE = 2;
var PUBLIC_SHARING_SERVICE = 3;
var IN_CHANNEL_PERMISSION = 4;
+75
View File
@@ -0,0 +1,75 @@
const AccessToken = require('../src/AccessToken').AccessToken
const Priviledges = require('../src/AccessToken').priviledges
const Role = {
// DEPRECATED. Role::ATTENDEE has the same privileges as Role.PUBLISHER.
ATTENDEE: 0,
// RECOMMENDED. Use this role for a voice/video call or a live broadcast, if your scenario does not require authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in).
PUBLISHER: 1,
/* Only use this role if your scenario require authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in).
* @note In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role.SUBSCRIBER still has the same privileges as Role.PUBLISHER.
*/
SUBSCRIBER: 2,
// DEPRECATED. Role.ADMIN has the same privileges as Role.PUBLISHER.
ADMIN: 101
}
class RtcTokenBuilder {
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} uid User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
static buildTokenWithUid(appID, appCertificate, channelName, uid, role, privilegeExpiredTs) {
return this.buildTokenWithAccount(appID, appCertificate, channelName, uid, role, privilegeExpiredTs)
}
/**
* Builds an RTC token using an Integer uid.
* @param {*} appID The App ID issued to you by Agora.
* @param {*} appCertificate Certificate of the application that you registered in the Agora Dashboard.
* @param {*} channelName The unique channel name for the AgoraRTC session in the string format. The string length must be less than 64 bytes. Supported character scopes are:
* - The 26 lowercase English letters: a to z.
* - The 26 uppercase English letters: A to Z.
* - The 10 digits: 0 to 9.
* - The space.
* - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
* @param {*} account The user account.
* @param {*} role See #userRole.
* - Role.PUBLISHER; RECOMMENDED. Use this role for a voice/video call or a live broadcast.
* - Role.SUBSCRIBER: ONLY use this role if your live-broadcast scenario requires authentication for [Hosting-in](https://docs.agora.io/en/Agora%20Platform/terms?platform=All%20Platforms#hosting-in). In order for this role to take effect, please contact our support team to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber still has the same privileges as Role_Publisher.
* @param {*} privilegeExpiredTs represented by the number of seconds elapsed since 1/1/1970. If, for example, you want to access the Agora Service within 10 minutes after the token is generated, set expireTimestamp as the current timestamp + 600 (seconds).
* @return The new Token.
*/
static buildTokenWithAccount(appID, appCertificate, channelName, account, role, privilegeExpiredTs) {
this.key = new AccessToken(appID, appCertificate, channelName, account)
this.key.addPriviledge(Priviledges.kJoinChannel, privilegeExpiredTs)
if (role == Role.ATTENDEE ||
role == Role.PUBLISHER ||
role == Role.ADMIN) {
this.key.addPriviledge(Priviledges.kPublishAudioStream, privilegeExpiredTs)
this.key.addPriviledge(Priviledges.kPublishVideoStream, privilegeExpiredTs)
this.key.addPriviledge(Priviledges.kPublishDataStream, privilegeExpiredTs)
}
return this.key.build();
}
}
module.exports.RtcTokenBuilder = RtcTokenBuilder;
module.exports.Role = Role;
+31
View File
@@ -0,0 +1,31 @@
const AccessToken = require("../src/AccessToken").AccessToken
const Priviledges = require('../src/AccessToken').priviledges
const Role = {
Rtm_User: 1
}
class RtmTokenBuilder {
/**
* @param {*} appID: The App ID issued to you by Agora. Apply for a new App ID from
* Agora Dashboard if it is missing from your kit. See Get an App ID.
* @param {*} appCertificate: Certificate of the application that you registered in
* the Agora Dashboard. See Get an App Certificate.
* @param {*} account: The user account.
* @param {*} role : Role_Publisher = 1: A broadcaster (host) in a live-broadcast profile.
* Role_Subscriber = 2: (Default) A audience in a live-broadcast profile.
* @param {*} privilegeExpiredTs : represented by the number of seconds elapsed since
* 1/1/1970. If, for example, you want to access the
* Agora Service within 10 minutes after the token is
* generated, set expireTimestamp as the current
* @return token
*/
static buildToken (appID, appCertificate, account, role, privilegeExpiredTs) {
const key = new AccessToken(appID, appCertificate, account, "")
key.addPriviledge(Priviledges.kRtmLogin, privilegeExpiredTs)
return key.build()
}
}
module.exports.RtmTokenBuilder = RtmTokenBuilder
module.exports.Role = Role
+29
View File
@@ -0,0 +1,29 @@
const md5 = require("md5");
var SignalingToken = {}
SignalingToken.get = function(appid, appcertificate, account, validTimeInSeconds){
var expiredTime = parseInt(new Date().getTime() / 1000)+ validTimeInSeconds;
var token_items = [];
//append SDK VERSION
token_items.push("1");
//append appid
token_items.push(appid);
//expired time
token_items.push(expiredTime);
//md5 account + appid + appcertificate + expiredtime
token_items.push(md5(account + appid + appcertificate + expiredTime));
return token_items.join(":");
}
//convenience function to get token valid within 1 day
SignalingToken.get1DayToken = function(appid, appcertificate, account){
return SignalingToken.get(appid, appcertificate, account, 3600 * 24);
}
module.exports = SignalingToken;