mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-29 06:35:07 +03:00
document address, crypto, and util
This commit is contained in:
parent
903a8921fc
commit
cd99d04bd4
6 changed files with 104 additions and 40 deletions
|
@ -8,12 +8,14 @@ func init() {
|
|||
debug.SetGCPercent(25)
|
||||
}
|
||||
|
||||
// On mobile, just return a nil slice.
|
||||
// GetBytes always returns a nil slice on mobile platforms.
|
||||
func GetBytes() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// On mobile, don't do anything.
|
||||
// PutBytes does literally nothing on mobile platforms.
|
||||
// This is done rather than keeping a free list of bytes on platforms with memory constraints.
|
||||
// It's needed to help keep memory usage low enough to fall under the limits set for e.g. iOS NEPacketTunnelProvider apps.
|
||||
func PutBytes(bs []byte) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,12 +7,12 @@ import "sync"
|
|||
// This is used to buffer recently used slices of bytes, to prevent allocations in the hot loops.
|
||||
var byteStore = sync.Pool{New: func() interface{} { return []byte(nil) }}
|
||||
|
||||
// Gets an empty slice from the byte store.
|
||||
// GetBytes returns a 0-length (possibly nil) slice of bytes from a free list, so it may have a larger capacity.
|
||||
func GetBytes() []byte {
|
||||
return byteStore.Get().([]byte)[:0]
|
||||
}
|
||||
|
||||
// Puts a slice in the store.
|
||||
// PutBytes stores a slice in a free list, where it can potentially be reused to prevent future allocations.
|
||||
func PutBytes(bs []byte) {
|
||||
byteStore.Put(bs)
|
||||
}
|
||||
|
|
|
@ -7,15 +7,22 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Cancellation is used to signal when things should shut down, such as signaling anything associated with a Conn to exit.
|
||||
// This is and is similar to a context, but with an error to specify the reason for the cancellation.
|
||||
type Cancellation interface {
|
||||
Finished() <-chan struct{}
|
||||
Cancel(error) error
|
||||
Error() error
|
||||
Finished() <-chan struct{} // Finished returns a channel which will be closed when Cancellation.Cancel is first called.
|
||||
Cancel(error) error // Cancel closes the channel returned by Finished and sets the error returned by error, or else returns the existing error if the Cancellation has already run.
|
||||
Error() error // Error returns the error provided to Cancel, or nil if no error has been provided.
|
||||
}
|
||||
|
||||
// CancellationFinalized is an error returned if a cancellation object was garbage collected and the finalizer was run.
|
||||
// If you ever see this, then you're probably doing something wrong with your code.
|
||||
var CancellationFinalized = errors.New("finalizer called")
|
||||
|
||||
// CancellationTimeoutError is used when a CancellationWithTimeout or CancellationWithDeadline is cancelled due to said timeout.
|
||||
var CancellationTimeoutError = errors.New("timeout")
|
||||
|
||||
// CancellationFinalizer is set as a finalizer when creating a new cancellation with NewCancellation(), and generally shouldn't be needed by the user, but is included in case other implementations of the same interface want to make use of it.
|
||||
func CancellationFinalizer(c Cancellation) {
|
||||
c.Cancel(CancellationFinalized)
|
||||
}
|
||||
|
@ -27,6 +34,7 @@ type cancellation struct {
|
|||
done bool
|
||||
}
|
||||
|
||||
// NewCancellation returns a pointer to a struct satisfying the Cancellation interface.
|
||||
func NewCancellation() Cancellation {
|
||||
c := cancellation{
|
||||
cancel: make(chan struct{}),
|
||||
|
@ -35,10 +43,12 @@ func NewCancellation() Cancellation {
|
|||
return &c
|
||||
}
|
||||
|
||||
// Finished returns a channel which will be closed when Cancellation.Cancel is first called.
|
||||
func (c *cancellation) Finished() <-chan struct{} {
|
||||
return c.cancel
|
||||
}
|
||||
|
||||
// Cancel closes the channel returned by Finished and sets the error returned by error, or else returns the existing error if the Cancellation has already run.
|
||||
func (c *cancellation) Cancel(err error) error {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
|
@ -52,6 +62,7 @@ func (c *cancellation) Cancel(err error) error {
|
|||
}
|
||||
}
|
||||
|
||||
// Error returns the error provided to Cancel, or nil if no error has been provided.
|
||||
func (c *cancellation) Error() error {
|
||||
c.mutex.RLock()
|
||||
err := c.err
|
||||
|
@ -59,6 +70,7 @@ func (c *cancellation) Error() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// CancellationChild returns a new Cancellation which can be Cancelled independently of the parent, but which will also be Cancelled if the parent is Cancelled first.
|
||||
func CancellationChild(parent Cancellation) Cancellation {
|
||||
child := NewCancellation()
|
||||
go func() {
|
||||
|
@ -71,6 +83,7 @@ func CancellationChild(parent Cancellation) Cancellation {
|
|||
return child
|
||||
}
|
||||
|
||||
// CancellationWithTimeout returns a ChildCancellation that will automatically be Cancelled with a CancellationTimeoutError after the timeout.
|
||||
func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancellation {
|
||||
child := CancellationChild(parent)
|
||||
go func() {
|
||||
|
@ -85,6 +98,7 @@ func CancellationWithTimeout(parent Cancellation, timeout time.Duration) Cancell
|
|||
return child
|
||||
}
|
||||
|
||||
// CancellationWithTimeout returns a ChildCancellation that will automatically be Cancelled with a CancellationTimeoutError after the specified deadline.
|
||||
func CancellationWithDeadline(parent Cancellation, deadline time.Time) Cancellation {
|
||||
return CancellationWithTimeout(parent, deadline.Sub(time.Now()))
|
||||
}
|
||||
|
|
|
@ -9,22 +9,22 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// A wrapper around runtime.Gosched() so it doesn't need to be imported elsewhere.
|
||||
// Yield just executes runtime.Gosched(), and is included so we don't need to explicitly import runtime elsewhere.
|
||||
func Yield() {
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
// A wrapper around runtime.LockOSThread() so it doesn't need to be imported elsewhere.
|
||||
// LockThread executes runtime.LockOSThread(), and is included so we don't need to explicitly import runtime elsewhere.
|
||||
func LockThread() {
|
||||
runtime.LockOSThread()
|
||||
}
|
||||
|
||||
// A wrapper around runtime.UnlockOSThread() so it doesn't need to be imported elsewhere.
|
||||
// UnlockThread executes runtime.UnlockOSThread(), and is included so we don't need to explicitly import runtime elsewhere.
|
||||
func UnlockThread() {
|
||||
runtime.UnlockOSThread()
|
||||
}
|
||||
|
||||
// Gets a slice of the appropriate length, reusing existing slice capacity when possible
|
||||
// ResizeBytes returns a slice of the specified length. If the provided slice has sufficient capacity, it will be resized and returned rather than allocating a new slice.
|
||||
func ResizeBytes(bs []byte, length int) []byte {
|
||||
if cap(bs) >= length {
|
||||
return bs[:length]
|
||||
|
@ -33,7 +33,7 @@ func ResizeBytes(bs []byte, length int) []byte {
|
|||
}
|
||||
}
|
||||
|
||||
// This is a workaround to go's broken timer implementation
|
||||
// TimerStop stops a timer and makes sure the channel is drained, returns true if the timer was stopped before firing.
|
||||
func TimerStop(t *time.Timer) bool {
|
||||
stopped := t.Stop()
|
||||
select {
|
||||
|
@ -43,10 +43,8 @@ func TimerStop(t *time.Timer) bool {
|
|||
return stopped
|
||||
}
|
||||
|
||||
// Run a blocking function with a timeout.
|
||||
// Returns true if the function returns.
|
||||
// Returns false if the timer fires.
|
||||
// The blocked function remains blocked--the caller is responsible for somehow killing it.
|
||||
// FuncTimeout runs the provided function in a separate goroutine, and returns true if the function finishes executing before the timeout passes, or false if the timeout passes.
|
||||
// It includes no mechanism to stop the function if the timeout fires, so the user is expected to do so on their own (such as with a Cancellation or a context).
|
||||
func FuncTimeout(f func(), timeout time.Duration) bool {
|
||||
success := make(chan struct{})
|
||||
go func() {
|
||||
|
@ -63,9 +61,8 @@ func FuncTimeout(f func(), timeout time.Duration) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// This calculates the difference between two arrays and returns items
|
||||
// that appear in A but not in B - useful somewhat when reconfiguring
|
||||
// and working out what configuration items changed
|
||||
// Difference loops over two strings and returns the elements of A which do not appear in B.
|
||||
// This is somewhat useful when needing to determine which elements of a configuration file have changed.
|
||||
func Difference(a, b []string) []string {
|
||||
ab := []string{}
|
||||
mb := map[string]bool{}
|
||||
|
@ -93,7 +90,7 @@ func DecodeCoordString(in string) (out []uint64) {
|
|||
return out
|
||||
}
|
||||
|
||||
// GetFlowLabel takes an IP packet as an argument and returns some information about the traffic flow.
|
||||
// GetFlowKey takes an IP packet as an argument and returns some information about the traffic flow.
|
||||
// For IPv4 packets, this is derived from the source and destination protocol and port numbers.
|
||||
// For IPv6 packets, this is derived from the FlowLabel field of the packet if this was set, otherwise it's handled like IPv4.
|
||||
// The FlowKey is then used internally by Yggdrasil for congestion control.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue