update
This commit is contained in:
parent
baa77f4468
commit
b0007f4cfd
BIN
client.exe
Normal file
BIN
client.exe
Normal file
Binary file not shown.
21
http/miss.go
21
http/miss.go
@ -1,21 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
resp, err := http.Get("https://zh.xhamster.com/?ref=porndude")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("http get error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("read error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(string(body))
|
|
||||||
}
|
|
||||||
@ -6,46 +6,49 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UClientProxy struct {
|
type UClientProxy struct {
|
||||||
ServerConn *UPacketConnection
|
serverAddr string
|
||||||
|
clientAddr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientProxy() *UClientProxy {
|
func (client *UClientProxy) NewClientConnection() *PacketConnect {
|
||||||
return &UClientProxy{}
|
conn, err := net.Dial("tcp", client.clientAddr)
|
||||||
|
if err != nil {
|
||||||
|
zlog.Infof("connect local client error: %s %s", err.Error(), client.clientAddr)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return NewPacketConnect(conn, "local")
|
||||||
|
}
|
||||||
|
func (client *UClientProxy) NewTcpConnection(id uint32) *PacketConnect {
|
||||||
|
conn, err := net.Dial("tcp", client.serverAddr)
|
||||||
|
if err != nil {
|
||||||
|
zlog.Infof("connect server error: %s", err.Error())
|
||||||
|
}
|
||||||
|
remote := NewPacketConnect(conn, "remote")
|
||||||
|
remote.WriteHeader(id)
|
||||||
|
if id == RemoteID {
|
||||||
|
return remote
|
||||||
|
}
|
||||||
|
local := client.NewClientConnection()
|
||||||
|
if local == nil {
|
||||||
|
err = remote.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
go local.Forward(remote, 0)
|
||||||
|
go remote.Forward(local, 0)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
func (client *UClientProxy) ServeTCP(serverAddr string, clientAddr string) error {
|
func (client *UClientProxy) ServeTCP(serverAddr string, clientAddr string) error {
|
||||||
conn, err := net.Dial("tcp", serverAddr)
|
client.serverAddr = serverAddr
|
||||||
if err != nil {
|
client.clientAddr = clientAddr
|
||||||
return err
|
RemoteConn := client.NewTcpConnection(RemoteID)
|
||||||
}
|
zlog.Infof("connect to server %s", RemoteConn.Name())
|
||||||
zlog.Infof("connect server %s", serverAddr)
|
|
||||||
client.ServerConn = NewPacketConnection(conn)
|
|
||||||
_, err = client.ServerConn.Write([]byte("anki"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for {
|
for {
|
||||||
data := make([]byte, 4)
|
data := RemoteConn.ReadHeader()
|
||||||
_, err := client.ServerConn.Read(data, 0, 4)
|
if string(data[:4]) != "anki" {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if string(data) != "anki" {
|
|
||||||
zlog.Error("rcv package error:", data)
|
zlog.Error("rcv package error:", data)
|
||||||
client.ServerConn.Clear()
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
conn, err := net.Dial("tcp", clientAddr)
|
id := packetEndian.Uint32(data[4:])
|
||||||
if err != nil {
|
go client.NewTcpConnection(id)
|
||||||
zlog.Error("connect local anki error: ", err.Error(), clientAddr)
|
|
||||||
client.ServerConn.ForwardError(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pc := NewPacketConnection(conn)
|
|
||||||
client.ServerConn.Forward(pc)
|
|
||||||
pc.Forward(client.ServerConn)
|
|
||||||
err = pc.Close()
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("close local anki error: ", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
87
proxy/packet_connect.go
Normal file
87
proxy/packet_connect.go
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
packetEndian = binary.LittleEndian
|
||||||
|
RemoteID uint32 = 1
|
||||||
|
sid = RemoteID
|
||||||
|
maxSid uint32 = 1024 * 1024
|
||||||
|
HeaderSize = 16
|
||||||
|
Magic = "anki"
|
||||||
|
InitBuf = func() []byte {
|
||||||
|
buf := make([]byte, HeaderSize)
|
||||||
|
copy(buf[:len(Magic)], Magic)
|
||||||
|
return buf
|
||||||
|
}()
|
||||||
|
)
|
||||||
|
|
||||||
|
func IncID() uint32 {
|
||||||
|
if sid > maxSid {
|
||||||
|
sid = RemoteID
|
||||||
|
}
|
||||||
|
sid++
|
||||||
|
return sid
|
||||||
|
}
|
||||||
|
|
||||||
|
type PacketConnect struct {
|
||||||
|
net.Conn
|
||||||
|
header []byte
|
||||||
|
id uint32
|
||||||
|
readErr error
|
||||||
|
writeErr error
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPacketConnect(conn net.Conn, name string) *PacketConnect {
|
||||||
|
pc := &PacketConnect{Conn: conn, header: make([]byte, HeaderSize)}
|
||||||
|
pc.SetRemote(name, 0)
|
||||||
|
copy(pc.header, InitBuf)
|
||||||
|
return pc
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) Name() string {
|
||||||
|
return pc.name
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) SetRemote(name string, id uint32) {
|
||||||
|
pc.id = id
|
||||||
|
pc.name = "(" + name + ")" + strconv.Itoa(int(id)) + "::" + pc.RemoteAddr().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *PacketConnect) Write(data []byte) int {
|
||||||
|
n, err := pc.Conn.Write(data)
|
||||||
|
pc.writeErr = err
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) Read(data []byte) int {
|
||||||
|
n, err := pc.Conn.Read(data)
|
||||||
|
pc.readErr = err
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) ReadHeader() []byte {
|
||||||
|
pc.Read(pc.header)
|
||||||
|
return pc.header
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) WriteHeader(id uint32) {
|
||||||
|
packetEndian.PutUint32(pc.header[4:8], id)
|
||||||
|
pc.Write(pc.header)
|
||||||
|
}
|
||||||
|
func (pc *PacketConnect) Forward(dst *PacketConnect, rn int) {
|
||||||
|
if rn > 0 {
|
||||||
|
dst.Write(pc.header[:rn])
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = pc.Close()
|
||||||
|
}()
|
||||||
|
data := make([]byte, 1024)
|
||||||
|
for pc.readErr == nil && dst.writeErr == nil {
|
||||||
|
_ = pc.SetReadDeadline(time.Now().Add(time.Second))
|
||||||
|
n := pc.Read(data)
|
||||||
|
rn += n
|
||||||
|
dst.Write(data[:n])
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,85 +0,0 @@
|
|||||||
package proxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"zproxy/zlog"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UPacketConnection struct {
|
|
||||||
*UHttpRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建连接的方法
|
|
||||||
func NewPacketConnection(conn net.Conn) *UPacketConnection {
|
|
||||||
//初始化Conn属性
|
|
||||||
c := &UPacketConnection{
|
|
||||||
UHttpRequest: NewHttpRequest(conn),
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
func (pc *UPacketConnection) Forward(target *UPacketConnection) {
|
|
||||||
pc.DataSize = 0
|
|
||||||
pc.IsLoadHeader = false
|
|
||||||
for !pc.IsLoadHeader {
|
|
||||||
data, err := pc.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("read header line error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = target.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("write header line error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pc.DataSize == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data := make([]byte, 1024)
|
|
||||||
for pc.DataSize > 0 {
|
|
||||||
size := min(pc.DataSize, 1024)
|
|
||||||
n, err := pc.Read(data, 0, size)
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("read body error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pc.DataSize -= n
|
|
||||||
zlog.Infof("read body %d %s", n, data[:n])
|
|
||||||
_, err = target.Write(data[:n])
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("write body error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (pc *UPacketConnection) Close() error {
|
|
||||||
err := pc.Conn.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
func (pc *UPacketConnection) ForwardError(err error) {
|
|
||||||
pc.DataSize = 0
|
|
||||||
pc.IsLoadHeader = false
|
|
||||||
zlog.Infof("forward error: ", err.Error())
|
|
||||||
for !pc.IsLoadHeader {
|
|
||||||
_, err := pc.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("read header line error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for pc.DataSize > 0 {
|
|
||||||
data := make([]byte, 1024)
|
|
||||||
size := min(pc.DataSize, 1024)
|
|
||||||
n, err := pc.Read(data, 0, size)
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("Read body error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pc.DataSize -= n
|
|
||||||
}
|
|
||||||
err = pc.WriteError(err)
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("write error http error: ", err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
package proxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
func min(a int, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
type UReader struct {
|
|
||||||
io io.Reader
|
|
||||||
buf []byte
|
|
||||||
r, w int
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewReader(io io.Reader) *UReader {
|
|
||||||
return &UReader{
|
|
||||||
io: io,
|
|
||||||
buf: make([]byte, 4096),
|
|
||||||
r: 0,
|
|
||||||
w: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (b *UReader) Read(data []byte, s int, e int) (int, error) {
|
|
||||||
n := e - s
|
|
||||||
rn := 0
|
|
||||||
for rn < n {
|
|
||||||
d := min(b.w-b.r, n-rn)
|
|
||||||
if d > 0 {
|
|
||||||
copy(data[s+rn:s+rn+d], b.buf[b.r:b.r+d])
|
|
||||||
b.r += d
|
|
||||||
rn += d
|
|
||||||
if rn >= n {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err := b.fill()
|
|
||||||
if err != nil {
|
|
||||||
return rn, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rn, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
func (b *UReader) ReadLine() ([]byte, error) {
|
|
||||||
line, err := b.ReadSlice('\n')
|
|
||||||
return line, err
|
|
||||||
}
|
|
||||||
func (b *UReader) ReadSlice(delim byte) ([]byte, error) {
|
|
||||||
s := 0 // search start index
|
|
||||||
for {
|
|
||||||
// Search buffer.
|
|
||||||
if i := bytes.IndexByte(b.buf[b.r+s:b.w], delim); i >= 0 {
|
|
||||||
i += s + 1
|
|
||||||
b.r += i
|
|
||||||
return b.buf[b.r-i : b.r], nil
|
|
||||||
}
|
|
||||||
err := b.fill()
|
|
||||||
if err != nil {
|
|
||||||
return b.buf[b.r:], err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (b *UReader) fill() error {
|
|
||||||
d := b.w - b.r
|
|
||||||
if d >= len(b.buf) {
|
|
||||||
b.r = 0
|
|
||||||
b.w = 0
|
|
||||||
return ErrBufferFull
|
|
||||||
}
|
|
||||||
// Slide existing data to beginning.
|
|
||||||
if b.r > 0 {
|
|
||||||
copy(b.buf, b.buf[b.r:b.w])
|
|
||||||
b.w -= b.r
|
|
||||||
b.r = 0
|
|
||||||
}
|
|
||||||
// Read new data: try a limited number of times.
|
|
||||||
n, err := b.io.Read(b.buf[b.w:])
|
|
||||||
b.w += n
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
func (b *UReader) Clear() {
|
|
||||||
b.r = 0
|
|
||||||
b.w = 0
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
package proxy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UHttpRequest struct {
|
|
||||||
Conn net.Conn
|
|
||||||
io *UReader
|
|
||||||
IsLoadHeader bool
|
|
||||||
DataSize int
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHttpRequest(conn net.Conn) *UHttpRequest {
|
|
||||||
return &UHttpRequest{
|
|
||||||
Conn: conn,
|
|
||||||
io: NewReader(conn),
|
|
||||||
IsLoadHeader: false,
|
|
||||||
DataSize: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) ReadLine() ([]byte, error) {
|
|
||||||
line, err := req.io.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
return line, err
|
|
||||||
}
|
|
||||||
if !req.IsLoadHeader && bytes.Equal(line, []byte("\r\n")) {
|
|
||||||
req.IsLoadHeader = true
|
|
||||||
}
|
|
||||||
if !req.IsLoadHeader {
|
|
||||||
k, v, ok := bytes.Cut(line, []byte(":"))
|
|
||||||
if !ok {
|
|
||||||
return line, err
|
|
||||||
}
|
|
||||||
if bytes.Equal(k, []byte("Content-Length")) {
|
|
||||||
nv := strings.Trim(string(v), " \r\n")
|
|
||||||
n, err := strconv.ParseUint(nv, 10, 63)
|
|
||||||
if err != nil {
|
|
||||||
return line, err
|
|
||||||
}
|
|
||||||
req.DataSize = int(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line, err
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) Read(data []byte, s int, e int) (int, error) {
|
|
||||||
return req.io.Read(data, s, e)
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) Write(data []byte) (int, error) {
|
|
||||||
return req.Conn.Write(data)
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) WriteError(err error) error {
|
|
||||||
return req.WriteHttp([]byte("HTTP/1.1 200 OK\r\n"), []byte(err.Error()))
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) WriteHttp(header []byte, data []byte) error {
|
|
||||||
_, err := req.Write(header)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var bufBody bytes.Buffer
|
|
||||||
bufBody.WriteString("{\n \"error\" : \"")
|
|
||||||
bufBody.WriteString(string(data))
|
|
||||||
bufBody.WriteString("\"\n}")
|
|
||||||
var bufWrap bytes.Buffer
|
|
||||||
bufWrap.WriteString("Content-Length:")
|
|
||||||
bufWrap.WriteString(strconv.Itoa(bufBody.Len()))
|
|
||||||
bufWrap.WriteString("\r\n\r\n")
|
|
||||||
_, err = req.Write(bufWrap.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = req.Write(bufBody.Bytes())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
func (req *UHttpRequest) Clear() {
|
|
||||||
req.io.Clear()
|
|
||||||
}
|
|
||||||
@ -6,66 +6,85 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UServerProxy struct {
|
type UServerProxy struct {
|
||||||
AnkiConn *UPacketConnection
|
RemoteMap map[uint32]*PacketConnect
|
||||||
|
ClientMap map[uint32]*PacketConnect
|
||||||
|
RemoteConn *PacketConnect
|
||||||
|
MessageQueue chan uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerProxy() *UServerProxy {
|
func NewServerProxy() *UServerProxy {
|
||||||
return &UServerProxy{}
|
return &UServerProxy{
|
||||||
|
RemoteMap: make(map[uint32]*PacketConnect),
|
||||||
|
ClientMap: make(map[uint32]*PacketConnect),
|
||||||
|
MessageQueue: make(chan uint32, 32),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func (server *UServerProxy) NewTcpConnection(client *UPacketConnection) {
|
func (server *UServerProxy) NewTcpConnection(client *PacketConnect) {
|
||||||
defer func() {
|
data := client.ReadHeader()
|
||||||
if client == server.AnkiConn {
|
if string(data[:4]) == "anki" {
|
||||||
|
id := packetEndian.Uint32(data[4:8])
|
||||||
|
client.SetRemote("remote", id)
|
||||||
|
if id == RemoteID {
|
||||||
|
if server.RemoteConn != nil && server.RemoteConn != client {
|
||||||
|
_ = server.RemoteConn.Close()
|
||||||
|
}
|
||||||
|
server.RemoteConn = client
|
||||||
|
zlog.Infof("rcv %d %s", id, client.Name())
|
||||||
|
} else {
|
||||||
|
server.RemoteMap[id] = client
|
||||||
|
server.MessageQueue <- id
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := client.Close()
|
if server.RemoteConn == nil {
|
||||||
if err != nil {
|
return
|
||||||
zlog.Error("close client error: ", err)
|
|
||||||
}
|
}
|
||||||
|
id := IncID()
|
||||||
|
server.RemoteConn.WriteHeader(id)
|
||||||
|
server.ClientMap[id] = client
|
||||||
|
zlog.Infof("%d %s", id, data)
|
||||||
|
}
|
||||||
|
func (server *UServerProxy) MessageLoop() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case mid := <-server.MessageQueue:
|
||||||
|
remote := server.RemoteMap[mid]
|
||||||
|
client := server.ClientMap[mid]
|
||||||
|
if client == nil || remote == nil {
|
||||||
|
server.RemoteMap[mid] = nil
|
||||||
|
server.ClientMap[mid] = nil
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
client.Forward(remote, HeaderSize)
|
||||||
|
server.ClientMap[mid] = nil
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
remote.Forward(client, 0)
|
||||||
|
server.RemoteMap[mid] = nil
|
||||||
}()
|
}()
|
||||||
data := []byte("anki0000")
|
|
||||||
_, err := client.Read(data, 4, 8)
|
|
||||||
if err != nil {
|
|
||||||
zlog.Error("read client error: ", client.Conn.RemoteAddr(), err.Error())
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
zlog.Infof("new client %s %s", client.Conn.RemoteAddr(), data[4:])
|
|
||||||
if string(data[4:]) == "anki" {
|
|
||||||
server.AnkiConn = client
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if server.AnkiConn == nil {
|
|
||||||
client.ForwardError(ErrNoAnkiProxy)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = server.AnkiConn.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
client.Forward(server.AnkiConn)
|
|
||||||
server.AnkiConn.Forward(client)
|
|
||||||
}
|
}
|
||||||
func (server *UServerProxy) ServeTCP(listenAddr string) error {
|
func (server *UServerProxy) ServeTCP(listenAddr string) error {
|
||||||
// listenAddr 只能填端口号
|
// listenAddr 只能填端口号
|
||||||
ln, err := net.Listen("tcp", listenAddr)
|
ln, err := net.Listen("tcp", listenAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Error("listen server error: ", err.Error(), listenAddr)
|
zlog.Error("listen error:", err.Error())
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
zlog.Infof("listen server %s", listenAddr)
|
zlog.Infof("listen %s", ln.Addr())
|
||||||
defer func(ln net.Listener) {
|
defer func(ln net.Listener) {
|
||||||
err := ln.Close()
|
err := ln.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Error("close listen server error: ", err.Error(), listenAddr)
|
zlog.Error("close client error: ", err.Error())
|
||||||
}
|
}
|
||||||
}(ln)
|
}(ln)
|
||||||
|
go server.MessageLoop()
|
||||||
for {
|
for {
|
||||||
conn, err := ln.Accept()
|
conn, err := ln.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if IsTimeoutError(err) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go server.NewTcpConnection(NewPacketConnection(conn))
|
server.NewTcpConnection(NewPacketConnect(conn, "client"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +0,0 @@
|
|||||||
package proxy
|
|
||||||
|
|
||||||
type timeoutError interface {
|
|
||||||
Timeout() bool // Is it a timeout error
|
|
||||||
}
|
|
||||||
|
|
||||||
// fundamental is an error that has a message and a stack, but no caller.
|
|
||||||
type errors struct {
|
|
||||||
msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e errors) Error() string {
|
|
||||||
return e.msg
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewError(msg string) error {
|
|
||||||
return errors{msg: msg}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrBufferFull = NewError("read: buffer full")
|
|
||||||
ErrNoAnkiProxy = NewError("anki: no client proxy connect")
|
|
||||||
)
|
|
||||||
var (
|
|
||||||
ServerAddr = ":8765"
|
|
||||||
RemoteServerAddr = "175.24.226.114" + ServerAddr
|
|
||||||
ClientAddr = "127.0.0.1:8765"
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsTimeoutError checks if the error is a timeout error
|
|
||||||
func IsTimeoutError(err error) bool {
|
|
||||||
if err == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
ne, ok := err.(timeoutError)
|
|
||||||
return ok && ne.Timeout()
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
@ -1,155 +0,0 @@
|
|||||||
{
|
|
||||||
"cells": [
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 13,
|
|
||||||
"id": "1664172b",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"from http2 import *\n",
|
|
||||||
"class AnkiClient(Http):\n",
|
|
||||||
" def __init__(self):\n",
|
|
||||||
" Http.__init__(self)\n",
|
|
||||||
" self.url = 'http://127.0.0.1:8764'\n",
|
|
||||||
" self.version = None\n",
|
|
||||||
" def api(self, data):\n",
|
|
||||||
" print(data)\n",
|
|
||||||
" data = json.dumps(data)\n",
|
|
||||||
" res = self._post(self.url, data)\n",
|
|
||||||
" return res\n",
|
|
||||||
" def make_version(self):\n",
|
|
||||||
" self.version = self.api({\"action\":\"version\"})\n",
|
|
||||||
" return self.version\n",
|
|
||||||
" def deckNames(self):\n",
|
|
||||||
" return self.api({\"action\":\"deckNames\"})\n",
|
|
||||||
" def modelNames(self):\n",
|
|
||||||
" return self.api({\"action\":\"modelNames\"})\n",
|
|
||||||
" def modelFieldNames(self, modelName):\n",
|
|
||||||
" return self.api({\"action\":\"modelFieldNames\", \"params\" :{\"modelName\" : modelName}})\n",
|
|
||||||
" def addNote(self, note):\n",
|
|
||||||
" return self.api({\"action\":\"addNote\", \"params\" : {\"note\": note}})"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 14,
|
|
||||||
"id": "ee987c62",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"anki = AnkiClient()"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 16,
|
|
||||||
"id": "58e77a6b",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"{'action': 'deckNames'}\n",
|
|
||||||
"_post http://127.0.0.1:8764\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"b'[\"Git\", \"\\\\u53e5\\\\u7d20\", \"\\\\u793a\\\\u4f8b\\\\u724c\\\\u7ec4\", \"\\\\u7cfb\\\\u7edf\\\\u9ed8\\\\u8ba4\", \"\\\\u82f1\\\\u8bed\", \"\\\\u8d56\\\\u4e16\\\\u96c4\\\\u97f3\\\\u6807\", \"\\\\u97f3\\\\u6807\"]'"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 16,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"t = anki.deckNames()\n",
|
|
||||||
"t"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 18,
|
|
||||||
"id": "c3b5b237",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"b'{\\n error = \"anki: no client proxy connect\"\\n}'"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 18,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"t"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 15,
|
|
||||||
"id": "53bd0e19",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"b = b'{\\n error = \"anki: no client proxy connect\"\\n}'"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 16,
|
|
||||||
"id": "9d89217c",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"{\n",
|
|
||||||
" error = \"anki: no client proxy connect\"\n",
|
|
||||||
"}\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"print(b.decode())"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": null,
|
|
||||||
"id": "203e9f90",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"kernelspec": {
|
|
||||||
"display_name": "Python 3 (ipykernel)",
|
|
||||||
"language": "python",
|
|
||||||
"name": "python3"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"codemirror_mode": {
|
|
||||||
"name": "ipython",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"file_extension": ".py",
|
|
||||||
"mimetype": "text/x-python",
|
|
||||||
"name": "python",
|
|
||||||
"nbconvert_exporter": "python",
|
|
||||||
"pygments_lexer": "ipython3",
|
|
||||||
"version": "3.9.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 5
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
import inspect
|
|
||||||
import json, requests , zlib
|
|
||||||
from functools import wraps
|
|
||||||
from http.cookiejar import LWPCookieJar
|
|
||||||
import http.cookiejar as cookielib
|
|
||||||
default_headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\
|
|
||||||
/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
|
|
||||||
class Session(requests.Session):
|
|
||||||
def __init__(self, headers={}, cookie_file=None):
|
|
||||||
requests.Session.__init__(self)
|
|
||||||
if cookie_file:
|
|
||||||
self.cookies = LWPCookieJar(filename = cookie_file)
|
|
||||||
self.cookies.load(ignore_discard = True)
|
|
||||||
self.update(headers)
|
|
||||||
self.auth = ('user', 'pass')
|
|
||||||
def save(self, filename = None):
|
|
||||||
self.cookies.save()
|
|
||||||
def update(self, headers):
|
|
||||||
self.headers.update(headers)
|
|
||||||
def http_error(code):
|
|
||||||
def _with(func):
|
|
||||||
@wraps(func)
|
|
||||||
def _deco(self, url):
|
|
||||||
return func(self, url)
|
|
||||||
_deco.__error_code__ = code
|
|
||||||
return _deco
|
|
||||||
return _with
|
|
||||||
class Http():
|
|
||||||
def __init__(self, headers = default_headers, session = None):
|
|
||||||
session = session or Session()
|
|
||||||
session.update(headers)
|
|
||||||
self.session = session
|
|
||||||
self._type = 'str'
|
|
||||||
self._error_dict = self._get_error_dict()
|
|
||||||
def _gets(self, url, data = None):
|
|
||||||
res = self.session.get(url, params = data)
|
|
||||||
self._error(res, url)
|
|
||||||
return self._res_data(res, self._type)
|
|
||||||
def _posts(self, url, data = None):
|
|
||||||
res = self.session.get(url, params = data)
|
|
||||||
self._error(res, url)
|
|
||||||
return self._res_data(res, self._type)
|
|
||||||
def _get(self, url, data = None):
|
|
||||||
print("_get", url)
|
|
||||||
res = requests.get(url, params = data, headers = self.session.headers)
|
|
||||||
self._error(res, url)
|
|
||||||
return self._res_data(res, self._type)
|
|
||||||
def _post(self, url, data):
|
|
||||||
print("_post", url)
|
|
||||||
res = requests.get(url, data = data, headers = self.session.headers)
|
|
||||||
self._error(res, url)
|
|
||||||
return self._res_data(res, self._type)
|
|
||||||
def _get_error_dict(self):
|
|
||||||
error_dict = {}
|
|
||||||
methods = inspect.getmembers(self, predicate=inspect.ismethod)
|
|
||||||
for method in methods:
|
|
||||||
error_code = getattr(method[1], '__error_code__', None)
|
|
||||||
if error_code:
|
|
||||||
error_dict[error_code] = method[1]
|
|
||||||
return error_dict
|
|
||||||
def _error(self, res, url):
|
|
||||||
code = res.status_code
|
|
||||||
if code == 200:
|
|
||||||
return
|
|
||||||
print(res.content)
|
|
||||||
if code in self._error_dict:
|
|
||||||
self._error_dict[code](url)
|
|
||||||
return
|
|
||||||
raise RuntimeError(code + '- unknown error ' + url)
|
|
||||||
@http_error(403)
|
|
||||||
def _error_403(self, url):
|
|
||||||
raise RuntimeError('error:403 - Forbidden ' + url)
|
|
||||||
@http_error(404)
|
|
||||||
def _error_404(self, url):
|
|
||||||
raise RuntimeError('error:404 - Not Found ' + url)
|
|
||||||
def _res_data(self, res, _type):
|
|
||||||
# encoding = None
|
|
||||||
# if 'Content-Encoding' in res.headers:
|
|
||||||
# encoding = res.headers['Content-Encoding']
|
|
||||||
# if encoding == 'gzip':
|
|
||||||
# res.content = zlib.decompress(res.content, 16 + zlib.MAX_WBITS)
|
|
||||||
# if _type == 'json':
|
|
||||||
# return json.loads(res.content)
|
|
||||||
return res.content
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
{
|
|
||||||
"cells": [
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 1,
|
|
||||||
"id": "3f40720a",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": [
|
|
||||||
"import requests"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": 5,
|
|
||||||
"id": "d2986616",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [
|
|
||||||
{
|
|
||||||
"data": {
|
|
||||||
"text/plain": [
|
|
||||||
"<Response [200]>"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"execution_count": 5,
|
|
||||||
"metadata": {},
|
|
||||||
"output_type": "execute_result"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
|
||||||
"requests.get(\"http://localhost:8080/\",data = \"helloworld\")"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"cell_type": "code",
|
|
||||||
"execution_count": null,
|
|
||||||
"id": "7f2dd59b",
|
|
||||||
"metadata": {},
|
|
||||||
"outputs": [],
|
|
||||||
"source": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"metadata": {
|
|
||||||
"kernelspec": {
|
|
||||||
"display_name": "Python 3 (ipykernel)",
|
|
||||||
"language": "python",
|
|
||||||
"name": "python3"
|
|
||||||
},
|
|
||||||
"language_info": {
|
|
||||||
"codemirror_mode": {
|
|
||||||
"name": "ipython",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"file_extension": ".py",
|
|
||||||
"mimetype": "text/x-python",
|
|
||||||
"name": "python",
|
|
||||||
"nbconvert_exporter": "python",
|
|
||||||
"pygments_lexer": "ipython3",
|
|
||||||
"version": "3.9.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nbformat": 4,
|
|
||||||
"nbformat_minor": 5
|
|
||||||
}
|
|
||||||
@ -1,14 +1,41 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"strconv"
|
||||||
"zproxy/proxy"
|
"zproxy/proxy"
|
||||||
"zproxy/zlog"
|
"zproxy/zlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//ServerAddr = "127.0.0.1"
|
||||||
|
//ServerPort = 8765
|
||||||
|
|
||||||
|
ServerAddr = "175.24.226.114"
|
||||||
|
ServerPort = 7860
|
||||||
|
|
||||||
|
RemoteAddr = "127.0.0.1"
|
||||||
|
RemotePort = 7860
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
client := proxy.NewClientProxy()
|
client := &proxy.UClientProxy{}
|
||||||
err := client.ServeTCP(proxy.RemoteServerAddr, proxy.ClientAddr)
|
err := client.ServeTCP(ServerAddr+":"+strconv.Itoa(ServerPort), RemoteAddr+":"+strconv.Itoa(RemotePort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Error("exist client remote proxy: ", err.Error())
|
zlog.Error("exist server proxy: ", err.Error())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func init() {
|
||||||
|
_addr := flag.String("addr", ServerAddr, "server addr")
|
||||||
|
_port := flag.Int("port", ServerPort, "listen port")
|
||||||
|
|
||||||
|
remoteAddr := flag.String("remote_addr", RemoteAddr, "server addr")
|
||||||
|
remotePort := flag.Int("remote_port", RemotePort, "listen port")
|
||||||
|
flag.Parse()
|
||||||
|
ServerAddr = *_addr
|
||||||
|
ServerPort = *_port
|
||||||
|
|
||||||
|
RemoteAddr = *remoteAddr
|
||||||
|
RemotePort = *remotePort
|
||||||
|
}
|
||||||
|
|||||||
@ -1,15 +1,30 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
|
"strconv"
|
||||||
"zproxy/proxy"
|
"zproxy/proxy"
|
||||||
"zproxy/zlog"
|
"zproxy/zlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
//这里只有本地服务器可以访问,传0.0.0.0或空则支持所有连接
|
||||||
|
ServerAddr = "127.0.0.1"
|
||||||
|
ServerPort = 8765
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
server := proxy.NewServerProxy()
|
server := proxy.NewServerProxy()
|
||||||
err := server.ServeTCP(proxy.ServerAddr)
|
err := server.ServeTCP(ServerAddr + ":" + strconv.Itoa(ServerPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zlog.Error("exist server proxy: ", err.Error())
|
zlog.Error("exist server proxy: ", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func init() {
|
||||||
|
_addr := flag.String("addr", ServerAddr, "server addr")
|
||||||
|
_port := flag.Int("port", ServerPort, "listen port")
|
||||||
|
flag.Parse()
|
||||||
|
ServerAddr = *_addr
|
||||||
|
ServerPort = *_port
|
||||||
|
}
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "net/http"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(200)
|
|
||||||
w.Write([]byte("ok"))
|
|
||||||
})
|
|
||||||
http.ListenAndServe(":8080", nil)
|
|
||||||
}
|
|
||||||
BIN
server.exe
Normal file
BIN
server.exe
Normal file
Binary file not shown.
70
zlog/test
70
zlog/test
@ -1,70 +0,0 @@
|
|||||||
from .http import *
|
|
||||||
import json,functools
|
|
||||||
class util:
|
|
||||||
def api(func):
|
|
||||||
@functools.wraps(func)
|
|
||||||
def wrapper(self,**kwargs):
|
|
||||||
self._api({"params" : kwargs , "action":func.__name__ })
|
|
||||||
self.res = func(self, **kwargs) or self.res
|
|
||||||
return self.res
|
|
||||||
return wrapper
|
|
||||||
class AnkiClient(Http):
|
|
||||||
util = util
|
|
||||||
def __init__(self, url = None):
|
|
||||||
Http.__init__(self)
|
|
||||||
self.url = url or 'http://127.0.0.1:8765'
|
|
||||||
self._version = None
|
|
||||||
self.res = None
|
|
||||||
def _api(self, data):
|
|
||||||
if self._version and type(self._version) == int:
|
|
||||||
data["version"] = self._version
|
|
||||||
data = json.dumps(data)
|
|
||||||
res = self._post(self.url, data)
|
|
||||||
self.res = json.loads(res)
|
|
||||||
return self.res
|
|
||||||
@util.api
|
|
||||||
def version(self):
|
|
||||||
self._version = self.res
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def deckNames(self):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def modelNames(self):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def modelFieldNames(self, modelName = "示例牌组"):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def modelFieldDescriptions(self, modelName = "示例牌组"):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def modelTemplates(self, modelName = "示例牌组"):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def addNote(self, note = {}):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def findNotes(self, query = "note:basic"):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def updateNote(self, note = {}):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def updateNoteTags(self, note = {}, tags = []):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def notesInfo(self, notes = []):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def findCards(self, query = "deck:示例牌组"):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def cardsInfo(self, cards = []):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def updateNoteFields(self, note = {}):
|
|
||||||
pass
|
|
||||||
@util.api
|
|
||||||
def createModel(self, modelName = "basic", inOrderFields = {}, cardTemplates = {}, css = None, isCloze = False):
|
|
||||||
pass
|
|
||||||
Loading…
Reference in New Issue
Block a user