ble

package module
v0.0.0-...-f9dd7dd Latest Latest
Warning

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

Go to latest
Published: Jul 25, 2019 License: BSD-3-Clause Imports: 14 Imported by: 15

README

ble

ble is a Bluetooth Low Energy package for Linux.

This is a fork of rigado/ble for internal research development for J.M.S's research for the 2019 X-Force Red summer internship

Documentation

Index

Constants

View Source
const DefaultMTU = 23

DefaultMTU defines the default MTU of ATT protocol including 3 bytes of ATT header.

View Source
const MaxMTU = 512 + 3

MaxMTU is maximum of ATT_MTU, which is 512 bytes of value length, plus 3 bytes of ATT header. The maximum length of an attribute value shall be 512 octets [Vol 3, Part F, 3.2.9]

Variables

View Source
var (
	GAPUUID         = UUID16(0x1800) // Generic Access
	GATTUUID        = UUID16(0x1801) // Generic Attribute
	CurrentTimeUUID = UUID16(0x1805) // Current Time Service
	DeviceInfoUUID  = UUID16(0x180A) // Device Information
	BatteryUUID     = UUID16(0x180F) // Battery Service
	HIDUUID         = UUID16(0x1812) // Human Interface Device

	PrimaryServiceUUID   = UUID16(0x2800)
	SecondaryServiceUUID = UUID16(0x2801)
	IncludeUUID          = UUID16(0x2802)
	CharacteristicUUID   = UUID16(0x2803)

	ClientCharacteristicConfigUUID = UUID16(0x2902)
	ServerCharacteristicConfigUUID = UUID16(0x2903)

	DeviceNameUUID        = UUID16(0x2A00)
	AppearanceUUID        = UUID16(0x2A01)
	PeripheralPrivacyUUID = UUID16(0x2A02)
	ReconnectionAddrUUID  = UUID16(0x2A03)
	PeferredParamsUUID    = UUID16(0x2A04)
	ServiceChangedUUID    = UUID16(0x2A05)
)

UUIDs ...

View Source
var (
	// ContextKeySig for SigHandler context
	ContextKeySig = ContextKey("sig")
	// ContextKeyCCC for per connection contexts
	ContextKeyCCC = ContextKey("ccc")
)
View Source
var ErrDefaultDevice = errors.New("default device is not set")

ErrDefaultDevice ...

View Source
var ErrEIRPacketTooLong = errors.New("max packet length is 31")

ErrEIRPacketTooLong is the error returned when an AdvertisingPacket or ScanResponsePacket is too long.

View Source
var ErrNotImplemented = errors.New("not implemented")

ErrNotImplemented means the functionality is not implemented.

Functions

func AddService

func AddService(svc *Service) error

AddService adds a service to database.

func AdvertiseIBeacon

func AdvertiseIBeacon(ctx context.Context, u UUID, major, minor uint16, pwr int8) error

AdvertiseIBeacon advertises iBeacon with specified parameters.

func AdvertiseIBeaconData

func AdvertiseIBeaconData(ctx context.Context, b []byte) error

AdvertiseIBeaconData advertise iBeacon with given manufacturer data.

func AdvertiseNameAndServices

func AdvertiseNameAndServices(ctx context.Context, name string, uuids ...UUID) error

AdvertiseNameAndServices advertises device name, and specified service UUIDs. It tres to fit the UUIDs in the advertising packet as much as possi If name doesn't fit in the advertising packet, it will be put in scan response.

func Contains

func Contains(s []UUID, u UUID) bool

Contains returns a boolean reporting whether u is in the slice s.

func Name

func Name(u UUID) string

Name returns name of know services, characteristics, or descriptors.

func RemoveAllServices

func RemoveAllServices() error

RemoveAllServices removes all services that are currently in the database.

func Reverse

func Reverse(u []byte) []byte

Reverse returns a reversed copy of u.

func Scan

func Scan(ctx context.Context, allowDup bool, h AdvHandler, f AdvFilter) error

Scan starts scanning. Duplicated advertisements will be filtered out if allowDup is set to false.

func SetDefaultDevice

func SetDefaultDevice(d Device)

SetDefaultDevice returns the default HCI device.

func SetServices

func SetServices(svcs []*Service) error

SetServices set the specified service to the database. It removes all currently added services, if any.

func Stop

func Stop() error

Stop detatch the GATT server from a peripheral device.

func WithSigHandler

func WithSigHandler(ctx context.Context, cancel func()) context.Context

WithSigHandler ...

Types

type ATTError

type ATTError byte

ATTError is the error code of Attribute Protocol [Vol 3, Part F, 3.4.1.1].

const (
	ErrSuccess           ATTError = 0x00 // ErrSuccess measn the operation is success.
	ErrInvalidHandle     ATTError = 0x01 // ErrInvalidHandle means the attribute handle given was not valid on this server.
	ErrReadNotPerm       ATTError = 0x02 // ErrReadNotPerm eans the attribute cannot be read.
	ErrWriteNotPerm      ATTError = 0x03 // ErrWriteNotPerm eans the attribute cannot be written.
	ErrInvalidPDU        ATTError = 0x04 // ErrInvalidPDU means the attribute PDU was invalid.
	ErrAuthentication    ATTError = 0x05 // ErrAuthentication means the attribute requires authentication before it can be read or written.
	ErrReqNotSupp        ATTError = 0x06 // ErrReqNotSupp means the attribute server does not support the request received from the client.
	ErrInvalidOffset     ATTError = 0x07 // ErrInvalidOffset means the specified was past the end of the attribute.
	ErrAuthorization     ATTError = 0x08 // ErrAuthorization means the attribute requires authorization before it can be read or written.
	ErrPrepQueueFull     ATTError = 0x09 // ErrPrepQueueFull means too many prepare writes have been queued.
	ErrAttrNotFound      ATTError = 0x0a // ErrAttrNotFound means no attribute found within the given attribute handle range.
	ErrAttrNotLong       ATTError = 0x0b // ErrAttrNotLong means the attribute cannot be read or written using the Read Blob Request.
	ErrInsuffEncrKeySize ATTError = 0x0c // ErrInsuffEncrKeySize means the Encryption Key Size used for encrypting this link is insufficient.
	ErrInvalAttrValueLen ATTError = 0x0d // ErrInvalAttrValueLen means the attribute value length is invalid for the operation.
	ErrUnlikely          ATTError = 0x0e // ErrUnlikely means the attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested.
	ErrInsuffEnc         ATTError = 0x0f // ErrInsuffEnc means the attribute requires encryption before it can be read or written.
	ErrUnsuppGrpType     ATTError = 0x10 // ErrUnsuppGrpType means the attribute type is not a supported grouping attribute as defined by a higher layer specification.
	ErrInsuffResources   ATTError = 0x11 // ErrInsuffResources means insufficient resources to complete the request.
)

ATTError is the error code of Attribute Protocol [Vol 3, Part F, 3.4.1.1].

func (ATTError) Error

func (e ATTError) Error() string

type Addr

type Addr interface {
	String() string
}

Addr represents a network end point address. It's MAC address on Linux or Device UUID on OS X.

func NewAddr

func NewAddr(s string) Addr

NewAddr creates an Addr from string

type AdvFilter

type AdvFilter func(a Advertisement) bool

AdvFilter returns true if the advertisement matches specified condition.

type AdvHandler

type AdvHandler func(a Advertisement)

AdvHandler handles advertisement.

type Advertisement interface {
	LocalName() string
	ManufacturerData() []byte
	ServiceData() []ServiceData
	Services() []UUID
	OverflowService() []UUID
	TxPowerLevel() int
	Connectable() bool
	SolicitedService() []UUID

	RSSI() int
	Addr() Addr
}

Advertisement ...

func Find

func Find(ctx context.Context, allowDup bool, f AdvFilter) ([]Advertisement, error)

Find ...

type Characteristic

type Characteristic struct {
	UUID        UUID
	Property    Property
	Secure      Property // FIXME
	Descriptors []*Descriptor
	CCCD        *Descriptor

	Value []byte

	ReadHandler     ReadHandler
	WriteHandler    WriteHandler
	NotifyHandler   NotifyHandler
	IndicateHandler NotifyHandler

	Handle      uint16
	ValueHandle uint16
	EndHandle   uint16
}

A Characteristic is a BLE characteristic.

func NewCharacteristic

func NewCharacteristic(u UUID) *Characteristic

NewCharacteristic creates and returns a Characteristic.

func (*Characteristic) AddDescriptor

