yggdrasil-go: github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil Index | Files

package yggdrasil

import "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"

Package yggdrasil implements the core functionality of the Yggdrasil Network.

Introduction

Yggdrasil is a proof-of-concept mesh network which provides end-to-end encrypted communication between nodes in a decentralised fashion. The network is arranged using a globally-agreed spanning tree which provides each node with a locator (coordinates relative to the root) and a distributed hash table (DHT) mechanism for finding other nodes.

Each node also implements a router, which is responsible for encryption of traffic, searches and connections, and a switch, which is responsible ultimately for forwarding traffic across the network.

While many Yggdrasil nodes in existence today are IP nodes - that is, they are transporting IPv6 packets, like a kind of mesh VPN - it is also possible to integrate Yggdrasil into your own applications and use it as a generic data transport, similar to UDP.

This library is what you need to integrate and use Yggdrasil in your own application.

Basics

In order to start an Yggdrasil node, you should start by generating node configuration, which amongst other things, includes encryption keypairs which are used to generate the node's identity, and supply a logger which Yggdrasil's output will be written to.

This may look something like this:

import (
  "os"
  "github.com/gologme/log"
  "github.com/yggdrasil-network/yggdrasil-go/src/config"
  "github.com/yggdrasil-network/yggdrasil-go/src/yggdrasil"
)

type node struct {
  core   yggdrasil.Core
  config *config.NodeConfig
  log    *log.Logger
}

You then can supply node configuration and a logger:

n := node{}
n.log = log.New(os.Stdout, "", log.Flags())
n.config = config.GenerateConfig()

In the above example, we ask the config package to supply new configuration each time, which results in fresh encryption keys and therefore a new identity. It is normally preferable in most cases to persist node configuration onto the filesystem or into some configuration store so that the node's identity does not change each time that the program starts. Note that Yggdrasil will automatically fill in any missing configuration items with sane defaults.

Once you have supplied a logger and some node configuration, you can then start the node:

n.core.Start(n.config, n.log)

Add some peers to connect to the network:

n.core.AddPeer("tcp://some-host.net:54321", "")
n.core.AddPeer("tcp://[2001::1:2:3]:54321", "")
n.core.AddPeer("tcp://1.2.3.4:54321", "")

You can also ask the API for information about our node:

n.log.Println("My node ID is", n.core.NodeID())
n.log.Println("My public key is", n.core.EncryptionPublicKey())
n.log.Println("My coords are", n.core.Coords())

Incoming Connections

Once your node is started, you can then listen for connections from other nodes by asking the API for a Listener:

listener, err := n.core.ConnListen()
if err != nil {
  // ...
}

The Listener has a blocking Accept function which will wait for incoming connections from remote nodes. It will return a Conn when a connection is received. If the node never receives any incoming connections then this function can block forever, so be prepared for that, perhaps by listening in a separate goroutine.

Assuming that you have defined a myConnectionHandler function to deal with incoming connections:

for {
  conn, err := listener.Accept()
  if err != nil {
    // ...
  }

  // We've got a new connection
  go myConnectionHandler(conn)
}

Outgoing Connections

If you know the node ID of the remote node that you want to talk to, you can dial an outbound connection to it. To do this, you should first ask the API for a Dialer:

dialer, err := n.core.ConnDialer()
if err != nil {
  // ...
}

You can then dial using the node's public key in hexadecimal format, for example:

conn, err := dialer.Dial("curve25519", "55071be281f50d0abbda63aadc59755624280c44b2f1f47684317aa4e0325604")
if err != nil {
  // ...
}

Using Connections

Conn objects are implementations of io.ReadWriteCloser, and as such, you can Read, Write and Close them as necessary.

Each Read or Write operation can deal with a buffer with a maximum size of 65535 bytes - any bigger than this and the operation will return an error.

For example, to write to the Conn from the supplied buffer:

buf := []byte{1, 2, 3, 4, 5}
w, err := conn.Write(buf)
if err != nil {
  // ...
} else {
  // written w bytes
}

Reading from the Conn into the supplied buffer:

buf := make([]byte, 65535)
r, err := conn.Read(buf)
if err != nil {
  // ...
} else {
  // read r bytes
}

When you are happy that a connection is no longer required, you can discard it:

err := conn.Close()
if err != nil {
  // ...
}

Limitations

You should be aware of the following limitations when working with the Yggdrasil library:

Individual messages written through Yggdrasil connections can not exceed 65535 bytes in size. Yggdrasil has no concept of fragmentation, so if you try to send a message that exceeds 65535 bytes in size, it will be dropped altogether and an error will be returned.

Yggdrasil connections are unreliable by nature. Messages are delivered on a best-effort basis, and employs congestion control where appropriate to ensure that congestion does not affect message transport, but Yggdrasil will not retransmit any messages that have been lost. If reliable delivery is important then you should manually implement acknowledgement and retransmission of messages.

Index

Package Files

api.go conn.go core.go dht.go dialer.go doc.go link.go listener.go nodeinfo.go peer.go router.go search.go session.go stream.go switch.go tcp.go tcp_linux.go tls.go version.go wire.go

Constants

const SwitchQueueTotalMinSize = 4 * 1024 * 1024

Minimum allowed total size of switch queues.

type Conn Uses

type Conn struct {
    phony.Inbox
    // contains filtered or unexported fields
}

The Conn struct is a reference to an active connection session between the local node and a remote node. Conn implements the io.ReadWriteCloser interface and is used to send and receive traffic with a remote node.

func (*Conn) Close Uses

func (c *Conn) Close() (err error)

Close will close an open connection and any blocking operations on the connection will unblock and return. From this point forward, the connection can no longer be used and you should no longer attempt to Read or Write to the connection.

func (*Conn) LocalAddr Uses

func (c *Conn) LocalAddr() net.Addr

LocalAddr returns the complete public key of the local side of the connection. This is always going to return your own node's public key.

func (*Conn) Read Uses

func (c *Conn) Read(b []byte) (int, error)

Read allows you to read from the connection in a synchronous fashion. The function will block up until the point that either new data is available, the connection has been closed or the read deadline has been reached. If the function succeeds, the number of bytes read from the connection will be returned. Otherwise, an error condition will be returned.

Note that you can also implement asynchronous reads by using SetReadCallback. If you do that, you should no longer attempt to use the Read function.

func (*Conn) RemoteAddr Uses

func (c *Conn) RemoteAddr() net.Addr

RemoteAddr returns the complete public key of the remote side of the connection.

func (*Conn) SetDeadline Uses

func (c *Conn) SetDeadline(t time.Time) error

SetDeadline is equivalent to calling both SetReadDeadline and SetWriteDeadline with the same value, configuring the maximum amount of time that synchronous Read and Write operations can block for. If no deadline is configured, Read and Write operations can potentially block indefinitely.

func (*Conn) SetReadCallback Uses

func (c *Conn) SetReadCallback(callback func([]byte))

SetReadCallback allows you to specify a function that will be called whenever a packet is received. This should be used if you wish to implement asynchronous patterns for receiving data from the remote node.

Note that if a read callback has been supplied, you should no longer attempt to use the synchronous Read function.

func (*Conn) SetReadDeadline Uses

func (c *Conn) SetReadDeadline(t time.Time) error

SetReadDeadline configures the maximum amount of time that a synchronous Read operation can block for. A Read operation will unblock at the point that the read deadline is reached if no other condition (such as data arrival or connection closure) happens first. If no deadline is configured, Read operations can potentially block indefinitely.

func (*Conn) SetWriteDeadline Uses

func (c *Conn) SetWriteDeadline(t time.Time) error

SetWriteDeadline configures the maximum amount of time that a synchronous Write operation can block for. A Write operation will unblock at the point that the read deadline is reached if no other condition (such as data sending or connection closure) happens first. If no deadline is configured, Write operations can potentially block indefinitely.

func (*Conn) String Uses

func (c *Conn) String() string

String returns a string that uniquely identifies a connection. Currently this takes a form similar to "conn=0x0000000", which contains a memory reference to the Conn object. While this value should always be unique for each Conn object, the format of this is not strictly defined and may change in the future.

func (*Conn) Write Uses

func (c *Conn) Write(b []byte) (int, error)

Write allows you to write to the connection in a synchronous fashion. This function may block until either the write has completed, the connection has been closed or the write deadline has been reached. If the function succeeds, the number of written bytes is returned. Otherwise, an error condition is returned.

func (*Conn) WriteFrom Uses

func (c *Conn) WriteFrom(from phony.Actor, msg FlowKeyMessage, callback func(error))

WriteFrom should be called by a phony.Actor, and tells the Conn to send a message. This is used internally by Write. If the callback is called with a non-nil value, then it is safe to reuse the argument FlowKeyMessage.

type ConnError Uses

type ConnError struct {
    // contains filtered or unexported fields
}

ConnError implements the net.Error interface

func (*ConnError) Closed Uses

func (e *ConnError) Closed() bool

Closed returns if the session is already closed and is now unusable.

func (*ConnError) PacketMaximumSize Uses

func (e *ConnError) PacketMaximumSize() int

PacketMaximumSize returns the maximum supported packet size. This will only return a non-zero value if ConnError.PacketTooBig() returns true.

func (*ConnError) PacketTooBig Uses

func (e *ConnError) PacketTooBig() bool

PacketTooBig returns in response to sending a packet that is too large, and if so, the maximum supported packet size that should be used for the connection.

func (*ConnError) Temporary Uses

func (e *ConnError) Temporary() bool

Temporary return true if the error is temporary or false if it is a permanent error condition.

func (*ConnError) Timeout Uses

func (e *ConnError) Timeout() bool

Timeout returns true if the error relates to a timeout condition on the connection.

type Core Uses

type Core struct {
    // This is the main data structure that holds everything else for a node
    // We're going to keep our own copy of the provided config - that way we can
    // guarantee that it will be covered by the mutex
    phony.Inbox
    // contains filtered or unexported fields
}

The Core object represents the Yggdrasil node. You should create a Core object for each Yggdrasil node you plan to run.

func (*Core) AddAllowedEncryptionPublicKey Uses

func (c *Core) AddAllowedEncryptionPublicKey(bstr string) (err error)

AddAllowedEncryptionPublicKey whitelists a key for incoming peer connections. By default all incoming peer connections are accepted, but adding public keys to the whitelist using this function enables strict checking from that point forward. Once the whitelist is enabled, only peer connections from whitelisted public keys will be accepted.

func (*Core) AddPeer Uses

func (c *Core) AddPeer(addr string, sintf string) error

AddPeer adds a peer. This should be specified in the peer URI format, e.g.:

tcp://a.b.c.d:e
socks://a.b.c.d:e/f.g.h.i:j

This adds the peer to the peer list, so that they will be called again if the connection drops.

func (*Core) Address Uses

func (c *Core) Address() net.IP

Address gets the IPv6 address of the Yggdrasil node. This is always a /128 address. The IPv6 address is only relevant when the node is operating as an IP router and often is meaningless when embedded into an application, unless that application also implements either VPN functionality or deals with IP packets specifically.

func (*Core) CallPeer Uses

func (c *Core) CallPeer(addr string, sintf string) error

CallPeer calls a peer once. This should be specified in the peer URI format, e.g.:

tcp://a.b.c.d:e
socks://a.b.c.d:e/f.g.h.i:j

This does not add the peer to the peer list, so if the connection drops, the peer will not be called again automatically.

func (*Core) ConnDialer Uses

func (c *Core) ConnDialer() (*Dialer, error)

ConnDialer returns a dialer for Yggdrasil session connections. Since ConnDialers are stateless, you can request as many dialers as you like, although ideally you should request only one and keep the reference to it for as long as it is needed.

func (*Core) ConnListen Uses

func (c *Core) ConnListen() (*Listener, error)

ConnListen returns a listener for Yggdrasil session connections. You can only call this function once as each Yggdrasil node can only have a single ConnListener. Make sure to keep the reference to this for as long as it is needed.

func (*Core) Coords Uses

func (c *Core) Coords() []uint64

Coords returns the current coordinates of the node. Note that these can change at any time for a number of reasons, not limited to but including changes to peerings (either yours or a parent nodes) or changes to the network root.

This function may return an empty array - this is normal behaviour if either you are the root of the network that you are connected to, or you are not connected to any other nodes (effectively making you the root of a single-node network).

func (*Core) DHTPing Uses

func (c *Core) DHTPing(key crypto.BoxPubKey, coords []uint64, target *crypto.NodeID) (DHTRes, error)

DHTPing sends a DHT ping to the node with the provided key and coords, optionally looking up the specified target NodeID.

func (*Core) DisconnectPeer Uses

func (c *Core) DisconnectPeer(port uint64) error

DisconnectPeer disconnects a peer once. This should be specified as a port number.

