mirror of
https://github.com/gowvp/gb28181.git
synced 2026-04-22 23:17:19 +08:00
265 lines
5.6 KiB
Go
265 lines
5.6 KiB
Go
package sip
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"encoding/xml"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log/slog"
|
|
"math/rand"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"golang.org/x/text/encoding/simplifiedchinese"
|
|
"golang.org/x/text/transform"
|
|
)
|
|
|
|
// Error Error
|
|
type Error struct {
|
|
err error
|
|
params []interface{}
|
|
}
|
|
|
|
func (err *Error) Error() string {
|
|
if err == nil {
|
|
return "<nil>"
|
|
}
|
|
str := fmt.Sprint(err.params...)
|
|
if err.err != nil {
|
|
str += fmt.Sprintf(" err:%s", err.err.Error())
|
|
}
|
|
return str
|
|
}
|
|
|
|
// NewError NewError
|
|
func NewError(err error, params ...interface{}) error {
|
|
return &Error{err, params}
|
|
}
|
|
|
|
// JSONEncode JSONEncode
|
|
func JSONEncode(data interface{}) []byte {
|
|
d, err := json.Marshal(data)
|
|
if err != nil {
|
|
slog.Error("JSONEncode error:", "err", err)
|
|
}
|
|
return d
|
|
}
|
|
|
|
// JSONDecode JSONDecode
|
|
func JSONDecode(data []byte, obj interface{}) error {
|
|
return json.Unmarshal(data, obj)
|
|
}
|
|
|
|
func RandInt(min, max int) int {
|
|
if max < min {
|
|
return 0
|
|
}
|
|
max++
|
|
max -= min
|
|
rand.Seed(time.Now().UnixNano())
|
|
r := rand.Int()
|
|
return r%max + min
|
|
}
|
|
|
|
const (
|
|
letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
)
|
|
|
|
// RandString https://github.com/kpbird/golang_random_string
|
|
func RandString(n int) string {
|
|
rand.Seed(time.Now().UnixNano())
|
|
output := make([]byte, n)
|
|
// We will take n bytes, one byte for each character of output.
|
|
randomness := make([]byte, n)
|
|
// read all random
|
|
_, err := rand.Read(randomness)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
l := len(letterBytes)
|
|
// fill output
|
|
for pos := range output {
|
|
// get random item
|
|
random := randomness[pos]
|
|
// random % 64
|
|
randomPos := random % uint8(l)
|
|
// put into output
|
|
output[pos] = letterBytes[randomPos]
|
|
}
|
|
|
|
return string(output)
|
|
}
|
|
|
|
func timeoutClient() *http.Client {
|
|
connectTimeout := time.Duration(20 * time.Second)
|
|
readWriteTimeout := time.Duration(30 * time.Second)
|
|
return &http.Client{
|
|
Transport: &http.Transport{
|
|
DialContext: timeoutDialer(connectTimeout, readWriteTimeout),
|
|
MaxIdleConnsPerHost: 200,
|
|
DisableKeepAlives: true,
|
|
},
|
|
}
|
|
}
|
|
|
|
func timeoutDialer(cTimeout time.Duration,
|
|
rwTimeout time.Duration,
|
|
) func(ctx context.Context, net, addr string) (c net.Conn, err error) {
|
|
return func(ctx context.Context, netw, addr string) (net.Conn, error) {
|
|
conn, err := net.DialTimeout(netw, addr, cTimeout)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
conn.SetDeadline(time.Now().Add(rwTimeout))
|
|
return conn, nil
|
|
}
|
|
}
|
|
|
|
// PostRequest PostRequest
|
|
func PostRequest(url string, bodyType string, body io.Reader) ([]byte, error) {
|
|
client := timeoutClient()
|
|
resp, err := client.Post(url, bodyType, body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respbody, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return respbody, nil
|
|
}
|
|
|
|
// PostJSONRequest PostJSONRequest
|
|
func PostJSONRequest(url string, data interface{}) ([]byte, error) {
|
|
bytesData, err := json.Marshal(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return PostRequest(url, "application/json;charset=UTF-8", bytes.NewReader(bytesData))
|
|
}
|
|
|
|
// GetRequest GetRequest
|
|
func GetRequest(url string) ([]byte, error) {
|
|
client := timeoutClient()
|
|
resp, err := client.Get(url)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
respbody, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return respbody, nil
|
|
}
|
|
|
|
// XMLDecode 解码 xml
|
|
func XMLDecode(data []byte, v interface{}) error {
|
|
if err := xmlDecode(data, v); err == nil {
|
|
return nil
|
|
}
|
|
// 有些body xml发送过来的不带encoding ,而且格式不是utf8的,导致xml解析失败,此处使用gbk转utf8后再次尝试xml解析
|
|
body, err := GbkToUtf8(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return xmlDecode(body, v)
|
|
}
|
|
|
|
func xmlDecode(data []byte, v interface{}) error {
|
|
decoder := xml.NewDecoder(bytes.NewReader(data))
|
|
decoder.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
|
|
if utf8.Valid(data) {
|
|
return input, nil
|
|
}
|
|
return simplifiedchinese.GB18030.NewDecoder().Reader(input), nil
|
|
}
|
|
return decoder.Decode(v)
|
|
}
|
|
|
|
// XMLEncode XML编码器
|
|
func XMLEncode(data any) ([]byte, error) {
|
|
b, err := xml.Marshal(data)
|
|
if err != nil {
|
|
slog.Error("MarshalIndent", "err", err)
|
|
return nil, err
|
|
}
|
|
xmlHeader := "<?xml version=\"1.0\" encoding=\"GB2312\"?>\n"
|
|
return Utf8ToGbk([]byte(xmlHeader + string(b)))
|
|
}
|
|
|
|
// Max Max
|
|
func Max(a, b int64) int64 {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
// ResolveSelfIP ResolveSelfIP
|
|
func ResolveSelfIP() (net.IP, error) {
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, iface := range ifaces {
|
|
if iface.Flags&net.FlagUp == 0 {
|
|
continue // interface down
|
|
}
|
|
if iface.Flags&net.FlagLoopback != 0 {
|
|
continue // loopback interface
|
|
}
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, addr := range addrs {
|
|
var ip net.IP
|
|
switch v := addr.(type) {
|
|
case *net.IPNet:
|
|
ip = v.IP
|
|
case *net.IPAddr:
|
|
ip = v.IP
|
|
}
|
|
if ip == nil || ip.IsLoopback() {
|
|
continue
|
|
}
|
|
ip = ip.To4()
|
|
if ip == nil {
|
|
continue // not an ipv4 address
|
|
}
|
|
return ip, nil
|
|
}
|
|
}
|
|
return nil, errors.New("server not connected to any network")
|
|
}
|
|
|
|
// GBK 转 UTF-8
|
|
func GbkToUtf8(s []byte) ([]byte, error) {
|
|
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
|
|
d, e := io.ReadAll(reader)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return d, nil
|
|
}
|
|
|
|
// UTF-8 转 GBK
|
|
func Utf8ToGbk(s []byte) ([]byte, error) {
|
|
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
|
|
d, e := io.ReadAll(reader)
|
|
if e != nil {
|
|
return nil, e
|
|
}
|
|
return d, nil
|
|
}
|