Documentation
¶
Overview ¶
Package proto defines the building blocks for API defined protocols with HBI
Index ¶
- func ClosedChan() chan struct{}
- func NewConnection(wire HBIWire, env *HostingEnv) (*PostingEnd, *HostingEnd, error)
- func Repr(val interface{}) string
- type CancellableContext
- type CleanupMagicFunction
- type HBIC
- type HBIWire
- type HoCo
- func (co *HoCo) Close() error
- func (co *HoCo) CoSeq() string
- func (co *HoCo) FinishRecv() error
- func (co *HoCo) RecvData(d []byte) error
- func (co *HoCo) RecvObj() (interface{}, error)
- func (co *HoCo) RecvStream(ds func() ([]byte, error)) error
- func (co *HoCo) SendCode(code string) error
- func (co *HoCo) SendData(d []byte) error
- func (co *HoCo) SendObj(code string) error
- func (co *HoCo) SendStream(ds func() ([]byte, error)) error
- func (co *HoCo) StartSend() error
- type HostingEnd
- func (ho *HostingEnd) Close()
- func (ho *HostingEnd) Co() *HoCo
- func (ho *HostingEnd) Context() context.Context
- func (ho *HostingEnd) Disconnect(errReason string, trySendPeerError bool)
- func (ho *HostingEnd) Disconnected() bool
- func (ho *HostingEnd) Env() *HostingEnv
- func (ho *HostingEnd) LocalAddr() string
- func (ho *HostingEnd) NetIdent() string
- type HostingEnv
- func (he *HostingEnv) AnkoEnv() *vm.Env
- func (he *HostingEnv) Augment(overridesAndExtras map[string]interface{}) *HostingEnv
- func (he *HostingEnv) ExposeCtor(ctorFunc interface{}, typeAlias string)
- func (he *HostingEnv) ExposeFunction(name string, fun interface{})
- func (he *HostingEnv) ExposeReactor(reactor interface{})
- func (he *HostingEnv) ExposeValue(name string, val interface{})
- func (he *HostingEnv) ExposedNames() []string
- func (he *HostingEnv) Get(name string) interface{}
- func (he *HostingEnv) Ho() *HostingEnd
- func (he *HostingEnv) NameExposed(name string) bool
- func (he *HostingEnv) Po() *PostingEnd
- func (he *HostingEnv) RunInEnv(ctx context.Context, code string) (result interface{}, err error)
- type InitMagicFunction
- type Packet
- type PoCo
- func (co *PoCo) Close() error
- func (co *PoCo) CoSeq() string
- func (co *PoCo) Completed() <-chan struct{}
- func (co *PoCo) RecvData(d []byte) error
- func (co *PoCo) RecvObj() (obj interface{}, err error)
- func (co *PoCo) RecvStream(ds func() ([]byte, error)) error
- func (co *PoCo) SendCode(code string) error
- func (co *PoCo) SendData(d []byte) error
- func (co *PoCo) SendObj(code string) error
- func (co *PoCo) SendStream(ds func() ([]byte, error)) error
- func (co *PoCo) StartRecv() error
- type PostingEnd
- func (po *PostingEnd) Close()
- func (po *PostingEnd) Context() context.Context
- func (po *PostingEnd) Disconnect(errReason string, trySendPeerError bool)
- func (po *PostingEnd) Disconnected() bool
- func (po *PostingEnd) NetIdent() string
- func (po *PostingEnd) NewCo(he *HostingEnv) (*PoCo, error)
- func (po *PostingEnd) Notif(code string) (completed <-chan struct{}, err error)
- func (po *PostingEnd) NotifData(code string, d []byte) (completed <-chan struct{}, err error)
- func (po *PostingEnd) RemoteAddr() string
- type Reactor
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ClosedChan ¶
func ClosedChan() chan struct{}
ClosedChan returns a non-nil channnel guaranteed to have been closed.
func NewConnection ¶
func NewConnection(wire HBIWire, env *HostingEnv) (*PostingEnd, *HostingEnd, error)
NewConnection creates the posting & hosting endpoints from a transport wire with a hosting environment
func Repr ¶
func Repr(val interface{}) string
Repr converts a value object to its textual representation, that can be used to reconstruct the object by Anko (https://github.com/mattn/anko), or an HBI HostingEnv implemented in other programming languages / runtimes.
The syntax is very much JSON like, with `[]interface{}` maps to JSON array, and `map[interface{}]interface{}` maps to JSON object. But note it's not JSON compatible when a non-string key is present.
Despite those few special types, the representation of a value is majorly obtained via `Sprintf("%#v", v)`, which can be customized by overriding `Format(fmt.State, rune)` method of its type, like the example shows. For desired result:
fmt.Printf("(%6s) %s\n", "Repr", hbi.Repr(msg)) fmt.Printf("(%6s) %#v\n", "Repr", msg) fmt.Printf("(%6s) %+v\n", "Long", msg) fmt.Printf("(%6s) %v\n", "Short", msg) fmt.Printf("(%6s) %s\n", "String", msg) // Output: // ( Repr) Msg("Compl","Hello, HBI world!",1557998919) // ( Repr) Msg("Compl","Hello, HBI world!",1557998919) // ( Long) [May 16 17:28:39+08] @Compl: Hello, HBI world! // ( Short) @Compl: Hello, HBI world! // (String) Msg<@Compl
Implement the `Format(fmt.State, rune)` method like this:
func (msg *Msg) Format(s fmt.State, verb rune) { switch verb { case 's': // string form io.WriteString(s, "Msg<@") io.WriteString(s, msg.From) case 'v': if s.Flag('#') { // repr form io.WriteString(s, "Msg(") io.WriteString(s, fmt.Sprintf("%#v", msg.From)) io.WriteString(s, ",") io.WriteString(s, fmt.Sprintf("%#v", msg.Content)) io.WriteString(s, ",") io.WriteString(s, fmt.Sprintf("%d", msg.Time.Unix())) io.WriteString(s, ")") } else { // value form if s.Flag('+') { io.WriteString(s, "[") io.WriteString(s, msg.Time.Format("Jan 02 15:04:05Z07")) io.WriteString(s, "] ") } io.WriteString(s, "@") io.WriteString(s, msg.From) io.WriteString(s, ": ") io.WriteString(s, msg.Content) } } }
See: https://docs.python.org/3/library/functions.html#repr and https://docs.python.org/3/reference/datamodel.html#object.__repr__ for a similar construct in Python.
Expand the `Example` section below to see full source.
Types ¶
type CancellableContext ¶
type CancellableContext interface { // be a context.Context context.Context // allow explicit cancel and query of cancelled state Cancel(err error) Cancelled() bool }
CancellableContext defines an interface compatible with `context.Context`, and its cancelled status can be queried without blocking wait.
This comes at a cost of an extra `sync.RWMutex` to synchronize the querying and setting of the state.
func NewCancellableContext ¶
func NewCancellableContext() CancellableContext
NewCancellableContext creates a new context that is cancellable.
type CleanupMagicFunction ¶
type CleanupMagicFunction = func(po *PostingEnd, ho *HostingEnd, discReason string)
CleanupMagicFunction is the prototype for magic functions to be called on HBI wire disconnected.
Such a function should be exposed with name `__hbi_cleanup__` from the `HostingEnv`.
note: this interface should really be defined in `he` package, but that'll create cyclic imports between `proto` and `he`.
type HBIC ¶
type HBIC struct { // embed a cancellable context CancellableContext // contains filtered or unexported fields }
HBIC is designed to interface with HBI wire protocol implementations, HBI applications should not use HBIC directly.
func (*HBIC) Disconnect ¶
func (*HBIC) Ho ¶
func (hbic *HBIC) Ho() *HostingEnd
func (*HBIC) Po ¶
func (hbic *HBIC) Po() *PostingEnd
type HBIWire ¶
type HBIWire interface { NetIdent() string LocalAddr() string RemoteAddr() string SendPacket(payload, wireDir string) (n int64, err error) SendData(d []byte) (n int64, err error) SendStream(ds func() ([]byte, error)) (n int64, err error) RecvPacket() (packet *Packet, err error) RecvData(d []byte) (n int64, err error) RecvStream(ds func() ([]byte, error)) (n int64, err error) Disconnect() }
HBIWire is the abstract interface an HBI wire should implement
type HoCo ¶
type HoCo struct { // hosting env to use for this conversation, if not nil HE *HostingEnv // contains filtered or unexported fields }
HoCo is the passive, hosting conversation.
A HoCo is triggered by a PoCo from peer's posting endpoint, it is automatically available to application, obtained by calling HostingEnd.Co()
func (*HoCo) Close ¶
Close closes this hosting conversation, neither send nor recv operation can be performed with a closed hosting conversation.
Note this can only be called from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) CoSeq ¶
CoSeq returns the sequence number of this conversation.
The sequence of a hosting conversation is always the same as the peer's posting conversation that triggered it.
func (*HoCo) FinishRecv ¶
FinishRecv transits this hosting conversation from `recv` to `work` stage.
As soon as all recv operations done, if some time-consuming work should be carried out to prepare the response to be sent back, a hosting conversation should transit to `work` stage by calling `FinishRecv()`; a hosting conversion should be closed directly, if nothing is supposed to be sent back.
Note this can only be called from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) RecvData ¶
RecvData receives the binary data/stream sent by calling PoCo.SendData() or PoCo.SendStream() with the remote posting conversation which triggered this ho co.
Note this can only be called in `recv` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) RecvObj ¶
RecvObj returns the landed result of a piece of peer-scripting-code sent by calling PoCo.SendObj() with the remote posting conversation which triggered this ho co.
Note this can only be called in `recv` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) RecvStream ¶
RecvStream receives the binary data/stream sent by calling PoCo.SendData() or PoCo.SendStream() with the remote posting conversation which triggered this ho co.
Note this can only be called in `recv` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) SendCode ¶
SendCode sends `code` as back-script to peer's hosting endpoint for landing by its hosting environment. Only side effects are expected from landing of `code` at peer site.
Note this can only be called in `send` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) SendData ¶
SendData sends a single chunk of binary data to peer site, to be received with the remote posting conversation which triggered this ho co, by calling PoCo.RecvData() or PoCo.RecvStream()
Note this can only be called in `send` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) SendObj ¶
SendObj sends `code` to peer's hosting endpoint for landing by its hosting environment, and the landed value to be received by calling PoCo.RecvObj() with the remote posting conversation which triggered this ho co.
Note this can only be called in `send` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) SendStream ¶
SendStream polls callback function `ds()` until it returns a nil []byte or non-nil error, and send each chunk to peer site in order to be received with the remote posting conversation which triggered this ho co, by calling PoCo.RecvData() or PoCo.RecvStream()
`ds()` will be called each time after the chunk returned from the previous call has been sent out.
Note this can only be called in `send` stage, and from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
func (*HoCo) StartSend ¶
StartSend transits this hosting conversation from `recv` or `work` stage to `send` stage.
As soon as all recv operations done, if no time-consuming work needs to be carried out to prepare the response to be sent back, a hosting conversation should transit to `send` stage by calling `StartSend()`; a hosting conversion should be closed directly, if nothing is supposed to be sent back.
As soon as no further back-script and/or data/stream is to be sent with a hosting conversation, it should close to release the underlying HBI transport wire for the next posting conversation to start off or next send-ready hosting conversation to start sending.
Note this can only be called from the dedicated hosting goroutine, i.e. from functions exposed to the hosting environment and called by the peer-scripting-code from the remote posting conversation which triggered this ho co.
type HostingEnd ¶
type HostingEnd struct {
// contains filtered or unexported fields
}
HostingEnd is the application programming interface of a hosting endpoint.
func (*HostingEnd) Close ¶
func (ho *HostingEnd) Close()
Close disconnects the underlying wire of the HBI connection.
func (*HostingEnd) Co ¶
func (ho *HostingEnd) Co() *HoCo
Co returns the current hosting conversation in `recv` stage.
func (*HostingEnd) Context ¶
func (ho *HostingEnd) Context() context.Context
Context returns the conttext associated with the underlying HBI connection.
func (*HostingEnd) Disconnect ¶
func (ho *HostingEnd) Disconnect(errReason string, trySendPeerError bool)
Disconnect disconnects the underlying wire of the HBI connection, optionally with a error message sent to peer site for information purpose.
func (*HostingEnd) Disconnected ¶
func (ho *HostingEnd) Disconnected() bool
Disconnected tells whether the underlying HBI connection has been disconnected.
func (*HostingEnd) Env ¶
func (ho *HostingEnd) Env() *HostingEnv
Env returns the hosting environment that this hosting endpoint is attached to.
func (*HostingEnd) LocalAddr ¶
func (ho *HostingEnd) LocalAddr() string
LocalAddr returns the local network address of the underlying wire.
func (*HostingEnd) NetIdent ¶
func (ho *HostingEnd) NetIdent() string
NetIdent returns the network identification string of the underlying wire.
type HostingEnv ¶
type HostingEnv struct {
// contains filtered or unexported fields
}
HostingEnv is the container of HBI artifacts, including:
- functions
- object constructors (special functions taking n args, returning 1 object)
- reactor methods
- value objects
These artifacts need to be explicitly exposed to a hosting environment, to accomodate landing of `peer-scripting-code` from the other end.
func NewHostingEnv ¶
func NewHostingEnv() *HostingEnv
NewHostingEnv creates a new, empty hosting environment.
func (*HostingEnv) AnkoEnv ¶
func (he *HostingEnv) AnkoEnv() *vm.Env
AnkoEnv returns the underlying Anko (https://github.com/mattn/anko) env.
func (*HostingEnv) Augment ¶
func (he *HostingEnv) Augment(overridesAndExtras map[string]interface{}) *HostingEnv
Augment creates a new hosting environment with the same set of exposed artifacts, optionally having some of the artifacts overridden, and some extra artifacts available.
todo consider spliting overrides and extras as 2 separate args, validate them against exposed named list.
func (*HostingEnv) ExposeCtor ¶
func (he *HostingEnv) ExposeCtor(ctorFunc interface{}, typeAlias string)
ExposeCtor exposes the specified constructor function, with expose name as the function's return type name, or `typeAlias` if it's not empty.
note a constructor function should return one and only one value.
func (*HostingEnv) ExposeFunction ¶
func (he *HostingEnv) ExposeFunction(name string, fun interface{})
ExposeFunction exposes an arbitrary function to this env.
func (*HostingEnv) ExposeReactor ¶
func (he *HostingEnv) ExposeReactor(reactor interface{})
ExposeReactor exposes all methods declared (by the list returned from `NamesToExpose`) from `reactor`. If `reactor` does not implements `Reactor`, all its exported methods are exposed.
func (*HostingEnv) ExposeValue ¶
func (he *HostingEnv) ExposeValue(name string, val interface{})
ExposeValue exposes the specified `val` with `name`.
func (*HostingEnv) ExposedNames ¶
func (he *HostingEnv) ExposedNames() []string
ExposedNames returns a copy of the slice of names, ever exposed through the `Expose*()` calles, up to the point it is called.
func (*HostingEnv) Get ¶
func (he *HostingEnv) Get(name string) interface{}
Get returns what ever value associated with `name` in this env, which can be an:
- exposed artifact
- intrinsic object
- implanted artifact by peer script
or nil if the name does not bind to anything in this env.
func (*HostingEnv) Ho ¶
func (he *HostingEnv) Ho() *HostingEnd
Ho returns the hosting endpoint attached to this env.
func (*HostingEnv) NameExposed ¶
func (he *HostingEnv) NameExposed(name string) bool
NameExposed tells whether the specified name is exported from this env, up to the point it is called.
func (*HostingEnv) Po ¶
func (he *HostingEnv) Po() *PostingEnd
Po reutrns the posting endpoint attached to this env.
type InitMagicFunction ¶
type InitMagicFunction = func(po *PostingEnd, ho *HostingEnd)
InitMagicFunction is the prototype for magic functions to be called on HBI wire connection made.
Such a function should be exposed with name `__hbi_init__` from the `HostingEnv`.
note: this interface should really be defined in `he` package, but that'll create cyclic imports between `proto` and `he`.
type Packet ¶
Packet is the atomic textual unit to be transfered over an HBI wire
type PoCo ¶
type PoCo struct { // hosting env to use for this conversation, if not nil HE *HostingEnv // contains filtered or unexported fields }
PoCo is the active, posting conversation.
A PoCo is created from application by calling PostingEnd.NewCo()
func (*PoCo) Close ¶
Close closes this posting conversation, neither send nor recv operation can be performed with a closed posting conversation.
Note this can only be called from the goroutine which created this conversation.
func (*PoCo) CoSeq ¶
CoSeq returns the sequence number of this conversation.
The sequence number of a posting conversation is assigned by the posting endpoint created it, the value does not necessarily be unique across a long time period, but won't repeat among a lot of conversations per sent over a wire in line.
func (*PoCo) Completed ¶
func (co *PoCo) Completed() <-chan struct{}
Completed returns the channel that get closed when this posting conversation has been fully processed with the triggered hosting conversation at remote site done.
Subsequent processes depending on the success of this conversation's completion can receive from the returned channel to wait the signal of proceed, with the backing hbic's Done() channel selected together.
Closing of this channel before its backing hbic is closed can confirm the final success of this conversation, as well its `recv` stage. i.e. all peer-scripting-code and data/stream sent with this conversation has been landed by peer's hosting endpoint, with a triggered hosting conversation, and all back-scripts (plus data/stream if any) as the response from that hosting conversation has been landed by local hosting endpoint, and received with this posting conversation (if any recv ops involved).
func (*PoCo) RecvData ¶
RecvData receives the binary data/stream sent with the triggered hosting conversation at remote site via HoCo.SendData() or HoCo.SendStream()
Note this can only be called in `recv` stage, and from the goroutine which created this conversation.
func (*PoCo) RecvObj ¶
RecvObj returns the landed result of a piece of back-script `code` sent with the triggered hosting conversation at remote site via HoCo.SendObj(code)
Note this can only be called in `recv` stage, and from the goroutine which created this conversation.
func (*PoCo) RecvStream ¶
RecvStream receives the binary data/stream sent with the triggered hosting conversation at remote site via HoCo.SendData() or HoCo.SendStream()
Note this can only be called in `recv` stage, and from the goroutine which created this conversation.
func (*PoCo) SendCode ¶
SendCode sends `code` to peer's hosting endpoint for landing by its hosting environment.
Only side effects are expected from landing of `code` at peer site.
Note this can only be called in `send` stage, and from the goroutine which created this conversation.
func (*PoCo) SendData ¶
SendData sends a single chunk of binary data to peer site.
The respective hosting conversation at peer site is expected to receive the data by calling HoCo.RecvData() or HoCo.RecvStream()
Note this can only be called in `send` stage, and from the goroutine which created this conversation.
func (*PoCo) SendObj ¶
SendObj sends `code` to peer's hosting endpoint for landing by its hosting environment.
The respective hosting conversation at peer site is expected to receive the result value from landing of `code`, by calling HoCo.RecvObj()
Note this can only be called in `send` stage, and from the goroutine which created this conversation.
func (*PoCo) SendStream ¶
SendStream polls callback function `ds()` until it returns a nil []byte or non-nil error, and send each chunk to peer site in line. `ds()` will be called another time after the chunk returned from the previous call has been sent out.
The respective hosting conversation at peer site is expected to receive the data by calling HoCo.RecvData() or HoCo.RecvStream()
Note this can only be called in `send` stage, and from the goroutine which created this conversation.
func (*PoCo) StartRecv ¶
StartRecv transits this posting conversation from `send` stage to `recv` stage.
Once in `recv` stage, no `send` operation can be performed any more with this conversation, the underlying wire is released for other posting conversation to start off.
Note this can only be called in `send` stage, and from the goroutine which created this conversation.
type PostingEnd ¶
type PostingEnd struct {
// contains filtered or unexported fields
}
PostingEnd is the application programming interface of a posting endpoint.
func (*PostingEnd) Close ¶
func (po *PostingEnd) Close()
Close disconnects the underlying wire of the HBI connection.
func (*PostingEnd) Context ¶
func (po *PostingEnd) Context() context.Context
Context returns the conttext associated with the underlying HBI connection.
func (*PostingEnd) Disconnect ¶
func (po *PostingEnd) Disconnect(errReason string, trySendPeerError bool)
Disconnect disconnects the underlying wire of the HBI connection, optionally with a error message sent to peer site for information purpose.
func (*PostingEnd) Disconnected ¶
func (po *PostingEnd) Disconnected() bool
Disconnected tells whether the underlying HBI connection has been disconnected.
func (*PostingEnd) NetIdent ¶
func (po *PostingEnd) NetIdent() string
NetIdent returns the network identification string of the underlying wire.
func (*PostingEnd) NewCo ¶
func (po *PostingEnd) NewCo(he *HostingEnv) (*PoCo, error)
NewCo starts a new posting conversation.
func (*PostingEnd) Notif ¶
func (po *PostingEnd) Notif(code string) (completed <-chan struct{}, err error)
Notif is shorthand to (implicitly) create a posting conversation, which is closed immediately after `code` is sent with it.
the `completed` channel returned can be received from, to wait acknowledgement for end of conversation has been received from remote peer.
func (*PostingEnd) NotifData ¶
func (po *PostingEnd) NotifData(code string, d []byte) (completed <-chan struct{}, err error)
NotifData is shorthand to (implicitly) create a posting conversation, which is closed immediately after `code` and `d` are sent with it.
the `completed` channel returned can be received from, to wait acknowledgement for end of conversation has been received from remote peer.
func (*PostingEnd) RemoteAddr ¶
func (po *PostingEnd) RemoteAddr() string
RemoteAddr returns the remote network address of the underlying wire.
type Reactor ¶
type Reactor interface {
NamesToExpose() []string
}
Reactor is the interface optionally implemented by a type whose instances are to be exposed to a `HostingEnv` by calling `he.ExposeReactor()`.
If a reactor object does not implement this interface, all its exported fields and methods will be exposed.