package socket
import (
"net"
"net/netip"
"sync"
"sync/atomic"
"github.com/tmc/go-iroh/key"
"github.com/tmc/go-iroh/netaddr"
)
type Socket struct {
endpointAddrs *AddrMap [key .EndpointID , EndpointIDMappedAddr ]
relayAddrs *AddrMap [string , RelayMappedAddr ]
relayMu sync .Mutex
relayByKey map [string ]RelayKey
customAddrs *AddrMap [string , CustomMappedAddr ]
customMu sync .Mutex
customByKey map [string ]netaddr .CustomAddr
closed atomic .Bool
}
func relayKeyString(url netaddr .RelayURL , eid key .EndpointID ) string {
return url .String () + "|" + eid .String ()
}
type RelayKey struct {
URL netaddr .RelayURL
EID key .EndpointID
}
func NewSocket () *Socket {
return &Socket {
endpointAddrs : NewAddrMap [key .EndpointID , EndpointIDMappedAddr ](
NewEndpointIDMappedAddr ,
func (v EndpointIDMappedAddr ) netip .Addr { return v .Addr () },
),
relayAddrs : NewAddrMap [string , RelayMappedAddr ](
NewRelayMappedAddr ,
func (v RelayMappedAddr ) netip .Addr { return v .Addr () },
),
relayByKey : make (map [string ]RelayKey ),
customAddrs : NewAddrMap [string , CustomMappedAddr ](
NewCustomMappedAddr ,
func (v CustomMappedAddr ) netip .Addr { return v .Addr () },
),
customByKey : make (map [string ]netaddr .CustomAddr ),
}
}
func (s *Socket ) Close () { s .closed .Store (true ) }
func (s *Socket ) IsClosed () bool { return s .closed .Load () }
func (s *Socket ) EndpointIDMappedAddrFor (id key .EndpointID ) EndpointIDMappedAddr {
return s .endpointAddrs .Get (id )
}
func (s *Socket ) LookupEndpointID (m EndpointIDMappedAddr ) (key .EndpointID , bool ) {
return s .endpointAddrs .Lookup (m .Addr ())
}
func (s *Socket ) RelayMappedAddrFor (url netaddr .RelayURL , eid key .EndpointID ) RelayMappedAddr {
key := relayKeyString (url , eid )
s .relayMu .Lock ()
s .relayByKey [key ] = RelayKey {URL : url , EID : eid }
s .relayMu .Unlock ()
return s .relayAddrs .Get (key )
}
func (s *Socket ) LookupRelay (m RelayMappedAddr ) (RelayKey , bool ) {
key , ok := s .relayAddrs .Lookup (m .Addr ())
if !ok {
return RelayKey {}, false
}
s .relayMu .Lock ()
rk , ok := s .relayByKey [key ]
s .relayMu .Unlock ()
return rk , ok
}
func (s *Socket ) CustomMappedAddrFor (c netaddr .CustomAddr ) CustomMappedAddr {
key := c .String ()
s .customMu .Lock ()
s .customByKey [key ] = c
s .customMu .Unlock ()
return s .customAddrs .Get (key )
}
func (s *Socket ) PathAddr (remoteID key .EndpointID , ra net .Addr ) Addr {
ap , ok := addrPort (ra )
if !ok {
return Addr {}
}
switch Classify (ap .Addr ()) {
case KindRelay :
if rk , ok := s .LookupRelay (RelayMappedAddrFromAddr (ap .Addr ())); ok {
return RelayAddr (rk .URL , rk .EID )
}
return IPAddr (ap )
case KindCustom :
if c , ok := s .LookupCustom (CustomMappedAddr {a : ap .Addr ()}); ok {
return CustomAddr (c )
}
return IPAddr (ap )
default :
return IPAddr (ap )
}
}
func (s *Socket ) EvictRemote (id key .EndpointID , addrs []Addr ) {
s .endpointAddrs .Remove (id )
s .relayMu .Lock ()
var relayKeys []string
for k , rk := range s .relayByKey {
if rk .EID == id {
relayKeys = append (relayKeys , k )
delete (s .relayByKey , k )
}
}
s .relayMu .Unlock ()
for _ , k := range relayKeys {
s .relayAddrs .Remove (k )
}
for _ , a := range addrs {
c , ok := a .Custom ()
if !ok {
continue
}
k := c .String ()
s .customMu .Lock ()
delete (s .customByKey , k )
s .customMu .Unlock ()
s .customAddrs .Remove (k )
}
}
func (s *Socket ) LookupCustom (m CustomMappedAddr ) (netaddr .CustomAddr , bool ) {
key , ok := s .customAddrs .Lookup (m .Addr ())
if !ok {
return netaddr .CustomAddr {}, false
}
s .customMu .Lock ()
c , ok := s .customByKey [key ]
s .customMu .Unlock ()
return c , ok
}
The pages are generated with Golds v0.8.4 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .