code refactoring
@ -1,88 +0,0 @@
|
||||
package addon
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/lqqyt2423/go-mitmproxy/connection"
|
||||
"github.com/lqqyt2423/go-mitmproxy/flow"
|
||||
_log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var log = _log.WithField("at", "addon")
|
||||
|
||||
type Addon interface {
|
||||
// A client has connected to mitmproxy. Note that a connection can correspond to multiple HTTP requests.
|
||||
ClientConnected(*connection.Client)
|
||||
|
||||
// A client connection has been closed (either by us or the client).
|
||||
ClientDisconnected(*connection.Client)
|
||||
|
||||
// Mitmproxy has connected to a server.
|
||||
ServerConnected(*flow.ConnContext)
|
||||
|
||||
// A server connection has been closed (either by us or the server).
|
||||
ServerDisconnected(*flow.ConnContext)
|
||||
|
||||
// HTTP request headers were successfully read. At this point, the body is empty.
|
||||
Requestheaders(*flow.Flow)
|
||||
|
||||
// The full HTTP request has been read.
|
||||
Request(*flow.Flow)
|
||||
|
||||
// HTTP response headers were successfully read. At this point, the body is empty.
|
||||
Responseheaders(*flow.Flow)
|
||||
|
||||
// The full HTTP response has been read.
|
||||
Response(*flow.Flow)
|
||||
}
|
||||
|
||||
// Base do nothing
|
||||
type Base struct{}
|
||||
|
||||
func (addon *Base) ClientConnected(*connection.Client) {}
|
||||
func (addon *Base) ClientDisconnected(*connection.Client) {}
|
||||
func (addon *Base) ServerConnected(*flow.ConnContext) {}
|
||||
func (addon *Base) ServerDisconnected(*flow.ConnContext) {}
|
||||
|
||||
func (addon *Base) Requestheaders(*flow.Flow) {}
|
||||
func (addon *Base) Request(*flow.Flow) {}
|
||||
func (addon *Base) Responseheaders(*flow.Flow) {}
|
||||
func (addon *Base) Response(*flow.Flow) {}
|
||||
|
||||
// Log log http record
|
||||
type Log struct {
|
||||
Base
|
||||
}
|
||||
|
||||
func (addon *Log) ClientConnected(client *connection.Client) {
|
||||
log.Infof("%v client connect\n", client.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *Log) ClientDisconnected(client *connection.Client) {
|
||||
log.Infof("%v client disconnect\n", client.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *Log) ServerConnected(connCtx *flow.ConnContext) {
|
||||
log.Infof("%v server connect %v (%v)\n", connCtx.Client.Conn.RemoteAddr(), connCtx.Server.Address, connCtx.Server.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *Log) ServerDisconnected(connCtx *flow.ConnContext) {
|
||||
log.Infof("%v server disconnect %v (%v)\n", connCtx.Client.Conn.RemoteAddr(), connCtx.Server.Address, connCtx.Server.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *Log) Requestheaders(f *flow.Flow) {
|
||||
log := log.WithField("in", "Log")
|
||||
start := time.Now()
|
||||
go func() {
|
||||
<-f.Done()
|
||||
var StatusCode int
|
||||
if f.Response != nil {
|
||||
StatusCode = f.Response.StatusCode
|
||||
}
|
||||
var contentLen int
|
||||
if f.Response != nil && f.Response.Body != nil {
|
||||
contentLen = len(f.Response.Body)
|
||||
}
|
||||
log.Infof("%v %v %v %v %v - %v ms\n", f.ConnContext.Client.Conn.RemoteAddr(), f.Request.Method, f.Request.URL.String(), StatusCode, contentLen, time.Since(start).Milliseconds())
|
||||
}()
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
package addon
|
||||
|
||||
import "github.com/lqqyt2423/go-mitmproxy/flow"
|
||||
import "github.com/lqqyt2423/go-mitmproxy/proxy"
|
||||
|
||||
// decode content-encoding then respond to client
|
||||
|
||||
type Decoder struct {
|
||||
Base
|
||||
proxy.BaseAddon
|
||||
}
|
||||
|
||||
func (d *Decoder) Response(f *flow.Flow) {
|
||||
func (d *Decoder) Response(f *proxy.Flow) {
|
||||
f.Response.ReplaceToDecodedBody()
|
||||
}
|
||||
|
@ -1,96 +0,0 @@
|
||||
package flowmapper
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/lqqyt2423/go-mitmproxy/addon"
|
||||
"github.com/lqqyt2423/go-mitmproxy/flow"
|
||||
_log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var log = _log.WithField("at", "changeflow addon")
|
||||
var httpsRegexp = regexp.MustCompile(`^https://`)
|
||||
|
||||
type Mapper struct {
|
||||
addon.Base
|
||||
reqResMap map[string]*flow.Response
|
||||
}
|
||||
|
||||
func NewMapper(dirname string) *Mapper {
|
||||
infos, err := ioutil.ReadDir(dirname)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
filenames := make([]string, 0)
|
||||
|
||||
for _, info := range infos {
|
||||
if info.IsDir() {
|
||||
continue
|
||||
}
|
||||
if !strings.HasSuffix(info.Name(), ".map.txt") {
|
||||
continue
|
||||
}
|
||||
|
||||
filenames = append(filenames, filepath.Join(dirname, info.Name()))
|
||||
}
|
||||
|
||||
if len(filenames) == 0 {
|
||||
return &Mapper{
|
||||
reqResMap: make(map[string]*flow.Response),
|
||||
}
|
||||
}
|
||||
|
||||
ch := make(chan interface{}, len(filenames))
|
||||
for _, filename := range filenames {
|
||||
go func(filename string, ch chan<- interface{}) {
|
||||
f, err := ParseFlowFromFile(filename)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
ch <- f
|
||||
}(filename, ch)
|
||||
}
|
||||
|
||||
reqResMap := make(map[string]*flow.Response)
|
||||
|
||||
for i := 0; i < len(filenames); i++ {
|
||||
flowOrErr := <-ch
|
||||
if f, ok := flowOrErr.(*flow.Flow); ok {
|
||||
key := buildReqKey(f.Request)
|
||||
log.Infof("add request mapper: %v", key)
|
||||
reqResMap[key] = f.Response
|
||||
}
|
||||
}
|
||||
|
||||
return &Mapper{
|
||||
reqResMap: reqResMap,
|
||||
}
|
||||
}
|
||||
|
||||
func ParseFlowFromFile(filename string) (*flow.Flow, error) {
|
||||
p, err := NewParserFromFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return p.Parse()
|
||||
}
|
||||
|
||||
func (c *Mapper) Request(f *flow.Flow) {
|
||||
key := buildReqKey(f.Request)
|
||||
if resp, ok := c.reqResMap[key]; ok {
|
||||
f.Response = resp
|
||||
}
|
||||
}
|
||||
|
||||
func buildReqKey(req *flow.Request) string {
|
||||
url := req.URL.String()
|
||||
url = httpsRegexp.ReplaceAllString(url, "http://")
|
||||
key := req.Method + " " + url
|
||||
return key
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
package connection
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Id uuid.UUID
|
||||
Conn net.Conn
|
||||
Tls bool
|
||||
}
|
||||
|
||||
func NewClient(c net.Conn) *Client {
|
||||
return &Client{
|
||||
Id: uuid.NewV4(),
|
||||
Conn: c,
|
||||
Tls: false,
|
||||
}
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
Id uuid.UUID
|
||||
Conn net.Conn
|
||||
Client *http.Client
|
||||
Address string
|
||||
}
|
||||
|
||||
func NewServer() *Server {
|
||||
return &Server{
|
||||
Id: uuid.NewV4(),
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/lqqyt2423/go-mitmproxy/connection"
|
||||
)
|
||||
|
||||
var ConnContextKey = new(struct{})
|
||||
|
||||
type ConnContext struct {
|
||||
Client *connection.Client
|
||||
Server *connection.Server
|
||||
}
|
||||
|
||||
func NewConnContext(c net.Conn) *ConnContext {
|
||||
client := connection.NewClient(c)
|
||||
return &ConnContext{
|
||||
Client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (connCtx *ConnContext) InitHttpServer(sslInsecure bool, connWrap func(net.Conn) net.Conn, whenConnected func()) {
|
||||
if connCtx.Server != nil {
|
||||
return
|
||||
}
|
||||
if connCtx.Client.Tls {
|
||||
return
|
||||
}
|
||||
|
||||
server := connection.NewServer()
|
||||
server.Client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
|
||||
// todo: change here
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
c, err := (&net.Dialer{
|
||||
// Timeout: 30 * time.Second,
|
||||
// KeepAlive: 30 * time.Second,
|
||||
}).DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cw := connWrap(c)
|
||||
server.Conn = cw
|
||||
server.Address = addr
|
||||
defer whenConnected()
|
||||
return cw, nil
|
||||
},
|
||||
ForceAttemptHTTP2: false, // disable http2
|
||||
|
||||
DisableCompression: true, // To get the original response from the server, set Transport.DisableCompression to true.
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: sslInsecure,
|
||||
KeyLogWriter: GetTlsKeyLogWriter(),
|
||||
},
|
||||
},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
// 禁止自动重定向
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
connCtx.Server = server
|
||||
}
|
||||
|
||||
func (connCtx *ConnContext) InitHttpsServer(sslInsecure bool, connWrap func(net.Conn) net.Conn, whenConnected func()) {
|
||||
if connCtx.Server != nil {
|
||||
return
|
||||
}
|
||||
if !connCtx.Client.Tls {
|
||||
return
|
||||
}
|
||||
|
||||
server := connection.NewServer()
|
||||
server.Client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
|
||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
log.Debugln("in https DialTLSContext")
|
||||
|
||||
plainConn, err := (&net.Dialer{}).DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cw := connWrap(plainConn)
|
||||
server.Conn = cw
|
||||
server.Address = addr
|
||||
whenConnected()
|
||||
|
||||
firstTLSHost, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := &tls.Config{
|
||||
InsecureSkipVerify: sslInsecure,
|
||||
KeyLogWriter: GetTlsKeyLogWriter(),
|
||||
ServerName: firstTLSHost,
|
||||
}
|
||||
tlsConn := tls.Client(cw, cfg)
|
||||
return tlsConn, nil
|
||||
},
|
||||
ForceAttemptHTTP2: false, // disable http2
|
||||
|
||||
DisableCompression: true, // To get the original response from the server, set Transport.DisableCompression to true.
|
||||
},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
// 禁止自动重定向
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
connCtx.Server = server
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package flow
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Wireshark 解析 https 设置
|
||||
var tlsKeyLogWriter io.Writer
|
||||
var tlsKeyLogOnce sync.Once
|
||||
|
||||
func GetTlsKeyLogWriter() io.Writer {
|
||||
tlsKeyLogOnce.Do(func() {
|
||||
logfile := os.Getenv("SSLKEYLOGFILE")
|
||||
if logfile == "" {
|
||||
return
|
||||
}
|
||||
|
||||
writer, err := os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
log.WithField("in", "GetTlsKeyLogWriter").Debug(err)
|
||||
return
|
||||
}
|
||||
|
||||
tlsKeyLogWriter = writer
|
||||
})
|
||||
return tlsKeyLogWriter
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Addon interface {
|
||||
// A client has connected to mitmproxy. Note that a connection can correspond to multiple HTTP requests.
|
||||
ClientConnected(*ClientConn)
|
||||
|
||||
// A client connection has been closed (either by us or the client).
|
||||
ClientDisconnected(*ClientConn)
|
||||
|
||||
// Mitmproxy has connected to a server.
|
||||
ServerConnected(*ConnContext)
|
||||
|
||||
// A server connection has been closed (either by us or the server).
|
||||
ServerDisconnected(*ConnContext)
|
||||
|
||||
// HTTP request headers were successfully read. At this point, the body is empty.
|
||||
Requestheaders(*Flow)
|
||||
|
||||
// The full HTTP request has been read.
|
||||
Request(*Flow)
|
||||
|
||||
// HTTP response headers were successfully read. At this point, the body is empty.
|
||||
Responseheaders(*Flow)
|
||||
|
||||
// The full HTTP response has been read.
|
||||
Response(*Flow)
|
||||
}
|
||||
|
||||
// BaseAddon do nothing
|
||||
type BaseAddon struct{}
|
||||
|
||||
func (addon *BaseAddon) ClientConnected(*ClientConn) {}
|
||||
func (addon *BaseAddon) ClientDisconnected(*ClientConn) {}
|
||||
func (addon *BaseAddon) ServerConnected(*ConnContext) {}
|
||||
func (addon *BaseAddon) ServerDisconnected(*ConnContext) {}
|
||||
|
||||
func (addon *BaseAddon) Requestheaders(*Flow) {}
|
||||
func (addon *BaseAddon) Request(*Flow) {}
|
||||
func (addon *BaseAddon) Responseheaders(*Flow) {}
|
||||
func (addon *BaseAddon) Response(*Flow) {}
|
||||
|
||||
// LogAddon log connection and flow
|
||||
type LogAddon struct {
|
||||
BaseAddon
|
||||
}
|
||||
|
||||
func (addon *LogAddon) ClientConnected(client *ClientConn) {
|
||||
log.Infof("%v client connect\n", client.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *LogAddon) ClientDisconnected(client *ClientConn) {
|
||||
log.Infof("%v client disconnect\n", client.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *LogAddon) ServerConnected(connCtx *ConnContext) {
|
||||
log.Infof("%v server connect %v (%v)\n", connCtx.ClientConn.Conn.RemoteAddr(), connCtx.ServerConn.Address, connCtx.ServerConn.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *LogAddon) ServerDisconnected(connCtx *ConnContext) {
|
||||
log.Infof("%v server disconnect %v (%v)\n", connCtx.ClientConn.Conn.RemoteAddr(), connCtx.ServerConn.Address, connCtx.ServerConn.Conn.RemoteAddr())
|
||||
}
|
||||
|
||||
func (addon *LogAddon) Requestheaders(f *Flow) {
|
||||
start := time.Now()
|
||||
go func() {
|
||||
<-f.Done()
|
||||
var StatusCode int
|
||||
if f.Response != nil {
|
||||
StatusCode = f.Response.StatusCode
|
||||
}
|
||||
var contentLen int
|
||||
if f.Response != nil && f.Response.Body != nil {
|
||||
contentLen = len(f.Response.Body)
|
||||
}
|
||||
log.Infof("%v %v %v %v %v - %v ms\n", f.ConnContext.ClientConn.Conn.RemoteAddr(), f.Request.Method, f.Request.URL.String(), StatusCode, contentLen, time.Since(start).Milliseconds())
|
||||
}()
|
||||
}
|
@ -0,0 +1,232 @@
|
||||
package proxy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
// client connection
|
||||
type ClientConn struct {
|
||||
Id uuid.UUID
|
||||
Conn net.Conn
|
||||
Tls bool
|
||||
}
|
||||
|
||||
func newClientConn(c net.Conn) *ClientConn {
|
||||
return &ClientConn{
|
||||
Id: uuid.NewV4(),
|
||||
Conn: c,
|
||||
Tls: false,
|
||||
}
|
||||
}
|
||||
|
||||
// server connection
|
||||
type ServerConn struct {
|
||||
Id uuid.UUID
|
||||
Address string
|
||||
Conn net.Conn
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func newServerConn() *ServerConn {
|
||||
return &ServerConn{
|
||||
Id: uuid.NewV4(),
|
||||
}
|
||||
}
|
||||
|
||||
// connection context ctx key
|
||||
var connContextKey = new(struct{})
|
||||
|
||||
// connection context
|
||||
type ConnContext struct {
|
||||
ClientConn *ClientConn
|
||||
ServerConn *ServerConn
|
||||
|
||||
proxy *Proxy
|
||||
}
|
||||
|
||||
func newConnContext(c net.Conn, proxy *Proxy) *ConnContext {
|
||||
clientConn := newClientConn(c)
|
||||
return &ConnContext{
|
||||
ClientConn: clientConn,
|
||||
proxy: proxy,
|
||||
}
|
||||
}
|
||||
|
||||
func (connCtx *ConnContext) InitHttpServerConn() {
|
||||
if connCtx.ServerConn != nil {
|
||||
return
|
||||
}
|
||||
if connCtx.ClientConn.Tls {
|
||||
return
|
||||
}
|
||||
|
||||
serverConn := newServerConn()
|
||||
serverConn.client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
c, err := (&net.Dialer{}).DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cw := &wrapServerConn{
|
||||
Conn: c,
|
||||
proxy: connCtx.proxy,
|
||||
connCtx: connCtx,
|
||||
}
|
||||
serverConn.Conn = cw
|
||||
serverConn.Address = addr
|
||||
defer func() {
|
||||
for _, addon := range connCtx.proxy.Addons {
|
||||
addon.ServerConnected(connCtx)
|
||||
}
|
||||
}()
|
||||
return cw, nil
|
||||
},
|
||||
ForceAttemptHTTP2: false, // disable http2
|
||||
DisableCompression: true, // To get the original response from the server, set Transport.DisableCompression to true.
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: connCtx.proxy.Opts.SslInsecure,
|
||||
KeyLogWriter: getTlsKeyLogWriter(),
|
||||
},
|
||||
},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
// 禁止自动重定向
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
connCtx.ServerConn = serverConn
|
||||
}
|
||||
|
||||
func (connCtx *ConnContext) InitHttpsServerConn() {
|
||||
if connCtx.ServerConn != nil {
|
||||
return
|
||||
}
|
||||
if !connCtx.ClientConn.Tls {
|
||||
return
|
||||
}
|
||||
|
||||
ServerConn := newServerConn()
|
||||
ServerConn.client = &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||
log.Debugln("in https DialTLSContext")
|
||||
plainConn, err := (&net.Dialer{}).DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cw := &wrapServerConn{
|
||||
Conn: plainConn,
|
||||
proxy: connCtx.proxy,
|
||||
connCtx: connCtx,
|
||||
}
|
||||
ServerConn.Conn = cw
|
||||
ServerConn.Address = addr
|
||||
|
||||
for _, addon := range connCtx.proxy.Addons {
|
||||
addon.ServerConnected(connCtx)
|
||||
}
|
||||
|
||||
firstTLSHost, _, err := net.SplitHostPort(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := &tls.Config{
|
||||
InsecureSkipVerify: connCtx.proxy.Opts.SslInsecure,
|
||||
KeyLogWriter: getTlsKeyLogWriter(),
|
||||
ServerName: firstTLSHost,
|
||||
}
|
||||
tlsConn := tls.Client(cw, cfg)
|
||||
return tlsConn, nil
|
||||
},
|
||||
ForceAttemptHTTP2: false, // disable http2
|
||||
DisableCompression: true, // To get the original response from the server, set Transport.DisableCompression to true.
|
||||
},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
// 禁止自动重定向
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
connCtx.ServerConn = ServerConn
|
||||
}
|
||||
|
||||
// wrap tcpConn for remote client
|
||||
type wrapClientConn struct {
|
||||
net.Conn
|
||||
proxy *Proxy
|
||||
connCtx *ConnContext
|
||||
closed bool
|
||||
closeErr error
|
||||
}
|
||||
|
||||
func (c *wrapClientConn) Close() error {
|
||||
log.Debugln("in wrapClientConn close")
|
||||
if c.closed {
|
||||
return c.closeErr
|
||||
}
|
||||
|
||||
c.closed = true
|
||||
c.closeErr = c.Conn.Close()
|
||||
|
||||
for _, addon := range c.proxy.Addons {
|
||||
addon.ClientDisconnected(c.connCtx.ClientConn)
|
||||
}
|
||||
|
||||
if c.connCtx.ServerConn != nil && c.connCtx.ServerConn.Conn != nil {
|
||||
c.connCtx.ServerConn.Conn.Close()
|
||||
}
|
||||
|
||||
return c.closeErr
|
||||
}
|
||||
|
||||
// wrap tcpListener for remote client
|
||||
type wrapListener struct {
|
||||
net.Listener
|
||||
proxy *Proxy
|
||||
}
|
||||
|
||||
func (l *wrapListener) Accept() (net.Conn, error) {
|
||||
c, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &wrapClientConn{
|
||||
Conn: c,
|
||||
proxy: l.proxy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// wrap tcpConn for remote server
|
||||
type wrapServerConn struct {
|
||||
net.Conn
|
||||
proxy *Proxy
|
||||
connCtx *ConnContext
|
||||
closed bool
|
||||
closeErr error
|
||||
}
|
||||
|
||||
func (c *wrapServerConn) Close() error {
|
||||
log.Debugln("in wrapServerConn close")
|
||||
if c.closed {
|
||||
return c.closeErr
|
||||
}
|
||||
|
||||
c.closed = true
|
||||
c.closeErr = c.Conn.Close()
|
||||
|
||||
for _, addon := range c.proxy.Addons {
|
||||
addon.ServerDisconnected(c.connCtx)
|
||||
}
|
||||
|
||||
c.connCtx.ClientConn.Conn.Close()
|
||||
|
||||
return c.closeErr
|
||||
}
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |