gtcp

package module
v0.0.0-...-2c3aaa8 Latest Latest
Warning

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

Go to latest
Published: Jan 10, 2017 License: Apache-2.0 Imports: 11 Imported by: 0

README

gtcp

Go Report Card Build Status Coverage Status GoDoc

Package gtcp is a TCP server framework that inherits battle-tested code from net/http and can be extended through built-in interfaces.

Features
  • Can be used in the same manner with http.Server(>= 1.8).

    • Make API as much compatible as possible.
    • Make the zero value useful.
  • Inherits as much battle tested code from net/http.

  • Provides much flexiblity through built-in interfaces.

    • ConnHandler
      • ConnHandler
      • KeepAliveHandler that makes it easy to implement keepalive.
      • PipelineHandler that makes it easy to implement pipelining.
    • ConnTracker
      • MapConnTracker that handles force closing active connections also graceful shutdown.
      • WGConnTracker that handles only graceful shutdown using a naive way with sync.WaitGroup.
    • Conn
      • BufferedConn that wraps Conn in bufio.Reader/Writer.
      • StatsConn that wraps Conn to measure incomming/outgoing bytes.
      • DebugConn that wraps Conn to output debug information.
    • Logger
      • BuiltinLogger that logs using standard log package.
    • Retry
      • ExponentialRetry that implements exponential backoff algorithm without jitter.
    • Statistics
      • TrafficStatistics that measures incomming/outgoing traffic across a server.
    • Limiter
      • MaxConnLimiter that limits connections based on the maximum number.
  • Gets GC pressure as little as possible with sync.Pool.

  • Zero 3rd party depentencies.

TODO
  • Support TLS

  • Support multiple listeners

Example

import "github.com/cat2neat/gtcp"

// echo server:
// https://tools.ietf.org/html/rfc862
func echoServer() error {
	srv := &gtcp.Server{
		Addr:    ":1979",
		NewConn: gtcp.NewStatsConn,
		ConnHandler: func(ctx context.Context, conn gtcp.Conn) {
			buf := make([]byte, 1024)
			for {
				n, err := conn.Read(buf)
				if err != nil {
					return
				}
				conn.Write(buf[:n])
				err = conn.Flush()
				if err != nil {
					return
				}
				select {
				case <-ctx.Done():
					// canceled by parent
					return
				default:
				}
			}
		},
	}
	return srv.ListenAndServe()
}

Install

go get -u github.com/cat2neat/gtcp

Documentation

Overview

Package gtcp is a TCP server framework that inherits battle-tested code from net/http and can be extended through built-in interfaces.

### Features

- Can be used in the same manner with http.Server(>= 1.8).

  • Make API as much compatible as possible.
  • Make the zero value useful.

- Inherits as much battle tested code from net/http.

- Provides much flexiblity through built-in interfaces.

  • ConnHandler
  • ConnHandler
  • KeepAliveHandler that makes it easy to implement keepalive.
  • PipelineHandler that makes it easy to implement pipelining.
  • ConnTracker
  • MapConnTracker that handles force closing active connections also graceful shutdown.
  • WGConnTracker that handles only graceful shutdown using a naive way with sync.WaitGroup.
  • Conn
  • BufferedConn that wraps Conn in bufio.Reader/Writer.
  • StatsConn that wraps Conn to measure incomming/outgoing bytes.
  • DebugConn that wraps Conn to output debug information.
  • Logger
  • BuiltinLogger that logs using standard log package.
  • Retry
  • ExponentialRetry that implements exponential backoff algorithm without jitter.
  • Statistics
  • TrafficStatistics that measures incomming/outgoing traffic across a server.
  • Limiter
  • MaxConnLimiter that limits connections based on the maximum number.

- Gets GC pressure as little as possible with sync.Pool.

- Zero 3rd party depentencies.

### TODO

- Support TLS

