This commit is contained in:
arraykeys
2019-08-08 17:13:34 +08:00
parent e8e5966a8c
commit f0bf2d5fec
2885 changed files with 1195993 additions and 12 deletions
+57
View File
@@ -0,0 +1,57 @@
package at_common
import (
"crypto/tls"
"fmt"
)
type Author struct {
cstype int
token string
clusterHost string
clusterPort int
Conn *tls.Conn
Channel MessageChannel
}
func NewAuthor(token, clusterHost string, clusterPort, cstype int) (author Author, err error) {
conn, err := TlsConnect(clusterHost, clusterPort, 5000)
if err != nil {
return
}
author = Author{
cstype: cstype,
token: token,
Conn: &conn,
clusterHost: clusterHost,
clusterPort: clusterPort,
Channel: NewMessageChannelTls(&conn),
}
return
}
func (a *Author) DoControlAuth() (err error) {
err = a.Channel.Write(MsgLogin{
Msg: Msg{MsgType: MSG_TYPE_LOGIN},
Token: a.token,
CSType: a.cstype,
})
if err != nil {
return
}
var resp MsgResponse
err = a.Channel.ReadTimeout(&resp, 30000)
if err != nil {
return
}
if !resp.IsSuccess() {
err = fmt.Errorf(resp.Message)
}
return
}
func (a *Author) IsServer() bool {
return a.cstype == CSTYPE_SERVER
}
func (a *Author) IsClient() bool {
return a.cstype == CSTYPE_CLIENT
}
+147
View File
@@ -0,0 +1,147 @@
package at_common
var (
server_cert_bytes []byte
server_key_bytes []byte
client_cert_bytes []byte
client_key_bytes []byte
root_cert_bytes []byte
)
func init() {
server_cert_bytes = []byte(`-----BEGIN CERTIFICATE-----
MIIDOTCCAiECCQDW3K+RyvKd8DANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJD
TjESMBAGA1UECAwJR3VhbmdEb25nMRYwFAYDVQQKDA1Mb2NhbGhvc3QgTHRkMRcw
FQYDVQQDDA5Mb2NhbGhvc3QgUm9vdDAeFw0xNzA5MTgwNzEzMDRaFw0yNzA5MTYw
NzEzMDRaMGsxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxEjAQBgNV
BAcMCUd1YW5nemhvdTEZMBcGA1UECgwQTG9jYWxob3N0IFNlcnZlcjEZMBcGA1UE
AwwQYW55dHVubmVsLXNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMDOzjT2PlwzbPqSvS9EMsqyY1G7/l770623Qp1S9Z2/A7fpldvblMh5Jttr
zfQCJcx2RMb7InF3yFwsbaUqxFcR3hNzzzL6ib4Zyui5eNRggVSCw9W9oq4fYguK
K83JtUE7sJDDgYF11ASDZUXVzIMF+RWG3VS38hs0w0TeTztyufSW8CHi2F8Txtim
cyOVG2z0/a/wWaZ49C9ptTOJ5h4RrItA9yUtt6RVGNYaAA1UwMKLMQbPsPXSaxHK
vanBQP2VH5ol1+efvfYc5WvaOqlAoXrAp9mv0a/QX5En+MPTmMnfQZS1y+jfXUTU
5nqgRt7YEv7Ps04LyAJWS+8S8FcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAYL1L
ai5WRxBzt6qCIujLaJY3zfFDu7WN1V4f8q/DwsXhfj9RwmTGU0s4e0HVhqL9ClbW
0z40idlswbVf3UfvE0PhHyAtljjWoF03Gj/gGUiIaACP/UvtAeIzS3bKdI2wTHg+
gmvp7sNCK7GyDdVKzsOYl2GO//EdHrmBEYaV2I3SBlPa4Zd9Ucg1WRvrtZz5jXwk
/e3t9lEY2f02Q6CmCBjSaoJmXnTByexx/A7gYNG6/zYRBN+mmSndmOU3m2vyW99k
xz/rNufScuVPM9Wx2kTyl+do75meSOabDpvS7Et/HkII8NFtuLU4KohmV/0SN9iS
Jc6sB8ooIsRakdxVtQ==
-----END CERTIFICATE-----
`)
server_key_bytes = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEoQIBAAKCAQEAwM7ONPY+XDNs+pK9L0QyyrJjUbv+XvvTrbdCnVL1nb8Dt+mV
29uUyHkm22vN9AIlzHZExvsicXfIXCxtpSrEVxHeE3PPMvqJvhnK6Ll41GCBVILD
1b2irh9iC4orzcm1QTuwkMOBgXXUBINlRdXMgwX5FYbdVLfyGzTDRN5PO3K59Jbw
IeLYXxPG2KZzI5UbbPT9r/BZpnj0L2m1M4nmHhGsi0D3JS23pFUY1hoADVTAwosx
Bs+w9dJrEcq9qcFA/ZUfmiXX55+99hzla9o6qUChesCn2a/Rr9BfkSf4w9OYyd9B
lLXL6N9dRNTmeqBG3tgS/s+zTgvIAlZL7xLwVwIDAQABAoIBACZ2myhxn0shbzIl
p9wQDNnm8G1TxZEJR9c14fIkpJ8Nhh5gWOb9TRcZJClNvk5ZR1UcmuffHaXpMW1B
57W1bGm6RMU4qzMOTABCgPogVfx4LBTB6XNwW03FMPgAXnC1NpWG5NhcSC+dY+hq
lf9ygVP6ExC6UNkfwQqwYewRNVk0VreJ7CTKLwIK/oSgp43379Ifri717w/WfpNz
hO27tlaFHGoSa37ajGDhSgO5rU1KkK96xcbV+XpsGmOAkMl1VWpz51n+LML8ghf5
vy1a6N1KE3mLueAQbtQet1kcQ/aAV9C6VYEu2gvH3j6wwKEgat1kHzGclgxXPqBu
Sw+vRMECgYEA+E4hFPNaLjWudgAGd/94tq/xK67+lksg8QyCK+4LQ0/sson4sO8B
OiQioKLHmKkkLPt9P+HqntdofcnwO2/97ePqP+9Efz30oeh5GBVz3RqsBKwf8hqZ
/aEAkV6X5IC/M55oqwtjhJlXNep70e49WkfCbubaUZUB53snmgpHa2cCgYEAxshm
quutrSw3IhgzV8kR5v0r6neaHmmHbdBZh0nyUXY8urxXZi6JUYiLi3zBkFXl+YTN
sTNjtqshRBwhYr0596lxgXJNBra5Oc6Dqrx0G16q12aDMYBhoL7GLp3zpXVlfixS
Zeg0BYu5nUwIz+Z6G6qRV2GMMzg/5rjSSIKSLZECgYBaNAfQlJcuMlIui9PNxAEW
XNRAClJyRtiwuNqRGuj8iwxxz62ImUrY1EfAE2JvEwMRVEsr6eZRze8nwzSCYyzc
Pu/aShGYJ+m2570WArUUnZvgFqeETCWk/dg29yY23I6ZMfLUME723L3R2F0i5mlj
Yq4/m520BW2rqhG45AMOAQJ/Jgw1moGBvKO56cy4BxV1V8EdpsM9vJR2V46JlFuT
BgSbmyJxmB1QK0r3art2USof2qKQvFoZu90FgQPhYATYE49bKmu2UpKm4WmlyghI
MPTtvkzgz5jDFwFs7X9OI11VD9Fr9BV935He9TyYczKqLKF5MEB7lVIu6Pp3RWm4
kQKBgQCqu2Lj5tFb76ec97de62tV74YLc46Me5HGBD/Nbq8BmhSmmTkNOMzmm3pe
1e/d2j3flzDBAj1jZ40GnJ2tWzbwZyQHzPiCHqvWa99Yvgn3masknDR463CJcAsW
n667udC8bjyP6DXXjXtQaZGvUh9wzs9ErtRdE5g39JauHNGF2w==
-----END RSA PRIVATE KEY-----
`)
client_cert_bytes = []byte(`-----BEGIN CERTIFICATE-----
MIIDOTCCAiECCQDW3K+RyvKd8TANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJD
TjESMBAGA1UECAwJR3VhbmdEb25nMRYwFAYDVQQKDA1Mb2NhbGhvc3QgTHRkMRcw
FQYDVQQDDA5Mb2NhbGhvc3QgUm9vdDAeFw0xNzA5MTgwNzEzMDRaFw0yNzA5MTYw
NzEzMDRaMGsxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxEjAQBgNV
BAcMCUd1YW5nemhvdTEZMBcGA1UECgwQTG9jYWxob3N0IENsaWVudDEZMBcGA1UE
AwwQYW55dHVubmVsLWNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALBoyM/0i+JxCra8hVMDNs7l8s0xAXImw3+d2UhqtRq5BC0lsyTBpfId5hrF
fsUlZaO4ksAqzRN39XCgm4pM3DwR0M5vHqDpQ9IcVZBT+2Yq7THtrAO4a3n4PJ/0
DfefWtmpN933rCBsFnPbId4qI6QBxYTto8Wd36LyPa1yGBL5n6sPhQp9UmiFcRYx
SSv4tRbMilypHe/YLF2IkUhX+UGRqAZku7g2jisSd5FP1VD0U3OhockyjkKJv5/f
TFwfXXliEb1p8uwpL5YFzTy98DDn7Cygdy7cg6zw5cd/gpRNZLNQhC28r4vE8wKg
hwmRdy29CKgQMZGxre1cab0lA8ECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAZGeU
qWRQf66ycYvI7tT8BeKAM++ONWcEkFlflSel3EUq+r2wYzpDZo5qm2kZoE63ibNb
Frr2SfH4+RS7RnGQwgzyqrRhFiSKEXOFWUvT7M0eY3fPBZpZjunnyVXXZvchS0Qy
s5w391H4td96PiVrqVAFdZmYUM0juexTx+wMYVfZnViJjrPvfaoS8I3RJz1ZNuia
nBWMq9gKmLl9KMy05A2EqNMMb8XaooVfigDA53izXDPVS5xhF/0vvGb021+YMzXS
qjk7Yrn2JFTm58dp1YBfOAoO566rCXgBhvTxniCnub12cq0m7hjtSKkbOFCPvOvl
pMg9UF1tz8uTos/MkQ==
-----END CERTIFICATE-----
`)
client_key_bytes = []byte(`-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAsGjIz/SL4nEKtryFUwM2zuXyzTEBcibDf53ZSGq1GrkELSWz
JMGl8h3mGsV+xSVlo7iSwCrNE3f1cKCbikzcPBHQzm8eoOlD0hxVkFP7ZirtMe2s
A7hrefg8n/QN959a2ak33fesIGwWc9sh3iojpAHFhO2jxZ3fovI9rXIYEvmfqw+F
Cn1SaIVxFjFJK/i1FsyKXKkd79gsXYiRSFf5QZGoBmS7uDaOKxJ3kU/VUPRTc6Gh
yTKOQom/n99MXB9deWIRvWny7CkvlgXNPL3wMOfsLKB3LtyDrPDlx3+ClE1ks1CE
Lbyvi8TzAqCHCZF3Lb0IqBAxkbGt7VxpvSUDwQIDAQABAoIBAC/criclzVIpo2OC
8JVeON+XqfGcCy1icQZN2Gb6dJqEeiqZoOonFBQFoqm+za9FfzcVW9OBiVRv5oqh
OLIkOlid6M4pfeDgiQMXputarcnBectjFZmIzrgv7prjR2rYtHh7nem+SdgeG1Vh
reWt/y9/P4zaQOXb+JIoMS2+1+NFnYKatpGkVqaiEk6awdwkMpobksvaJbOCszQs
QTs8TuPHCraMc+lCUUKwAVu0hTb4AFDvwPumaxbRDmHZn2XoMy/eqWrg0pYhbdtu
3o0S8ytsCFW8LHChHkk4krQsDQlgfm+xXhPSDfxSyiGn5OanWRyKxl//QGw6qy9n
9YtZlmUCgYEA2OOjj9PeJ0cqbxndoCzCYFZGEy2bzNfQpJC6bB3WnASdlafG/0OO
9VGbxYsOO703Q//Id0Exl390UFR5vBdRyoSHJsW+EolwcOm/+szCRKBR1KWP1u/c
OJlijN3Z6F6D3H6jOIA5YNec7nRhSfRnVe7ridXrepuWiDIXBaBtZFsCgYEA0Dhz
0PwC5R2+6YAXPfQrKZHju7WRUYfc0Uk/7AQHGYpTcokhF2EdN11atMr7447pi1Bu
AezAPKwh16mc+byF6rjR+RGyy4KVNlTmH298gkg425+XPTHkODX/IzbOWA/1KKl4
rSyYxtgyO7+zoixa7Q5x2s8gFktAOqZdLR/EgxMCgYAt+kvhIJPWlcKMHNqbqwFl
tMRUKnX9vb5wNHIgm060clIJuLB5ypOSs8Mm5GyXA2yk0KNpjHt71zwMD2xjEDp5
iRCxinfZrCMW/KaC/0crjyTpxFMyyFRR90op/JnGJcskQgBN6PjA69RLxIYfTF1f
nS93X870hekqZBv3SGQIQwKBgGR8mgglVxBThqsRkiXoDFyHd6xDN9ptAvhNrXet
ie+dfiAsZbfuujbZ6siNnXp4oeUF79El/LBLMhnuVT+A5/AbOdpF3E+yuWf7GQPa
ve/yAt6a6lYyGb228WaBMJv3N41kHEUW3LQ56iRDo+GEHm2BJxk+FHIt5tVnLFh2
mFPZAoGAC6Qy4DaCDl2ghr1n3ovX1+TRwu+XVGfCFPxGMKeY8Pph6IADN/Zm08gL
i2TAKdk+V42rpzqCs7Tp2jCUqSZdgACgckNA9EtOq5ec3JCkvF/8PKNcjmqAGipK
5rzS1cyEfXOvuYMVp2bzTiiTI1pMALfjFqPkDCOnN57BSfTvjRo=
-----END RSA PRIVATE KEY-----
`)
root_cert_bytes = []byte(`-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIJANzSq37zesapMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
BAYTAkNOMRIwEAYDVQQIDAlHdWFuZ0RvbmcxFjAUBgNVBAoMDUxvY2FsaG9zdCBM
dGQxFzAVBgNVBAMMDkxvY2FsaG9zdCBSb290MB4XDTE3MDkxODA3MTMwNFoXDTI3
MDkxNjA3MTMwNFowUjELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzEW
MBQGA1UECgwNTG9jYWxob3N0IEx0ZDEXMBUGA1UEAwwOTG9jYWxob3N0IFJvb3Qw
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+V42izvaDJzkkxyCKrszL
QoK7yxTvf7xCyzh+y7wMMWam+IsVzuv7SYv5FYQ8w1lzaoygsKin2+djtlbgvmrv
9bEb1YnuwJz39DmtR2j+w3XlZFGUg+qhp7mJEHSe0mOm5hL8vMQmW0Itcd3lR+wh
XP9B63NSxiJHVs+6WlY9g3+889w11fUfVECVea6p5JYp4UUN1F/PosUtMURLGcER
Q80fw7h+2GnBlIaDbtuZDPEiaGrNIfHHiVJUOaylfQDWFYDjLi2ytM7xfhggRuwt
zyo4Xbk+SRTUlloTTRw4zdzuhFQ2qtfhh9gSvVXVpsPNKmkIl3sIkxklRt6vAaWx
AgMBAAGjUDBOMB0GA1UdDgQWBBSM7gXj5Rdow6NUI6pE9SYj6tflZTAfBgNVHSME
GDAWgBSM7gXj5Rdow6NUI6pE9SYj6tflZTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3
DQEBCwUAA4IBAQB3xR5Z6ksN2nb2JNgjG7hkJjr5jdXwA7LAX8ZYkQ+bGVQMcUO8
eYePyXPmSj03a6362Cc/QENY8g+n/i7r22e2/q6BOnsomc4JQumO25ulsMNxi+Ar
fDwPg3ixYJFEzlNipcPrr8AOsfJGTh41qQr9cqhk2ciTEOG3Xcfkdp26u9h/D/rm
cL4tsSWQ7b1dgoUFLfRvMMRhKUU9ounWiDt+CvMNK1FWV642jKyCE5kEsZ+QHFDW
Cc2Xg/3AyG3/8BsKpqtsoI72u6mGsGsyNClwoQTOdMgs3Gert5Q+elp/2NddrOJD
hSKTBrKUOEhWpAwPz2DMArggBfM4CAiQbpQ5
-----END CERTIFICATE-----
`)
}
func GetServerCert() []byte {
return server_cert_bytes
}
func GetServerKey() []byte {
return server_key_bytes
}
func GetClientCert() []byte {
return client_cert_bytes
}
func GetClientKey() []byte {
return client_key_bytes
}
func GetRootCert() []byte {
return root_cert_bytes
}
+81
View File
@@ -0,0 +1,81 @@
package des
import (
utils "anytunnel/at-common"
"bytes"
"crypto/des"
"encoding/hex"
"errors"
)
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{0}, padding)
return append(ciphertext, padtext...)
}
func ZeroUnPadding(origData []byte) []byte {
return bytes.TrimFunc(origData,
func(r rune) bool {
return r == rune(0)
})
}
func Encrypt(src []byte, key string) (string, error) {
block, err := des.NewCipher([]byte(utils.Md5(key)[0:8]))
if err != nil {
return "", err
}
bs := block.BlockSize()
src = ZeroPadding(src, bs)
// src = PKCS5Padding(src, bs)
if len(src)%bs != 0 {
return "", errors.New("Need a multiple of the blocksize")
}
out := make([]byte, len(src))
dst := out
for len(src) > 0 {
block.Encrypt(dst, src[:bs])
src = src[bs:]
dst = dst[bs:]
}
return hex.EncodeToString(out), nil
}
func Decrypt(_src string, _key string) ([]byte, error) {
key := []byte(utils.Md5(_key)[0:8])
src, err := hex.DecodeString(_src)
if err != nil {
return nil, err
}
block, err := des.NewCipher(key)
if err != nil {
return nil, err
}
out := make([]byte, len(src))
dst := out
bs := block.BlockSize()
if len(src)%bs != 0 {
return nil, errors.New("crypto/cipher: input not full blocks")
}
for len(src) > 0 {
block.Decrypt(dst, src[:bs])
src = src[bs:]
dst = dst[bs:]
}
out = ZeroUnPadding(out)
// out = PKCS5UnPadding(out)
return out, nil
}
+51
View File
@@ -0,0 +1,51 @@
package at_common
import (
"crypto/md5"
"encoding/base64"
"encoding/hex"
)
const (
BASE_64_TABLE = "1234567890poiuytreqwasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM-_"
)
type Encrypt struct{}
func NewEncrypt() *Encrypt {
return &Encrypt{}
}
//base64 加密
func (encrypt *Encrypt) Base64Encode(str string) string {
var coder = base64.NewEncoding(BASE_64_TABLE)
var src []byte = []byte(str)
return string([]byte(coder.EncodeToString(src)))
}
//base64 加密
func (encrypt *Encrypt) Base64EncodeBytes(bytes []byte) []byte {
var coder = base64.NewEncoding(BASE_64_TABLE)
return []byte(coder.EncodeToString(bytes))
}
//base64 解密
func (encrypt *Encrypt) Base64Decode(str string) (string, error) {
var src []byte = []byte(str)
var coder = base64.NewEncoding(BASE_64_TABLE)
by, err := coder.DecodeString(string(src))
return string(by), err
}
//base64 解密
func (encrypt *Encrypt) Base64DecodeBytes(str string) ([]byte, error) {
var coder = base64.NewEncoding(BASE_64_TABLE)
return coder.DecodeString(str)
}
//md5加密
func (encrypt *Encrypt) Md5Encode(str string) string {
hash := md5.New()
hash.Write([]byte(str))
return hex.EncodeToString(hash.Sum(nil))
}
+343
View File
@@ -0,0 +1,343 @@
package at_common
import (
"bufio"
"bytes"
"crypto/md5"
"crypto/tls"
"crypto/x509"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"reflect"
"strconv"
"strings"
"time"
)
const (
DES_KEY_HOSTPORT = "3j49d723"
)
//fileGetContents
func FileGetContents(file string) (content string, err error) {
defer func(err *error) {
e := recover()
if e != nil {
*err = fmt.Errorf("%s", e)
}
}(&err)
bytes, err := ioutil.ReadFile(file)
content = string(bytes)
return
}
func InArray(val interface{}, array interface{}) (exists bool, index int) {
exists = false
index = -1
switch reflect.TypeOf(array).Kind() {
case reflect.Slice:
s := reflect.ValueOf(array)
for i := 0; i < s.Len(); i++ {
if reflect.DeepEqual(val, s.Index(i).Interface()) == true {
index = i
exists = true
return
}
}
}
return
}
func PathExists(_path string) bool {
_, err := os.Stat(_path)
if err != nil && os.IsNotExist(err) {
return false
}
return true
}
func IoBind(dst io.ReadWriter, src io.ReadWriter, fn func(err error), cfn func(count int, isPositive bool), bytesPreSec float64) {
go func() {
errchn := make(chan error, 2)
go func() {
var err error
if bytesPreSec > 0 {
newreader := NewReader(src)
newreader.SetRateLimit(bytesPreSec)
_, err = ioCopy(dst, newreader, func(c int) {
cfn(c, false)
})
} else {
_, err = ioCopy(dst, src, func(c int) {
cfn(c, false)
})
}
errchn <- err
}()
go func() {
var err error
if bytesPreSec > 0 {
newReader := NewReader(dst)
newReader.SetRateLimit(bytesPreSec)
_, err = ioCopy(src, newReader, func(c int) {
cfn(c, true)
})
} else {
_, err = ioCopy(src, dst, func(c int) {
cfn(c, true)
})
}
errchn <- err
}()
fn(<-errchn)
}()
}
func ioCopy(dst io.Writer, src io.Reader, fn ...func(count int)) (written int64, err error) {
buf := make([]byte, 32*1024)
for {
nr, er := src.Read(buf)
if nr > 0 {
nw, ew := dst.Write(buf[0:nr])
if nw > 0 {
written += int64(nw)
if len(fn) == 1 {
fn[0](nw)
}
}
if ew != nil {
err = ew
break
}
if nr != nw {
err = io.ErrShortWrite
break
}
}
if er != nil {
err = er
break
}
}
return written, err
}
func TlsConnectHost(host string, timeout int) (conn tls.Conn, err error) {
h := strings.Split(host, ":")
port, _ := strconv.Atoi(h[1])
return TlsConnect(h[0], port, timeout)
}
func TlsConnect(host string, port, timeout int) (conn tls.Conn, err error) {
conf, err := getRequestTlsConfig(true)
if err != nil {
return
}
_conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond)
if err != nil {
return
}
return *tls.Client(_conn, conf), err
}
func getRequestTlsConfig(isInternal bool) (conf *tls.Config, err error) {
if isInternal {
var cert tls.Certificate
cert, err = tls.X509KeyPair(GetClientCert(), GetClientKey())
if err != nil {
return
}
serverCertPool := x509.NewCertPool()
ok := serverCertPool.AppendCertsFromPEM(GetRootCert())
if !ok {
err = errors.New("failed to parse root certificate")
}
conf = &tls.Config{
RootCAs: serverCertPool,
Certificates: []tls.Certificate{cert},
ServerName: "anytunnel-server",
InsecureSkipVerify: false,
}
} else {
conf = &tls.Config{
InsecureSkipVerify: true,
}
}
return
}
func Connect(host string, port, timeout int) (conn net.Conn, err error) {
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", host, port), time.Duration(timeout)*time.Millisecond)
return
}
func ConnectHost(hostAndPort string, timeout int) (conn net.Conn, err error) {
conn, err = net.DialTimeout("tcp", hostAndPort, time.Duration(timeout)*time.Millisecond)
return
}
func ListenTls(ip string, port int) (ln *net.Listener, err error) {
var cert tls.Certificate
cert, err = tls.X509KeyPair(GetServerCert(), GetServerKey())
if err != nil {
return
}
clientCertPool := x509.NewCertPool()
ok := clientCertPool.AppendCertsFromPEM(GetRootCert())
if !ok {
err = errors.New("failed to parse root certificate")
}
config := &tls.Config{
ClientCAs: clientCertPool,
ServerName: "anytunnel-client",
Certificates: []tls.Certificate{cert},
ClientAuth: tls.RequireAndVerifyClientCert,
}
_ln, err := tls.Listen("tcp", fmt.Sprintf("%s:%d", ip, port), config)
if err == nil {
ln = &_ln
}
return
}
func Response(channel *MessageChannel, success bool, msg string) (err error) {
status := STATUS_FAIL
if success {
status = STATUS_SUCCESS
}
resp := MsgResponse{
Msg: Msg{MsgType: MSG_RESPONSE},
Status: status,
Message: msg,
}
err = channel.Write(resp)
return
}
func GetClusterHost(url, token, typ string) (addr string, err error) {
if url == "" {
err = fmt.Errorf("url is empty")
return
}
if strings.Contains(url, "?") {
url += fmt.Sprintf("&token=%s&type=%s", token, typ)
} else {
url += fmt.Sprintf("?token=%s&type=%s", token, typ)
}
d, code, err := HttpGet(url)
if err != nil {
return
}
if code != 200 {
err = fmt.Errorf(string(d))
return
}
addr = string(d)
return
}
func GetAllInterfaceAddr() ([]net.IP, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
addresses := []net.IP{}
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 {
continue
}
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
}
addresses = append(addresses, ip)
}
}
if len(addresses) == 0 {
return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses)
}
//only need first
return addresses, nil
}
var allChina = strings.Split("北京,海淀,东城,西城,宣武,丰台,朝阳,崇文,大兴,石景山,门头沟,房山,通州,顺义,怀柔,昌平,平谷,密云县,延庆县,天津,和平,河西,河北,河东,南开,红桥,北辰,津南,武清,塘沽,西青,汉沽,大港,宝坻,东丽,蓟县,静海县,宁河县,上海,黄浦,卢湾,徐汇,长宁,静安,普陀,闸北,杨浦,虹口,闵行,宝山,嘉定,浦东新,金山,松江,青浦,南汇,奉贤,崇明县,重庆,渝中,大渡口,江北,沙坪坝,九龙坡,南岸,北碚,万盛,双桥,渝北,巴南,万州,涪陵,黔江,长寿,江津,永川,南川,綦江县,潼南县,铜梁县,大足县,荣昌县,璧山县,垫江县,武隆县,丰都县,城口县,梁平县,开县,巫溪县,巫山县,奉节县,云阳县,忠县,石柱土家族,彭水苗族土家族,酉阳苗族,秀山土家族苗族,新疆维吾尔,乌鲁木齐,克拉玛依,石河子,阿拉尔,图木舒克,五家渠,哈密,吐鲁番,阿克苏,喀什,和田,伊宁,塔城,阿勒泰,奎屯,博乐,昌吉,阜康,库尔勒,阿图什,乌苏,西藏,拉萨,日喀则,宁夏回族,银川,石嘴山,吴忠,固原,中卫,青,铜峡,灵武,内蒙古,呼和浩特,包头,乌海,赤峰,通辽,鄂尔多斯,呼伦贝尔,巴彦淖尔,乌兰察布,霍林郭勒,满洲里,牙克石,扎兰屯,根河,额尔古纳,丰镇,锡林浩特,二连浩特,乌兰浩特,阿尔山,广西壮族,南宁,柳州,桂林,梧州,北海,崇左,来宾,贺州,玉林,百色,河池,钦州,防城港,贵港,岑溪,凭祥,合山,北流,宜州,东兴,桂平,黑龙江,哈尔滨,大庆,齐齐哈尔,佳木斯,鸡西,鹤岗,双鸭山,牡丹江,伊春,七台河,黑河,绥化,五常,双城,尚志,纳河,虎林,密山,铁力,同江,富锦,绥芬河,海林,宁安,穆林,北安,五大连池,肇东,海伦,安达,长春,吉林,四平,辽源,通化,白山,松原,白城,九台,榆树,德惠,舒兰,桦甸,蛟河,磐石,公主岭,双辽,梅河口,集安,临江,大安,洮南,延吉,图们,敦化,龙井,珲春,和龙,辽宁,沈阳,大连,鞍山,抚顺,本溪,丹东,锦州,营口,阜新,辽阳,盘锦,铁岭,朝阳,葫芦岛,新民,瓦房店,普兰,庄河,海城,东港,凤城,凌海,北镇,大石桥,盖州,灯塔,调兵山,开原,凌源,北票,兴城,河北,石家庄,唐山,邯郸,秦皇岛,保定,张家口,承德,廊坊,沧州,衡水,邢台,辛集,藁城,晋州,新乐,鹿泉,遵化,迁安,武安,南宫,沙河,涿州,定州,安国,高碑店,泊头,任丘,黄骅,河间,霸州,三河,冀州,深州,山东,济南,青岛,淄博,枣庄,东营,烟台,潍坊,济宁,泰安,威海,日照,莱芜,临沂,德州,聊城,菏泽,滨州,章丘,胶南,胶州,平度,莱西,即墨,滕州,龙口,莱阳,莱州,招远,蓬莱,栖霞,海阳,青州,诸城,安丘,高密,昌邑,兖州,曲阜,邹城,乳山,文登,荣成,乐陵,临清,禹城,江苏,南京,镇江,常州,无锡,苏州,徐州,连云港,淮安,盐城,扬州,泰州,南通,宿迁,江阴,宜兴,邳州,新沂,金坛,溧阳,常熟,张家港,太仓,昆山,吴江,如皋,通州,海门,启东,东台,大丰,高邮,江都,仪征,丹阳,扬中,句容,泰兴,姜堰,靖江,兴化,安徽,合肥,蚌埠,芜湖,淮南,亳州,阜阳,淮北,宿州,滁州,安庆,巢湖,马鞍山,宣城,黄山,池州,铜陵,界首,天长,明光,桐城,宁国,浙江,杭州,嘉兴,湖州,宁波,金华,温州,丽水,绍兴,衢州,舟山,台州,建德,富阳,临安,余姚,慈溪,奉化,瑞安,乐清,海宁,平湖,桐乡,诸暨,上虞,嵊州,兰溪,义乌,东阳,永康,江山,临海,温岭,龙泉,福建,福州,厦门,泉州,三明,南平,漳州,莆田,宁德,龙岩,福清,长乐,永安,石狮,晋江,南安,龙海,邵武,武夷山,建瓯,建阳,漳平,福安,福鼎,广东,广州,深圳,汕头,惠州,珠海,揭阳,佛山,河源,阳江,茂名,湛江,梅州,肇庆,韶关,潮州,东莞,中山,清远,江门,汕尾,云浮,增城,从化,乐昌,南雄,台山,开平,鹤山,恩平,廉江,雷州,吴川,高州,化州,高要,四会,兴宁,陆丰,阳春,英德,连州,普宁,罗定,海南,海口,三亚,琼海,文昌,万宁,五指山,儋州,东方,云南,昆明,曲靖,玉溪,保山,昭通,丽江,普洱,临沧,安宁,宣威,个旧,开远,景洪,楚雄,大理,潞西,瑞丽,贵州,贵阳,六盘水,遵义,安顺,清镇,赤水,仁怀,铜仁,毕节,兴义,凯里,都匀,福泉,四川,成都,绵阳,德阳,广元,自贡,攀枝花,乐山,南充,内江,遂宁,广安,泸州,达州,眉山,宜宾,雅安,资阳,都江堰,彭州,邛崃,崇州,广汉,什邡,绵竹,江油,峨眉山,阆中,华蓥,万源,简阳,西昌,湖南,长沙,株洲,湘潭,衡阳,岳阳,郴州,永州,邵阳,怀化,常德,益阳,张家界,娄底,浏阳,醴陵,湘乡,韶山,耒阳,常宁,武冈,临湘,汨罗津,沅江,资兴,洪江,冷水江,涟源,吉首,湖北,武汉,襄樊,宜昌,黄石,鄂州,随州,荆州,荆门,十堰,孝感,黄冈,咸宁,大冶,丹江口,洪湖,石首,松滋,宜都,当阳,枝江,老河口,枣阳,宜城,钟祥,应城,安陆,汉川,麻城,武穴,赤壁,广水,仙桃,天门,潜江,恩施,利川,河南,郑州,洛阳,开封,漯河,安阳,新乡,周口,三门峡,焦作,平顶山,信阳,南阳,鹤壁,濮阳,许昌,商丘,驻马店,巩义,新郑,新密,登封,荥阳,偃师,汝州,舞钢,林州,卫辉,辉县,沁阳,孟州,禹州,长葛,义马,灵宝,邓州,永城,项城,济源,山西,太原,大同,忻州,阳泉,长治,晋城,朔州,晋中,运城,临汾,吕梁,古交,潞城,高平,介休,永济,河津,原平,侯马,霍州,孝义,汾阳,陕西,西安,咸阳,铜川,延安,宝鸡,渭南,汉中,安康,商洛,榆林,兴平,韩城,华阴,甘肃,兰州,天水,平凉,酒泉,嘉峪关,金昌,白银,武威,张掖,庆阳,定西,陇南,玉门,敦煌,临夏,合作,青海,西宁,格尔木,德令哈,江西,南昌,九江,赣州,吉安,鹰潭,上饶,萍乡,景德镇,新余,宜春,抚州,乐平,瑞昌,贵溪,瑞金,南康,井冈山,丰城,樟树,高安,德兴", ",")
func IsChina(country string) bool {
for _, v := range allChina {
if strings.HasPrefix(country, v) {
return true
}
}
return false
}
//md5加密
func Md5(str string) string {
hash := md5.New()
hash.Write([]byte(str))
return hex.EncodeToString(hash.Sum(nil))
}
func UDPPacket(srcAddr string, packet []byte) []byte {
addrBytes := []byte(srcAddr)
addrLength := uint16(len(addrBytes))
bodyLength := uint16(len(packet))
pkg := new(bytes.Buffer)
binary.Write(pkg, binary.LittleEndian, addrLength)
binary.Write(pkg, binary.LittleEndian, addrBytes)
binary.Write(pkg, binary.LittleEndian, bodyLength)
binary.Write(pkg, binary.LittleEndian, packet)
return pkg.Bytes()
}
func ReadUDPPacket(conn *tls.Conn) (srcAddr string, packet []byte, err error) {
reader := bufio.NewReader(conn)
var addrLength uint16
var bodyLength uint16
err = binary.Read(reader, binary.LittleEndian, &addrLength)
if err != nil {
return
}
_srcAddr := make([]byte, addrLength)
n, err := reader.Read(_srcAddr)
if err != nil {
return
}
if n != int(addrLength) {
return
}
srcAddr = string(_srcAddr)
err = binary.Read(reader, binary.LittleEndian, &bodyLength)
if err != nil {
return
}
packet = make([]byte, bodyLength)
n, err = reader.Read(packet)
if err != nil {
return
}
if n != int(bodyLength) {
return
}
return
}
+110
View File
@@ -0,0 +1,110 @@
package at_common
import (
"crypto/tls"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
func HttpGetNotInternal(URL string) (body []byte, code int, err error) {
return _HttpGet(URL, false)
}
func HttpPostNotInternal(URL string, data map[string]string, header map[string]string) (body []byte, code int, err error) {
return _HttpPost(URL, data, header, false)
}
func HttpPost(URL string, data map[string]string, header map[string]string) (body []byte, code int, err error) {
return _HttpPost(URL, data, header, true)
}
func HttpGet(URL string) (body []byte, code int, err error) {
return _HttpGet(URL, true)
}
func _HttpGet(URL string, isInternal bool) (body []byte, code int, err error) {
client, tr, err := getRequestClient(URL, isInternal)
if err != nil {
return
}
resp, err := client.Get(URL)
if err != nil {
return
}
defer resp.Body.Close()
defer tr.CloseIdleConnections()
code = resp.StatusCode
body, err = ioutil.ReadAll(resp.Body)
return
}
func _HttpPost(URL string, data map[string]string, header map[string]string, isInternal bool) (body []byte, code int, err error) {
postParamsString := ""
if data != nil {
postParams := []string{}
for k, v := range data {
postParams = append(postParams, url.QueryEscape(k)+"="+url.QueryEscape(v))
}
postParamsString = strings.Join(postParams, "&")
}
return HttpPostRaw(URL, postParamsString, header, isInternal)
}
func HttpPostRaw(URL, postParamsString string, header map[string]string, isInternal bool) (body []byte, code int, err error) {
var resp *http.Response
var client *http.Client
var tr *http.Transport
defer func() {
if resp != nil && resp.Body != nil {
resp.Body.Close()
}
if tr != nil {
tr.CloseIdleConnections()
}
}()
req, err := http.NewRequest("POST", URL, strings.NewReader(postParamsString))
if err != nil {
return
}
client, tr, err = getRequestClient(URL, isInternal)
if err != nil {
return
}
if header != nil {
for k, v := range header {
req.Header.Set(k, v)
}
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err = client.Do(req)
if err != nil {
return
}
body, err = ioutil.ReadAll(resp.Body)
code = resp.StatusCode
if err != nil {
return
}
return
}
func getRequestClient(url string, isInternal bool) (client *http.Client, tr *http.Transport, err error) {
var conf *tls.Config
conf, err = getRequestTlsConfig(isInternal)
if err != nil {
return
}
if strings.Contains(url, "https://") {
tr = &http.Transport{TLSClientConfig: conf}
client = &http.Client{Timeout: time.Second * 5, Transport: tr}
} else {
tr = &http.Transport{}
client = &http.Client{Timeout: time.Second * 5, Transport: tr}
}
return
}
func UrlArgs(url, args string) string {
if strings.Contains(url, "?") {
return url + "&" + args
}
return url + "?" + args
}
+303
View File
@@ -0,0 +1,303 @@
package at_common
import (
"fmt"
"math/rand"
"net"
"testing"
"time"
)
func TestNotInternal(t *testing.T) {
for {
fmt.Println(rand.Uint64() / 10000)
time.Sleep(time.Second)
}
}
func TestOpenPort(t *testing.T) {
// /port/open/:TunnelID/:ServerToken/:ServerBindIP/:ServerListenPort
// /:ClientToken/:ClientLocalHost/:ClientLocalPort/:Protocol/:BytesPerSec
body, code, err := HttpGet("https://127.0.0.1:37080/port/open/3/guest/0.0.0.0/20090/guest_client/8.8.8.8/53/2/102400")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestClosePort(t *testing.T) {
// /port/close/:TunnelID
body, code, err := HttpGet("https://127.0.0.1:37080/port/close/3")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestStatusPort(t *testing.T) {
// /port/close/:TunnelID
body, code, err := HttpGet("https://127.0.0.1:37080/port/status/1")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestTrafficCount(t *testing.T) {
// /traffic/count
body, code, err := HttpGet("https://127.0.0.1:37080/traffic/count")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestTrafficCountTunnel(t *testing.T) {
// /traffic/count/:TunnelID
body, code, err := HttpGet("https://127.0.0.1:37080/traffic/count/1")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestServerOffline(t *testing.T) {
// /server/offline/:ServerToken
body, code, err := HttpGet("https://127.0.0.1:37080/server/offline/guest")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestClientOffline(t *testing.T) {
// /server/offline/:ClientToken
body, code, err := HttpGet("https://127.0.0.1:37080/client/offline/guest_client")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestCsAdd(t *testing.T) {
values := map[string]string{
"server_ip": "127.0.0.1",
"server_token": "akdhkajhdkashdksdhk",
"client_ip": "124.176.89.90",
"client_token": "akhdkahdah",
"cluster_ip": "34.67.78.89",
"comment": "djadjllajd",
}
body, _, err := HttpPost("https://127.0.0.1:37081/cs/add", values, nil)
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(b)
}
}
func TestCsUpdate(t *testing.T) {
values := map[string]string{
"cs_id": "2",
"server_ip": "127.0.0.1",
"server_token": "akdhkajhdkashdksdhk",
"client_ip": "124.176.89.90",
"client_token": "tokentoken",
"cluster_ip": "34.67.78.89",
"comment": "djadjllajd",
}
body, _, err := HttpPost("https://127.0.0.1:37081/cs/update", values, nil)
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(b)
}
}
func TestCsList(t *testing.T) {
//body, err := HttpGet("https://127.0.0.1:37081/cs/list")
body, _, err := HttpGet("https://127.0.0.1:37081/cs/list?keyword=tokentoken")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(b)
}
}
func TestCsDelete(t *testing.T) {
body, _, err := HttpGet("https://127.0.0.1:37081/cs/delete?cs_id=1")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(b)
}
}
func TestCsGetCsByCsId(t *testing.T) {
body, _, err := HttpGet("https://127.0.0.1:37081/cs/getCsByCsId?cs_id=1")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(b)
}
}
func TestClusterReport(t *testing.T) {
values := map[string]string{
"sys_conn_number": "1312",
"tunnel_conn_number": "3443",
"bandwidth": "1232",
}
body, code, err := HttpPost("https://127.0.0.1:37081/cluster/report", values, nil)
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestCSAuth(t *testing.T) {
body, code, err := HttpGet("https://127.0.0.1:37081/cs/auth?token=guest&type=server")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestCSOnlineOffline(t *testing.T) {
body, code, err := HttpGet("https://127.0.0.1:37081/cs/status?token=guest_client&type=client&action=offline")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestUserTraffic(t *testing.T) {
data := `{"1":{"positive":32300100,"negative":5324},"2":{"negative":3997696,"positive":0},"3":{"positive":3231,"negative":5324}}`
body, code, err := HttpPostRaw("https://127.0.0.1:37081/user/traffic", data, nil, true)
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
func TestCSCluster(t *testing.T) {
body, code, err := HttpGet("https://127.0.0.1:29531/cluster/get?token=guest&type=server")
if err != nil {
t.Error(err)
} else {
b := string(body)
fmt.Println(code)
fmt.Println(b)
}
}
type ClusterTunnel struct {
TunnelID uint64
ServerToken string
ServerBindIP string
ServerListenPort int
ClientToken string
ClientLocalHost string
ClientLocalPort int
Protocol int
BytesPerSec float64
}
func Test(t *testing.T) {
_, code, err := HttpGet("https://127.0.0.1:37080/port/open/2/guest/0.0.0.0/20080/guest_client/127.0.0.1/80/1/102400")
fmt.Println(code, err)
}
func getMyInterfaceAddr() ([]net.IP, error) {
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
addresses := []net.IP{}
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 {
continue
}
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
}
addresses = append(addresses, ip)
}
}
if len(addresses) == 0 {
return nil, fmt.Errorf("no address Found, net.InterfaceAddrs: %v", addresses)
}
//only need first
return addresses, nil
}
func TestReadTimeout(t *testing.T) {
conn, err := TlsConnect("127.0.0.1", 29531, 3000)
if err != nil {
t.Error(err)
} else {
byt := make([]byte, 1)
_, err := conn.Read(byt)
if err != nil {
t.Error(err)
}
}
}
+97
View File
@@ -0,0 +1,97 @@
package at_common
import (
"context"
"io"
"time"
"golang.org/x/time/rate"
)
const burstLimit = 1000 * 1000 * 1000
type Reader struct {
r io.Reader
limiter *rate.Limiter
ctx context.Context
}
type Writer struct {
w io.Writer
limiter *rate.Limiter
ctx context.Context
}
// NewReader returns a reader that implements io.Reader with rate limiting.
func NewReader(r io.Reader) *Reader {
return &Reader{
r: r,
ctx: context.Background(),
}
}
// NewReaderWithContext returns a reader that implements io.Reader with rate limiting.
func NewReaderWithContext(r io.Reader, ctx context.Context) *Reader {
return &Reader{
r: r,
ctx: ctx,
}
}
// NewWriter returns a writer that implements io.Writer with rate limiting.
func NewWriter(w io.Writer) *Writer {
return &Writer{
w: w,
ctx: context.Background(),
}
}
// NewWriterWithContext returns a writer that implements io.Writer with rate limiting.
func NewWriterWithContext(w io.Writer, ctx context.Context) *Writer {
return &Writer{
w: w,
ctx: ctx,
}
}
// SetRateLimit sets rate limit (bytes/sec) to the reader.
func (s *Reader) SetRateLimit(bytesPerSec float64) {
s.limiter = rate.NewLimiter(rate.Limit(bytesPerSec), burstLimit)
s.limiter.AllowN(time.Now(), burstLimit) // spend initial burst
}
// Read reads bytes into p.
func (s *Reader) Read(p []byte) (int, error) {
if s.limiter == nil {
return s.r.Read(p)
}
n, err := s.r.Read(p)
if err != nil {
return n, err
}
if err := s.limiter.WaitN(s.ctx, n); err != nil {
return n, err
}
return n, nil
}
// SetRateLimit sets rate limit (bytes/sec) to the writer.
func (s *Writer) SetRateLimit(bytesPerSec float64) {
s.limiter = rate.NewLimiter(rate.Limit(bytesPerSec), burstLimit)
s.limiter.AllowN(time.Now(), burstLimit) // spend initial burst
}
// Write writes bytes from p.
func (s *Writer) Write(p []byte) (int, error) {
if s.limiter == nil {
return s.w.Write(p)
}
n, err := s.w.Write(p)
if err != nil {
return n, err
}
if err := s.limiter.WaitN(s.ctx, n); err != nil {
return n, err
}
return n, err
}
+315
View File
@@ -0,0 +1,315 @@
package at_common
import (
"encoding/json"
"sync"
)
var SHARD_COUNT = 32
// A "thread" safe map of type string:Anything.
// To avoid lock bottlenecks this map is dived to several (SHARD_COUNT) map shards.
type ConcurrentMap []*ConcurrentMapShared
// A "thread" safe string to anything map.
type ConcurrentMapShared struct {
items map[string]interface{}
sync.RWMutex // Read Write mutex, guards access to internal map.
}
// Creates a new concurrent map.
func NewConcurrentMap() ConcurrentMap {
m := make(ConcurrentMap, SHARD_COUNT)
for i := 0; i < SHARD_COUNT; i++ {
m[i] = &ConcurrentMapShared{items: make(map[string]interface{})}
}
return m
}
// Returns shard under given key
func (m ConcurrentMap) GetShard(key string) *ConcurrentMapShared {
return m[uint(fnv32(key))%uint(SHARD_COUNT)]
}
func (m ConcurrentMap) MSet(data map[string]interface{}) {
for key, value := range data {
shard := m.GetShard(key)
shard.Lock()
shard.items[key] = value
shard.Unlock()
}
}
// Sets the given value under the specified key.
func (m ConcurrentMap) Set(key string, value interface{}) {
// Get map shard.
shard := m.GetShard(key)
shard.Lock()
shard.items[key] = value
shard.Unlock()
}
// Callback to return new element to be inserted into the map
// It is called while lock is held, therefore it MUST NOT
// try to access other keys in same map, as it can lead to deadlock since
// Go sync.RWLock is not reentrant
type UpsertCb func(exist bool, valueInMap interface{}, newValue interface{}) interface{}
// Insert or Update - updates existing element or inserts a new one using UpsertCb
func (m ConcurrentMap) Upsert(key string, value interface{}, cb UpsertCb) (res interface{}) {
shard := m.GetShard(key)
shard.Lock()
v, ok := shard.items[key]
res = cb(ok, v, value)
shard.items[key] = res
shard.Unlock()
return res
}
// Sets the given value under the specified key if no value was associated with it.
func (m ConcurrentMap) SetIfAbsent(key string, value interface{}) bool {
// Get map shard.
shard := m.GetShard(key)
shard.Lock()
_, ok := shard.items[key]
if !ok {
shard.items[key] = value
}
shard.Unlock()
return !ok
}
// Retrieves an element from map under given key.
func (m ConcurrentMap) Get(key string) (interface{}, bool) {
// Get shard
shard := m.GetShard(key)
shard.RLock()
// Get item from shard.
val, ok := shard.items[key]
shard.RUnlock()
return val, ok
}
// Returns the number of elements within the map.
func (m ConcurrentMap) Count() int {
count := 0
for i := 0; i < SHARD_COUNT; i++ {
shard := m[i]
shard.RLock()
count += len(shard.items)
shard.RUnlock()
}
return count
}
// Looks up an item under specified key
func (m ConcurrentMap) Has(key string) bool {
// Get shard
shard := m.GetShard(key)
shard.RLock()
// See if element is within shard.
_, ok := shard.items[key]
shard.RUnlock()
return ok
}
// Removes an element from the map.
func (m ConcurrentMap) Remove(key string) {
// Try to get shard.
shard := m.GetShard(key)
shard.Lock()
delete(shard.items, key)
shard.Unlock()
}
// Removes an element from the map and returns it
func (m ConcurrentMap) Pop(key string) (v interface{}, exists bool) {
// Try to get shard.
shard := m.GetShard(key)
shard.Lock()
v, exists = shard.items[key]
delete(shard.items, key)
shard.Unlock()
return v, exists
}
// Checks if map is empty.
func (m ConcurrentMap) IsEmpty() bool {
return m.Count() == 0
}
// Used by the Iter & IterBuffered functions to wrap two variables together over a channel,
type Tuple struct {
Key string
Val interface{}
}
// Returns an iterator which could be used in a for range loop.
//
// Deprecated: using IterBuffered() will get a better performence
func (m ConcurrentMap) Iter() <-chan Tuple {
chans := snapshot(m)
ch := make(chan Tuple)
go fanIn(chans, ch)
return ch
}
// Returns a buffered iterator which could be used in a for range loop.
func (m ConcurrentMap) IterBuffered() <-chan Tuple {
chans := snapshot(m)
total := 0
for _, c := range chans {
total += cap(c)
}
ch := make(chan Tuple, total)
go fanIn(chans, ch)
return ch
}
// Returns a array of channels that contains elements in each shard,
// which likely takes a snapshot of `m`.
// It returns once the size of each buffered channel is determined,
// before all the channels are populated using goroutines.
func snapshot(m ConcurrentMap) (chans []chan Tuple) {
chans = make([]chan Tuple, SHARD_COUNT)
wg := sync.WaitGroup{}
wg.Add(SHARD_COUNT)
// Foreach shard.
for index, shard := range m {
go func(index int, shard *ConcurrentMapShared) {
// Foreach key, value pair.
shard.RLock()
chans[index] = make(chan Tuple, len(shard.items))
wg.Done()
for key, val := range shard.items {
chans[index] <- Tuple{key, val}
}
shard.RUnlock()
close(chans[index])
}(index, shard)
}
wg.Wait()
return chans
}
// fanIn reads elements from channels `chans` into channel `out`
func fanIn(chans []chan Tuple, out chan Tuple) {
wg := sync.WaitGroup{}
wg.Add(len(chans))
for _, ch := range chans {
go func(ch chan Tuple) {
for t := range ch {
out <- t
}
wg.Done()
}(ch)
}
wg.Wait()
close(out)
}
// Returns all items as map[string]interface{}
func (m ConcurrentMap) Items() map[string]interface{} {
tmp := make(map[string]interface{})
// Insert items to temporary map.
for item := range m.IterBuffered() {
tmp[item.Key] = item.Val
}
return tmp
}
// Iterator callback,called for every key,value found in
// maps. RLock is held for all calls for a given shard
// therefore callback sess consistent view of a shard,
// but not across the shards
type IterCb func(key string, v interface{})
// Callback based iterator, cheapest way to read
// all elements in a map.
func (m ConcurrentMap) IterCb(fn IterCb) {
for idx := range m {
shard := (m)[idx]
shard.RLock()
for key, value := range shard.items {
fn(key, value)
}
shard.RUnlock()
}
}
// Return all keys as []string
func (m ConcurrentMap) Keys() []string {
count := m.Count()
ch := make(chan string, count)
go func() {
// Foreach shard.
wg := sync.WaitGroup{}
wg.Add(SHARD_COUNT)
for _, shard := range m {
go func(shard *ConcurrentMapShared) {
// Foreach key, value pair.
shard.RLock()
for key := range shard.items {
ch <- key
}
shard.RUnlock()
wg.Done()
}(shard)
}
wg.Wait()
close(ch)
}()
// Generate keys
keys := make([]string, 0, count)
for k := range ch {
keys = append(keys, k)
}
return keys
}
//Reviles ConcurrentMap "private" variables to json marshal.
func (m ConcurrentMap) MarshalJSON() ([]byte, error) {
// Create a temporary map, which will hold all item spread across shards.
tmp := make(map[string]interface{})
// Insert items to temporary map.
for item := range m.IterBuffered() {
tmp[item.Key] = item.Val
}
return json.Marshal(tmp)
}
func fnv32(key string) uint32 {
hash := uint32(2166136261)
const prime32 = uint32(16777619)
for i := 0; i < len(key); i++ {
hash *= prime32
hash ^= uint32(key[i])
}
return hash
}
// Concurrent map uses Interface{} as its value, therefor JSON Unmarshal
// will probably won't know which to type to unmarshal into, in such case
// we'll end up with a value of type map[string]interface{}, In most cases this isn't
// out value type, this is why we've decided to remove this functionality.
// func (m *ConcurrentMap) UnmarshalJSON(b []byte) (err error) {
// // Reverse process of Marshal.
// tmp := make(map[string]interface{})
// // Unmarshal into a single map.
// if err := json.Unmarshal(b, &tmp); err != nil {
// return nil
// }
// // foreach key,value pair in temporary map insert into our concurrent map.
// for key, val := range tmp {
// m.Set(key, val)
// }
// return nil
// }
+315
View File
@@ -0,0 +1,315 @@
package at_common
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/binary"
"encoding/json"
"fmt"
"math/rand"
"net"
"reflect"
"sync"
"time"
)
type Msg struct {
MsgType int
}
type message struct {
Type int
Data interface{}
}
type msgErrorHandler func(channel *MessageChannel, rawMsg interface{}, err error)
type msgCallback func(channel *MessageChannel, msg interface{})
type closeCallback func(channel *MessageChannel, isPeerClose bool)
type MessageChannel struct {
reader *bufio.Reader
writer *bufio.Writer
msgHandler map[int][]msgCallback
msgErrorHandler msgErrorHandler
msgTypeMap map[int]interface{}
readlock *sync.Mutex
writelock *sync.Mutex
readHandler func(msg message)
serveStared bool
ConnectionID uint64
Conn *net.Conn
remoteAddr net.Addr
localAddr net.Addr
}
func NewMessageChannel(conn *net.Conn) MessageChannel {
ch := MessageChannel{
Conn: conn,
remoteAddr: (*conn).RemoteAddr(),
localAddr: (*conn).LocalAddr(),
reader: bufio.NewReader(*conn),
writer: bufio.NewWriter(*conn),
msgTypeMap: map[int]interface{}{},
readlock: &sync.Mutex{},
writelock: &sync.Mutex{},
ConnectionID: rand.Uint64(),
msgErrorHandler: func(channel *MessageChannel, rawMsg interface{}, err error) {},
msgHandler: map[int][]msgCallback{},
}
ch.RegMsg(MSG_TYPE_PING, new(MsgPing), func(channel *MessageChannel, msg interface{}) {
msgPing := msg.(*MsgPing)
channel.Pong(msgPing.ID)
return
})
return ch
}
func NewMessageChannelTls(conn *tls.Conn) MessageChannel {
con := net.Conn(conn)
return NewMessageChannel(&con)
}
func (mc *MessageChannel) CloseConn() (err error) {
(*mc.Conn).SetDeadline(time.Now().Add(time.Millisecond))
return (*mc.Conn).Close()
}
func (mc *MessageChannel) RegMsg(msgType int, msg interface{}, fn msgCallback, fns ...msgCallback) {
mc.msgTypeMap[msgType] = msg
mc.msgHandler[msgType] = append(fns, fn)
}
func (mc *MessageChannel) SetMsgErrorHandler(fn func(channel *MessageChannel, rawMsg interface{}, err error)) {
mc.msgErrorHandler = fn
}
func (mc *MessageChannel) encode(data interface{}) (msg []byte, err error) {
var message []byte
message, err = json.Marshal(data)
if err != nil {
return
}
// 读取消息的长度
var length int32 = int32(len(message))
var pkg *bytes.Buffer = new(bytes.Buffer)
// 写入消息头
err = binary.Write(pkg, binary.LittleEndian, length)
if err != nil {
return
}
// 写入消息实体
err = binary.Write(pkg, binary.LittleEndian, message)
if err != nil {
return
}
return pkg.Bytes(), nil
}
func (mc *MessageChannel) Write(msg interface{}) (err error) {
defer mc.writelock.Unlock()
mc.writelock.Lock()
if reflect.TypeOf(msg).Kind().String() != "struct" {
err = fmt.Errorf("error : message must be a struct , send to %s", mc.remoteAddr)
return
}
if _, ok := reflect.TypeOf(msg).FieldByName("MsgType"); !ok {
err = fmt.Errorf("error : message must be has MsgType field , send to %s", mc.remoteAddr)
return
}
if reflect.ValueOf(msg).FieldByName("MsgType").Int() <= 0 {
err = fmt.Errorf("error : message's MsgType field must be great than 0, send to %s", mc.remoteAddr)
return
}
v := reflect.ValueOf(msg).FieldByName("MsgType").Int()
pack := message{
Type: int(v),
Data: msg,
}
var msgData []byte
msgData, err = mc.encode(pack)
if err != nil {
err = fmt.Errorf("encode message error : %s , to : %s", err, mc.remoteAddr)
return
}
_, err = mc.writer.Write(msgData)
if err != nil {
err = fmt.Errorf("write messasge fail to %s , ERR : %s", mc.remoteAddr, err)
return
}
err = mc.writer.Flush()
if err != nil {
err = fmt.Errorf("flush messasge fail %s , ERR : %s", mc.remoteAddr, err)
return
}
return
}
func (mc *MessageChannel) ReadTimeout(msg interface{}, timeout int) (err error) {
if !mc.serveStared {
err = fmt.Errorf("DoServe() must be called before call Read(),From : %s", mc.remoteAddr)
return
}
type M struct {
Err error
Msg interface{}
}
msgChn := make(chan M, 1)
mc.readHandler = func(rawMsg message) {
_, err = mc.toStruct(rawMsg.Data, &msg)
msgChn <- M{
Msg: msg,
Err: err,
}
}
m := M{}
if timeout > 0 {
select {
case m = <-msgChn:
msg = m.Msg
err = m.Err
case <-time.After(time.Duration(timeout) * time.Millisecond):
err = fmt.Errorf("read channel message timeout from %s", mc.remoteAddr)
}
} else {
m = <-msgChn
msg = m.Msg
err = m.Err
}
return
}
func (mc *MessageChannel) Read(msg interface{}) (err error) {
return mc.ReadTimeout(msg, 0)
}
func (mc *MessageChannel) read() (msg message, err error) {
defer func() {
if err != nil {
(*mc.Conn).Close()
}
mc.readlock.Unlock()
}()
mc.readlock.Lock()
// 读取消息的长度
lengthByte, err := mc.reader.Peek(4)
if err != nil {
err = fmt.Errorf("read message length error : %s , from %s", err, mc.remoteAddr)
return
}
lengthBuff := bytes.NewBuffer(lengthByte)
var length int32
err = binary.Read(lengthBuff, binary.LittleEndian, &length)
if err != nil {
err = fmt.Errorf("read message error : %s , from %s", err, mc.remoteAddr)
return
}
if int32(mc.reader.Buffered()) < length+4 {
err = fmt.Errorf("message data length error from %s", mc.remoteAddr)
return
}
// 读取消息真正的内容
pack := make([]byte, int(4+length))
_, err = mc.reader.Read(pack)
if err != nil {
err = fmt.Errorf("read message error : %s , from %s", err, mc.remoteAddr)
return
}
err = json.Unmarshal(pack[4:], &msg)
if err != nil {
err = fmt.Errorf("unmarshal message error : %s , from %s", err, mc.remoteAddr)
return
}
return
}
func (mc *MessageChannel) DoServe(errfn func(err error)) {
mc.serveStared = true
go func() {
var err error
var msg message
for {
msg, err = mc.read()
if err != nil {
go errfn(err)
mc.serveStared = false
return
}
if mc.readHandler != nil {
go mc.readHandler(msg)
mc.readHandler = nil
continue
}
h, ok := mc.msgHandler[msg.Type]
var data interface{}
if ok {
data, err = mc.parse(msg)
} else {
err = fmt.Errorf("msg handler not found , msgType:%d", msg.Type)
}
if err != nil {
go mc.msgErrorHandler(mc, msg.Data, err)
} else {
for i := len(h) - 1; i >= 0; i-- {
go h[i](mc, data)
}
}
}
}()
return
}
func (mc *MessageChannel) Ping() (id string, err error) {
id = randStr(32)
ping := MsgPing{
Msg: Msg{MsgType: MSG_TYPE_PING},
ID: id,
}
err = mc.Write(ping)
return
}
func (mc *MessageChannel) Pong(id string) (err error) {
pong := MsgPong{
Msg: Msg{MsgType: MSG_TYPE_PONG},
ID: id,
}
err = mc.Write(pong)
return
}
func (mc *MessageChannel) RemoteAddr() net.Addr {
return mc.remoteAddr
}
func (mc *MessageChannel) LocalAddr() net.Addr {
return mc.localAddr
}
func (mc *MessageChannel) parse(msg message) (data interface{}, err error) {
data, ok := mc.msgTypeMap[msg.Type]
if !ok {
err = fmt.Errorf("message type not registed")
return
}
mbytes, err := json.Marshal(msg.Data)
if err != nil {
return
}
err = json.Unmarshal(mbytes, data)
return
}
func (mc *MessageChannel) toStruct(msg, struc interface{}) (data interface{}, err error) {
mbytes, err := json.Marshal(msg)
if err != nil {
return
}
err = json.Unmarshal(mbytes, &struc)
data = struc
return
}
func randStr(strlen int) string {
codes := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
codeLen := len(codes)
data := make([]byte, strlen)
rand.Seed(time.Now().UnixNano() + rand.Int63() + rand.Int63() + rand.Int63() + rand.Int63())
for i := 0; i < strlen; i++ {
idx := rand.Intn(codeLen)
data[i] = byte(codes[idx])
}
return string(data)
}
+162
View File
@@ -0,0 +1,162 @@
package at_common
import (
"bufio"
"bytes"
"encoding/binary"
"encoding/json"
"errors"
)
const (
nONE = iota
TUNNEL_PROTOCOL_TCP
TUNNEL_PROTOCOL_UDP
CSTYPE_SERVER
CSTYPE_CLIENT
MSG_CLIENT_OPEN_CONNECTION
MSG_SERVER_OPEN_PORT
MSG_SERVER_CLOSE_PORT
MSG_SERVER_STATUS_PORT
MSG_RESPONSE
STATUS_SUCCESS
STATUS_FAIL
MSG_TYPE_LOGIN
MSG_TYPE_PING
MSG_TYPE_PONG
CS_CLIENT uint8 = 1
CS_SERVER uint8 = 2
)
type MsgPing struct {
Msg
ID string
}
type MsgPong struct {
Msg
ID string
}
type MsgClientOpenConnection struct {
Msg
TunnelID uint64
ConnectinID uint64
LocalHost string
LocalPort int
Protocol int
}
type MsgServerOpenPort struct {
Msg
TunnelID uint64
BindPort int
BindIP string
Protocol int
}
func (m *MsgServerOpenPort) ProtocolString() string {
return GetProtocolString(m.Protocol)
}
type MsgServerClosePort struct {
Msg
TunnelID uint64
Protocol int
}
type MsgServerStatusPort struct {
Msg
TunnelID uint64
Protocol int
}
type MsgLogin struct {
Msg
Token string
CSType int
}
func (m *MsgLogin) IsServer() bool {
return m.CSType == CSTYPE_SERVER
}
func (m *MsgLogin) IsClient() bool {
return m.CSType == CSTYPE_CLIENT
}
func (m *MsgLogin) CSTypeString() string {
return GetCSTypeString(m.CSType)
}
type MsgResponse struct {
Msg
Status int
Message string
}
func (m *MsgResponse) IsSuccess() bool {
return m.Status == STATUS_SUCCESS
}
func Encode(data interface{}) (msg []byte, err error) {
var message []byte
message, err = json.Marshal(data)
if err != nil {
return
}
// 读取消息的长度
var length int32 = int32(len(message))
var pkg *bytes.Buffer = new(bytes.Buffer)
// 写入消息头
err = binary.Write(pkg, binary.LittleEndian, length)
if err != nil {
return
}
// 写入消息实体
err = binary.Write(pkg, binary.LittleEndian, message)
if err != nil {
return
}
return pkg.Bytes(), nil
}
func Decode(reader *bufio.Reader) (msg message, err error) {
// 读取消息的长度
lengthByte, _ := reader.Peek(4)
lengthBuff := bytes.NewBuffer(lengthByte)
var length int32
err = binary.Read(lengthBuff, binary.LittleEndian, &length)
if err != nil {
return
}
if int32(reader.Buffered()) < length+4 {
err = errors.New("data length error")
return
}
// 读取消息真正的内容
pack := make([]byte, int(4+length))
_, err = reader.Read(pack)
if err != nil {
return
}
var _msg message
err = json.Unmarshal(pack[4:], &_msg)
if err != nil {
return
}
return _msg, nil
}
func GetCSTypeString(cstype int) string {
switch cstype {
case CSTYPE_CLIENT:
return "CLIENT"
case CSTYPE_SERVER:
return "SERVER"
}
return "UNKONWN_CSTYPE"
}
func GetProtocolString(protocol int) string {
switch protocol {
case TUNNEL_PROTOCOL_UDP:
return "udp"
case TUNNEL_PROTOCOL_TCP:
return "tcp"
}
return "UNKONWN_PROTOCOL"
}
+282
View File
@@ -0,0 +1,282 @@
package qqwry
import (
"encoding/binary"
"errors"
"io/ioutil"
"log"
"net"
"os"
"strings"
"time"
"golang.org/x/text/encoding/simplifiedchinese"
)
// qqwry.LoadData("data/qqwry.dat")
// rs := qqwry.Find("32.30.50.128")
// log.Println(rs)
const (
// IndexLen 索引长度
IndexLen = 7
// RedirectMode1 国家的类型, 指向另一个指向
RedirectMode1 = 0x01
// RedirectMode2 国家的类型, 指向一个指向
RedirectMode2 = 0x02
)
// ResultQQwry 归属地信息
type ResultQQwry struct {
IP string `json:"ip"`
Country string `json:"country"`
Area string `json:"area"`
}
type fileData struct {
Data []byte
FilePath string
Path *os.File
IPNum int64
}
// QQwry 纯真ip库
type QQwry struct {
Data *fileData
Offset int64
}
func LoadData(datFile string) {
IPData.FilePath = datFile
startTime := time.Now().UnixNano()
res := IPData.InitIPData()
if v, ok := res.(error); ok {
log.Panic(v)
}
endTime := time.Now().UnixNano()
log.Printf("IP 库加载完成 共加载:%d 条 IP 记录, 所花时间:%.1f ms\n", IPData.IPNum, float64(endTime-startTime)/1000000)
}
// IPData IP库的数据
var IPData fileData
var q = NewQQwry()
func Find(ip string) (res ResultQQwry) {
return q.Find(ip)
}
func FindIPs(ips []string) (rs map[string]ResultQQwry) {
return q.FindIPs(ips)
}
// InitIPData 初始化ip库数据到内存中
func (f *fileData) InitIPData() (rs interface{}) {
// 判断文件是否存在
_, err := os.Stat(f.FilePath)
if err != nil && os.IsNotExist(err) {
rs = errors.New("文件不存在")
return
}
// 打开文件句柄
f.Path, err = os.OpenFile(f.FilePath, os.O_RDONLY, 0400)
if err != nil {
rs = err
return
}
defer f.Path.Close()
tmpData, err := ioutil.ReadAll(f.Path)
if err != nil {
log.Println(err)
rs = err
return
}
f.Data = tmpData
buf := f.Data[0:8]
start := binary.LittleEndian.Uint32(buf[:4])
end := binary.LittleEndian.Uint32(buf[4:])
f.IPNum = int64((end-start)/IndexLen + 1)
return true
}
// NewQQwry 新建 qqwry 类型
func NewQQwry() QQwry {
return QQwry{
Data: &IPData,
}
}
// ReadData 从文件中读取数据
func (q *QQwry) ReadData(num int, offset ...int64) (rs []byte) {
if len(offset) > 0 {
q.SetOffset(offset[0])
}
nums := int64(num)
end := q.Offset + nums
dataNum := int64(len(q.Data.Data))
if q.Offset > dataNum {
return nil
}
if end > dataNum {
end = dataNum
}
rs = q.Data.Data[q.Offset:end]
q.Offset = end
return
}
// SetOffset 设置偏移量
func (q *QQwry) SetOffset(offset int64) {
q.Offset = offset
}
func (q *QQwry) FindIPs(ips []string) (rs map[string]ResultQQwry) {
rs = map[string]ResultQQwry{}
if len(ips) > 0 {
for _, v := range ips {
rs[v] = q.Find(v)
}
}
return
}
// Find ip地址查询对应归属地信息
func (q *QQwry) Find(ip string) (res ResultQQwry) {
res = ResultQQwry{}
res.IP = ip
if strings.Count(ip, ".") != 3 {
return res
}
offset := q.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
if offset <= 0 {
return
}
var country []byte
var area []byte
mode := q.readMode(offset + 4)
if mode == RedirectMode1 {
countryOffset := q.readUInt24()
mode = q.readMode(countryOffset)
if mode == RedirectMode2 {
c := q.readUInt24()
country = q.readString(c)
countryOffset += 4
} else {
country = q.readString(countryOffset)
countryOffset += uint32(len(country) + 1)
}
area = q.readArea(countryOffset)
} else if mode == RedirectMode2 {
countryOffset := q.readUInt24()
country = q.readString(countryOffset)
area = q.readArea(offset + 8)
} else {
country = q.readString(offset + 4)
area = q.readArea(offset + uint32(5+len(country)))
}
enc := simplifiedchinese.GBK.NewDecoder()
res.Country, _ = enc.String(string(country))
res.Area, _ = enc.String(string(area))
return
}
// readMode 获取偏移值类型
func (q *QQwry) readMode(offset uint32) byte {
mode := q.ReadData(1, int64(offset))
return mode[0]
}
// readArea 读取区域
func (q *QQwry) readArea(offset uint32) []byte {
mode := q.readMode(offset)
if mode == RedirectMode1 || mode == RedirectMode2 {
areaOffset := q.readUInt24()
if areaOffset == 0 {
return []byte("")
}
return q.readString(areaOffset)
}
return q.readString(offset)
}
// readString 获取字符串
func (q *QQwry) readString(offset uint32) []byte {
q.SetOffset(int64(offset))
data := make([]byte, 0, 30)
buf := make([]byte, 1)
for {
buf = q.ReadData(1)
if buf[0] == 0 {
break
}
data = append(data, buf[0])
}
return data
}
// searchIndex 查找索引位置
func (q *QQwry) searchIndex(ip uint32) uint32 {
header := q.ReadData(8, 0)
start := binary.LittleEndian.Uint32(header[:4])
end := binary.LittleEndian.Uint32(header[4:])
buf := make([]byte, IndexLen)
mid := uint32(0)
_ip := uint32(0)
for {
mid = q.getMiddleOffset(start, end)
buf = q.ReadData(IndexLen, int64(mid))
_ip = binary.LittleEndian.Uint32(buf[:4])
if end-start == IndexLen {
offset := byteToUInt32(buf[4:])
buf = q.ReadData(IndexLen)
if ip < binary.LittleEndian.Uint32(buf[:4]) {
return offset
}
return 0
}
// 找到的比较大,向前移
if _ip > ip {
end = mid
} else if _ip < ip { // 找到的比较小,向后移
start = mid
} else if _ip == ip {
return byteToUInt32(buf[4:])
}
}
}
// readUInt24
func (q *QQwry) readUInt24() uint32 {
buf := q.ReadData(3)
return byteToUInt32(buf)
}
// getMiddleOffset
func (q *QQwry) getMiddleOffset(start uint32, end uint32) uint32 {
records := ((end - start) / IndexLen) >> 1
return start + records*IndexLen
}
// byteToUInt32 将 byte 转换为uint32
func byteToUInt32(data []byte) uint32 {
i := uint32(data[0]) & 0xff
i |= (uint32(data[1]) << 8) & 0xff00
i |= (uint32(data[2]) << 16) & 0xff0000
return i
}
+181
View File
@@ -0,0 +1,181 @@
package qqwry
import (
"encoding/binary"
"github.com/yinheli/mahonia"
// "encoding/hex"
"net"
"os"
)
// q := qqwry.NewQQwry("data/qqwry.dat")
// q.Find("103.30.50.128")
// log.Println(q.Country, q.City, q.Ip)
const (
INDEX_LEN = 7
REDIRECT_MODE_1 = 0x01
REDIRECT_MODE_2 = 0x02
)
// @author yinheli
type QQwry struct {
Ip string
Country string
City string
filepath string
file *os.File
}
func NewQQwry(file string) (qqwry *QQwry) {
qqwry = &QQwry{filepath: file}
return
}
func (this *QQwry) Find(ip string) {
if this.filepath == "" {
return
}
file, err := os.OpenFile(this.filepath, os.O_RDONLY, 0400)
defer file.Close()
if err != nil {
return
}
this.file = file
this.Ip = ip
offset := this.searchIndex(binary.BigEndian.Uint32(net.ParseIP(ip).To4()))
// log.Println("loc offset:", offset)
if offset <= 0 {
return
}
var country []byte
var area []byte
mode := this.readMode(offset + 4)
// log.Println("mode", mode)
if mode == REDIRECT_MODE_1 {
countryOffset := this.readUInt24()
mode = this.readMode(countryOffset)
// log.Println("1 - mode", mode)
if mode == REDIRECT_MODE_2 {
c := this.readUInt24()
country = this.readString(c)
countryOffset += 4
} else {
country = this.readString(countryOffset)
countryOffset += uint32(len(country) + 1)
}
area = this.readArea(countryOffset)
} else if mode == REDIRECT_MODE_2 {
countryOffset := this.readUInt24()
country = this.readString(countryOffset)
area = this.readArea(offset + 8)
} else {
country = this.readString(offset + 4)
area = this.readArea(offset + uint32(5+len(country)))
}
enc := mahonia.NewDecoder("gbk")
this.Country = enc.ConvertString(string(country))
this.City = enc.ConvertString(string(area))
}
func (this *QQwry) readMode(offset uint32) byte {
this.file.Seek(int64(offset), 0)
mode := make([]byte, 1)
this.file.Read(mode)
return mode[0]
}
func (this *QQwry) readArea(offset uint32) []byte {
mode := this.readMode(offset)
if mode == REDIRECT_MODE_1 || mode == REDIRECT_MODE_2 {
areaOffset := this.readUInt24()
if areaOffset == 0 {
return []byte("")
} else {
return this.readString(areaOffset)
}
} else {
return this.readString(offset)
}
return []byte("")
}
func (this *QQwry) readString(offset uint32) []byte {
this.file.Seek(int64(offset), 0)
data := make([]byte, 0, 30)
buf := make([]byte, 1)
for {
this.file.Read(buf)
if buf[0] == 0 {
break
}
data = append(data, buf[0])
}
return data
}
func (this *QQwry) searchIndex(ip uint32) uint32 {
header := make([]byte, 8)
this.file.Seek(0, 0)
this.file.Read(header)
start := binary.LittleEndian.Uint32(header[:4])
end := binary.LittleEndian.Uint32(header[4:])
// log.Printf("len info %v, %v ---- %v, %v", start, end, hex.EncodeToString(header[:4]), hex.EncodeToString(header[4:]))
for {
mid := this.getMiddleOffset(start, end)
this.file.Seek(int64(mid), 0)
buf := make([]byte, INDEX_LEN)
this.file.Read(buf)
_ip := binary.LittleEndian.Uint32(buf[:4])
// log.Printf(">> %v, %v, %v -- %v", start, mid, end, hex.EncodeToString(buf[:4]))
if end-start == INDEX_LEN {
offset := byte3ToUInt32(buf[4:])
this.file.Read(buf)
if ip < binary.LittleEndian.Uint32(buf[:4]) {
return offset
} else {
return 0
}
}
// 找到的比较大,向前移
if _ip > ip {
end = mid
} else if _ip < ip { // 找到的比较小,向后移
start = mid
} else if _ip == ip {
return byte3ToUInt32(buf[4:])
}
}
return 0
}
func (this *QQwry) readUInt24() uint32 {
buf := make([]byte, 3)
this.file.Read(buf)
return byte3ToUInt32(buf)
}
func (this *QQwry) getMiddleOffset(start uint32, end uint32) uint32 {
records := ((end - start) / INDEX_LEN) >> 1
return start + records*INDEX_LEN
}
func byte3ToUInt32(data []byte) uint32 {
i := uint32(data[0]) & 0xff
i |= (uint32(data[1]) << 8) & 0xff00
i |= (uint32(data[2]) << 16) & 0xff0000
return i
}
+93
View File
@@ -0,0 +1,93 @@
package at_common
import (
"fmt"
"net"
)
type ServerChannel struct {
ip string
port int
Listener *net.Listener
UDPListener *net.UDPConn
errAcceptHandler func(err error)
}
func NewServerChannel(ip string, port int) ServerChannel {
return ServerChannel{
ip: ip,
port: port,
errAcceptHandler: func(err error) {
fmt.Printf("accept error , ERR:%s", err)
},
}
}
func (sc *ServerChannel) SetErrAcceptHandler(fn func(err error)) {
sc.errAcceptHandler = fn
}
func (sc *ServerChannel) ListenTls(fn func(channel MessageChannel, conn net.Conn)) (err error) {
sc.Listener, err = ListenTls(sc.ip, sc.port)
if err == nil {
go func() {
for {
var conn net.Conn
conn, err = (*sc.Listener).Accept()
if err == nil {
go func() {
fn(NewMessageChannel(&conn), conn)
}()
} else {
sc.errAcceptHandler(err)
(*sc.Listener).Close()
break
}
}
}()
}
return
}
func (sc *ServerChannel) ListenTCP(fn func(channel MessageChannel, conn net.Conn)) (err error) {
l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", sc.ip, sc.port))
if err == nil {
sc.Listener = &l
go func() {
for {
var conn net.Conn
conn, err = (*sc.Listener).Accept()
if err == nil {
go func() {
fn(NewMessageChannel(&conn), conn)
}()
} else {
sc.errAcceptHandler(err)
break
}
}
}()
}
return
}
func (sc *ServerChannel) ListenUDP(fn func(packet []byte, localAddr, srcAddr *net.UDPAddr)) (err error) {
addr := &net.UDPAddr{IP: net.ParseIP(sc.ip), Port: sc.port}
l, err := net.ListenUDP("udp", addr)
if err == nil {
sc.UDPListener = l
go func() {
for {
var buf = make([]byte, 2048)
n, srcAddr, err := (*sc.UDPListener).ReadFromUDP(buf)
if err == nil {
packet := buf[0:n]
go func() {
fn(packet, addr, srcAddr)
}()
} else {
sc.errAcceptHandler(err)
break
}
}
}()
}
return
}
+15
View File
@@ -0,0 +1,15 @@
package at_common
type TrafficTotal struct {
Tunnels int `json="tunnels"`
Servers int `json="servers"`
Clients int `json="clinets"`
UploadBytes uint64 `json="uploadBytes"`
DownloadBytes uint64 `json="downloadBytes"`
TotalBytes uint64 `json="totalBytes"`
Connections int `json="connections"`
}
type TrafficStatistics struct {
Total TrafficTotal `json="total"`
Traffic map[string]map[string]uint64 `json="traffic"`
}