mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-22 01:57:12 -05:00
udp hub
This commit is contained in:
parent
925c06aeed
commit
4be27a6377
@ -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()
|
|
||||||
this.udpMutex.RLock()
|
|
||||||
if !this.accepting {
|
|
||||||
this.udpMutex.RUnlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
nBytes, addr, err := this.udpConn.ReadFromUDP(buffer.Value)
|
|
||||||
this.udpMutex.RUnlock()
|
|
||||||
buffer.Slice(0, nBytes)
|
|
||||||
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)
|
ray := this.space.PacketDispatcher().DispatchToOutbound(packet)
|
||||||
close(ray.InboundInput())
|
close(ray.InboundInput())
|
||||||
|
|
||||||
for payload := range ray.InboundOutput() {
|
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
|
||||||
}
|
}
|
||||||
this.udpConn.WriteToUDP(payload.Value, addr)
|
this.udpHub.WriteTo(resp.Value, dest)
|
||||||
this.udpMutex.RUnlock()
|
this.udpMutex.RUnlock()
|
||||||
}
|
resp.Release()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
59
transport/hub/udp.go
Normal file
59
transport/hub/udp.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user