58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
|
package socks
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
)
|
||
|
|
||
|
// ConnectionHandler is the Serve method to handle connections
|
||
|
// from a local TCP listener of the standard library (net.Listener)
|
||
|
type ConnectionHandler interface {
|
||
|
Serve(io.ReadWriter) error
|
||
|
}
|
||
|
|
||
|
// StandardConnectionHandler is the base implementation of handling SOCKS5 requests
|
||
|
type StandardConnectionHandler struct {
|
||
|
requestHandler RequestHandler
|
||
|
authHandler AuthHandler
|
||
|
}
|
||
|
|
||
|
// NewConnectionHandler creates a standard SOCKS5 connection handler
|
||
|
// This process connections from a generic TCP listener from the standard library
|
||
|
func NewConnectionHandler(requestHandler RequestHandler) ConnectionHandler {
|
||
|
return &StandardConnectionHandler{
|
||
|
requestHandler: requestHandler,
|
||
|
authHandler: NewAuthHandler(),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Serve process new connection created after calling `Accept()` in the standard library
|
||
|
func (h *StandardConnectionHandler) Serve(c io.ReadWriter) error {
|
||
|
bufConn := bufio.NewReader(c)
|
||
|
|
||
|
// read the version byte
|
||
|
version := []byte{0}
|
||
|
if _, err := bufConn.Read(version); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// ensure compatibility
|
||
|
if version[0] != socks5Version {
|
||
|
return fmt.Errorf("Unsupported SOCKS version: %v", version)
|
||
|
}
|
||
|
|
||
|
// handle auth
|
||
|
if err := h.authHandler.Handle(bufConn, c); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
// process command/request
|
||
|
req, err := NewRequest(bufConn)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return h.requestHandler.Handle(req, c)
|
||
|
}
|