1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-11-04 09:17:32 -05:00
This commit is contained in:
Darien Raymond 2016-01-28 16:43:47 +00:00
parent 925c06aeed
commit 4be27a6377
2 changed files with 74 additions and 36 deletions

View File

@ -2,7 +2,6 @@ package dokodemo
import ( import (
"io" "io"
"net"
"sync" "sync"
"github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app"
@ -22,7 +21,7 @@ type DokodemoDoor struct {
port v2net.Port port v2net.Port
space app.Space space app.Space
tcpListener *hub.TCPListener tcpListener *hub.TCPListener
udpConn *net.UDPConn udpHub *hub.UDPHub
listeningPort v2net.Port listeningPort v2net.Port
} }
@ -47,10 +46,10 @@ func (this *DokodemoDoor) Close() {
this.tcpListener = nil this.tcpListener = nil
this.tcpMutex.Unlock() this.tcpMutex.Unlock()
} }
if this.udpConn != nil { if this.udpHub != nil {
this.udpConn.Close()
this.udpMutex.Lock() this.udpMutex.Lock()
this.udpConn = nil this.udpHub.Close()
this.udpHub = nil
this.udpMutex.Unlock() this.udpMutex.Unlock()
} }
} }
@ -82,52 +81,32 @@ func (this *DokodemoDoor) Listen(port v2net.Port) error {
} }
func (this *DokodemoDoor) ListenUDP(port v2net.Port) error { func (this *DokodemoDoor) ListenUDP(port v2net.Port) error {
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{ udpHub, err := hub.ListenUDP(port, this.handleUDPPackets)
IP: []byte{0, 0, 0, 0},
Port: int(port),
Zone: "",
})
if err != nil { if err != nil {
log.Error("Dokodemo failed to listen on port ", port, ": ", err) log.Error("Dokodemo failed to listen on port ", port, ": ", err)
return err return err
} }
this.udpMutex.Lock() this.udpMutex.Lock()
this.udpConn = udpConn this.udpHub = udpHub
this.udpMutex.Unlock() this.udpMutex.Unlock()
go this.handleUDPPackets()
return nil return nil
} }
func (this *DokodemoDoor) handleUDPPackets() { func (this *DokodemoDoor) handleUDPPackets(payload *alloc.Buffer, dest v2net.Destination) {
for this.accepting { packet := v2net.NewPacket(v2net.UDPDestination(this.address, this.port), payload, false)
buffer := alloc.NewBuffer() ray := this.space.PacketDispatcher().DispatchToOutbound(packet)
close(ray.InboundInput())
for resp := range ray.InboundOutput() {
this.udpMutex.RLock() this.udpMutex.RLock()
if !this.accepting { if !this.accepting {
this.udpMutex.RUnlock() this.udpMutex.RUnlock()
resp.Release()
return return
} }
nBytes, addr, err := this.udpConn.ReadFromUDP(buffer.Value) this.udpHub.WriteTo(resp.Value, dest)
this.udpMutex.RUnlock() this.udpMutex.RUnlock()
buffer.Slice(0, nBytes) resp.Release()
if err != nil {
buffer.Release()
log.Error("Dokodemo failed to read from UDP: ", err)
return
}
packet := v2net.NewPacket(v2net.UDPDestination(this.address, this.port), buffer, false)
ray := this.space.PacketDispatcher().DispatchToOutbound(packet)
close(ray.InboundInput())
for payload := range ray.InboundOutput() {
this.udpMutex.RLock()
if !this.accepting {
this.udpMutex.RUnlock()
return
}
this.udpConn.WriteToUDP(payload.Value, addr)
this.udpMutex.RUnlock()
}
} }
} }

59
transport/hub/udp.go Normal file
View File

@ -0,0 +1,59 @@
package hub
import (
"net"
"github.com/v2ray/v2ray-core/common/alloc"
v2net "github.com/v2ray/v2ray-core/common/net"
)
type UDPPayloadHandler func(*alloc.Buffer, v2net.Destination)
type UDPHub struct {
conn *net.UDPConn
callback UDPPayloadHandler
accepting bool
}
func ListenUDP(port v2net.Port, callback UDPPayloadHandler) (*UDPHub, error) {
udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
IP: []byte{0, 0, 0, 0},
Port: int(port),
})
if err != nil {
return nil, err
}
hub := &UDPHub{
conn: udpConn,
callback: callback,
}
go hub.start()
return hub, nil
}
func (this *UDPHub) Close() {
this.accepting = false
this.conn.Close()
}
func (this *UDPHub) WriteTo(payload []byte, dest v2net.Destination) (int, error) {
return this.conn.WriteToUDP(payload, &net.UDPAddr{
IP: dest.Address().IP(),
Port: int(dest.Port()),
})
}
func (this *UDPHub) start() {
this.accepting = true
for this.accepting {
buffer := alloc.NewBuffer()
nBytes, addr, err := this.conn.ReadFromUDP(buffer.Value)
if err != nil {
buffer.Release()
continue
}
buffer.Slice(0, nBytes)
dest := v2net.UDPDestination(v2net.IPAddress(addr.IP), v2net.Port(addr.Port))
go this.callback(buffer, dest)
}
}