|
@@ -1,308 +0,0 @@
|
|
|
-using Newtonsoft.Json;
|
|
|
-using Newtonsoft.Json.Linq;
|
|
|
-using System;
|
|
|
-using System.Collections.Concurrent;
|
|
|
-using System.Collections.Generic;
|
|
|
-using System.IO;
|
|
|
-using System.Linq;
|
|
|
-using System.Security.Cryptography;
|
|
|
-using System.Text;
|
|
|
-using WingServerCommon.Config;
|
|
|
-using WingServerCommon.Log;
|
|
|
-using ComponentAce.Compression.Libs.zlib;
|
|
|
-
|
|
|
-namespace WingLiveConsultationService.Utilities
|
|
|
-{
|
|
|
- class TRTCHelper
|
|
|
- {
|
|
|
- private static ConcurrentDictionary<string, uint> ids = new ConcurrentDictionary<string, uint>();
|
|
|
- private static string _appIdStr;
|
|
|
- private static int _appId;
|
|
|
- public static readonly string ServiceId = "WingLiveConsultationService";
|
|
|
- public static bool IsTestAccount { get; private set; }
|
|
|
- private readonly static TLSSigAPIv2 _tLSSigAPIv2;
|
|
|
- private static int _bizid;//旁路推流 id
|
|
|
- private static string _protocol;//网址协议 http or https
|
|
|
- private static string _playDomain;//旁路推流域名
|
|
|
- private static uint _initRoomId;//房间起始id,分布式不同服务器起始id不同,避免id相同
|
|
|
- static TRTCHelper()
|
|
|
- {
|
|
|
- _appIdStr = ConfigurationManager.GetValue(ServiceId, "TRTCAppId", "1400299969");
|
|
|
- var appKey = ConfigurationManager.GetValue(ServiceId, "TRTCAppKey", "59faebabcb036b898fb9a5323ef9d2be91d76c048a77aaa81f6dbfa6bac91bb3");
|
|
|
- _bizid = ConfigurationManager.GetValue<int>(ServiceId, "TRTCBizid", 71678);
|
|
|
- _protocol = ConfigurationManager.GetValue(ServiceId, "TRTCUseSSL", "false") == "true" ? "https:" : "http:";
|
|
|
- _playDomain = ConfigurationManager.GetValue(ServiceId, "TRTCPlayDomain", "liveplay.fis.plus");//旁路推流域名
|
|
|
- _initRoomId = (uint)ConfigurationManager.GetValue(ServiceId, "TRTCInitRoomId", 0);//旁路推流域名
|
|
|
- IsTestAccount = _appIdStr != "1400299969";
|
|
|
- if (int.TryParse(_appIdStr, out int appId))
|
|
|
- {
|
|
|
- _appId = appId;
|
|
|
- _tLSSigAPIv2 = new TLSSigAPIv2(appId, appKey);
|
|
|
- }
|
|
|
- }
|
|
|
- /// <summary>
|
|
|
- /// get uint room id with a uniqueId
|
|
|
- /// </summary>
|
|
|
- /// <param name="uiqueId"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static uint GetRoomId(string uniqueId)
|
|
|
- {
|
|
|
- return ids.GetOrAdd(uniqueId, (uid) =>
|
|
|
- {
|
|
|
- if (ids.Count <= 0)
|
|
|
- {
|
|
|
- return _initRoomId+1;
|
|
|
- }
|
|
|
- var maxId =ids.Values.Max();
|
|
|
- return maxId + 1;
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Get user Sign for TRTC
|
|
|
- /// </summary>
|
|
|
- /// <param name="id"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string GetUserSign(string id)
|
|
|
- {
|
|
|
- return _tLSSigAPIv2.GenSig(id);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Get the trtc app id
|
|
|
- /// </summary>
|
|
|
- /// <returns>string</returns>
|
|
|
- public static int GetAppId()
|
|
|
- {
|
|
|
- return _appId;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Generate rtmp url with room id and user id
|
|
|
- /// </summary>
|
|
|
- /// <param name="roomId"></param>
|
|
|
- /// <param name="userId"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string GenerateRtmpUrl(uint roomId, string userId)
|
|
|
- {
|
|
|
- //appid: 1300984704 bizid:71678
|
|
|
- // 计算 CDN 地址(格式: rtmp://liveplay.fis.plus/live/[bizid]_[streamid] )
|
|
|
- // int bizId = 71678;
|
|
|
- // streamid = MD5 (房间号_用户名_流类型)
|
|
|
- string streamId = MD5(String.Format("{0}_{1}_{2}", roomId, UTF16To8(userId), "main"));
|
|
|
- string shareUrl;
|
|
|
- if (!IsTestAccount)
|
|
|
- {
|
|
|
- shareUrl = String.Format("rtmp://{0}/live/{1}_{2}", _playDomain, _bizid, streamId);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- shareUrl = String.Format("rtmp://{0}/live/{1}_{2}_{3}_main", _playDomain, _appId, roomId, userId); //小号播放地址
|
|
|
- }
|
|
|
- return shareUrl;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Generate hls url with room id and user id
|
|
|
- /// </summary>
|
|
|
- /// <param name="roomId"></param>
|
|
|
- /// <param name="userId"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string GenerateHlsUrl(uint roomId, string userId)
|
|
|
- {
|
|
|
- string streamId = MD5(String.Format("{0}_{1}_{2}", roomId, UTF16To8(userId), "main"));
|
|
|
- string shareUrl;
|
|
|
- if (!IsTestAccount)
|
|
|
- {
|
|
|
- shareUrl = $"{_protocol}//{_playDomain}/live/{_bizid}_{streamId}.m3u8";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- shareUrl = $"{_protocol}//{_playDomain}/live/{_appId}_{roomId}_{userId}_main.m3u8"; //小号播放地址
|
|
|
- }
|
|
|
- return shareUrl;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// Generate hls url with room id and user id
|
|
|
- /// </summary>
|
|
|
- /// <param name="roomId"></param>
|
|
|
- /// <param name="userId"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string GenerateFlvUrl(uint roomId, string userId)
|
|
|
- {
|
|
|
- string streamId = MD5(String.Format("{0}_{1}_{2}", roomId, UTF16To8(userId), "main"));
|
|
|
- string shareUrl;
|
|
|
- if (!IsTestAccount)
|
|
|
- {
|
|
|
- shareUrl = $"{_protocol}//{_playDomain}/live/{_bizid}_{streamId}.flv";
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- shareUrl = $"{_protocol}//{_playDomain}/live/{_appId}_{roomId}_{userId}_main.flv"; //小号播放地址
|
|
|
- }
|
|
|
- return shareUrl;
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// MD5 Cryptography
|
|
|
- /// </summary>
|
|
|
- /// <param name="str"></param>
|
|
|
- /// <returns></returns>
|
|
|
- private static string MD5(string str)
|
|
|
- {
|
|
|
- MD5 md5 = System.Security.Cryptography.MD5.Create();
|
|
|
- byte[] byteOld = Encoding.UTF8.GetBytes(str);
|
|
|
- byte[] byteNew = md5.ComputeHash(byteOld);
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- foreach (byte b in byteNew)
|
|
|
- {
|
|
|
- // 将字节转换成16进制表示的字符串
|
|
|
- sb.Append(b.ToString("x2"));
|
|
|
- }
|
|
|
- return sb.ToString();
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 统一转换为UTF8,SDK内部是用UTF8编码。
|
|
|
- /// </summary>
|
|
|
- /// <param name="str"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string UTF16To8(string str)
|
|
|
- {
|
|
|
- byte[] utf16Bytes = Encoding.Unicode.GetBytes(str);
|
|
|
- byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
|
|
|
- return Encoding.UTF8.GetString(utf8Bytes);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// TRTC
|
|
|
- /// </summary>
|
|
|
- public class TLSSigAPIv2
|
|
|
- {
|
|
|
- private readonly int sdkappid;
|
|
|
- private readonly string key;
|
|
|
-
|
|
|
- public TLSSigAPIv2(int sdkappid, string key)
|
|
|
- {
|
|
|
- this.sdkappid = sdkappid;
|
|
|
- this.key = key;
|
|
|
- }
|
|
|
-
|
|
|
- private byte[] CompressBytes(byte[] sourceByte)
|
|
|
- {
|
|
|
- return CompressStream(sourceByte);
|
|
|
- }
|
|
|
-
|
|
|
- private byte[] CompressStream(byte[] sourceByte)
|
|
|
- {
|
|
|
- using (MemoryStream streamOut = new MemoryStream())
|
|
|
- {
|
|
|
- using (ZOutputStream streamZOut = new ZOutputStream(streamOut, zlibConst.Z_DEFAULT_COMPRESSION))
|
|
|
- {
|
|
|
- streamZOut.Write(sourceByte, 0, sourceByte.Length);
|
|
|
- streamZOut.finish();
|
|
|
- return streamOut.ToArray();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private string HMACSHA256(string identifier, long currTime, int expire, string base64UserBuf, bool userBufEnabled)
|
|
|
- {
|
|
|
- string rawContentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
|
|
- + "TLS.sdkappid:" + sdkappid + "\n"
|
|
|
- + "TLS.time:" + currTime + "\n"
|
|
|
- + "TLS.expire:" + expire + "\n";
|
|
|
- if (true == userBufEnabled)
|
|
|
- {
|
|
|
- rawContentToBeSigned += "TLS.userbuf:" + base64UserBuf + "\n";
|
|
|
- }
|
|
|
- using (HMACSHA256 hmac = new HMACSHA256())
|
|
|
- {
|
|
|
- UTF8Encoding encoding = new UTF8Encoding();
|
|
|
- Byte[] textBytes = encoding.GetBytes(rawContentToBeSigned);
|
|
|
- Byte[] keyBytes = encoding.GetBytes(key);
|
|
|
- Byte[] hashBytes;
|
|
|
- using (HMACSHA256 hash = new HMACSHA256(keyBytes))
|
|
|
- hashBytes = hash.ComputeHash(textBytes);
|
|
|
- return Convert.ToBase64String(hashBytes);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private string GenSig(string identifier, int expire, byte[] userbuf, bool userBufEnabled)
|
|
|
- {
|
|
|
- DateTime epoch = new DateTime(1970, 1, 1); // unix 时间戳
|
|
|
- Int64 currTime = (Int64)(DateTime.UtcNow - epoch).TotalMilliseconds / 1000;
|
|
|
-
|
|
|
- string base64UserBuf;
|
|
|
- string jsonData;
|
|
|
- if (true == userBufEnabled)
|
|
|
- {
|
|
|
- base64UserBuf = Convert.ToBase64String(userbuf);
|
|
|
- string base64sig = HMACSHA256(identifier, currTime, expire, base64UserBuf, userBufEnabled);
|
|
|
- dynamic jsonObj = new JObject();
|
|
|
- jsonObj["TLS.ver"] = "2.0";
|
|
|
- jsonObj["TLS.identifier"] = identifier;
|
|
|
- jsonObj["TLS.sdkappid"] = sdkappid;
|
|
|
- jsonObj["TLS.expire"] = expire;
|
|
|
- jsonObj["TLS.time"] = currTime;
|
|
|
- jsonObj["TLS.sig"] = base64sig;
|
|
|
- jsonObj["TLS.userbuf"] = base64UserBuf;
|
|
|
- jsonData = JsonConvert.SerializeObject(jsonObj);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- string base64sig = HMACSHA256(identifier, currTime, expire, "", false);
|
|
|
- dynamic jsonObj = new JObject();
|
|
|
- jsonObj["TLS.ver"] = "2.0";
|
|
|
- jsonObj["TLS.identifier"] = identifier;
|
|
|
- jsonObj["TLS.sdkappid"] = sdkappid;
|
|
|
- jsonObj["TLS.expire"] = expire;
|
|
|
- jsonObj["TLS.time"] = currTime;
|
|
|
- jsonObj["TLS.sig"] = base64sig;
|
|
|
- jsonData = JsonConvert.SerializeObject(jsonObj);
|
|
|
- }
|
|
|
- byte[] buffer = Encoding.UTF8.GetBytes(jsonData);
|
|
|
- return Convert.ToBase64String(CompressBytes(buffer))
|
|
|
- .Replace('+', '*').Replace('/', '-').Replace('=', '_');
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// convert user Id to json string
|
|
|
- /// </summary>
|
|
|
- /// <param name="identifier"></param>
|
|
|
- /// <param name="expire"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public string GenSig(string identifier, int expire = 180 * 86400)
|
|
|
- {
|
|
|
- var utf8String = UTF16To8(identifier);
|
|
|
- return GenSig(utf8String, expire, null, false);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// convert user Id to json string (advancement)
|
|
|
- /// </summary>
|
|
|
- /// <param name="identifier"></param>
|
|
|
- /// <param name="expire"></param>
|
|
|
- /// <param name="userbuf"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public string GenSigWithUserBuf(string identifier, int expire, byte[] userbuf)
|
|
|
- {
|
|
|
- var utf8String = UTF16To8(identifier);
|
|
|
- return GenSig(utf8String, expire, userbuf, true);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 统一转换为UTF8,SDK内部是用UTF8编码。
|
|
|
- /// </summary>
|
|
|
- /// <param name="str"></param>
|
|
|
- /// <returns></returns>
|
|
|
- public static string UTF16To8(string str)
|
|
|
- {
|
|
|
- byte[] utf16Bytes = Encoding.Unicode.GetBytes(str);
|
|
|
- byte[] utf8Bytes = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, utf16Bytes);
|
|
|
- return Encoding.UTF8.GetString(utf8Bytes);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|