123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414 |
- package agora
-
- import (
- "bytes"
- "crypto/hmac"
- "crypto/sha256"
- "encoding/base64"
- "encoding/binary"
- "encoding/hex"
- "fmt"
- "hash/crc32"
- "io"
- "math/rand"
- "sort"
- "time"
- )
-
- // 这里引用了agoda给出的demo,写的并不好,若他们将来有sdk,可以替换成sdk
-
- // Role 角色
- type Role uint16
-
- // Roles
- const (
- Role_Attendee = 1
- Role_Publisher = 2
- Role_Subscriber = 3
- Role_Admin = 4
- )
-
- var attendeePrivileges = map[uint16]uint32{
- KJoinChannel: 0,
- KPublishAudioStream: 0,
- KPublishVideoStream: 0,
- KPublishDataStream: 0,
- }
- var publisherPrivileges = map[uint16]uint32{
- KJoinChannel: 0,
- KPublishAudioStream: 0,
- KPublishVideoStream: 0,
- KPublishDataStream: 0,
- KPublishAudiocdn: 0,
- KPublishVideoCdn: 0,
- KInvitePublishAudioStream: 0,
- KInvitePublishVideoStream: 0,
- KInvitePublishDataStream: 0,
- }
-
- var subscriberPrivileges = map[uint16]uint32{
- KJoinChannel: 0,
- KRequestPublishAudioStream: 0,
- KRequestPublishVideoStream: 0,
- KRequestPublishDataStream: 0,
- }
-
- var adminPrivileges = map[uint16]uint32{
- KJoinChannel: 0,
- KPublishAudioStream: 0,
- KPublishVideoStream: 0,
- KPublishDataStream: 0,
- KAdministrateChannel: 0,
- }
-
- // RolePrivileges 角色权限
- var RolePrivileges = map[uint16](map[uint16]uint32){
- Role_Attendee: attendeePrivileges,
- Role_Publisher: publisherPrivileges,
- Role_Subscriber: subscriberPrivileges,
- Role_Admin: adminPrivileges,
- }
-
- // SimpleTokenBuilder
- type SimpleTokenBuilder struct {
- Token AccessToken
- }
-
- func CreateSimpleTokenBuilder(appID, appCertificate, channelName string, uid uint32) SimpleTokenBuilder {
- return SimpleTokenBuilder{CreateAccessToken(appID, appCertificate, channelName, uid)}
- }
-
- // InitPrivileges expireTimestamp 为0时长期有效
- func (builder *SimpleTokenBuilder) InitPrivileges(role Role, expireTimestamp uint32) {
- rolepri := uint16(role)
- for key, value := range RolePrivileges[rolepri] {
- builder.Token.Message[key] = value
- }
- }
-
- func (builder *SimpleTokenBuilder) InitTokenBuilder(originToken string) bool {
- return builder.Token.FromString(originToken)
- }
-
- func (builder *SimpleTokenBuilder) SetPrivilege(privilege Privileges, expireTimestamp uint32) {
- pri := uint16(privilege)
- builder.Token.Message[pri] = expireTimestamp
- }
-
- func (builder *SimpleTokenBuilder) RemovePrivilege(privilege Privileges) {
- pri := uint16(privilege)
- delete(builder.Token.Message, pri)
- }
-
- func (builder *SimpleTokenBuilder) BuildToken() (string, error) {
- return builder.Token.Build()
- }
-
- // 官方的 AccessToken文件
- const VERSION_LENGTH = 3
- const APP_ID_LENGTH = 32
-
- type Privileges uint16
-
- const (
- 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
- )
-
- type AccessToken struct {
- AppID string
- AppCertificate string
- ChannelName string
- UidStr string
- Ts uint32
- Salt uint32
- Message map[uint16]uint32
- Signature string
- CrcChannelName uint32
- CrcUid uint32
- MsgRawContent string
- }
-
- func random(min int, max int) int {
- rand.Seed(time.Now().UnixNano())
- return rand.Intn(max-min) + min
- }
-
- func panichandler() {
- if r := recover(); r != nil {
- fmt.Println("error: ", r)
- }
- }
-
- func getVersion() string {
- return "006"
- }
-
- func CreateAccessToken(appID, appCertificate, channelName string, uid uint32) AccessToken {
- var uidStr string
- if uid == 0 {
- uidStr = ""
- } else {
- uidStr = fmt.Sprintf("%d", uid)
- }
- ts := uint32(time.Now().Unix()) + 24*3600
- salt := uint32(random(1, 99999999))
- message := make(map[uint16]uint32)
- return AccessToken{appID, appCertificate, channelName, uidStr, ts, salt, message, "", 0, 0, ""}
- }
-
- func (token *AccessToken) FromString(originToken string) bool {
- defer panichandler()
-
- dk6version := getVersion()
- originVersion := originToken[:VERSION_LENGTH]
- if originVersion != dk6version {
- return false
- }
-
- //originAppID := originToken[VERSION_LENGTH:(VERSION_LENGTH + APP_ID_LENGTH)]
- originContent := originToken[(VERSION_LENGTH + APP_ID_LENGTH):]
- originContentDecoded, err := base64.StdEncoding.DecodeString(originContent)
- if err != nil {
- return false
- }
-
- signature_, crc_channel_name_, crc_uid_, msg_raw_content_, err := unPackContent(originContentDecoded)
- if err != nil {
- return false
- }
- token.Signature = signature_
- token.CrcChannelName = crc_channel_name_
- token.CrcUid = crc_uid_
- token.MsgRawContent = msg_raw_content_
-
- salt_, ts_, messages_, err := unPackMessages(token.MsgRawContent)
- if err != nil {
- return false
- }
- token.Salt = salt_
- token.Ts = ts_
- token.Message = messages_
-
- return true
- }
-
- func (token *AccessToken) AddPrivilege(privilege Privileges, expireTimestamp uint32) {
- pri := uint16(privilege)
- token.Message[pri] = expireTimestamp
- }
-
- func (token *AccessToken) Build() (string, error) {
- ret := ""
- version := getVersion()
-
- buf_m := new(bytes.Buffer)
- if err := packUint32(buf_m, token.Salt); err != nil {
- return ret, err
- }
- if err := packUint32(buf_m, token.Ts); err != nil {
- return ret, err
- }
- if err := packMapUint32(buf_m, token.Message); err != nil {
- return ret, err
- }
- bytes_m := buf_m.Bytes()
-
- buf_val := new(bytes.Buffer)
- val := token.AppID + token.ChannelName + token.UidStr
- buf_val.Write([]byte(val))
- buf_val.Write(bytes_m)
- bytes_val := buf_val.Bytes()
-
- buf_sig := hmac.New(sha256.New, []byte(token.AppCertificate))
- buf_sig.Write(bytes_val)
- bytes_sig := buf_sig.Sum(nil)
-
- crc32q := crc32.MakeTable(0xedb88320)
- crc_channel_name := crc32.Checksum([]byte(token.ChannelName), crc32q)
- crc_uid := crc32.Checksum([]byte(token.UidStr), crc32q)
-
- buf_content := new(bytes.Buffer)
- if err := packString(buf_content, string(bytes_sig[:])); err != nil {
- return ret, err
- }
- if err := packUint32(buf_content, crc_channel_name); err != nil {
- return ret, err
- }
- if err := packUint32(buf_content, crc_uid); err != nil {
- return ret, err
- }
- if err := packString(buf_content, string(bytes_m[:])); err != nil {
- return ret, err
- }
- bytes_content := buf_content.Bytes()
-
- ret = version + token.AppID + base64.StdEncoding.EncodeToString(bytes_content)
- return ret, nil
- }
-
- func packUint16(w io.Writer, n uint16) error {
- return binary.Write(w, binary.LittleEndian, n)
- }
-
- func packUint32(w io.Writer, n uint32) error {
- return binary.Write(w, binary.LittleEndian, n)
- }
-
- func packString(w io.Writer, s string) error {
- err := packUint16(w, uint16(len(s)))
- if err != nil {
- return err
- }
- _, err = w.Write([]byte(s))
- return err
- }
-
- func packHexString(w io.Writer, s string) error {
- b, err := hex.DecodeString(s)
- if err != nil {
- return err
- }
- return packString(w, string(b))
- }
-
- func packExtra(w io.Writer, extra map[uint16]string) error {
- keys := []int{}
- if err := packUint16(w, uint16(len(extra))); err != nil {
- return err
- }
- for k := range extra {
- keys = append(keys, int(k))
- }
- //should sorted keys
- sort.Ints(keys)
-
- for _, k := range keys {
- v := extra[uint16(k)]
- if err := packUint16(w, uint16(k)); err != nil {
- return err
- }
- if err := packString(w, v); err != nil {
- return err
- }
- }
- return nil
- }
-
- func packMapUint32(w io.Writer, extra map[uint16]uint32) error {
- keys := []int{}
- if err := packUint16(w, uint16(len(extra))); err != nil {
- return err
- }
- for k := range extra {
- keys = append(keys, int(k))
- }
- //should sorted keys
- sort.Ints(keys)
-
- for _, k := range keys {
- v := extra[uint16(k)]
- if err := packUint16(w, uint16(k)); err != nil {
- return err
- }
- if err := packUint32(w, v); err != nil {
- return err
- }
- }
- return nil
- }
-
- func unPackUint16(r io.Reader) (uint16, error) {
- var n uint16
- err := binary.Read(r, binary.LittleEndian, &n)
- return n, err
- }
-
- func unPackUint32(r io.Reader) (uint32, error) {
- var n uint32
- err := binary.Read(r, binary.LittleEndian, &n)
- return n, err
- }
-
- func unPackString(r io.Reader) (string, error) {
- n, err := unPackUint16(r)
- if err != nil {
- return "", err
- }
-
- buf := make([]byte, n)
- r.Read(buf)
- s := string(buf[:])
- return s, err
- }
-
- func unPackContent(buff []byte) (string, uint32, uint32, string, error) {
- in := bytes.NewReader(buff)
- sig, err := unPackString(in)
- if err != nil {
- return "", 0, 0, "", err
- }
-
- crc_channel_name, err := unPackUint32(in)
- if err != nil {
- return "", 0, 0, "", err
- }
- crc_uid, err := unPackUint32(in)
- if err != nil {
- return "", 0, 0, "", err
- }
- m, err := unPackString(in)
- if err != nil {
- return "", 0, 0, "", err
- }
-
- return sig, crc_channel_name, crc_uid, m, nil
- }
-
- func unPackMessages(msg_str string) (uint32, uint32, map[uint16]uint32, error) {
- msg_map := make(map[uint16]uint32)
-
- msg_byte := []byte(msg_str)
- in := bytes.NewReader(msg_byte)
-
- salt, err := unPackUint32(in)
- if err != nil {
- return 0, 0, msg_map, err
- }
- ts, err := unPackUint32(in)
- if err != nil {
- return 0, 0, msg_map, err
- }
-
- len, err := unPackUint16(in)
- if err != nil {
- return 0, 0, msg_map, err
- }
- for i := uint16(0); i < len; i++ {
- key, err := unPackUint16(in)
- if err != nil {
- return 0, 0, msg_map, err
- }
- value, err := unPackUint32(in)
- if err != nil {
- return 0, 0, msg_map, err
- }
- msg_map[key] = value
- }
-
- return salt, ts, msg_map, nil
- }
|