func (*Core) EncryptionPublicKey Uses

func (c *Core) EncryptionPublicKey() string

EncryptionPublicKey gets the node's encryption public key, as used by the router.

func (*Core) GetAllowedEncryptionPublicKeys Uses

func (c *Core) GetAllowedEncryptionPublicKeys() []string

GetAllowedEncryptionPublicKeys returns the public keys permitted for incoming peer connections. If this list is empty then all incoming peer connections are accepted by default.

func (*Core) GetDHT Uses

func (c *Core) GetDHT() []DHTEntry

GetDHT returns zero or more entries as stored in the DHT, cached primarily from searches that have already taken place.

func (*Core) GetMaximumSessionMTU Uses

func (c *Core) GetMaximumSessionMTU() MTU

GetMaximumSessionMTU returns the maximum allowed session MTU size.

func (*Core) GetNodeInfo Uses

func (c *Core) GetNodeInfo(key crypto.BoxPubKey, coords []uint64, nocache bool) (NodeInfoPayload, error)

GetNodeInfo requests nodeinfo from a remote node, as specified by the public key and coordinates specified. The third parameter specifies whether a cached result is acceptable - this results in less traffic being generated than is necessary when, e.g. crawling the network.

func (*Core) GetPeers Uses

func (c *Core) GetPeers() []Peer

GetPeers returns one or more Peer objects containing information about active peerings with other Yggdrasil nodes, where one of the responses always includes information about the current node (with a port number of 0). If there is exactly one entry then this node is not connected to any other nodes and is therefore isolated.

func (*Core) GetSessions Uses

func (c *Core) GetSessions() []Session

GetSessions returns a list of open sessions from this node to other nodes.

func (*Core) GetSwitchPeers Uses

func (c *Core) GetSwitchPeers() []SwitchPeer

GetSwitchPeers returns zero or more SwitchPeer objects containing information about switch port connections with other Yggdrasil nodes. Note that, unlike GetPeers, GetSwitchPeers does not include information about the current node, therefore it is possible for this to return zero elements if the node is isolated or not connected to any peers.

func (*Core) GetSwitchQueues Uses

func (c *Core) GetSwitchQueues() SwitchQueues

GetSwitchQueues returns information about the switch queues that are currently in effect. These values can change within an instant.

func (*Core) ListenTCP Uses

func (c *Core) ListenTCP(uri string) (*TcpListener, error)

ListenTCP starts a new TCP listener. The input URI should match that of the "Listen" configuration item, e.g.

tcp://a.b.c.d:e

func (*Core) ListenTLS Uses

func (c *Core) ListenTLS(uri string) (*TcpListener, error)

ListenTLS starts a new TLS listener. The input URI should match that of the "Listen" configuration item, e.g.

tls://a.b.c.d:e

func (*Core) MyNodeInfo Uses

func (c *Core) MyNodeInfo() NodeInfoPayload

MyNodeInfo gets the currently configured nodeinfo. NodeInfo is typically specified through the "NodeInfo" option in the node configuration or using the SetNodeInfo function, although it may also contain other built-in values such as "buildname", "buildversion" etc.

func (*Core) NodeID Uses

func (c *Core) NodeID() *crypto.NodeID

NodeID gets the node ID. This is derived from your router encryption keys. Remote nodes wanting to open connections to your node will need to know your node ID.

func (*Core) RemoveAllowedEncryptionPublicKey Uses

func (c *Core) RemoveAllowedEncryptionPublicKey(bstr string) (err error)

RemoveAllowedEncryptionPublicKey removes a key from the whitelist for incoming peer connections. If none are set, an empty list permits all incoming connections.

func (*Core) RemovePeer Uses

func (c *Core) RemovePeer(addr string, sintf string) error

RemovePeer is not implemented yet.

func (*Core) SetLogger Uses

func (c *Core) SetLogger(log *log.Logger)

SetLogger sets the output logger of the Yggdrasil node after startup. This may be useful if you want to redirect the output later. Note that this expects a Logger from the github.com/gologme/log package and not from Go's built-in log package.

func (*Core) SetMaximumSessionMTU Uses

func (c *Core) SetMaximumSessionMTU(mtu MTU)

SetMaximumSessionMTU sets the maximum allowed session MTU size. The default value is 65535 bytes. Session pings will be sent to update all open sessions if the MTU has changed.

func (*Core) SetNodeInfo Uses

