forked from q191201771/lal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- [feat] httpflv, httpts, hls支持跨域请求播放 - [feat] 新增package alpha/stun,学习stun协议
- Loading branch information
1 parent
395b434
commit 5f4ec66
Showing
14 changed files
with
389 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
github.com/q191201771/naza v0.13.4 h1:ogdobhcSMGqxKUH3tAbiQvF3gHXqMTt7AUdewiqgrWs= | ||
github.com/q191201771/naza v0.13.4/go.mod h1:SE14GBGO9mAn6JZl3NlfWGtNOT7xQjxOG7f3YOdBThM= | ||
github.com/q191201771/naza v0.14.0 h1:bgjiNRmaSxoYwuyjNvCOtvJgwFYmGlBj6tQpaaK2zhE= | ||
github.com/q191201771/naza v0.14.0/go.mod h1:SE14GBGO9mAn6JZl3NlfWGtNOT7xQjxOG7f3YOdBThM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2020, Chef. All rights reserved. | ||
// https://github.com/q191201771/lal | ||
// | ||
// Use of this source code is governed by a MIT-style license | ||
// that can be found in the License file. | ||
// | ||
// Author: Chef (191201771@qq.com) | ||
|
||
package stun | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/q191201771/naza/pkg/nazanet" | ||
) | ||
|
||
// TODO chef: | ||
// - 设置超时 | ||
// - 重试 | ||
|
||
type Client struct { | ||
} | ||
|
||
// @param addr 填入server地址,如果不包含端口,则使用默认端口3478 | ||
func (c *Client) Query(addr string, timeoutMS int) (ip string, port int, err error) { | ||
if !strings.Contains(addr, ":") { | ||
addr = fmt.Sprintf("%s:%d", addr, DefaultPort) | ||
} | ||
|
||
uc, err := nazanet.NewUDPConnection("", addr) | ||
if err != nil { | ||
return "", 0, err | ||
} | ||
req, err := PackBindingRequest() | ||
if err != nil { | ||
return "", 0, err | ||
} | ||
if err := uc.Write(req); err != nil { | ||
return "", 0, err | ||
} | ||
|
||
b, _, err := uc.ReadWithTimeout(timeoutMS) | ||
if err != nil { | ||
return "", 0, err | ||
} | ||
|
||
_ = uc.Dispose() | ||
|
||
return ParseMessage(b) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
// Copyright 2020, Chef. All rights reserved. | ||
// https://github.com/q191201771/lal | ||
// | ||
// Use of this source code is governed by a MIT-style license | ||
// that can be found in the License file. | ||
// | ||
// Author: Chef (191201771@qq.com) | ||
|
||
package stun | ||
|
||
import ( | ||
"bytes" | ||
"crypto/rand" | ||
"fmt" | ||
|
||
"github.com/q191201771/naza/pkg/bele" | ||
) | ||
|
||
// 0 1 2 3 | ||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | ||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
// |0 0| STUN Message Type | Message Length | | ||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
// | Magic Cookie | | ||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
// | | | ||
// | Transaction ID (96 bits) | | ||
// | | | ||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
// | ||
// Figure 2: Format of STUN Message Header | ||
|
||
const minStunMessageSize = 20 | ||
|
||
var ( | ||
magicCookie = []byte{0x21, 0x12, 0xa4, 0x42} | ||
magicCookieBE = 0x2112a442 | ||
|
||
//typeBindSuccessResponse = []byte{0x1, 0x1} | ||
typeBindingRequest = []byte{0x0, 0x1} | ||
typeBindSuccessResponseBE = 0x0101 | ||
|
||
//attrTypeXORMappedAddress = []byte{0x0, 0x20} | ||
//attrTypeXORMappedAddress2 = []byte{0x80, 0x20} | ||
//attrTypeMappedAddress = []byte{0x0, 0x1} | ||
attrTypeXORMappedAddressBE = 0x0020 | ||
attrTypeXORMappedAddress2BE = 0x8020 | ||
attrTypeMappedAddressBE = 0x0001 | ||
|
||
protocolFamilyIPv4 = []byte{0x0, 0x1} | ||
) | ||
|
||
func PackBindingRequest() ([]byte, error) { | ||
b := make([]byte, minStunMessageSize) | ||
copy(b, typeBindingRequest) | ||
// b[2:4] message length 0 | ||
copy(b[4:], magicCookie) | ||
// transaction id | ||
if _, err := rand.Reader.Read(b[8:]); err != nil { | ||
return nil, err | ||
} | ||
return b, nil | ||
} | ||
|
||
func ParseMessage(b []byte) (ip string, port int, err error) { | ||
if len(b) < minStunMessageSize { | ||
return "", 0, ErrStun | ||
} | ||
// TODO chef: only impled bind success response | ||
if int(bele.BEUint16(b[:2])) != typeBindSuccessResponseBE { | ||
return "", 0, ErrStun | ||
} | ||
|
||
messageLength := bele.BEUint16(b[2:]) | ||
|
||
if bytes.Compare(b[4:8], magicCookie) != 0 { | ||
return "", 0, ErrStun | ||
} | ||
|
||
// transaction id | ||
|
||
if len(b) < minStunMessageSize+int(messageLength) { | ||
return "", 0, ErrStun | ||
} | ||
|
||
// attr list | ||
pos := minStunMessageSize | ||
for { | ||
if len(b[pos:]) < 4 { | ||
return "", 0, ErrStun | ||
} | ||
at := int(bele.BEUint16(b[pos : pos+2])) | ||
al := int(bele.BEUint16(b[pos+2 : pos+4])) | ||
pos += 4 | ||
if len(b[pos:]) < al { | ||
return "", 0, ErrStun | ||
} | ||
|
||
if at == attrTypeXORMappedAddressBE || at == attrTypeXORMappedAddress2BE { | ||
ip, port, err = parseAttrXORMappedAddress(b[pos:]) | ||
if err != nil { | ||
return "", 0, err | ||
} | ||
} | ||
if at == attrTypeMappedAddressBE { | ||
ip, port, err = parseAttrMappedAddress(b[pos:]) | ||
if err != nil { | ||
return "", 0, err | ||
} | ||
} | ||
|
||
pos += al | ||
if pos == minStunMessageSize+int(messageLength) { | ||
break | ||
} | ||
} | ||
|
||
return ip, port, nil | ||
} | ||
|
||
func parseAttrXORMappedAddress(b []byte) (ip string, port int, err error) { | ||
if bytes.Compare(b[:2], protocolFamilyIPv4) != 0 { | ||
return "", 0, ErrStun | ||
} | ||
|
||
port = int(bele.BEUint16(b[2:])) ^ (magicCookieBE >> 16) | ||
|
||
ipb := make([]byte, 4) | ||
xor(b[4:], magicCookie, ipb) | ||
ip = fmt.Sprintf("%d.%d.%d.%d", ipb[0], ipb[1], ipb[2], ipb[3]) | ||
return | ||
} | ||
|
||
func parseAttrMappedAddress(b []byte) (ip string, port int, err error) { | ||
if bytes.Compare(b[:2], protocolFamilyIPv4) != 0 { | ||
return "", 0, ErrStun | ||
} | ||
|
||
port = int(bele.BEUint16(b[2:])) | ||
ip = fmt.Sprintf("%d.%d.%d.%d", b[4], b[5], b[6], b[7]) | ||
return | ||
} | ||
|
||
func xor(a, b, res []byte) { | ||
n := len(a) | ||
if n > len(b) { | ||
n = len(b) | ||
} | ||
for i := 0; i < n; i++ { | ||
res[i] = a[i] ^ b[i] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2020, Chef. All rights reserved. | ||
// https://github.com/q191201771/lal | ||
// | ||
// Use of this source code is governed by a MIT-style license | ||
// that can be found in the License file. | ||
// | ||
// Author: Chef (191201771@qq.com) | ||
|
||
package stun | ||
|
||
import "errors" | ||
|
||
// TODO chef: | ||
// - attr soft | ||
|
||
// Session Traversal Utilities for NAT | ||
// | ||
// rfc 5389 | ||
// | ||
|
||
var ErrStun = errors.New("lal.stun: fxxk") | ||
|
||
var DefaultPort = 3478 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Copyright 2020, Chef. All rights reserved. | ||
// https://github.com/q191201771/lal | ||
// | ||
// Use of this source code is governed by a MIT-style license | ||
// that can be found in the License file. | ||
// | ||
// Author: Chef (191201771@qq.com) | ||
|
||
package stun | ||
|
||
import ( | ||
"sync" | ||
"testing" | ||
|
||
"github.com/q191201771/naza/pkg/nazalog" | ||
) | ||
|
||
var serverAddrList = []string{ | ||
// dial udp: lookup stun01.sipphone.com: no such host | ||
// ---------- | ||
//"stun01.sipphone.com", | ||
|
||
// XOR-MAPPED-ADDRESS | ||
// ---------- | ||
"stun.l.google.com:19302", | ||
"stun4.l.google.com:19302", | ||
|
||
// XOR-MAPPED-ADDRESS | ||
// MAPPED-ADDRESS | ||
// RESPONSE-ORIGIN | ||
// OTHER-ADDRESS | ||
// SOFTWARE | ||
// FINGERPRINT | ||
// ---------- | ||
"stun.freeswitch.org:3478", | ||
|
||
// MAPPED-ADDRESS | ||
// SOURCE_ADDRESS | ||
// CHANGED_ADDRESS | ||
// XOR-MAPPED-ADDRESS | ||
// SOFTWARE | ||
// ---------- | ||
"stun.xten.com", | ||
"stun.ekiga.net", | ||
"stun.schlund.de", | ||
|
||
// MAPPED-ADDRESS | ||
// SOURCE_ADDRESS | ||
// CHANGED_ADDRESS | ||
// ---------- | ||
"stun.ideasip.com", | ||
"stun.voiparound.com", | ||
"stun.voipbuster.com", | ||
"stun.voipstunt.com", | ||
} | ||
|
||
func TestClient(t *testing.T) { | ||
var wg sync.WaitGroup | ||
for _, s := range serverAddrList { | ||
wg.Add(1) | ||
go func(ss string) { | ||
var c Client | ||
ip, port, err := c.Query(ss, 200) | ||
nazalog.Debugf("server=%s, addr=%s:%d, err=%+v", ss, ip, port, err) | ||
wg.Done() | ||
}(s) | ||
} | ||
wg.Wait() | ||
} | ||
|
||
func TestServer(t *testing.T) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2020, Chef. All rights reserved. | ||
// https://github.com/q191201771/lal | ||
// | ||
// Use of this source code is governed by a MIT-style license | ||
// that can be found in the License file. | ||
// | ||
// Author: Chef (191201771@qq.com) | ||
|
||
package hls | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os" | ||
"strconv" | ||
) | ||
|
||
// @param content 需写入文件的内容 | ||
// @param filename m3u8文件名 | ||
// @param filenameBak m3u8临时文件名 | ||
// | ||
func writeM3U8File(content []byte, filename string, filenameBak string) error { | ||
var fp *os.File | ||
var err error | ||
if fp, err = os.Create(filenameBak); err != nil { | ||
return err | ||
} | ||
if _, err = fp.Write(content); err != nil { | ||
return err | ||
} | ||
if err = fp.Close(); err != nil { | ||
return err | ||
} | ||
if err = os.Rename(filenameBak, filename); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func updateTargetDurationInM3U8(content []byte, currDuration int) ([]byte, error) { | ||
l := bytes.Index(content, []byte("#EXT-X-TARGETDURATION:")) | ||
if l == -1 { | ||
return content, ErrHLS | ||
} | ||
r := bytes.Index(content[l:], []byte{'\n'}) | ||
if r == -1 { | ||
return content, ErrHLS | ||
} | ||
oldDurationStr := bytes.TrimPrefix(content[l:l+r], []byte("#EXT-X-TARGETDURATION:")) | ||
oldDuration, err := strconv.Atoi(string(oldDurationStr)) | ||
if err != nil { | ||
return content, err | ||
} | ||
if currDuration > oldDuration { | ||
tmpContent := make([]byte, l) | ||
copy(tmpContent, content[:l]) | ||
tmpContent = append(tmpContent, []byte(fmt.Sprintf("#EXT-X-TARGETDURATION:%d", currDuration))...) | ||
tmpContent = append(tmpContent, content[l+r:]...) | ||
content = tmpContent | ||
} | ||
return content, nil | ||
} |
Oops, something went wrong.