trafficshape

package
v3.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2024 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package trafficshape provides tools for simulating latency and bandwidth at the network layer.

Index

Constants

This section is empty.

Variables

View Source
var DefaultBitrate int64 = 500000000000 // 500Gbps (unlimited)

DefaultBitrate represents the bitrate that will be for all url regexs for which a shape has not been specified.

View Source
var (
	// ErrBucketOverflow is an error that indicates the bucket has been overflown
	// by the user. This error is only returned iff fill > capacity.
	ErrBucketOverflow = errors.New("trafficshape: bucket overflow")
)

Functions

This section is empty.

Types

type Action

type Action interface {
	// contains filtered or unexported methods
}

Action represents an arbitrary event that needs to be executed while writing back to the client.

type Bandwidth

type Bandwidth struct {
	Up   int64 `json:"up"`
	Down int64 `json:"down"`
}

Bandwidth encloses information about the upstream and downstream bandwidths.

type Bucket

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

Bucket is a generic leaky bucket that drains at a configurable interval and fills at user defined rate. The bucket may be used concurrently.

func NewBucket

func NewBucket(capacity int64, interval time.Duration) *Bucket

NewBucket returns a new leaky bucket with capacity that is drained at interval.

func (*Bucket) Capacity

func (b *Bucket) Capacity() int64

Capacity returns the capacity of the bucket.

func (*Bucket) Close

func (b *Bucket) Close() error

Close stops the drain loop and marks the bucket as closed.

func (*Bucket) Fill

func (b *Bucket) Fill(fn func(int64) (int64, error)) (int64, error)

Fill calls fn with the available capacity remaining (capacity-fill) and fills the bucket with the number of tokens returned by fn. If the remaining capacity is 0, Fill returns 0, nil. If the remaining capacity is < 0, Fill returns 0, ErrBucketOverflow.

If fn returns an error, it will be returned by Fill along with the remaining capacity.

fn is provided the remaining capacity as a soft maximum, fn is allowed to use more than the remaining capacity without incurring spillage, though this will cause subsequent calls to Fill to return ErrBucketOverflow until the next drain.

If the bucket is closed when Fill is called, fn will not be executed and Fill will return with an error.

func (*Bucket) FillThrottle

func (b *Bucket) FillThrottle(fn func(int64) (int64, error)) (int64, error)

FillThrottle calls fn with the available capacity remaining (capacity-fill) and fills the bucket with the number of tokens returned by fn. If the remaining capacity is <= 0, FillThrottle will wait for the next drain before running fn.

If fn returns an error, it will be returned by FillThrottle along with the number of tokens processed by fn.

fn is provided the remaining capacity as a soft maximum, fn is allowed to use more than the remaining capacity without incurring spillage.

If the bucket is closed when FillThrottle is called, or while waiting for the next drain, fn will not be executed and FillThrottle will return with an error.

func (*Bucket) FillThrottleLocked

func (b *Bucket) FillThrottleLocked(fn func(int64) (int64, error)) (int64, error)

FillThrottleLocked is like FillThrottle, except that it uses a lock to protect the critical section between accessing the fill value and updating it.

func (*Bucket) SetCapacity

func (b *Bucket) SetCapacity(capacity int64)

SetCapacity sets the capacity for the bucket and resets the fill to zero.

type Buckets

type Buckets struct {
	ReadBucket  *Bucket
	WriteBucket *Bucket
}

Buckets contains the read and write buckets for a url_regex.

func NewBuckets

func NewBuckets(up int64, down int64) *Buckets

NewBuckets returns a *Buckets with the specified up and down bandwidths.

type ChangeBandwidth

type ChangeBandwidth struct {
	Byte      int64
	Bandwidth int64
}

ChangeBandwidth represents the event of changing the current bandwidth. It is used as an endpoint of a Throttle. It implements the Action interface.

type CloseConnection

type CloseConnection struct {
	Byte  int64 `json:"byte"`
	Count int64 `json:"count"`
}

CloseConnection is an event that represents the closing of a connection with a client. It implements the Action interface.

type ConfigRequest

type ConfigRequest struct {
	Trafficshape *Trafficshape `json:"trafficshape"`
}

ConfigRequest represents a request to configure the global traffic shape.

type Conn

type Conn struct {
	Context *Context

	// Shapes represents the traffic shape map inherited from the listener.
	Shapes        *urlShapes
	GlobalBuckets map[string]*Bucket
	// LocalBuckets represents a map from the url_regexes to their dedicated buckets.
	LocalBuckets map[string]*Buckets
	Established  time.Time
	// Established is the time that the connection is established.
	DefaultBandwidth Bandwidth
	Listener         *Listener
	ReadBucket       *Bucket // Shared by listener.
	WriteBucket      *Bucket // Shared by listener.
	// contains filtered or unexported fields
}

Conn wraps a net.Conn and simulates connection latency and bandwidth charateristics.

func (*Conn) CheckExistenceAndValidity

func (c *Conn) CheckExistenceAndValidity(URLRegex string) bool

CheckExistenceAndValidity checks that the current url regex is present in the map, and that the connection was established before the url shape map was last updated. We do not allow the updated url shape map to traffic shape older connections. Important: Assumes you have acquired the required locks and will release them youself.

func (*Conn) Close

func (c *Conn) Close() error

Close closes the connection. Any blocked Read or Write operations will be unblocked and return errors.

func (*Conn) GetCurrentThrottle

func (c *Conn) GetCurrentThrottle(start int64) *ThrottleContext

GetCurrentThrottle uses binary search to determine if the current byte offset ('start') lies within a throttle interval. If so, also returns the bandwidth specified for that interval.

func (*Conn) GetNextActionFromByte

func (c *Conn) GetNextActionFromByte(start int64) *NextActionInfo

GetNextActionFromByte takes in a byte offset and uses binary search to determine the upcoming action, i.e the first action after the byte that still has a non zero count.

func (*Conn) GetNextActionFromIndex

func (c *Conn) GetNextActionFromIndex(ind int64) *NextActionInfo

GetNextActionFromIndex takes in an index and returns the first action after the index that has a non zero count, if there is one.

func (*Conn) GetWrappedConn

func (c *Conn) GetWrappedConn() net.Conn

GetWrappedConn returns the undrelying trafficshaped net.Conn.

func (*Conn) LocalAddr

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

LocalAddr returns the local network address.

func (*Conn) Read

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

Read reads bytes from connection into b, optionally simulating connection latency and throttling read throughput based on desired bandwidth constraints.

func (*Conn) ReadFrom

func (c *Conn) ReadFrom(r io.Reader) (int64, error)

ReadFrom reads data from r until EOF or error, optionally simulating connection latency and throttling read throughput based on desired bandwidth constraints.

func (*Conn) RemoteAddr

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

RemoteAddr returns the remote network address.

func (*Conn) SetDeadline

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

SetDeadline sets the read and write deadlines associated with the connection. It is equivalent to calling both SetReadDeadline and SetWriteDeadline.

A deadline is an absolute time after which I/O operations fail with a timeout (see type Error) instead of blocking. The deadline applies to all future and pending I/O, not just the immediately following call to Read or Write. After a deadline has been exceeded, the connection can be refreshed by setting a deadline in the future.

An idle timeout can be implemented by repeatedly extending the deadline after successful Read or Write calls.

A zero value for t means I/O operations will not time out.

Note that if a TCP connection has keep-alive turned on, which is the default unless overridden by Dialer.KeepAlive or ListenConfig.KeepAlive, then a keep-alive failure may also return a timeout error. On Unix systems a keep-alive failure on I/O can be detected using errors.Is(err, syscall.ETIMEDOUT).

func (*Conn) SetReadDeadline

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

SetReadDeadline sets the deadline for future Read calls and any currently-blocked Read call. A zero value for t means Read will not time out.

func (*Conn) SetWriteDeadline

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

SetWriteDeadline sets the deadline for future Write calls and any currently-blocked Write call. Even if write times out, it may return n > 0, indicating that some of the data was successfully written. A zero value for t means Write will not time out.

func (*Conn) Write

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

Write writes bytes from b to the connection, while enforcing throttles and performing actions. It uses and updates the Context in the connection.

func (*Conn) WriteDefaultBuckets

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

WriteDefaultBuckets writes bytes from b to the connection, optionally simulating connection latency and throttling write throughput based on desired bandwidth constraints. It uses the WriteBucket inherited from the listener.

func (*Conn) WriteTo

func (c *Conn) WriteTo(w io.Writer) (int64, error)

WriteTo writes data to w from the connection, optionally simulating connection latency and throttling write throughput based on desired bandwidth constraints.

type Context

type Context struct {
	Shaping            bool
	RangeStart         int64
	URLRegex           string
	Buckets            *Buckets
	GlobalBucket       *Bucket
	ThrottleContext    *ThrottleContext
	NextActionInfo     *NextActionInfo
	ByteOffset         int64
	HeaderLen          int64
	HeaderBytesWritten int64
}

Context represents the current information that is needed while writing back to the client. Only if Shaping is true, that is we are currently writing back a response that matches a certain url_regex will the other values be set correctly. If so, the Buckets represent the buckets to be used for the current url_regex. NextActionInfo tells us whether there is an upcoming action that needs to be performed, and ThrottleContext tells us whether we are currently in a throttle interval (according to the RangeStart). Note, the ThrottleContext is only used once in the start to determine the beginning bandwidth. It need not be updated after that. This is because the subsequent throttles are captured in the upcoming ChangeBandwidth actions. Byte Offset represents the absolute byte offset of response data that we are currently writing back. It does not account for the header data.

