mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 05:04:03 +03:00
Proxy is working in a simple mode now
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
package relay
|
||||
|
||||
import "io"
|
||||
|
||||
type conn struct {
|
||||
io.ReadWriteCloser
|
||||
|
||||
relay *Relay
|
||||
}
|
||||
|
||||
func (c conn) Read(p []byte) (int, error) {
|
||||
ctx := c.relay.ctx
|
||||
n, err := c.ReadWriteCloser.Read(p)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case c.relay.tickChannel <- struct{}{}:
|
||||
}
|
||||
|
||||
return n, err // nolint: wrapcheck
|
||||
}
|
||||
|
||||
func (c conn) Write(p []byte) (int, error) {
|
||||
ctx := c.relay.ctx
|
||||
n, err := c.ReadWriteCloser.Write(p)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case c.relay.tickChannel <- struct{}{}:
|
||||
}
|
||||
|
||||
return n, err // nolint: wrapcheck
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var relayPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Relay{
|
||||
tickChannel: make(chan struct{}),
|
||||
errorChannel: make(chan error, 1),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func AcquireRelay(ctx context.Context, logger Logger, bufferSize int, idleTimeout time.Duration) *Relay {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
r := relayPool.Get().(*Relay)
|
||||
r.ctx = ctx
|
||||
r.ctxCancel = cancel
|
||||
r.logger = logger
|
||||
r.tickTimeout = idleTimeout
|
||||
|
||||
if len(r.eastBuffer) != bufferSize {
|
||||
r.eastBuffer = make([]byte, bufferSize)
|
||||
}
|
||||
|
||||
if len(r.westBuffer) != bufferSize {
|
||||
r.westBuffer = make([]byte, bufferSize)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func ReleaseRelay(r *Relay) {
|
||||
r.ctxCancel()
|
||||
|
||||
r.ctx = nil
|
||||
r.ctxCancel = nil
|
||||
r.logger = nil
|
||||
|
||||
relayPool.Put(r)
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Relay struct {
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
logger Logger
|
||||
eastBuffer []byte
|
||||
westBuffer []byte
|
||||
tickChannel chan struct{}
|
||||
errorChannel chan error
|
||||
tickTimeout time.Duration
|
||||
}
|
||||
|
||||
func (r *Relay) Process(eastConn, westConn io.ReadWriteCloser) error {
|
||||
eastConn = conn{
|
||||
ReadWriteCloser: eastConn,
|
||||
relay: r,
|
||||
}
|
||||
westConn = conn{
|
||||
ReadWriteCloser: westConn,
|
||||
relay: r,
|
||||
}
|
||||
|
||||
defer func() {
|
||||
r.ctxCancel()
|
||||
eastConn.Close()
|
||||
westConn.Close()
|
||||
}()
|
||||
|
||||
go r.runObserver()
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2) // nolint: gomnd
|
||||
|
||||
go r.transmit(eastConn, westConn, r.westBuffer, "west", wg)
|
||||
|
||||
r.transmit(westConn, eastConn, r.eastBuffer, "east", wg)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return <-r.errorChannel
|
||||
}
|
||||
|
||||
func (r *Relay) transmit(src io.ReadCloser, dst io.WriteCloser,
|
||||
buffer []byte, direction string, wg *sync.WaitGroup) {
|
||||
defer func() {
|
||||
wg.Done()
|
||||
src.Close()
|
||||
dst.Close()
|
||||
}()
|
||||
|
||||
if _, err := io.CopyBuffer(dst, src, buffer); err != nil {
|
||||
r.logger.Printf("error '%v' happened on direction %s", err, direction)
|
||||
|
||||
select {
|
||||
case <-r.ctx.Done():
|
||||
case r.errorChannel <- err:
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Relay) runObserver() {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
|
||||
defer func() {
|
||||
ticker.Stop()
|
||||
|
||||
select {
|
||||
case <-ticker.C:
|
||||
default:
|
||||
}
|
||||
}()
|
||||
|
||||
lastTickAt := time.Now()
|
||||
ctx := r.ctx
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-r.tickChannel:
|
||||
lastTickAt = time.Now()
|
||||
case <-ticker.C:
|
||||
if time.Since(lastTickAt) > r.tickTimeout {
|
||||
r.logger.Printf("exit due to a timeout")
|
||||
r.ctxCancel()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user