func (c *Core) SetNodeInfo(nodeinfo interface{}, nodeinfoprivacy bool)

SetNodeInfo sets the local nodeinfo. Note that nodeinfo can be any value or struct, it will be serialised into JSON automatically.

func (*Core) SetSessionGatekeeper Uses

func (c *Core) SetSessionGatekeeper(f func(pubkey *crypto.BoxPubKey, initiator bool) bool)

SetSessionGatekeeper allows you to configure a handler function for deciding whether a session should be allowed or not. The default session firewall is implemented in this way. The function receives the public key of the remote side and a boolean which is true if we initiated the session or false if we received an incoming session request. The function should return true to allow the session or false to reject it.

func (*Core) SigningPublicKey Uses

func (c *Core) SigningPublicKey() string

SigningPublicKey gets the node's signing public key, as used by the switch.

func (*Core) Start Uses

func (c *Core) Start(nc *config.NodeConfig, log *log.Logger) (conf *config.NodeState, err error)

Start starts up Yggdrasil using the provided config.NodeConfig, and outputs debug logging through the provided log.Logger. The started stack will include TCP and UDP sockets, a multicast discovery socket, an admin socket, router, switch and DHT node. A config.NodeState is returned which contains both the current and previous configurations (from reconfigures).

func (*Core) Stop Uses

func (c *Core) Stop()

Stop shuts down the Yggdrasil node.

func (*Core) Subnet Uses

func (c *Core) Subnet() net.IPNet

Subnet gets the routed IPv6 subnet of the Yggdrasil node. This is always a /64 subnet. The IPv6 subnet is only relevant when the node is operating as an IP router and often is meaningless when embedded into an application, unless that application also implements either VPN functionality or deals with IP packets specifically.

func (*Core) TreeID Uses

func (c *Core) TreeID() *crypto.TreeID

TreeID gets the tree ID. This is derived from your switch signing keys. There is typically no need to share this key.

func (*Core) UpdateConfig Uses

func (c *Core) UpdateConfig(config *config.NodeConfig)

UpdateConfig updates the configuration in Core with the provided config.NodeConfig and then signals the various module goroutines to reconfigure themselves if needed.

type DHTEntry Uses

type DHTEntry struct {
    PublicKey crypto.BoxPubKey
    Coords    []uint64
    LastSeen  time.Duration
}

DHTEntry represents a single DHT entry that has been learned or cached from DHT searches.

type DHTRes Uses

type DHTRes struct {
    PublicKey crypto.BoxPubKey // key of the sender
    Coords    []uint64         // coords of the sender
    Dest      crypto.NodeID    // the destination node ID
    Infos     []DHTEntry       // response
}

DHTRes represents a DHT response, as returned by DHTPing.

type Dialer Uses

type Dialer struct {
    // contains filtered or unexported fields
}

Dialer represents an Yggdrasil connection dialer.

func (*Dialer) Dial Uses

func (d *Dialer) Dial(network, address string) (net.Conn, error)

Dial opens a session to the given node. The first parameter should be "curve25519" or "nodeid" and the second parameter should contain a hexadecimal representation of the target. It uses DialContext internally.

func (*Dialer) DialByNodeIDandMask Uses

func (d *Dialer) DialByNodeIDandMask(ctx context.Context, nodeID, nodeMask *crypto.NodeID) (net.Conn, error)

DialByNodeIDandMask opens a session to the given node based on raw NodeID parameters. If ctx is nil or has no timeout, then a default timeout of 6 seconds will apply, beginning *after* the search finishes.

func (*Dialer) DialByPublicKey Uses

func (d *Dialer) DialByPublicKey(ctx context.Context, pubKey *crypto.BoxPubKey) (net.Conn, error)

DialByPublicKey opens a session to the given node based on the public key. If ctx is nil or has no timeout, then a default timeout of 6 seconds will apply, beginning *after* the search finishes.

func (*Dialer) DialContext Uses

func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error)

DialContext is used internally by Dial, and should only be used with a context that includes a timeout. It uses DialByNodeIDandMask internally when the network is "nodeid", or DialByPublicKey when the network is "curve25519".

type FlowKeyMessage Uses

type FlowKeyMessage struct {
    FlowKey uint64
    Message []byte
}

type Listener Uses

type Listener struct {
    // contains filtered or unexported fields
}