func (c *Characteristic) AddDescriptor(d *Descriptor) *Descriptor

AddDescriptor adds a descriptor to a characteristic. AddDescriptor panics if the characteristic already contains another descriptor with the same UUID.

func (*Characteristic) HandleIndicate

func (c *Characteristic) HandleIndicate(h NotifyHandler)

HandleIndicate makes the characteristic support indicate requests, and routes notification requests to h. HandleIndicate must be called before the containing service is added to a server.

func (*Characteristic) HandleNotify

func (c *Characteristic) HandleNotify(h NotifyHandler)

HandleNotify makes the characteristic support notify requests, and routes notification requests to h. HandleNotify must be called before the containing service is added to a server.

func (*Characteristic) HandleRead

func (c *Characteristic) HandleRead(h ReadHandler)

HandleRead makes the characteristic support read requests, and routes read requests to h. HandleRead must be called before the containing service is added to a server. HandleRead panics if the characteristic has been configured with a static value.

func (*Characteristic) HandleWrite

func (c *Characteristic) HandleWrite(h WriteHandler)

HandleWrite makes the characteristic support write and write-no-response requests, and routes write requests to h. The WriteHandler does not differentiate between write and write-no-response requests; it is handled automatically. HandleWrite must be called before the containing service is added to a server.

func (*Characteristic) NewDescriptor

func (c *Characteristic) NewDescriptor(u UUID) *Descriptor

NewDescriptor adds a descriptor to a characteristic. NewDescriptor panics if the characteristic already contains another descriptor with the same UUID.

func (*Characteristic) SetValue

func (c *Characteristic) SetValue(b []byte)

SetValue makes the characteristic support read requests, and returns a static value. SetValue must be called before the containing service is added to a server. SetValue panics if the characteristic has been configured with a ReadHandler.

type Client

type Client interface {
	// Addr returns platform specific unique ID of the remote peripheral, e.g. MAC on Linux, Client UUID on OS X.
	Addr() Addr

	// Name returns the name of the remote peripheral.
	// This can be the advertised name, if exists, or the GAP device name, which takes priority.
	Name() string

	// Profile returns discovered profile.
	Profile() *Profile

	// DiscoverProfile discovers the whole hierarchy of a server.
	DiscoverProfile(force bool) (*Profile, error)

	// DiscoverServices finds all the primary services on a server. [Vol 3, Part G, 4.4.1]
	// If filter is specified, only filtered services are returned.
	DiscoverServices(filter []UUID) ([]*Service, error)

	// DiscoverIncludedServices finds the included services of a service. [Vol 3, Part G, 4.5.1]
	// If filter is specified, only filtered services are returned.
	DiscoverIncludedServices(filter []UUID, s *Service) ([]*Service, error)

	// DiscoverCharacteristics finds all the characteristics within a service. [Vol 3, Part G, 4.6.1]
	// If filter is specified, only filtered characteristics are returned.
	DiscoverCharacteristics(filter []UUID, s *Service) ([]*Characteristic, error)

	// DiscoverDescriptors finds all the descriptors within a characteristic. [Vol 3, Part G, 4.7.1]
	// If filter is specified, only filtered descriptors are returned.
	DiscoverDescriptors(filter []UUID, c *Characteristic) ([]*Descriptor, error)

	// ReadCharacteristic reads a characteristic value from a server. [Vol 3, Part G, 4.8.1]
	ReadCharacteristic(c *Characteristic) ([]byte, error)

	// ReadLongCharacteristic reads a characteristic value which is longer than the MTU. [Vol 3, Part G, 4.8.3]
	ReadLongCharacteristic(c *Characteristic) ([]byte, error)

	// WriteCharacteristic writes a characteristic value to a server. [Vol 3, Part G, 4.9.3]
	WriteCharacteristic(c *Characteristic, value []byte, noRsp bool) error

	// ReadDescriptor reads a characteristic descriptor from a server. [Vol 3, Part G, 4.12.1]
	ReadDescriptor(d *Descriptor) ([]byte, error)

	// WriteDescriptor writes a characteristic descriptor to a server. [Vol 3, Part G, 4.12.3]
	WriteDescriptor(d *Descriptor, v []byte) error

	// ReadRSSI retrieves the current RSSI value of remote peripheral. [Vol 2, Part E, 7.5.4]
	ReadRSSI() int

	// ExchangeMTU set the ATT_MTU to the maximum possible value that can be supported by both devices [Vol 3, Part G, 4.3.1]
	ExchangeMTU(rxMTU int) (txMTU int, err error)

	// Subscribe subscribes to indication (if ind is set true), or notification of a characteristic value. [Vol 3, Part G, 4.10 & 4.11]
	Subscribe(c *Characteristic, ind bool, h NotificationHandler) error

	// Unsubscribe unsubscribes to indication (if ind is set true), or notification of a specified characteristic value. [Vol 3, Part G, 4.10 & 4.11]
	Unsubscribe(c *Characteristic, ind bool) error

	// ClearSubscriptions clears all subscriptions to notifications and indications.
	ClearSubscriptions() error

	// CancelConnection disconnects the connection.
	CancelConnection() error

	// Disconnected returns a receiving channel, which is closed when the client disconnects.
	Disconnected() <-chan struct{}

	// Conn returns the client's current connection.
	Conn() Conn
}

A Client is a GATT client.

func Connect

func Connect(ctx context.Context, f AdvFilter) (Client, error)

Connect searches for and connects to a Peripheral which matches specified condition.

func Dial

func Dial(ctx context.Context, a Addr) (Client, error)

Dial ...

type Conn

type Conn interface {
	io.ReadWriteCloser

	// Context returns the context that is used by this Conn.
	Context() context.Context

	// SetContext sets the context that is used by this Conn.
	SetContext(ctx context.Context)

	// LocalAddr returns local device's address.
	LocalAddr() Addr

	// Handle returns the underlying bluetooth firmware connection handle
	Handle() uint16

	// RemoteAddr returns remote device's address.
	RemoteAddr() Addr

	// RxMTU returns the ATT_MTU which the local device is capable of accepting.
	RxMTU() int

	// SetRxMTU sets the ATT_MTU which the local device is capable of accepting.
	SetRxMTU(mtu int)

	// TxMTU returns the ATT_MTU which the remote device is capable of accepting.
	TxMTU() int

	// SetTxMTU sets the ATT_MTU which the remote device is capable of accepting.
	SetTxMTU(mtu int)

	// Disconnected returns a receiving channel, which is closed when the connection disconnects.
	Disconnected() <-chan struct{}
}

Conn implements a L2CAP connection.

type ContextKey

type ContextKey string

ContextKey is a type used for keys of a context

type Descriptor

type Descriptor struct {
	UUID     UUID
	Property Property

	Handle uint16
	Value  []byte

	ReadHandler  ReadHandler
	WriteHandler WriteHandler
}

Descriptor is a BLE descriptor

func NewDescriptor

func NewDescriptor(u UUID) *Descriptor

NewDescriptor creates and returns a Descriptor.

func (*Descriptor) HandleRead

func (d *Descriptor) HandleRead(h ReadHandler)

HandleRead makes the descriptor support read requests, and routes read requests to h. HandleRead must be called before the containing service is added to a server. HandleRead panics if the descriptor has been configured with a static value.

func (*Descriptor) HandleWrite

func (d *Descriptor) HandleWrite(h WriteHandler)

HandleWrite makes the descriptor support write and write-no-response requests, and routes write requests to h. The WriteHandler does not differentiate between write and write-no-response requests; it is handled automatically. HandleWrite must be called before the containing service is added to a server.

func (*Descriptor) SetValue

func (d *Descriptor) SetValue(b []byte)

SetValue makes the descriptor support read requests, and returns a static value. SetValue must be called before the containing service is added to a server. SetValue panics if the descriptor has already configured with a ReadHandler.

type Device

type Device interface {
	// AddService adds a service to database.
	AddService(svc *Service) error

	// RemoveAllServices removes all services that are currently in the database.
	RemoveAllServices() error

	// SetServices set the specified service to the database.
	// It removes all currently added services, if any.
	SetServices(svcs []*Service) error

	// Stop detatch the GATT server from a peripheral device.
	Stop() error

	// Advertise advertises a given Advertisement
	Advertise(ctx context.Context, adv Advertisement) error

	// AdvertiseNameAndServices advertises device name, and specified service UUIDs.
	// It tres to fit the UUIDs in the advertising packet as much as possi
	// If name doesn't fit in the advertising packet, it will be put in scan response.
	AdvertiseNameAndServices(ctx context.Context, name string, uuids ...UUID) error

	// AdvertiseMfgData avertises the given manufacturer data.
	AdvertiseMfgData(ctx context.Context, id uint16, b []byte) error

	// AdvertiseServiceData16 advertises data associated with a 16bit service uuid
	AdvertiseServiceData16(ctx context.Context, id uint16, b []byte) error

	// AdvertiseIBeaconData advertise iBeacon with given manufacturer data.
	AdvertiseIBeaconData(ctx context.Context, b []byte) error

	// AdvertiseIBeacon advertises iBeacon with specified parameters.
	AdvertiseIBeacon(ctx context.Context, u UUID, major, minor uint16, pwr int8) error

	// Scan starts scanning. Duplicated advertisements will be filtered out if allowDup is set to false.
	Scan(ctx context.Context, allowDup bool, h AdvHandler) error

	// Dial ...
	Dial(ctx context.Context, a Addr) (Client, error)
}

Device ...

type DeviceOption

type DeviceOption interface {
	SetDeviceID(int) error
	SetDialerTimeout(time.Duration) error
	SetListenerTimeout(time.Duration) error
	SetConnParams(cmd.LECreateConnection) error
	SetScanParams(cmd.LESetScanParameters) error
	SetAdvParams(cmd.LESetAdvertisingParameters) error
	SetPeripheralRole() error
	SetCentralRole() error
}

DeviceOption is an interface which the device should implement to allow using configuration options

type NotificationHandler

type NotificationHandler func(req []byte)

A NotificationHandler handles notification or indication from a server.

type Notifier

type Notifier interface {
	// Context sends data to the central.
	Context() context.Context

	// Write sends data to the central.
	Write(b []byte) (int, error)

	// Close ...
	Close() error

	// Cap returns the maximum number of bytes that may be sent in a single notification.
	Cap() int
}

Notifier ...

func NewNotifier

func NewNotifier(send func([]byte) (int, error)) Notifier

NewNotifier ...

type NotifyHandler

type NotifyHandler interface {
	ServeNotify(req Request, n Notifier)
}

A NotifyHandler handles GATT requests.

type NotifyHandlerFunc

type NotifyHandlerFunc func(req Request, n Notifier)

NotifyHandlerFunc is an adapter to allow the use of ordinary functions as Handlers.

func (NotifyHandlerFunc) ServeNotify

func (f NotifyHandlerFunc) ServeNotify(req Request, n Notifier)

ServeNotify returns f(r, maxlen, offset).

type Option

type Option func(DeviceOption) error

An Option is a configuration function, which configures the device.

func OptAdvParams

func OptAdvParams(param cmd.LESetAdvertisingParameters) Option

OptAdvParams overrides default advertising parameters.

func OptCentralRole

func OptCentralRole() Option

OptCentralRole configures the device to perform Central tasks.

func OptConnParams

func OptConnParams(param cmd.LECreateConnection) Option

OptConnParams overrides default connection parameters.

func OptDeviceID

func OptDeviceID(id int) Option

OptDeviceID sets HCI device ID.

func OptDialerTimeout

func OptDialerTimeout(d time.Duration) Option

OptDialerTimeout sets dialing timeout for Dialer.

func OptListenerTimeout

func OptListenerTimeout(d time.Duration) Option

OptListenerTimeout sets dialing timeout for Listener.

func OptPeripheralRole

func OptPeripheralRole() Option

OptPeripheralRole configures the device to perform Peripheral tasks.

func OptScanParams

func OptScanParams(param cmd.LESetScanParameters) Option

OptScanParams overrides default scanning parameters.

type Profile

type Profile struct {
	Services []*Service
}

A Profile is composed of one or more services necessary to fulfill a use case.

func (*Profile) Find

func (p *Profile) Find(target interface{}) interface{}

Find searches discovered profile for the specified target's type and UUID. The target must has the type of *Service, *Characteristic, or *Descriptor.

func (*Profile) FindCharacteristic

func (p *Profile) FindCharacteristic(char *Characteristic) *Characteristic

FindCharacteristic searches discoverd profile for the specified characteristic and UUID

func (*Profile) FindDescriptor

func (p *Profile) FindDescriptor(desc *Descriptor) *Descriptor

