Dokodemo proxy

pull/55/head
V2Ray 9 years ago
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) { func (reader *TimeOutReader) Read(p []byte) (n int, err error) {
if reader.timeout > 0 {
deadline := time.Duration(reader.timeout) * time.Second deadline := time.Duration(reader.timeout) * time.Second
reader.connection.SetReadDeadline(time.Now().Add(deadline)) reader.connection.SetReadDeadline(time.Now().Add(deadline))
}
n, err = reader.connection.Read(p) n, err = reader.connection.Read(p)
if reader.timeout > 0 {
reader.connection.SetReadDeadline(emptyTime) reader.connection.SetReadDeadline(emptyTime)
}
return 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" jsonconf "github.com/v2ray/v2ray-core/config/json"
// The following are neccesary as they register handlers in their init functions. // 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"
_ "github.com/v2ray/v2ray-core/proxy/freedom/config/json" _ "github.com/v2ray/v2ray-core/proxy/freedom/config/json"
_ "github.com/v2ray/v2ray-core/proxy/socks" _ "github.com/v2ray/v2ray-core/proxy/socks"

Loading…
Cancel
Save