mirror of https://github.com/v2ray/v2ray-core
				
				
				
			Dokodemo proxy
							parent
							
								
									f93b29993b
								
							
						
					
					
						commit
						c56e17fff9
					
				| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
package json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/common/net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type NetworkList []string
 | 
			
		||||
 | 
			
		||||
func (this *NetworkList) UnmarshalJSON(data []byte) error {
 | 
			
		||||
	var strList []string
 | 
			
		||||
	err := json.Unmarshal(data, &strList)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*this = make([]string, len(strList))
 | 
			
		||||
	for idx, str := range strList {
 | 
			
		||||
		(*this)[idx] = strings.ToLower(str)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *NetworkList) HasNetwork(network v2net.Network) bool {
 | 
			
		||||
	for _, value := range *this {
 | 
			
		||||
		if value == string(network) {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
package net
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	TCPNetwork = Network("tcp")
 | 
			
		||||
	UDPNetwork = Network("udp")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Network string
 | 
			
		||||
 | 
			
		||||
type NetworkList interface {
 | 
			
		||||
	HasNetwork(Network) bool
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -22,10 +22,14 @@ func NewTimeOutReader(timeout int, connection net.Conn) *TimeOutReader {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (reader *TimeOutReader) Read(p []byte) (n int, err error) {
 | 
			
		||||
	deadline := time.Duration(reader.timeout) * time.Second
 | 
			
		||||
	reader.connection.SetReadDeadline(time.Now().Add(deadline))
 | 
			
		||||
	if reader.timeout > 0 {
 | 
			
		||||
		deadline := time.Duration(reader.timeout) * time.Second
 | 
			
		||||
		reader.connection.SetReadDeadline(time.Now().Add(deadline))
 | 
			
		||||
	}
 | 
			
		||||
	n, err = reader.connection.Read(p)
 | 
			
		||||
	reader.connection.SetReadDeadline(emptyTime)
 | 
			
		||||
	if reader.timeout > 0 {
 | 
			
		||||
		reader.connection.SetReadDeadline(emptyTime)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
package json
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/common/net"
 | 
			
		||||
	v2netjson "github.com/v2ray/v2ray-core/common/net/json"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/config"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/config/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DokodemoConfig struct {
 | 
			
		||||
	Host    string                 `json:"address"`
 | 
			
		||||
	Port    int                    `json:"port"`
 | 
			
		||||
	Network *v2netjson.NetworkList `json:"network"`
 | 
			
		||||
	Timeout int                    `json:"timeout"`
 | 
			
		||||
 | 
			
		||||
	address v2net.Address
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	json.RegisterConfigType("dokodemo-door", config.TypeInbound, func() interface{} {
 | 
			
		||||
		return new(DokodemoConfig)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,102 @@
 | 
			
		|||
package dokodemo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/v2ray/v2ray-core/app"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/common/alloc"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/common/log"
 | 
			
		||||
	v2net "github.com/v2ray/v2ray-core/common/net"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/common/retry"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DokodemoDoor struct {
 | 
			
		||||
	config     *json.DokodemoConfig
 | 
			
		||||
	accepting  bool
 | 
			
		||||
	address    v2net.Address
 | 
			
		||||
	dispatcher app.PacketDispatcher
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewDokodemoDoor(dispatcher app.PacketDispatcher, config *json.DokodemoConfig) *DokodemoDoor {
 | 
			
		||||
	d := &DokodemoDoor{
 | 
			
		||||
		config:     config,
 | 
			
		||||
		dispatcher: dispatcher,
 | 
			
		||||
	}
 | 
			
		||||
	ip := net.ParseIP(config.Host)
 | 
			
		||||
	if ip != nil {
 | 
			
		||||
		d.address = v2net.IPAddress(ip, uint16(config.Port))
 | 
			
		||||
	} else {
 | 
			
		||||
		d.address = v2net.DomainAddress(config.Host, uint16(config.Port))
 | 
			
		||||
	}
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DokodemoDoor) Listen(port uint16) error {
 | 
			
		||||
	if this.config.Network.HasNetwork(v2net.TCPNetwork) {
 | 
			
		||||
		err := this.ListenTCP(port)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DokodemoDoor) ListenTCP(port uint16) error {
 | 
			
		||||
	tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
 | 
			
		||||
		IP:   []byte{0, 0, 0, 0},
 | 
			
		||||
		Port: int(port),
 | 
			
		||||
		Zone: "",
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("Dokodemo failed to listen on port %d: %v", port, err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	this.accepting = true
 | 
			
		||||
	go this.AcceptTCPConnections(tcpListener)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DokodemoDoor) AcceptTCPConnections(tcpListener *net.TCPListener) {
 | 
			
		||||
	for this.accepting {
 | 
			
		||||
		retry.Timed(100, 100).On(func() error {
 | 
			
		||||
			connection, err := tcpListener.AcceptTCP()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Error("Dokodemo failed to accept new connections: %v", err)
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			go this.HandleTCPConnection(connection)
 | 
			
		||||
			return nil
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *DokodemoDoor) HandleTCPConnection(conn *net.TCPConn) {
 | 
			
		||||
	defer conn.Close()
 | 
			
		||||
 | 
			
		||||
	packet := v2net.NewPacket(v2net.NewTCPDestination(this.address), nil, true)
 | 
			
		||||
	ray := this.dispatcher.DispatchToOutbound(packet)
 | 
			
		||||
 | 
			
		||||
	var inputFinish, outputFinish sync.Mutex
 | 
			
		||||
	inputFinish.Lock()
 | 
			
		||||
	outputFinish.Lock()
 | 
			
		||||
 | 
			
		||||
	reader := v2net.NewTimeOutReader(this.config.Timeout, conn)
 | 
			
		||||
	go dumpInput(reader, ray.InboundInput(), &inputFinish)
 | 
			
		||||
	go dumpOutput(conn, ray.InboundOutput(), &outputFinish)
 | 
			
		||||
 | 
			
		||||
	outputFinish.Lock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func dumpInput(reader io.Reader, input chan<- *alloc.Buffer, finish *sync.Mutex) {
 | 
			
		||||
	v2net.ReaderToChan(input, reader)
 | 
			
		||||
	finish.Unlock()
 | 
			
		||||
	close(input)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func dumpOutput(writer io.Writer, output <-chan *alloc.Buffer, finish *sync.Mutex) {
 | 
			
		||||
	v2net.ChanToWriter(writer, output)
 | 
			
		||||
	finish.Unlock()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package dokodemo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/v2ray/v2ray-core/app"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/proxy/common/connhandler"
 | 
			
		||||
	"github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DokodemoDoorFactory struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this DokodemoDoorFactory) Create(dispatcher app.PacketDispatcher, rawConfig interface{}) (connhandler.InboundConnectionHandler, error) {
 | 
			
		||||
	config := rawConfig.(*json.DokodemoConfig)
 | 
			
		||||
	return NewDokodemoDoor(dispatcher, config), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	connhandler.RegisterInboundConnectionHandlerFactory("dokodemo-door", DokodemoDoorFactory{})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -12,6 +12,8 @@ import (
 | 
			
		|||
	jsonconf "github.com/v2ray/v2ray-core/config/json"
 | 
			
		||||
 | 
			
		||||
	// The following are neccesary as they register handlers in their init functions.
 | 
			
		||||
	_ "github.com/v2ray/v2ray-core/proxy/dokodemo"
 | 
			
		||||
	_ "github.com/v2ray/v2ray-core/proxy/dokodemo/config/json"
 | 
			
		||||
	_ "github.com/v2ray/v2ray-core/proxy/freedom"
 | 
			
		||||
	_ "github.com/v2ray/v2ray-core/proxy/freedom/config/json"
 | 
			
		||||
	_ "github.com/v2ray/v2ray-core/proxy/socks"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue