github.com/iDigitalFlame/xmt@v0.5.4/com/ip.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package com 18 19 import ( 20 "context" 21 "io" 22 "net" 23 "time" 24 25 "github.com/iDigitalFlame/xmt/util" 26 "github.com/iDigitalFlame/xmt/util/bugtrack" 27 ) 28 29 type ipStream struct { 30 udpStream 31 } 32 type ipListener struct { 33 _ [0]func() 34 net.Listener 35 proto byte 36 } 37 type ipConnector struct { 38 net.Dialer 39 proto byte 40 } 41 type ipPacketConn struct { 42 _ [0]func() 43 net.PacketConn 44 } 45 46 // NewIP creates a new simple IP based connector with the supplied timeout and 47 // protocol number. 48 func NewIP(t time.Duration, p byte) Connector { 49 return &ipConnector{proto: p, Dialer: net.Dialer{Timeout: t, KeepAlive: t}} 50 } 51 func (i *ipStream) Read(b []byte) (int, error) { 52 n, err := i.udpStream.Read(b) 53 if n > 20 { 54 if bugtrack.Enabled { 55 bugtrack.Track("com.(*ipStream).Read(): Cutting off IP header n=%d, after n=%d", n, n-20) 56 } 57 copy(b, b[20:]) 58 n -= 20 59 } 60 if err == nil && n < len(b)-20 { 61 err = io.EOF 62 } 63 return n, err 64 } 65 func (i *ipConnector) Connect(x context.Context, s string) (net.Conn, error) { 66 c, err := i.DialContext(x, NameIP+":"+util.Uitoa(uint64(i.proto)), s) 67 if err != nil { 68 return nil, err 69 } 70 return &ipStream{udpStream{Conn: c}}, nil 71 } 72 func (i *ipConnector) Listen(x context.Context, s string) (net.Listener, error) { 73 c, err := ListenConfig.ListenPacket(x, NameIP+":"+util.Uitoa(uint64(i.proto)), s) 74 if err != nil { 75 return nil, err 76 } 77 l := &udpListener{ 78 del: make(chan udpAddr, 16), 79 new: make(chan *udpConn, 16), 80 cons: make(map[udpAddr]*udpConn), 81 sock: &udpCompat{&ipPacketConn{PacketConn: c}}, 82 } 83 l.ctx, l.cancel = context.WithCancel(x) 84 go l.purge() 85 go l.listen() 86 return &ipListener{proto: i.proto, Listener: l}, nil 87 }