- Support multiple listeners

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrServerClosed returned when listener got closed through Close/Shutdown.
	ErrServerClosed = errors.New("gtcp: Server closed")
	// ErrAbortHandler is a sentinel panic value to abort a handler.
	// panicking with ErrAbortHandler also suppresses logging of a stack
	// trace to the server's error log.
	ErrAbortHandler = errors.New("gtcp: abort Handler")
)
View Source
var (
	// ErrBufferFull returned when Peek takes a larger value than its buffer.
	ErrBufferFull = errors.New("gtcp: buffer full")
)

Functions

func ListenAndServe

func ListenAndServe(addr string, handler ConnHandler) error

ListenAndServe listens on the TCP network address addr and then calls Serve to handle requests on incoming connections. ListenAndServe always returns a non-nil error.

Types

type BufferedConn

type BufferedConn struct {
	Conn
	// contains filtered or unexported fields
}

BufferedConn implements Conn that wraps Conn in bufio.Reader|Writer.

func (*BufferedConn) Close

func (b *BufferedConn) Close() (err error)

Close closes the internal bufio.Reader|Writer and also Conn. It's protected by sync.Once as multiple goroutines can call especially in case using gtcp.Server.Close|Shutdown.

func (*BufferedConn) Flush

func (b *BufferedConn) Flush() (err error)

Flush writes any buffered data to the underlying Conn.

func (*BufferedConn) Peek

func (b *BufferedConn) Peek(n int) ([]byte, error)

Peek returns the next n bytes without advancing the reader.

func (*BufferedConn) Read

func (b *BufferedConn) Read(buf []byte) (n int, err error)

Read reads data into buf using internal bufio.Reader. It returns the number of bytes read into buf.

func (*BufferedConn) Write

func (b *BufferedConn) Write(buf []byte) (n int, err error)

Write writes the contents of buf into the internal bufio.Writer. It returns the number of bytes written.

type BuiltinLogger

type BuiltinLogger struct{}

BuiltinLogger implements Logger based on the standard log package.

func (BuiltinLogger) Errorf

func (l BuiltinLogger) Errorf(format string, args ...interface{})

Errorf logs error information using the standard log package.

type Conn

type Conn interface {
	net.Conn
	// Flush writes any buffered data to the underlying net.Conn.
	Flush() error

	// SetCancelFunc sets context.CancelFunc that called automatically
	// when Read/Write failed.
	SetCancelFunc(context.CancelFunc)

	// Stats returns in/out bytes gone through this Conn.
	Stats() (int64, int64)

	// SetIdle sets whether this Conn is idle or not.
	// It's used to realize gtcp.Server.Shutdown.
	SetIdle(bool)

	// IsIdle returns whether this Conn is idle or not.
	// It's used to realize gtcp.Server.Shutdown.
	IsIdle() bool

	// Peek returns the next n bytes without advancing the reader.
	Peek(int) ([]byte, error)
}

Conn is the interface that wraps connetcion specific operations in addition to net.Conn.

func NewBaseConn

func NewBaseConn(conn net.Conn) Conn

NewBaseConn takes net.Conn and returns Conn that wraps net.Conn. It's exported only for test purpose.

func NewBufferedConn

func NewBufferedConn(conn Conn) Conn

NewBufferedConn returns Conn wraps a given Conn in bufio.Reader|Writer.

func NewDebugConn

func NewDebugConn(conn Conn) Conn

NewDebugConn returns Conn that logs debug information using standard log.

func NewStatsConn

func NewStatsConn(conn Conn) Conn

NewStatsConn returns Conn that holds in/out bytes.

type ConnHandler

type ConnHandler func(context.Context, Conn)

ConnHandler is the callback function called when Conn gets ready to communicate with peer. You can use ConnHandler to gain full control on socket.

type ConnTracker

type ConnTracker interface {
	// AddConn adds Conn to active connections.
	AddConn(Conn)
	// DelConn deletes Conn from active connections.
	DelConn(Conn)
	// Close closes active connections with the same manner on net/http/Server.Close.
	// In short, force close.
	Close() error
	// Shutdown closes active connections with the same manner on net/http/Server.Shutdown.
	// In short, graceful shutdown.
	Shutdown(context.Context) error
}

ConnTracker is the interface that wraps operations to track active connections.

func NewMapConnTracker

func NewMapConnTracker() ConnTracker

NewMapConnTracker returns a new MapConnTracker as a ConnTracker.

type DebugConn

type DebugConn struct {
	Conn
}

DebugConn implements Conn that logs every Read/Write/Close operations using standard log.

func (*DebugConn) Close

func (d *DebugConn) Close() (err error)

Close closes the internal Conn. It also outputs debug information before/after calling internal Conn.Close().

func (*DebugConn) Read

func (d *DebugConn) Read(buf []byte) (n int, err error)

Read reads data into buf and returns the number of bytes read into buf. It also outputs debug information before/after calling internal Conn.Read.

func (*DebugConn) Write

func (d *DebugConn) Write(buf []byte) (n int, err error)

Write writes the contents of buf and returns the number of bytes written. It also outputs debug information before/after calling internal Conn.Write.

type ExponentialRetry

type ExponentialRetry struct {
	// InitialDelay defines the retry interval at the first retry.
	InitialDelay time.Duration
	// MaxDelay defines the maximum retry interval.
	MaxDelay time.Duration
}

ExponentialRetry implements exponential backoff algorithm without jitter.

func (ExponentialRetry) Backoff

func (er ExponentialRetry) Backoff(retry uint64) time.Duration

Backoff returns a retry interval based on retry.

type Limiter

type Limiter interface {
	// OnConnected is called when Conn accepted on a listener.
	// Returns false if limits it otherwise true.
	OnConnected(Conn) bool
	// OnClosed is called when Conn closed.
	OnClosed(Conn)
}

Limiter is the interface that limits connections accepted.

type Logger

type Logger interface {
	// Errorf logs error information.
	// Arguments are handled in the manner of fmt.Printf.
	Errorf(format string, args ...interface{})
}

Logger is the interface that wraps logging operations.

var (
	// DefaultLogger is the default Logger.
	DefaultLogger Logger = BuiltinLogger{}
)

type MapConnTracker

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

MapConnTracker implements ConnTracker with the same manner on net/http/Server.

func (*MapConnTracker) AddConn

func (ct *MapConnTracker) AddConn(conn Conn)

AddConn adds Conn to active connections using map.

func (*MapConnTracker) Close

func (ct *MapConnTracker) Close() error

Close closes active connections forcefully.

func (*MapConnTracker) DelConn

func (ct *MapConnTracker) DelConn(conn Conn)

DelConn deletes Conn from active connections using map.

func (*MapConnTracker) Shutdown

func (ct *MapConnTracker) Shutdown(ctx context.Context) error

Shutdown closes active connections with the same manner on net/http/Server.Shutdown. It's useful when you use gtcp.Server.SetKeepAliveHandler or use ConnHandler directly with gtcp.Conn.(SetIdle|IsIdle) as Shutdown only try to close idle connections. If the provided context expires before the shutdown is complete, then the context's error is returned.

type MaxConnLimiter

type MaxConnLimiter struct {
	// Max defines the maximum connections.
	Max uint32
	// contains filtered or unexported fields
}

MaxConnLimiter implements Limiter based on the maximum connections.

func (*MaxConnLimiter) OnClosed

func (mc *MaxConnLimiter) OnClosed(conn Conn)

OnClosed decreases the number of current active connections.

func (*MaxConnLimiter) OnConnected

func (mc *MaxConnLimiter) OnConnected(conn Conn) bool

OnConnected returns false if the number of current active connections exceeds Max, otherwise true.

type NewConn

type NewConn func(Conn) Conn

NewConn is the function that takes a Conn and returns another Conn that enables to generate multi layered Conn. ex)

func(conn Conn) Conn {
	return gtcp.NewBufferedConn(gtcp.NewStatsConn(conn))
}

type PipelineReader

type PipelineReader func(io.Reader) ([]byte, error)

PipelineReader is the callback function used with SetPipelineHandler. SetPipelineHandler enables to implement protocol pipelining easily. It's used for reading part of pipelining and dispatch meaningful []byte to PipelineWriter via return value.

type PipelineWriter

type PipelineWriter func([]byte, WriteFlusher) error

PipelineWriter is the callback function used with SetPipelineHandler. SetPipelineHandler enables to implement protocol pipelining easily. It's used for writing part of pipelining and called when receiving a meaningful []byte from PipelineReader.

type ReqHandler

type ReqHandler func(Conn) error

ReqHandler is the callback function used with SetKeepAliveHandler. It's called when Conn gets ready to communicate specifically - accepted by listener - receiving one more byte while being in keepalive You can use ReqHandler with SetKeepAliveHandler to implement keepalive easily.

type Retry

type Retry interface {
	// Backoff returns a retry interval.
	Backoff(uint64) time.Duration
}

Retry is the interface that provides a retry strategy based on a given retry counter.

var (
	// DefaultRetry implements the same behaviour with net/http/Server
	DefaultRetry Retry = ExponentialRetry{
		InitialDelay: 5 * time.Millisecond,
		MaxDelay:     1 * time.Second,
	}
)

type Server

type Server struct {
	// Addr to listen on, ":1979" if empty.
	Addr string

	// ConnHandler handles a tcp connection accepted.
	// It can be used not only directly setting ConnHandler but
	// - Server.SetKeepAliveHandler
	// - Server.SetPipelineHandler
	// Panic occurred if empty.
	ConnHandler ConnHandler

	// NewConn that applied to each tcp connection accepted by listener.
	// It can be
	// - gtcp.NewBufferedConn
	// - gtcp.NewStatsConn
	// - gtcp.NewDebugConn
	// also can be layered like the below.
	//		func(conn Conn) Conn {
	//			return gtcp.NewBufferedConn(gtcp.NewStatsConn(conn))
	//		}
	// None NewConn is applied if empty.
	NewConn NewConn

	// ConnTracker that handles active connections.
	// It can be
	// - gtcp.MapConnTracker
	// - gtcp.WGConnTracker
	// gtcp.MapConnTracker is set if empty.
	ConnTracker ConnTracker

	// Logger that logs if an error occurred in gtcp.
	// It can be
	// - gtcp.BuiltinLogger
	// gtcp.DefaultLogger is set if empty.
	Logger Logger

	// Retry that handles the retry interval when Accept on listner failed.
	// It can be
	// - gtcp.ExponentialRetry
	// gtcp.DefaultRetry is set if empty.(it behaves in the same manner with net/http/Server.
	Retry Retry

	// Limiters that limits connections.
	// It can be
	// - gtcp.MaxConnLimiter
	// also multiple limiters can be set.
	// None Limiter is set if empty.
	Limiters []Limiter

	// Statistics that measures some statistics.
	// It can be
	// - gtcp.TrafficStatistics
	// gtcp.TrafficStatistics is set if empty.
	Statistics Statistics
	// contains filtered or unexported fields
}

Server defines parameters for running a gtcp server. The zero value for Server is a valid configuration.

func (*Server) Close

func (s *Server) Close() (err error)

Close immediately closes the listner and any connections tracked by ConnTracker. Close returns any error returned from closing the listner.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe listens on the TCP network address Addr and then calls Serve to handle requests on incoming connections. If Addr is blank, ":1979" is used. ListenAndServe always returns a non-nil error.

func (*Server) ListenerAddr

func (s *Server) ListenerAddr() net.Addr

ListenerAddr returns the listner.Addr() or nil if listner is empty.

func (*Server) Serve

func (s *Server) Serve(l net.Listener) error