Listener waits for incoming sessions

func (*Listener) Accept Uses

func (l *Listener) Accept() (net.Conn, error)

Accept blocks until a new incoming session is received

func (*Listener) Addr Uses

func (l *Listener) Addr() net.Addr

Addr returns the address of the listener

func (*Listener) Close Uses

func (l *Listener) Close() (err error)

Close will stop the listener

type MTU Uses

type MTU = types.MTU

type NodeInfoPayload Uses

type NodeInfoPayload []byte

NodeInfoPayload represents a RequestNodeInfo response, in bytes.

type Peer Uses

type Peer struct {
    PublicKey  crypto.BoxPubKey // The public key of the remote node
    Endpoint   string           // The connection string used to connect to the peer
    BytesSent  uint64           // Number of bytes sent to this peer
    BytesRecvd uint64           // Number of bytes received from this peer
    Protocol   string           // The transport protocol that this peer is connected with, typically "tcp"
    Port       uint64           // Switch port number for this peer connection
    Uptime     time.Duration    // How long this peering has been active for
}

Peer represents a single peer object. This contains information from the preferred switch port for this peer, although there may be more than one active switch port connection to the peer in reality.

This struct is informational only - you cannot manipulate peer connections using instances of this struct. You should use the AddPeer or RemovePeer functions instead.

type Session Uses

type Session struct {
    PublicKey   crypto.BoxPubKey // The public key of the remote node
    Coords      []uint64         // The coordinates of the remote node
    BytesSent   uint64           // Bytes sent to the session
    BytesRecvd  uint64           // Bytes received from the session
    MTU         MTU              // The maximum supported message size of the session
    Uptime      time.Duration    // How long this session has been active for
    WasMTUFixed bool             // This field is no longer used
}

Session represents an open session with another node. Sessions are opened in response to traffic being exchanged between two nodes using Conn objects. Note that sessions will automatically be closed by Yggdrasil if no traffic is exchanged for around two minutes.

type SwitchPeer Uses

type SwitchPeer struct {
    PublicKey  crypto.BoxPubKey // The public key of the remote node
    Coords     []uint64         // The coordinates of the remote node
    BytesSent  uint64           // Number of bytes sent via this switch port
    BytesRecvd uint64           // Number of bytes received via this switch port
    Port       uint64           // Switch port number for this switch peer
    Protocol   string           // The transport protocol that this switch port is connected with, typically "tcp"
    Endpoint   string           // The connection string used to connect to the switch peer
}

SwitchPeer represents a switch connection to a peer. Note that there may be multiple switch peers per actual peer, e.g. if there are multiple connections to a given node.

This struct is informational only - you cannot manipulate switch peer connections using instances of this struct. You should use the AddPeer or RemovePeer functions instead.

type SwitchQueue Uses

type SwitchQueue struct {
    ID      string // The ID of the switch queue
    Size    uint64 // The total size, in bytes, of the queue
    Packets uint64 // The number of packets in the queue
    Port    uint64 // The switch port to which the queue applies
}

SwitchQueue represents a single switch queue. Switch queues are only created in response to congestion on a given link and represent how much data has been temporarily cached for sending once the congestion has cleared.

type SwitchQueues Uses

type SwitchQueues struct {
    Queues       []SwitchQueue // An array of SwitchQueue objects containing information about individual queues
    Count        uint64        // The current number of active switch queues
    Size         uint64        // The current total size of active switch queues
    HighestCount uint64        // The highest recorded number of switch queues so far
    HighestSize  uint64        // The highest recorded total size of switch queues so far
    MaximumSize  uint64        // The maximum allowed total size of switch queues, as specified by config
}

SwitchQueues represents information from the switch related to link congestion and a list of switch queues created in response to congestion on a given link.

type TcpListener Uses

type TcpListener struct {
    Listener net.Listener
    // contains filtered or unexported fields
}

TcpListener is a stoppable TCP listener interface. These are typically returned from calls to the ListenTCP() function and are also used internally to represent listeners created by the "Listen" configuration option and for multicast interfaces.

func (*TcpListener) Stop Uses

func (l *TcpListener) Stop()

type TcpUpgrade Uses

type TcpUpgrade struct {
    // contains filtered or unexported fields
}

Package yggdrasil imports 38 packages (graph) and is imported by 5 packages. Updated 2020-04-02. Refresh now. Tools for package owners.