FindDescriptor searches discoverd profile for the specified descriptor and UUID

func (*Profile) FindService

func (p *Profile) FindService(service *Service) *Service

FindService searches discoverd profile for the specified service and UUID

type Property

type Property int

Property ...

const (
	CharBroadcast   Property = 0x01 // may be brocasted
	CharRead        Property = 0x02 // may be read
	CharWriteNR     Property = 0x04 // may be written to, with no reply
	CharWrite       Property = 0x08 // may be written to, with a reply
	CharNotify      Property = 0x10 // supports notifications
	CharIndicate    Property = 0x20 // supports Indications
	CharSignedWrite Property = 0x40 // supports signed write
	CharExtended    Property = 0x80 // supports extended properties
)

Characteristic property flags (spec 3.3.3.1)

type ReadHandler

type ReadHandler interface {
	ServeRead(req Request, rsp ResponseWriter)
}

A ReadHandler handles GATT requests.

type ReadHandlerFunc

type ReadHandlerFunc func(req Request, rsp ResponseWriter)

ReadHandlerFunc is an adapter to allow the use of ordinary functions as Handlers.

func (ReadHandlerFunc) ServeRead

func (f ReadHandlerFunc) ServeRead(req Request, rsp ResponseWriter)

ServeRead returns f(r, maxlen, offset).

type Request

type Request interface {
	Conn() Conn
	Data() []byte
	Offset() int
}

Request ...

func NewRequest

func NewRequest(conn Conn, data []byte, offset int) Request

NewRequest returns a default implementation of Request.

type ResponseWriter

type ResponseWriter interface {
	// Write writes data to return as the characteristic value.
	Write(b []byte) (int, error)

	// Status reports the result of the request.
	Status() ATTError

	// SetStatus reports the result of the request.
	SetStatus(status ATTError)

	// Len ...
	Len() int

	// Cap ...
	Cap() int
}

ResponseWriter ...

func NewResponseWriter

func NewResponseWriter(buf *bytes.Buffer) ResponseWriter

NewResponseWriter ...

type Service

type Service struct {
	UUID            UUID
	Characteristics []*Characteristic

	Handle    uint16
	EndHandle uint16
}

A Service is a BLE service.

func NewService

func NewService(u UUID) *Service

NewService creates and initialize a new Service using u as it's UUID.

func (*Service) AddCharacteristic

func (s *Service) AddCharacteristic(c *Characteristic) *Characteristic

AddCharacteristic adds a characteristic to a service. AddCharacteristic panics if the service already contains another characteristic with the same UUID.

func (*Service) NewCharacteristic

func (s *Service) NewCharacteristic(u UUID) *Characteristic

NewCharacteristic adds a characteristic to a service. NewCharacteristic panics if the service already contains another characteristic with the same UUID.

type ServiceData

type ServiceData struct {
	UUID UUID
	Data []byte
}

ServiceData ...

type UUID

type UUID []byte

A UUID is a BLE UUID.

func MustParse

func MustParse(s string) UUID

MustParse parses a standard-format UUID string, like Parse, but panics in case of error.

func Parse

func Parse(s string) (UUID, error)

Parse parses a standard-format UUID string, such as "1800" or "34DA3AD1-7110-41A1-B1EF-4430F509CDE7".

func UUID16

func UUID16(i uint16) UUID

UUID16 converts a uint16 (such as 0x1800) to a UUID.

func (UUID) Equal

func (u UUID) Equal(v UUID) bool

Equal returns a boolean reporting whether v represent the same UUID as u.

func (UUID) Len

func (u UUID) Len() int

Len returns the length of the UUID, in bytes. BLE UUIDs are either 2 or 16 bytes.

func (UUID) String

func (u UUID) String() string

String hex-encodes a UUID.

type WriteHandler

type WriteHandler interface {
	ServeWrite(req Request, rsp ResponseWriter)
}

A WriteHandler handles GATT requests.

type WriteHandlerFunc

type WriteHandlerFunc func(req Request, rsp ResponseWriter)

WriteHandlerFunc is an adapter to allow the use of ordinary functions as Handlers.

func (WriteHandlerFunc) ServeWrite

func (f WriteHandlerFunc) ServeWrite(req Request, rsp ResponseWriter)

ServeWrite returns f(r, maxlen, offset).

Jump to

Keyboard shortcuts

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