status-go/vendor/github.com/pion/transport/vnet/chunk.go

284 lines
5.5 KiB
Go

package vnet
import (
"fmt"
"net"
"strconv"
"strings"
"sync/atomic"
"time"
)
type tcpFlag uint8
const (
tcpFIN tcpFlag = 0x01
tcpSYN tcpFlag = 0x02
tcpRST tcpFlag = 0x04
tcpPSH tcpFlag = 0x08
tcpACK tcpFlag = 0x10
)
func (f tcpFlag) String() string {
var sa []string
if f&tcpFIN != 0 {
sa = append(sa, "FIN")
}
if f&tcpSYN != 0 {
sa = append(sa, "SYN")
}
if f&tcpRST != 0 {
sa = append(sa, "RST")
}
if f&tcpPSH != 0 {
sa = append(sa, "PSH")
}
if f&tcpACK != 0 {
sa = append(sa, "ACK")
}
return strings.Join(sa, "-")
}
// Generate a base36-encoded unique tag
// See: https://play.golang.org/p/0ZaAID1q-HN
var assignChunkTag = func() func() string { //nolint:gochecknoglobals
var tagCtr uint64
return func() string {
n := atomic.AddUint64(&tagCtr, 1)
return strconv.FormatUint(n, 36)
}
}()
// Chunk represents a packet passed around in the vnet
type Chunk interface {
setTimestamp() time.Time // used by router
getTimestamp() time.Time // used by router
getSourceIP() net.IP // used by router
getDestinationIP() net.IP // used by router
setSourceAddr(address string) error // used by nat
setDestinationAddr(address string) error // used by nat
SourceAddr() net.Addr
DestinationAddr() net.Addr
UserData() []byte
Tag() string
Clone() Chunk
Network() string // returns "udp" or "tcp"
String() string
}
type chunkIP struct {
timestamp time.Time
sourceIP net.IP
destinationIP net.IP
tag string
}
func (c *chunkIP) setTimestamp() time.Time {
c.timestamp = time.Now()
return c.timestamp
}
func (c *chunkIP) getTimestamp() time.Time {
return c.timestamp
}
func (c *chunkIP) getDestinationIP() net.IP {
return c.destinationIP
}
func (c *chunkIP) getSourceIP() net.IP {
return c.sourceIP
}
func (c *chunkIP) Tag() string {
return c.tag
}
type chunkUDP struct {
chunkIP
sourcePort int
destinationPort int
userData []byte
}
func newChunkUDP(srcAddr, dstAddr *net.UDPAddr) *chunkUDP {
return &chunkUDP{
chunkIP: chunkIP{
sourceIP: srcAddr.IP,
destinationIP: dstAddr.IP,
tag: assignChunkTag(),
},
sourcePort: srcAddr.Port,
destinationPort: dstAddr.Port,
}
}
func (c *chunkUDP) SourceAddr() net.Addr {
return &net.UDPAddr{
IP: c.sourceIP,
Port: c.sourcePort,
}
}
func (c *chunkUDP) DestinationAddr() net.Addr {
return &net.UDPAddr{
IP: c.destinationIP,
Port: c.destinationPort,
}
}
func (c *chunkUDP) UserData() []byte {
return c.userData
}
func (c *chunkUDP) Clone() Chunk {
var userData []byte
if c.userData != nil {
userData = make([]byte, len(c.userData))
copy(userData, c.userData)
}
return &chunkUDP{
chunkIP: chunkIP{
timestamp: c.timestamp,
sourceIP: c.sourceIP,
destinationIP: c.destinationIP,
tag: c.tag,
},
sourcePort: c.sourcePort,
destinationPort: c.destinationPort,
userData: userData,
}
}
func (c *chunkUDP) Network() string {
return udpString
}
func (c *chunkUDP) String() string {
src := c.SourceAddr()
dst := c.DestinationAddr()
return fmt.Sprintf("%s chunk %s %s => %s",
src.Network(),
c.tag,
src.String(),
dst.String(),
)
}
func (c *chunkUDP) setSourceAddr(address string) error {
addr, err := net.ResolveUDPAddr(udpString, address)
if err != nil {
return err
}
c.sourceIP = addr.IP
c.sourcePort = addr.Port
return nil
}
func (c *chunkUDP) setDestinationAddr(address string) error {
addr, err := net.ResolveUDPAddr(udpString, address)
if err != nil {
return err
}
c.destinationIP = addr.IP
c.destinationPort = addr.Port
return nil
}
type chunkTCP struct {
chunkIP
sourcePort int
destinationPort int
flags tcpFlag // control bits
userData []byte // only with PSH flag
// seq uint32 // always starts with 0
// ack uint32 // always starts with 0
}
func newChunkTCP(srcAddr, dstAddr *net.TCPAddr, flags tcpFlag) *chunkTCP {
return &chunkTCP{
chunkIP: chunkIP{
sourceIP: srcAddr.IP,
destinationIP: dstAddr.IP,
tag: assignChunkTag(),
},
sourcePort: srcAddr.Port,
destinationPort: dstAddr.Port,
flags: flags,
}
}
func (c *chunkTCP) SourceAddr() net.Addr {
return &net.TCPAddr{
IP: c.sourceIP,
Port: c.sourcePort,
}
}
func (c *chunkTCP) DestinationAddr() net.Addr {
return &net.TCPAddr{
IP: c.destinationIP,
Port: c.destinationPort,
}
}
func (c *chunkTCP) UserData() []byte {
return c.userData
}
func (c *chunkTCP) Clone() Chunk {
userData := make([]byte, len(c.userData))
copy(userData, c.userData)
return &chunkTCP{
chunkIP: chunkIP{
timestamp: c.timestamp,
sourceIP: c.sourceIP,
destinationIP: c.destinationIP,
},
sourcePort: c.sourcePort,
destinationPort: c.destinationPort,
userData: userData,
}
}
func (c *chunkTCP) Network() string {
return "tcp"
}
func (c *chunkTCP) String() string {
src := c.SourceAddr()
dst := c.DestinationAddr()
return fmt.Sprintf("%s %s chunk %s %s => %s",
src.Network(),
c.flags.String(),
c.tag,
src.String(),
dst.String(),
)
}
func (c *chunkTCP) setSourceAddr(address string) error {
addr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return err
}
c.sourceIP = addr.IP
c.sourcePort = addr.Port
return nil
}
func (c *chunkTCP) setDestinationAddr(address string) error {
addr, err := net.ResolveTCPAddr("tcp", address)
if err != nil {
return err
}
c.destinationIP = addr.IP
c.destinationPort = addr.Port
return nil
}