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  }