Serve accepts incoming connections on the Listener l, creating a new service goroutine for each. The service goroutines call ConnHandler to reply to them.

func (*Server) SetKeepAliveHandler

func (s *Server) SetKeepAliveHandler(idle time.Duration, h ReqHandler)

SetKeepAliveHandler enables to implement keepalive easily. It call h and call again repeatedly if receiving one more byte while waiting idle time or stop communicating. It also stop when detecting listener got closed.

func (*Server) SetPipelineHandler

func (s *Server) SetPipelineHandler(
	numBuf int,
	pr PipelineReader,
	pw PipelineWriter)

SetPipelineHandler enables to implement protocol pipelining easily. It combines pr and pw with a buffered channel that has numBuf. pr need to implement reading part of pipelining and dispatch meaningful []byte to pw. pw need to implement writing part of pipelining. It stops if pr returns nil buf or any error. It also stop when detecting listener got closed.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) (err error)

Shutdown gracefully shuts down the server without interrupting any active connections. If the provided context expires before the shutdown is complete, then the context's error is returned.

type Statistics

type Statistics interface {
	// AddConnStats adds a Conn statistics.
	AddConnStats(Conn)
	// Reset clears statistics holden now.
	Reset()
	// String returns a string that represents the current statistics.
	String() string
}

Statistics is the interface that wraps operations for accumulating Conn statistics.

type StatsConn

type StatsConn struct {
	Conn
	// InBytes stores incomming bytes.
	InBytes int64
	// OutBytes stores outgoing bytes.
	OutBytes int64
}

StatsConn implements Conn that holds in/out bytes.

func (*StatsConn) Read

func (s *StatsConn) Read(buf []byte) (n int, err error)

Read reads data into buf and returns the number of bytes read into buf. It also adds InBytes and bytes read up.

func (*StatsConn) Stats

func (s *StatsConn) Stats() (int64, int64)

Stats returns in/out bytes gone through this Conn.

func (*StatsConn) Write

func (s *StatsConn) Write(buf []byte) (n int, err error)

Write writes the contents of buf and returns the number of bytes written. It also adds OutBytes and bytes written up.

type TrafficStatistics

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

TrafficStatistics implements Statistics to hold the in/out traffic on a gtcp server.

func (*TrafficStatistics) AddConnStats

func (ts *TrafficStatistics) AddConnStats(conn Conn)

AddConnStats ingests inBytes and outBytes from conn. You need to use StatsConn in gtcp.NewConn if you want in/out traffic.

func (*TrafficStatistics) Reset

func (ts *TrafficStatistics) Reset()

Reset clears statistics holden now.

func (*TrafficStatistics) String

func (ts *TrafficStatistics) String() (str string)

String returns the in/out traffic on a gtcp server as a json string.

type WGConnTracker

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

WGConnTracker implements ConnTracker with sync.WaitGroup. Its Close implemntation is semantically different from what ConnTracker.Close should be. Use MapConnTracker if you want force close active connections.

func (*WGConnTracker) AddConn

func (ct *WGConnTracker) AddConn(Conn)

AddConn adds Conn to active connections using sync.WaitGroup.Add.

func (*WGConnTracker) Close

func (ct *WGConnTracker) Close() error

Close closes(actually waits for get things done) active connections using sync.WaitGroup.Wait.

func (*WGConnTracker) DelConn

func (ct *WGConnTracker) DelConn(Conn)

DelConn deletes Conn from active connections using sync.WaitGroup.Done.

func (*WGConnTracker) Shutdown

func (ct *WGConnTracker) Shutdown(ctx context.Context) error

Shutdown waits for get active connections closed using sync.WaitGroup.Wait.

type WriteFlusher

type WriteFlusher interface {
	io.Writer
	// Flush writes any buffered data to the underlying Conn.
	Flush() error
}

WriteFlusher is the interface that wraps write operations on Conn.

Jump to

Keyboard shortcuts

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