type Default

type Default struct {
	Bandwidth Bandwidth `json:"bandwidth"`
	Latency   int64     `json:"latency"`
}

Default encloses information about the default traffic shaping parameters: bandwidth and latency.

type ErrForceClose

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

ErrForceClose is an error that communicates the need to close the connection.

func (*ErrForceClose) Error

func (efc *ErrForceClose) Error() string

type Halt

type Halt struct {
	Byte     int64 `json:"byte"`
	Duration int64 `json:"duration"`
	Count    int64 `json:"count"`
}

Halt is the event that represents a period of time to sleep while writing. It implements the Action interface.

type Handler

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

Handler configures a trafficshape.Listener.

func NewHandler

func NewHandler(l *Listener) *Handler

NewHandler returns an http.Handler to configure traffic shaping.

func (*Handler) ServeHTTP

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request)

ServeHTTP configures latency and bandwidth constraints.

The "latency" query string parameter accepts a duration string in any format supported by time.ParseDuration. The "up" and "down" query string parameters accept integers as bits per second to be used for read and write throughput.

type Listener

type Listener struct {
	net.Listener

	ReadBucket  *Bucket
	WriteBucket *Bucket

	GlobalBuckets map[string]*Bucket
	Shapes        *urlShapes
	// contains filtered or unexported fields
}

Listener wraps a net.Listener and simulates connection latency and bandwidth constraints.

func NewListener

func NewListener(l net.Listener) *Listener

NewListener returns a new bandwidth constrained listener. Defaults to DefaultBitrate (uncapped).

func (*Listener) Accept

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

Accept waits for and returns the next connection to the listener.

func (*Listener) Close

func (l *Listener) Close() error

Close closes the read and write buckets along with the underlying listener.

func (*Listener) Defaults

func (l *Listener) Defaults() *Default

Defaults returns the default traffic shaping parameters for the listener.

func (*Listener) GetTrafficShapedConn

func (l *Listener) GetTrafficShapedConn(oc net.Conn) *Conn

GetTrafficShapedConn takes in a normal connection and returns a traffic shaped connection.

func (*Listener) Latency

func (l *Listener) Latency() time.Duration

Latency returns the latency for connections.

func (*Listener) ReadBitrate

func (l *Listener) ReadBitrate() int64

ReadBitrate returns the bitrate in bits per second for reads.

func (*Listener) SetDefaults

func (l *Listener) SetDefaults(defaults *Default)

SetDefaults sets the default traffic shaping parameters for the listener.

func (*Listener) SetLatency

func (l *Listener) SetLatency(latency time.Duration)

SetLatency sets the initial latency for connections.

func (*Listener) SetReadBitrate

func (l *Listener) SetReadBitrate(bitrate int64)

SetReadBitrate sets the bitrate in bits per second for reads.

func (*Listener) SetWriteBitrate

func (l *Listener) SetWriteBitrate(bitrate int64)

SetWriteBitrate sets the bitrate in bits per second for writes.

func (*Listener) WriteBitrate

func (l *Listener) WriteBitrate() int64

WriteBitrate returns the bitrate in bits per second for writes.

type NextActionInfo

type NextActionInfo struct {
	ActionNext bool
	Index      int64
	ByteOffset int64
}

NextActionInfo represents whether there is an upcoming action. Only if ActionNext is true will the Index and ByteOffset be set correctly.

type Shape

type Shape struct {
	URLRegex         string             `json:"url_regex"`
	MaxBandwidth     int64              `json:"max_global_bandwidth"`
	Throttles        []*Throttle        `json:"throttles"`
	Halts            []*Halt            `json:"halts"`
	CloseConnections []*CloseConnection `json:"close_connections"`
	// Actions are populated after processing Throttles, Halts and CloseConnections.
	// Actions is sorted in the order of byte offset.
	Actions []Action
	// WriteBucket is initialized by us using MaxBandwidth.
	WriteBucket *Bucket
}

Shape encloses the traffic shape of a particular url regex.

type Throttle

type Throttle struct {
	Bytes     string `json:"bytes"`
	Bandwidth int64  `json:"bandwidth"`
	ByteStart int64
	ByteEnd   int64
}

Throttle represents a byte interval with a specific bandwidth.

type ThrottleContext

type ThrottleContext struct {
	ThrottleNow bool
	Bandwidth   int64
}

ThrottleContext represents whether we are currently in a throttle interval for a particular url_regex. If ThrottleNow is true, only then will the current throttle 'Bandwidth' be set correctly.

type Trafficshape

type Trafficshape struct {
	Defaults *Default `json:"default"`
	Shapes   []*Shape `json:"shapes"`
}

Trafficshape contains global shape of traffic, i.e information about shape of each url specified and the default traffic shaping parameters.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL