mirror of https://github.com/v2ray/v2ray-core
V2Ray
9 years ago
7 changed files with 197 additions and 3 deletions
@ -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 |
||||
} |
@ -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{}) |
||||
} |
Loading…
Reference in new issue