lime

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

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

Go to latest
Published: Dec 18, 2023 License: Apache-2.0 Imports: 22 Imported by: 0

README

LIME - A lightweight messaging library

This is a fork of takenet/lime-go

Go

LIME allows you to build scalable, real-time messaging applications using a JSON-based open protocol. It's fully asynchronous and supports persistent transports like TCP or Websockets.

You can send and receive any type of document into the wire as long it can be represented as JSON or text (plain or encoded with base64) and it has a MIME type to allow the other party to handle it in the right way.

The connected nodes can send receipts to the other parties to notify events about messages (for instance, a message was received or the content invalid or not supported).

Besides that, there's a REST capable command interface with verbs (get, set, and delete) and resource identifiers (URIs) to allow rich messaging scenarios. You can use that to provide services like on-band account registration or instance-messaging resources, like presence or roster management.

Finally, it has built-in support for authentication, transport encryption, and compression.

Getting started

Server

For creating a server and start receiving connections, you should use the lime.Server type, which can be built using the lime.NewServerBuilder() function.

At least one transport listener (TCP, WebSocket, or in-process) should be configured. You also should register handlers for processing the received envelopes.

The example below shows how to create a simple TCP server that echoes every received message to its originator:


package main

import (
	"context"
	"github.com/takenet/lime-go"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
)

func main() {
    // Message handler that echoes all received messages to the originator
    msgHandler := func(ctx context.Context, msg *lime.Message, s lime.Sender) error {
        echoMsg := &lime.Message{}
        echoMsg.SetContent(msg.Content).SetTo(msg.From)
        return s.SendMessage(ctx, echoMsg)
    }

    // Build a server, listening for TCP connections in the 55321 port
    server := lime.NewServerBuilder().
        MessagesHandlerFunc(msgHandler).
        ListenTCP(&net.TCPAddr{Port: 55321}, &lime.TCPConfig{}).
        Build()

    // Listen for the OS termination signals
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
    go func() {
        <-sigs
        if err := server.Close(); err != nil {
            log.Printf("close: %v\n", err)
        }
    }()

    // Start listening (blocking call)
    if err := server.ListenAndServe(); err != lime.ErrServerClosed {
        log.Printf("listen: %v\n", err)
    }
}
Client

On the client-side, you may use the lime.Client type, which can be built using the helper method lime.NewClientBuilder.

package main

import (
	"context"
	"github.com/takenet/lime-go"
	"log"
	"net"
	"time"
)

func main() {
    done := make(chan bool)

    // Defines a simple handler function for printing
    // the received messages to the stdout
    msgHandler := func(ctx context.Context, msg *lime.Message, s lime.Sender) error {
    if txt, ok := msg.Content.(lime.TextDocument); ok {
        log.Printf("Text message received - ID: %v - Type: %v - Content: %v\n", msg.ID, msg.Type, txt)
    }
        close(done)
        return nil
    }

    // Initialize the client
    client := lime.NewClientBuilder().
        UseTCP(&net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55321}, &lime.TCPConfig{}).
        MessagesHandlerFunc(msgHandler).
        Build()

    // Prepare a simple text message to be sent
    msg := &lime.Message{}
    msg.SetContent(lime.TextDocument("Hello world!"))

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    // Send the message
    if err := client.SendMessage(ctx, msg); err != nil {
        log.Printf("send message: %v\n", err)
    }

    // Wait for the echo message
    <-done

    // Close the client
    err := client.Close()
    if err != nil {
        log.Printf("close: %v\n", err)
    }
}

Protocol overview

The base protocol data package is called envelope and there are four types: Message, notification, command and session.

All envelope types share some properties, like the id - the envelope's unique identifier - and the from and to routing information. They also have the optional metadata property, which can be used to send any extra information about the envelope, much like a header in the HTTP protocol.

Message

The message envelope is used to transport a document between sessions. A document is just a type with a known MIME type.

For instance, a message with a text document can be represented like this in JSON:

{
  "id": "1",
  "to": "john",
  "type": "text/plain",
  "content": "Hello from Lime!"
}

In Go, the message envelope is implemented by the lime.Message type:

msg := &lime.Message{}
msg.SetContent(lime.TextDocument("Hello from Lime!")).
    SetID("1").
    SetToString("john")

In this example, the document value is the Hello from Lime! text and its MIME type is text/plain.

This message also has an id property with 1 value. The id value is useful to correlate notifications about the message. When the id is set, the sender may receive notifications (receipts) with message events, which will have the same id. For instance, you may want to know if a message was received or read by its destination. In this case, you should provide an id value to the message.

The to property sets the destination address of the message, and it is used by the server to route the envelope to the correct destination. The address format is called node and in its full form is presented in the name@domain/instance format, similar to the XMPP's Jabber ID. The node's domain and instance portions are optional, so the value john used in the example is a valid node address.

In the previous example, the content is plain text. But a message can be used to transport any type of document that can be represented as JSON.

For instance, to send a generic JSON document you can use the application/json type:

{
  "id": "1",
  "to": "john",
  "type": "application/json",
  "content": {
    "text": "Hello from Lime!",
    "timestamp": "2022-03-23T00:00:00.000Z"
  }
}

Building the same message in Go would be like this:

msg := &lime.Message{}
msg.SetContent(&lime.JsonDocument{
        "text": "Hello from Lime!",
        "timestamp": "2022-03-23T00:00:00.000Z"}).
    SetID("1").
    SetToString("john")

You can also can (and probably should) use custom MIME types for representing well-known types from your application domain:

{
  "id": "1",
  "to": "john",
  "type": "application/x-app-image+json",
  "content": {
    "caption": "Look at this kitten!",
    "url": "https://mycdn.com/cat.jpg"
  }
}

Using custom MIME types enables the mapping of documents with types from your code. For this to be possible, these types need to implement the lime.Document interface.

type Image struct {
    Caption string `json:"caption,omitempty"`
    URL     string `json:"url,omitempty"`
}

func (f *Image) MediaType() lime.MediaType {
    return lime.MediaType{
        Type:    "application",
        Subtype: "x-app-image",
        Suffix:  "json",
    }
}

// To register your custom type, use the RegisterDocumentFactory function.
func init() {
    lime.RegisterDocumentFactory(func() Document {
        return &Image{}
    })
}

For instance, to send a message to the john node, you can use the SendMessage method that is implemented both by the lime.Server and lime.Client types:

msg := &lime.Message{}
msg.SetContent(lime.TextDocument("Hello from Lime!")).
    SetID("1").
    SetToString("john")

err := client.SendMessage(context.Background(), msg)

And for receiving messages, you can use a message handler that can be registered during the instantiation of the client or the server:

client := lime.NewClientBuilder().
    MessagesHandlerFunc(
        func(ctx context.Context, msg *lime.Message, s lime.Sender) error {
            if txt, ok := msg.Content.(lime.TextDocument); ok {
                fmt.Printf("Text message received - ID: %v - Type: %v - Content: %v\n", msg.ID, msg.Type, txt)
            }
            return nil
        }).
	Build()
Notification

A notification provides information about a message to its sender. They are sent only for messages that have the id value defined.

To illustrate, a node may want to notify the sender that a message was received. It can be done like this:

{
  "id": "1",
  "to": "mary",
  "event": "received"
}

The notification to value should have the value of the from property of the message (or the pp value, if present).

In Go, you can use the Notification(event) method from the *lime.Message type for building a notification for the message:

// Creates a corresponding notification to the message
if msg.ID != "" {
    not := msg.Notification(lime.NotificationEventReceived)
    // Send the notification
    err := s.SendNotification(ctx, not)
}

Notifications can be emitted by the destination of the message or by intermediates - like a server that routes the message.

The protocol defines the following notification events:

  • accepted: The message was received and accepted by an intermediate.
  • dispatched: The message was dispatched to the destination by the intermediate.
  • received: The message was received by its destination.
  • consumed: The message was processed (read) by its destination.
  • failed: A problem occurred during the processing of the message.

A single message can have multiple notifications, one or more for each hop on its path to the destination.

By convention, the consumed and failed notifications are considered final, so no other notification should be received by the message sender after one of these.

In case of failed notifications, a reason value should be present.

For instance, a server (intermediate) should notify the sender if it is unable to determine the destination session of a message:

{
  "id": "1",
  "to": "mary",
  "event": "failed",
  "reason": {
    "code": 1,
    "description": "Destination not found"
  }
}

In Go, you can use the message's FailedNotification(reason) method for that:

not := msg.FailedNotification(&lime.Reason{Code: 1, Description: "Destination not found"})
Command

The command envelope is used to read and write resources of a remote node. It provides a REST capable interface, with URI and methods (verbs), similar to the HTTP protocol. It also supports multiplexing, so the connection is not blocked to wait for a response when a request is sent.

There are two types of commands: a request command - which contains a uri value - or a response command - with a status value.

For instance, you can use commands for managing your contact list or to set your current status (available, busy, away). Another common use is the in-band registration, where users can create accounts for your service in the protocol itself.

The advantage of using commands is that you can use the same existing connection that is used for messaging for handling resources, instead of creating out-of-band connections for that.

In practice, you can avoid having an external HTTP service for handling resources related to your messaging service.

This is more efficient in terms of energy consumption but also is usually more performatic as well. Using a session that is already established and authenticated avoids the additional overhead of a TLS handshake and authentication that an external connection would require.

But there is a limitation: the command interface only supports JSON payloads, so you should not use it for transporting binary or any kind of large content.

Like in an HTTP service, the URI and methods that you may use in commands depend on what the server implements.

For instance, a server could implement a contact management service. In this example, to retrieve all contacts, you could send a command like this:

{
  "id": "2",
  "method": "get",
  "uri": "/contacts"
}

And the server may respond to this request like this:

{
  "id": "2",
  "from": "postmaster@localhost/server1",
  "method": "get",
  "status": "success",
  "type": "application/vnd.lime.collection+json",
  "resource": {
    "total": 2,
    "itemType": "application/vnd.lime.contact+json",
    "items": [
      {
        "identity": "john@localhost",
        "name": "John Doe"
      },
      {
        "identity": "mary@localhost",
        "name": "Mary Jane"
      }
    ]
  }
}

This is a response command with a status and a resource value.

Note that the value of the id property is the same as the request. This is how we know that a response is to a specific request, so it is important to avoid using duplicate ids to avoid collisions. A way of doing this is to use GUID (UUID) values as id for the requests.

The status is always present in a response command, but the resource may be present depending on the method of the request and the status of the response. In successful get methods, the value of resource - and consequently type - should be present. In set requests, the resource value will probably not be present. This is similar to the HTTP methods and body, when GET requests will have a value in the response body if successful and not always in POST requests.

In case of failure response status, the command should have the reason property defined:

{
  "id": "2",
  "from": "postmaster@localhost/server1",
  "method": "get",
  "status": "failure",
  "reason": {
    "code": 10,
    "description": "No contact was found"
  }
}

For creating a request command in Go, you can use the lime.RequestCommand type:

reqCmd := &lime.RequestCommand{}
reqCmd.SetURIString("/contacts").
    SetMethod(lime.CommandMethodGet).
    SetID(lime.NewEnvelopeID())

Note that for the id value, we are using the value returned by the lime.NewEnvelopeID() function, which will return a UUID v4 string (something like 3cdd2654-911d-497e-834a-3b7865510155).

For sending a command request, you should use the ProcessCommand method instead of the SendCommand method. This is because the ProcessCommand method takes care of waiting for the corresponding response command.

respCmd, err := client.ProcessCommand(context.Background(), reqCmd)
if err == nil {
    // TODO: Handle the response
}

In the server side, you can add handlers for specific commands using the RequestCommandHandler* methods from the lime.Server type.

server := lime.NewServerBuilder().
    RequestCommandHandlerFunc(
        // Set a predicate for filtering only the get contacts commands
        func(cmd *lime.RequestCommand) bool {
            return cmd.Method == lime.CommandMethodGet && cmd.URI.Path() == "/contacts"
        },
        // The handler implementation
        func(ctx context.Context, cmd *lime.RequestCommand, s lime.Sender) error {
            // Create a document collection of contacts
            contacts := &lime.DocumentCollection{
                Total:    2,
                ItemType: chat.MediaTypeContact(),
                Items: []lime.Document{
                    &chat.Contact{Name: "John Doe"},
                    &chat.Contact{Name: "Mary"},
                },
            }
            // Send the response to the sender
            respCmd := cmd.SuccessResponseWithResource(contacts)
            return s.SendResponseCommand(ctx, respCmd)
        }).
    // TODO: Setup other server options
    Build()

This is also valid for the lime.Client type. In Lime, the client can receive and process commands requests from other nodes, like the server.

Session

Note: The session establishment flow is automatically handled by the library.

The session envelope is used for the negotiation, authentication, and establishment of the communication channel between the client and a server. It helps the parties to select the transport options, like compression and encryption (TLS), authentication credentials, and session metadata, like its id and local/remote node addresses.

The first envelope sent in every Lime session is the new session envelope, which the client sends to the server after the transport connection is established:

{
  "state": "new"
}

The server should reply to this with another session envelope, according to the session state that it wants to enforce.

For instance, the server may want to present the client with the transport options for negotiation. This is useful for applying the TLS encryption to an unencrypted connection (the TCP connection starts without encryption by default).

{
  "id": "0676a702-a7d6-43e6-947f-bde3c3e25eb5",
  "from": "server@localhost/s1",
  "state": "negotiating",
  "compressionOptions": ["none"],
  "encryptionOptions": ["none", "tls"]
}

Note that this envelope haves an id defined, which is the session id. The next session envelopes sent by the client should use this same id, until the end of the session. During the session establishment, only session envelopes are allowed.

The server can skip the negotiating state and jump directly to the authenticating or even to the established state. The session state progression can occur in the following order:

  1. new (started by the client)
  2. negotiating (optional)
  3. authenticating (optional)
  4. established
  5. finishing (optional, started by the client)
  6. finished OR failed (final)

In Go, the session negotiation, authentication, and establishment process is automatically handled by the lime.Client and lime.Server types. You just need to make sure that the server and client are configured accordingly the desired behavior.

For instance, if you want to ensure that the TCP transport connections are using TLS encryption, you will need to configure the server similarly to this:

server := lime.NewServerBuilder().
    // Enable the TLS encryption option for all sessions
    EncryptionOptions(lime.SessionEncryptionTLS).
    // Set up the TCP listener providing a certificate
    ListenTCP(addr, &lime.TCPConfig{
        TLSConfig: &tls.Config{
            GetCertificate: func(info *tls.ClientHelloInfo) (*tls.Certificate, error) {
                cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
                if err != nil {
                    return nil, err
                }
                return &cert, nil
            },
        }}).
    // TODO: Setup other server options
    Build()

And in the client side, you should set up the TLS encryption option and the TCP config:

client := lime.NewClientBuilder().
    Encryption(lime.SessionEncryptionTLS).
    UseTCP(addr, &lime.TCPConfig{
        TLSConfig:   &tls.Config{ServerName: "localhost"},
    }).
    // TODO: Setup other client options
    Build()

You may also want to configure the server and client authentication mechanisms. The Lime Go library supports the following schemes:

  • Guest (no authentication)
  • Plain (password)
  • Key
  • Transport (mutual TLS on TCP)
  • External (token emitted by an issuer)

To enable the use of plain authentication, in the server you should use the EnablePlainAuthentication method passing the authentication handler function, like in the example below:

server := lime.NewServerBuilder().
    EnablePlainAuthentication(
        func(ctx context.Context, i lime.Identity, pwd string) (*lime.AuthenticationResult, error) {
        // TODO: implement checkCredentials to validate the user/password in your secret store
        if checkCredentials(i.Name, pwd) {
            return &lime.AuthenticationResult{Role: lime.DomainRoleMember}, nil
        }
        return &lime.AuthenticationResult{Role: lime.DomainRoleUnknown}, nil
    }).
    // TODO: Setup other server options
    Build()

On the client side, you can use the PlainAuthentication method to set the password that should be used:

client := lime.NewClientBuilder().
    // Sets the identity name and password
    Name("john").
    PlainAuthentication("mysecretpassword").
    // TODO: Setup other client options
    Build()

Documentation

Index

Constants

View Source
const (
	// CommandMethodGet Get an existing value of a resource.
	CommandMethodGet = CommandMethod("get")
	// CommandMethodSet Create or updates the value of a resource.
	CommandMethodSet = CommandMethod("set")
	// CommandMethodDelete Delete a value of the resource or the resource itself.
	CommandMethodDelete = CommandMethod("delete")
	// CommandMethodSubscribe Subscribe To a resource, allowing the originator To be notified when the
	// value of the resource changes in the destination.
	CommandMethodSubscribe = CommandMethod("subscribe")
	// CommandMethodUnsubscribe Unsubscribe To the resource, signaling To the destination that the
	// originator do not want To receive further notifications about the resource.
	CommandMethodUnsubscribe = CommandMethod("unsubscribe")
	// CommandMethodObserve Notify the destination about a change in a resource value of the sender.
	// If the resource value is absent, it represents that the resource in the specified URI was deleted in the originator.
	// This method can be one way and the destination may not send a response for it.
	// Because of that, a command envelope with this method may not have an ID.
	CommandMethodObserve = CommandMethod("observe")
	// CommandMethodMerge Merge a resource document with an existing one. If the resource doesn't exist, it is created.
	CommandMethodMerge = CommandMethod("merge")
)
View Source
const (
	CommandStatusSuccess = CommandStatus("success")
	CommandStatusFailure = CommandStatus("failure")
)
View Source
const (
	MediaTypeText        = "text"
	MediaTypeApplication = "application"
	MediaTypeImage       = "image"
	MediaTypeAudio       = "audio"
	MediaTypeVideo       = "video"
)
View Source
const (
	// NotificationEventAccepted The message was received and accepted by the server.
	// This event is similar To 'received' but is emitted by an intermediate node (hop) and not by the message's final destination.
	NotificationEventAccepted = NotificationEvent("accepted")
	// NotificationEventDispatched The message was dispatched to the destination by the server.
	// This event is similar To the 'consumed' but is emitted by an intermediate node (hop) and not by the message's final destination.
	NotificationEventDispatched = NotificationEvent("dispatched")
	// NotificationEventReceived The node has received the message.
	NotificationEventReceived = NotificationEvent("received")
	// NotificationEventConsumed The node has consumed the Content of the message.
	NotificationEventConsumed = NotificationEvent("consumed")
	// NotificationEventFailed A problem occurred during the processing of the message.
	// In this case, the reason property of the notification should be present.
	NotificationEventFailed = NotificationEvent("failed")
)
View Source
const (
	DomainRoleUnknown       = DomainRole("unknown")       // The identity is not part of the domain.
	DomainRoleMember        = DomainRole("member")        // The identity is a member of the domain.
	DomainRoleAuthority     = DomainRole("authority")     // The identity is an authority of the domain.
	DomainRoleRootAuthority = DomainRole("rootAuthority") // The identity is an authority of the domain and its subdomains.
)
View Source
const (
	// SessionStateNew indicates that the session is new and doesn't exist an established context.
	// It is sent by a client node To start a session with a server.
	SessionStateNew = SessionState("new")
	// SessionStateNegotiating indicates that the server and the client are negotiating the session options,
	// like cryptography and compression.
	// The server sends To the client the options (if available) and
	// the client chooses the desired options. If there's no options
	// (for instance, if the connection is already encrypted or the
	// transport protocol doesn't support these options), the server
	// SHOULD skip the negotiation.
	SessionStateNegotiating = SessionState("negotiating")
	// SessionStateAuthenticating indicates that the session is being authenticated. The server sends To
	// the client the available authentication schemes list and
	// the client must choose one and send the specific authentication
	// data. The authentication can occur in multiple round trips,
	// according To the selected schema.
	SessionStateAuthenticating = SessionState("authenticating")
	// SessionStateEstablished indicates that the session is active, and it is possible To send and receive
	// messages and commands. The server sends this state
	// after the session was authenticated.
	SessionStateEstablished = SessionState("established")
	// SessionStateFinishing indicates that the client node is requesting to the server to finish the session.
	SessionStateFinishing = SessionState("finishing")
	// SessionStateFinished indicates that the session was gracefully finished by the server.
	SessionStateFinished = SessionState("finished")
	// SessionStateFailed indicates that a problem occurred while the session was established, under
	// negotiation or authentication, and it was closed by the server.
	// In this case, the property reason MUST be present to provide
	// more details about the problem.
	SessionStateFailed = SessionState("failed")
)
View Source
const (
	// SessionEncryptionNone The session is not encrypted.
	SessionEncryptionNone = SessionEncryption("none")
	// SessionEncryptionTLS The session is encrypted by TLS (Transport Layer Security).
	SessionEncryptionTLS = SessionEncryption("tls")
)
View Source
const (
	// SessionCompressionNone The session is not compressed.
	SessionCompressionNone = SessionCompression("none")
	// SessionCompressionGzip The session is using the GZip algorithm for compression.
	SessionCompressionGzip = SessionCompression("gzip")
)
View Source
const (
	// AuthenticationSchemeGuest The server doesn't require a client credential, and provides a temporary
	// identity to the node. Some restriction may apply To guest sessions, like
	// the inability of sending some commands or other nodes may want To block
	// messages originated by guest identities.
	AuthenticationSchemeGuest = AuthenticationScheme("guest")
	// AuthenticationSchemePlain Username and password authentication.
	AuthenticationSchemePlain = AuthenticationScheme("plain")
	// AuthenticationSchemeKey Key authentication.
	AuthenticationSchemeKey = AuthenticationScheme("key")
	// AuthenticationSchemeTransport Transport layer authentication.
	AuthenticationSchemeTransport = AuthenticationScheme("transport")
	// AuthenticationSchemeExternal Third-party authentication.
	AuthenticationSchemeExternal = AuthenticationScheme("external")
)
View Source
const DefaultReadLimit int64 = 8192 * 1024
View Source
const InProcessNetwork = "in.process"
View Source
const URISchemeLime = "lime"

Variables

View Source
var ErrServerClosed = errors.New("lime: Server closed")

ErrServerClosed is returned by the Server's ListenAndServe, method after a call to Close.

Functions

func ContextSessionID

func ContextSessionID(ctx context.Context) (string, bool)

ContextSessionID gets the session id from the context.

func GetDocumentFactory

func GetDocumentFactory(t MediaType) (func() Document, error)

func NewCtxConn

func NewCtxConn(conn net.Conn, readTimeout time.Duration, writeTimeout time.Duration) *ctxConn

func NewEnvelopeID

func NewEnvelopeID() string

NewEnvelopeID generates a new unique envelope ID.

func RegisterDocumentFactory

func RegisterDocumentFactory(f func() Document)

RegisterDocumentFactory allow the registration of new Document types, which allow these types to be discovered for the envelope deserialization process.

Types

type Authentication

type Authentication interface {
	GetAuthenticationScheme() AuthenticationScheme
}

Authentication defines a session authentications scheme container

type AuthenticationResult

type AuthenticationResult struct {
	Role      DomainRole
	RoundTrip Authentication
}

AuthenticationResult represents the result of a session authentication.

func AuthorityAuthenticationResult

func AuthorityAuthenticationResult() *AuthenticationResult

func MemberAuthenticationResult

func MemberAuthenticationResult() *AuthenticationResult

func RootAuthorityAuthenticationResult

func RootAuthorityAuthenticationResult() *AuthenticationResult

func UnknownAuthenticationResult

func UnknownAuthenticationResult() *AuthenticationResult

type AuthenticationScheme

type AuthenticationScheme string

AuthenticationScheme Defines the valid authentication schemes values.

type Authenticator

type Authenticator func(schemes []AuthenticationScheme, roundTrip Authentication) Authentication
var GuestAuthenticator Authenticator = func(schemes []AuthenticationScheme, roundTrip Authentication) Authentication {
	return &GuestAuthentication{}
}
var TransportAuthenticator Authenticator = func(schemes []AuthenticationScheme, roundTrip Authentication) Authentication {
	return &TransportAuthentication{}
}

type BoundListener

type BoundListener struct {
	Listener TransportListener
	Addr     net.Addr
}

BoundListener represents a pair of a TransportListener and a net.Addr values.

func NewBoundListener

func NewBoundListener(listener TransportListener, addr net.Addr) BoundListener

type Client

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

Client allow the creation of a Lime connection with a server. The connection lifetime is handled automatically, with automatic reconnections in case of unrequested disconnections. There are methods for sending messages, notifications and command. It also allows the definition of handles for receiving these envelopes from the remote party.

func NewClient

func NewClient(config *ClientConfig, mux *EnvelopeMux) *Client

NewClient creates a new instance of the Client type.

func (*Client) Close

func (c *Client) Close() error

Close stops the listener and finishes any established session with the server.

func (*Client) Establish

func (c *Client) Establish(ctx context.Context) error

Establish forces the establishment of a session, in case of not being already established. It also awaits for any establishment operation that is in progress, returning only when it succeeds.

func (*Client) ProcessCommand

func (c *Client) ProcessCommand(ctx context.Context, cmd *RequestCommand) (*ResponseCommand, error)

ProcessCommand send a RequestCommand to the server and returns the corresponding ResponseCommand.

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, msg *Message) error

SendMessage asynchronously sends a Message to the server. The server may route the Message to another node, accordingly to the specified destination address. It may also send back one or more Notification envelopes, containing status about the Message.

func (*Client) SendNotification

func (c *Client) SendNotification(ctx context.Context, not *Notification) error

SendNotification asynchronously sends a Notification to the server. The server may route the Notification to another node, accordingly to the specified destination address.

func (*Client) SendRequestCommand

func (c *Client) SendRequestCommand(ctx context.Context, cmd *RequestCommand) error

SendRequestCommand asynchronously sends a RequestCommand to the server. The server may route the RequestCommand to another node, accordingly to the specified destination address. This method can be used for sending request and response commands, but in case of requests, it does not await for response. For receiving the response, the ProcessCommand method should be used.

type ClientBuilder

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

ClientBuilder is a helper for building instances of Client. Avoid instantiating it directly, use the NewClientBuilder() function instead.

func NewClientBuilder

func NewClientBuilder() *ClientBuilder

NewClientBuilder creates a new ClientBuilder, which is a helper for building Client instances. It provides a fluent interface for convenience.

func (*ClientBuilder) AutoReplyPings

func (b *ClientBuilder) AutoReplyPings() *ClientBuilder

AutoReplyPings adds a RequestCommandHandler handler to automatically reply ping requests from the remote node.

func (*ClientBuilder) Build

func (b *ClientBuilder) Build() *Client

Build creates a new instance of Client.

func (*ClientBuilder) ChannelBufferSize

func (b *ClientBuilder) ChannelBufferSize(bufferSize int) *ClientBuilder

ChannelBufferSize is the size of the internal envelope buffer used by the ClientChannel. Greater values may improve the performance, but will also increase the process memory usage.

func (*ClientBuilder) Compression

func (b *ClientBuilder) Compression(c SessionCompression) *ClientBuilder

Compression sets the compression to be used in the session negotiation.

func (*ClientBuilder) Domain

func (b *ClientBuilder) Domain(domain string) *ClientBuilder

Domain sets the client's node domain.

func (*ClientBuilder) Encryption

func (b *ClientBuilder) Encryption(e SessionEncryption) *ClientBuilder

Encryption sets the encryption to be used in the session negotiation.

func (*ClientBuilder) ExternalAuthentication

func (b *ClientBuilder) ExternalAuthentication(token, issuer string) *ClientBuilder

ExternalAuthentication enables the use of the external authentication during the session establishment with the server.

func (*ClientBuilder) GuestAuthentication

func (b *ClientBuilder) GuestAuthentication() *ClientBuilder

GuestAuthentication enables the use of the guest authentication scheme during the session establishment with the server.

func (*ClientBuilder) Instance

func (b *ClientBuilder) Instance(instance string) *ClientBuilder

Instance sets the client's node instance.

func (*ClientBuilder) KeyAuthentication

func (b *ClientBuilder) KeyAuthentication(key string) *ClientBuilder

KeyAuthentication enables the use of the key authentication during the session establishment with the server.

func (*ClientBuilder) MessageHandler

func (b *ClientBuilder) MessageHandler(handler MessageHandler) *ClientBuilder

MessageHandler allows the registration of a MessageHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) MessageHandlerFunc

func (b *ClientBuilder) MessageHandlerFunc(predicate MessagePredicate, f MessageHandlerFunc) *ClientBuilder

MessageHandlerFunc allows the registration of a function for handling received messages that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) MessagesHandlerFunc

func (b *ClientBuilder) MessagesHandlerFunc(f MessageHandlerFunc) *ClientBuilder

MessagesHandlerFunc allows the registration of a function for handling all received messages. This handler should be the last one to be registered, since it will capture all messages received by the client.

func (*ClientBuilder) Name

func (b *ClientBuilder) Name(name string) *ClientBuilder

Name sets the client's node name.

func (*ClientBuilder) NotificationHandler

func (b *ClientBuilder) NotificationHandler(handler NotificationHandler) *ClientBuilder

NotificationHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) NotificationHandlerFunc

func (b *ClientBuilder) NotificationHandlerFunc(predicate NotificationPredicate, f NotificationHandlerFunc) *ClientBuilder

NotificationHandlerFunc allows the registration of a function for handling received notifications that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) NotificationsHandlerFunc

func (b *ClientBuilder) NotificationsHandlerFunc(f NotificationHandlerFunc) *ClientBuilder

NotificationsHandlerFunc allows the registration of a function for handling all received notifications. This handler should be the last one to be registered, since it will capture all notifications received by the client.

func (*ClientBuilder) PlainAuthentication

func (b *ClientBuilder) PlainAuthentication(password string) *ClientBuilder

PlainAuthentication enables the use of the password authentication during the session establishment with the server.

func (*ClientBuilder) RequestCommandHandler

func (b *ClientBuilder) RequestCommandHandler(handler RequestCommandHandler) *ClientBuilder

RequestCommandHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) RequestCommandHandlerFunc

func (b *ClientBuilder) RequestCommandHandlerFunc(predicate RequestCommandPredicate, f RequestCommandHandlerFunc) *ClientBuilder

RequestCommandHandlerFunc allows the registration of a function for handling received commands that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) RequestCommandsHandlerFunc

func (b *ClientBuilder) RequestCommandsHandlerFunc(f RequestCommandHandlerFunc) *ClientBuilder

RequestCommandsHandlerFunc allows the registration of a function for handling all received commands. This handler should be the last one to be registered, since it will capture all commands received by the client.

func (*ClientBuilder) ResponseCommandHandler

func (b *ClientBuilder) ResponseCommandHandler(handler ResponseCommandHandler) *ClientBuilder

ResponseCommandHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) ResponseCommandHandlerFunc

func (b *ClientBuilder) ResponseCommandHandlerFunc(predicate ResponseCommandPredicate, f ResponseCommandHandlerFunc) *ClientBuilder

ResponseCommandHandlerFunc allows the registration of a function for handling received commands that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ClientBuilder) ResponseCommandsHandlerFunc

func (b *ClientBuilder) ResponseCommandsHandlerFunc(f ResponseCommandHandlerFunc) *ClientBuilder

ResponseCommandsHandlerFunc allows the registration of a function for handling all received commands. This handler should be the last one to be registered, since it will capture all commands received by the client.

func (*ClientBuilder) TransportAuthentication

func (b *ClientBuilder) TransportAuthentication() *ClientBuilder

TransportAuthentication enables the use of the transport authentication scheme during the session establishment with the server. Note that the transport that are being used to communicate with the server will be asked to present the credentials, and the form of passing the credentials may vary depending on the transport type. For instance, in TCP transport connections, the client certificate used during the mutual TLS negotiation is considered the credentials by the server.

func (*ClientBuilder) UseInProcess

func (b *ClientBuilder) UseInProcess(addr InProcessAddr, bufferSize int) *ClientBuilder

UseInProcess adds an in-process listener to the server, allowing receiving virtual connections from this transport.

func (*ClientBuilder) UseTCP

func (b *ClientBuilder) UseTCP(addr net.Addr, config *TCPConfig) *ClientBuilder

UseTCP adds a TCP listener to the server, allowing receiving connections from this transport.

func (*ClientBuilder) UseWebsocket

func (b *ClientBuilder) UseWebsocket(urlStr string, requestHeader http.Header, tls *tls.Config) *ClientBuilder

UseWebsocket adds a Websockets listener to the server, allowing receiving connections from this transport.

type ClientChannel

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

ClientChannel implements the client-side communication channel in a Lime session.

func NewClientChannel

func NewClientChannel(t Transport, bufferSize int) *ClientChannel

func (ClientChannel) Close

func (c ClientChannel) Close() error

func (*ClientChannel) EstablishSession

func (c *ClientChannel) EstablishSession(
	ctx context.Context,
	compSelector CompressionSelector,
	encryptSelector EncryptionSelector,
	identity Identity,
	authenticator Authenticator,
	instance string,
) (*Session, error)

EstablishSession performs the client session negotiation and authentication handshake.

func (ClientChannel) Established

func (c ClientChannel) Established() bool

func (*ClientChannel) FinishSession

func (c *ClientChannel) FinishSession(ctx context.Context) (*Session, error)

FinishSession performs the session finishing handshake.

func (ClientChannel) ID

func (c ClientChannel) ID() string

func (ClientChannel) LocalNode

func (c ClientChannel) LocalNode() Node

func (ClientChannel) MsgChan

func (c ClientChannel) MsgChan() <-chan *Message

func (ClientChannel) NotChan

func (c ClientChannel) NotChan() <-chan *Notification

func (ClientChannel) ProcessCommand

func (c ClientChannel) ProcessCommand(ctx context.Context, reqCmd *RequestCommand) (*ResponseCommand, error)

func (ClientChannel) RcvDone

func (c ClientChannel) RcvDone() <-chan struct{}

RcvDone signals when the channel receiver goroutine is done. This usually indicates that the session with the remote node was finished.

func (ClientChannel) RemoteNode

func (c ClientChannel) RemoteNode() Node

func (ClientChannel) ReqCmdChan

func (c ClientChannel) ReqCmdChan() <-chan *RequestCommand

func (ClientChannel) RespCmdChan

func (c ClientChannel) RespCmdChan() <-chan *ResponseCommand

func (ClientChannel) SendMessage

func (c ClientChannel) SendMessage(ctx context.Context, msg *Message) error

func (ClientChannel) SendNotification

func (c ClientChannel) SendNotification(ctx context.Context, not *Notification) error

func (ClientChannel) SendRequestCommand

func (c ClientChannel) SendRequestCommand(ctx context.Context, cmd *RequestCommand) error

func (ClientChannel) SendResponseCommand

func (c ClientChannel) SendResponseCommand(ctx context.Context, cmd *ResponseCommand) error

func (ClientChannel) State

func (c ClientChannel) State() SessionState

type ClientConfig

type ClientConfig struct {
	// Node represents the address that the client should use in the session negotiation.
	// Note that the server may not use/accept the provided instance value, and it may be changed during the authentication.
	Node Node
	// The size of the internal envelope buffer used by the ClientChannel.
	// Greater values may improve the performance, but will also increase the process memory usage.
	ChannelBufferSize int
	// NewTransport represents the factory for Transport instances.
	NewTransport func(ctx context.Context) (Transport, error)
	// CompSelector is called during the session negotiation, for selecting the SessionCompression to be used.
	CompSelector CompressionSelector
	// EncryptSelector is called during the session negotiation, for selecting the SessionEncryption to be used.
	EncryptSelector EncryptionSelector
	// Authenticator is called during the session authentication and allows the client to provide its credentials
	// during the process.
	Authenticator Authenticator
}

ClientConfig defines the configurations for a Client instance.

func NewClientConfig

func NewClientConfig() *ClientConfig

NewClientConfig creates a new instance of ClientConfig with the default configuration values.

type Command

type Command struct {
	Envelope
	Method   CommandMethod // Method defines the action to be taken to the resource.
	Type     *MediaType    // Type defines MIME declaration of the resource type of the command.
	Resource Document      // Resource defines the document that is subject of the command.
}

Command is the base type for the RequestCommand and ResponseCommand types. It allows the manipulation of node resources, like server session parameters or information related to the network nodes.

func (*Command) SetMethod

func (cmd *Command) SetMethod(method CommandMethod) *Command

func (*Command) SetResource

func (cmd *Command) SetResource(d Document) *Command

type CommandMethod

type CommandMethod string

CommandMethod Defines methods for the manipulation of resources.

func (CommandMethod) MarshalText

func (m CommandMethod) MarshalText() ([]byte, error)

func (*CommandMethod) UnmarshalText

func (m *CommandMethod) UnmarshalText(text []byte) error

func (CommandMethod) Validate

func (m CommandMethod) Validate() error

type CommandProcessor

type CommandProcessor interface {
	ProcessCommand(ctx context.Context, cmd *RequestCommand) (*ResponseCommand, error)
}

type CommandStatus

type CommandStatus string

type CompressionSelector

type CompressionSelector func(options []SessionCompression) SessionCompression

CompressionSelector defines a function for selecting the compression for a session.

var NoneCompressionSelector CompressionSelector = func(options []SessionCompression) SessionCompression {
	return SessionCompressionNone
}

type Document

type Document interface {
	// MediaType gets the type of the media for the document.
	MediaType() MediaType
}

Document defines an entity with a media type.

func UnmarshalDocument

func UnmarshalDocument(d *json.RawMessage, t MediaType) (Document, error)

type DocumentCollection

type DocumentCollection struct {
	// The total of items in the collection.
	// This value refers to the original source collection,
	// without any applied filter that may exist in the
	// items on this instance.
	Total int
	// The media type of all items of the collection.
	ItemType MediaType
	// The collection items.
	Items []Document
}

DocumentCollection represents a collection of documents.

func NewDocumentCollection

func NewDocumentCollection(items []Document, t MediaType) *DocumentCollection

func (*DocumentCollection) MarshalJSON

func (d *DocumentCollection) MarshalJSON() ([]byte, error)

func (*DocumentCollection) MediaType

func (d *DocumentCollection) MediaType() MediaType

func (*DocumentCollection) UnmarshalJSON

func (d *DocumentCollection) UnmarshalJSON(b []byte) error

type DocumentContainer

type DocumentContainer struct {
	// The media type of the contained document.
	Type MediaType
	// The contained document value.
	Value Document
}

DocumentContainer represents a generic container for a document, providing a media type for the correct handling of its value by the nodes. This type can be used along with DocumentCollection to transport distinct document types in a single message.

func NewDocumentContainer

func NewDocumentContainer(d Document) *DocumentContainer

func (*DocumentContainer) MarshalJSON

func (d *DocumentContainer) MarshalJSON() ([]byte, error)

func (*DocumentContainer) MediaType

func (d *DocumentContainer) MediaType() MediaType

func (*DocumentContainer) UnmarshalJSON

func (d *DocumentContainer) UnmarshalJSON(b []byte) error

type DomainRole

type DomainRole string

DomainRole indicates the role of an identity in a domain.

type EncryptionSelector

type EncryptionSelector func(options []SessionEncryption) SessionEncryption

EncryptionSelector defines a function for selecting the encryption for a session.

var NoneEncryptionSelector EncryptionSelector = func(options []SessionEncryption) SessionEncryption {
	return SessionEncryptionNone
}
var TLSEncryptionSelector EncryptionSelector = func(options []SessionEncryption) SessionEncryption {
	return SessionEncryptionTLS
}

type Envelope

type Envelope struct {
	// ID is the envelope identifier
	ID string
	// From is the identifier of the sender node of the envelope.
	// If a node receives an envelope without this value, it means that the envelope was originated by the remote party.
	From Node
	// PP is the delegation node. It's an acronym for 'per procurationem'.
	// Identifier of a delegate node (a node that received a permission To send on behalf of another).
	// Allows a node to send an envelope on behalf of another identity.
	PP Node
	// To is the identifier of the destination node of the envelope.
	// If a node receives an envelope without this value, it means that the envelope is addressed To itself.
	To Node
	// Metadata holds additional information to be delivered with the envelope.
	Metadata map[string]string
}

Envelope is the base struct to all protocol envelopes.

func (*Envelope) Sender

func (env *Envelope) Sender() Node

Sender returns the envelope sender Node.

func (*Envelope) SetFrom

func (env *Envelope) SetFrom(from Node) *Envelope

func (*Envelope) SetFromString

func (env *Envelope) SetFromString(s string) *Envelope

func (*Envelope) SetID

func (env *Envelope) SetID(id string) *Envelope

func (*Envelope) SetMetadataKeyValue

func (env *Envelope) SetMetadataKeyValue(key string, value string) *Envelope

func (*Envelope) SetNewEnvelopeID

func (env *Envelope) SetNewEnvelopeID() *Envelope

func (*Envelope) SetPP

func (env *Envelope) SetPP(pp Node) *Envelope

func (*Envelope) SetPPString

func (env *Envelope) SetPPString(s string) *Envelope

func (*Envelope) SetTo

func (env *Envelope) SetTo(to Node) *Envelope

func (*Envelope) SetToString

func (env *Envelope) SetToString(s string) *Envelope

type EnvelopeMux

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

func (*EnvelopeMux) ListenClient

func (m *EnvelopeMux) ListenClient(ctx context.Context, c *ClientChannel) error

func (*EnvelopeMux) ListenServer

func (m *EnvelopeMux) ListenServer(ctx context.Context, c *ServerChannel) error

func (*EnvelopeMux) MessageHandler

func (m *EnvelopeMux) MessageHandler(handler MessageHandler)

func (*EnvelopeMux) MessageHandlerFunc

func (m *EnvelopeMux) MessageHandlerFunc(predicate MessagePredicate, f MessageHandlerFunc)

MessageHandlerFunc allows the definition of a function for handling received messages that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*EnvelopeMux) NotificationHandler

func (m *EnvelopeMux) NotificationHandler(handler NotificationHandler)

func (*EnvelopeMux) NotificationHandlerFunc

func (m *EnvelopeMux) NotificationHandlerFunc(predicate NotificationPredicate, f NotificationHandlerFunc)

func (*EnvelopeMux) RequestCommandHandler

func (m *EnvelopeMux) RequestCommandHandler(handler RequestCommandHandler)

func (*EnvelopeMux) RequestCommandHandlerFunc

func (m *EnvelopeMux) RequestCommandHandlerFunc(predicate RequestCommandPredicate, f RequestCommandHandlerFunc)

func (*EnvelopeMux) ResponseCommandHandler

func (m *EnvelopeMux) ResponseCommandHandler(handler ResponseCommandHandler)

func (*EnvelopeMux) ResponseCommandHandlerFunc

func (m *EnvelopeMux) ResponseCommandHandlerFunc(predicate ResponseCommandPredicate, f ResponseCommandHandlerFunc)

type ExternalAuthentication

type ExternalAuthentication struct {
	// The authentication token on base64 representation.
	Token string `json:"token"`
	// The trusted token issuer.
	Issuer string `json:"issuer"`
}

ExternalAuthentication defines an external authentication scheme, that uses third-party validation.

func (*ExternalAuthentication) GetAuthenticationScheme

func (a *ExternalAuthentication) GetAuthenticationScheme() AuthenticationScheme

type ExternalAuthenticator

type ExternalAuthenticator func(ctx context.Context, identity Identity, token string, issuer string) (*AuthenticationResult, error)

ExternalAuthenticator defines a function for authenticating an identity session using tokens emitted by an issuer.

type GuestAuthentication

type GuestAuthentication struct {
}

GuestAuthentication defines a guest authentication scheme.

func (*GuestAuthentication) GetAuthenticationScheme

func (g *GuestAuthentication) GetAuthenticationScheme() AuthenticationScheme

type Identity

type Identity struct {
	// Name represents the Identity unique name on its domain.
	Name string
	// Domain represents the network domain name of the Identity.
	Domain string
}

Identity represents a member of a domain.

func ParseIdentity

func ParseIdentity(s string) Identity

ParseIdentity parses the string To a valid Identity.

func (*Identity) IsComplete

func (i *Identity) IsComplete() bool

IsComplete indicates if all Identity fields has values.

func (Identity) MarshalText

func (i Identity) MarshalText() ([]byte, error)

func (Identity) String

func (i Identity) String() string

func (Identity) ToNode

func (i Identity) ToNode() Node

ToNode creates a Node instance based on the identity, with an empty value for the instance property.

func (*Identity) UnmarshalText

func (i *Identity) UnmarshalText(text []byte) error

type InProcessAddr

type InProcessAddr string

func (InProcessAddr) Network

func (i InProcessAddr) Network() string

func (InProcessAddr) String

func (i InProcessAddr) String() string

type JsonDocument

type JsonDocument map[string]interface{}

JsonDocument represents a generic JSON document.

func (*JsonDocument) MediaType

func (d *JsonDocument) MediaType() MediaType

type KeyAuthentication

type KeyAuthentication struct {
	// Base64 representation of the key
	Key string `json:"key"`
}

KeyAuthentication defines a plain authentication scheme, that uses a key for authentication. Should be used only with encrypted sessions.

func (*KeyAuthentication) GetAuthenticationScheme

func (a *KeyAuthentication) GetAuthenticationScheme() AuthenticationScheme

func (*KeyAuthentication) GetKeyFromBase64

func (a *KeyAuthentication) GetKeyFromBase64() (string, error)

func (*KeyAuthentication) SetKeyAsBase64

func (a *KeyAuthentication) SetKeyAsBase64(key string)

type KeyAuthenticator

type KeyAuthenticator func(ctx context.Context, identity Identity, key string) (*AuthenticationResult, error)

KeyAuthenticator defines a function for authenticating an identity session using a key.

type MediaType

type MediaType struct {
	// Type is the top-level type identifier.
	// The valid values are text, application, image, audio and video.
	Type string
	// Subtype is the MIME subtype.
	Subtype string
	// Suffix is the MIME suffix.
	Suffix string
}

MediaType represents a MIME type.

func MediaTypeApplicationJson

func MediaTypeApplicationJson() MediaType

func MediaTypePing

func MediaTypePing() MediaType

func MediaTypeTextPlain

func MediaTypeTextPlain() MediaType

func ParseMediaType

func ParseMediaType(s string) (MediaType, error)

func (MediaType) IsJson

func (m MediaType) IsJson() bool

IsJson indicates if the MIME represents a JSON type.

func (MediaType) MarshalText

func (m MediaType) MarshalText() ([]byte, error)

func (MediaType) String

func (m MediaType) String() string

func (*MediaType) UnmarshalText

func (m *MediaType) UnmarshalText(text []byte) error

type Message

type Message struct {
	Envelope
	// MIME Type declaration for the Content of the message.
	Type MediaType `json:"type"`
	// Content represents the Message body content
	Content Document `json:"content"`
}

Message encapsulates a document for transport between nodes in a network.

func (*Message) FailedNotification

func (msg *Message) FailedNotification(reason *Reason) *Notification

FailedNotification creates a notification for the current message with the 'failed' event.

func (*Message) MarshalJSON

func (msg *Message) MarshalJSON() ([]byte, error)

func (*Message) Notification

func (msg *Message) Notification(event NotificationEvent) *Notification

Notification creates a notification for the current message.

func (*Message) SetContent

func (msg *Message) SetContent(d Document) *Message

func (*Message) UnmarshalJSON

func (msg *Message) UnmarshalJSON(b []byte) error

type MessageHandler

type MessageHandler interface {
	// Match indicates if the specified Message should be handled by the instance.
	Match(msg *Message) bool

	// Handle execute an action for the specified Message.
	// If this method returns an error, it signals to the channel listener to stop.
	Handle(ctx context.Context, msg *Message, s Sender) error
}

MessageHandler defines a handler for processing Message instances received from a channel.

type MessageHandlerFunc

type MessageHandlerFunc func(ctx context.Context, msg *Message, s Sender) error

MessageHandlerFunc defines an action to be executed to a Message.

type MessagePredicate

type MessagePredicate func(msg *Message) bool

MessagePredicate defines an expression for checking if the specified Message satisfies a condition.

type MessageReceiver

type MessageReceiver interface {
	ReceiveMessage(ctx context.Context) (*Message, error)
	MsgChan() <-chan *Message
}

type MessageSender

type MessageSender interface {
	SendMessage(ctx context.Context, msg *Message) error
}

type Node

type Node struct {
	Identity
	// Instance represents the name of the instance used by the node to connect to the network.
	Instance string
}

Node represents an element of a network.

func ContextSessionLocalNode

func ContextSessionLocalNode(ctx context.Context) (Node, bool)

ContextSessionLocalNode gets the session local node from the context.

func ContextSessionRemoteNode

func ContextSessionRemoteNode(ctx context.Context) (Node, bool)

ContextSessionRemoteNode gets the session remote node from the context.

func ParseNode

func ParseNode(s string) Node

func (*Node) IsComplete

func (n *Node) IsComplete() bool

IsComplete indicates if all Node fields has values.

func (Node) MarshalText

func (n Node) MarshalText() ([]byte, error)

func (Node) String

func (n Node) String() string

func (*Node) UnmarshalText

func (n *Node) UnmarshalText(text []byte) error

type Notification

type Notification struct {
	Envelope
	// Event Related event to the notification
	Event NotificationEvent
	// In the case of a failed event, the Reason value brings more details about the problem.
	Reason *Reason
}

Notification provides information about events associated to a Message. It can be originated by an intermediate node, like a server, or by the destination of the message.

func (Notification) MarshalJSON

func (not Notification) MarshalJSON() ([]byte, error)

func (*Notification) SetEvent

func (not *Notification) SetEvent(event NotificationEvent) *Notification

func (*Notification) SetFailed

func (not *Notification) SetFailed(reason *Reason) *Notification

func (*Notification) UnmarshalJSON

func (not *Notification) UnmarshalJSON(b []byte) error

type NotificationEvent

type NotificationEvent string

NotificationEvent represent the events that can happen in the message pipeline.

func (NotificationEvent) MarshalText

func (e NotificationEvent) MarshalText() ([]byte, error)

func (*NotificationEvent) UnmarshalText

func (e *NotificationEvent) UnmarshalText(text []byte) error

func (*NotificationEvent) Validate

func (e *NotificationEvent) Validate() error

type NotificationHandler

type NotificationHandler interface {
	// Match indicates if the specified Notification should be handled by the instance.
	Match(not *Notification) bool

	// Handle execute an action for the specified Notification.
	// If this method returns an error, it signals to the channel listener to stop.
	Handle(ctx context.Context, not *Notification) error
}

NotificationHandler defines a handler for processing Notification instances received from a channel.

type NotificationHandlerFunc

type NotificationHandlerFunc func(ctx context.Context, not *Notification) error

NotificationHandlerFunc defines an action to be executed to a Notification.

type NotificationPredicate

type NotificationPredicate func(not *Notification) bool

NotificationPredicate defines an expression for checking if the specified Notification satisfies a condition.

type NotificationReceiver

type NotificationReceiver interface {
	ReceiveNotification(ctx context.Context) (*Notification, error)
	NotChan() <-chan *Notification
}

type NotificationSender

type NotificationSender interface {
	SendNotification(ctx context.Context, not *Notification) error
}

type Ping

type Ping struct{}

Ping allows the nodes to test the network connectivity.

func (*Ping) MediaType

func (p *Ping) MediaType() MediaType

type PlainAuthentication

type PlainAuthentication struct {
	// Password is the base64 representation of the password.
	Password string `json:"password"`
}

PlainAuthentication defines a plain authentication scheme, that uses a password for authentication. Should be used only with encrypted sessions.

func (*PlainAuthentication) GetAuthenticationScheme

func (a *PlainAuthentication) GetAuthenticationScheme() AuthenticationScheme

func (*PlainAuthentication) GetPasswordFromBase64

func (a *PlainAuthentication) GetPasswordFromBase64() (string, error)

func (*PlainAuthentication) SetPasswordAsBase64

func (a *PlainAuthentication) SetPasswordAsBase64(password string)

type PlainAuthenticator

type PlainAuthenticator func(ctx context.Context, identity Identity, password string) (*AuthenticationResult, error)

PlainAuthenticator defines a function for authenticating an identity session using a password.

type Reason

type Reason struct {
	Code        int    `json:"code,omitempty"`        // The reason code
	Description string `json:"description,omitempty"` // The reason description
}

Reason represents a known reason for events occurred during the client-server interactions.

func (Reason) String

func (r Reason) String() string

type RequestCommand

type RequestCommand struct {
	Command
	URI *URI // URI is the universal identifier of the resource. It should never be nil.
}

RequestCommand represents a request for a resource that can be sent to a remote party.

func (*RequestCommand) FailureResponse

func (cmd *RequestCommand) FailureResponse(reason *Reason) *ResponseCommand

FailureResponse creates a failure response Command for the current request.

func (*RequestCommand) MarshalJSON

func (cmd *RequestCommand) MarshalJSON() ([]byte, error)

func (*RequestCommand) SetURI

func (cmd *RequestCommand) SetURI(uri *URI) *RequestCommand

SetURI sets a value to the URI property.

func (*RequestCommand) SetURIString

func (cmd *RequestCommand) SetURIString(s string) *RequestCommand

SetURIString try parse the provided string to a URI and sets it to the request command. It fails silently in case of any parsing error.

func (*RequestCommand) SuccessResponse

func (cmd *RequestCommand) SuccessResponse() *ResponseCommand

SuccessResponse creates a success response Command for the current request.

func (*RequestCommand) SuccessResponseWithResource

func (cmd *RequestCommand) SuccessResponseWithResource(resource Document) *ResponseCommand

SuccessResponseWithResource creates a success response Command for the current request.

func (*RequestCommand) UnmarshalJSON

func (cmd *RequestCommand) UnmarshalJSON(b []byte) error

type RequestCommandHandler

type RequestCommandHandler interface {
	// Match indicates if the specified RequestCommand should be handled by the instance.
	Match(cmd *RequestCommand) bool

	// Handle execute an action for the specified RequestCommand.
	// If this method returns an error, it signals to the channel listener to stop.
	Handle(ctx context.Context, cmd *RequestCommand, s Sender) error
}

RequestCommandHandler defines a handler for processing Command instances received from a channel.

type RequestCommandHandlerFunc

type RequestCommandHandlerFunc func(ctx context.Context, cmd *RequestCommand, s Sender) error

RequestCommandHandlerFunc defines an action to be executed to a RequestCommand.

type RequestCommandPredicate

type RequestCommandPredicate func(cmd *RequestCommand) bool

RequestCommandPredicate defines an expression for checking if the specified RequestCommand satisfies a condition.

type RequestCommandReceiver

type RequestCommandReceiver interface {
	ReceiveRequestCommand(ctx context.Context) (*RequestCommand, error)
	ReqCmdChan() <-chan *RequestCommand
}

type RequestCommandSender

type RequestCommandSender interface {
	SendRequestCommand(ctx context.Context, cmd *RequestCommand) error
}

type ResponseCommand

type ResponseCommand struct {
	Command
	Status CommandStatus // Status indicates the status of the action taken To the resource, in case of a response command.
	Reason *Reason       // Reason indicates the cause for a failure response command.
}

ResponseCommand represents a response for a RequestCommand that was issued previously.

func (*ResponseCommand) MarshalJSON

func (cmd *ResponseCommand) MarshalJSON() ([]byte, error)

func (*ResponseCommand) SetStatusFailure

func (cmd *ResponseCommand) SetStatusFailure(r Reason)

func (*ResponseCommand) UnmarshalJSON

func (cmd *ResponseCommand) UnmarshalJSON(b []byte) error

type ResponseCommandHandler

type ResponseCommandHandler interface {
	// Match indicates if the specified ResponseCommand should be handled by the instance.
	Match(cmd *ResponseCommand) bool

	// Handle execute an action for the specified ResponseCommand.
	// If this method returns an error, it signals to the channel listener to stop.
	Handle(ctx context.Context, cmd *ResponseCommand, s Sender) error
}

ResponseCommandHandler defines a handler for processing Command instances received from a channel.

type ResponseCommandHandlerFunc

type ResponseCommandHandlerFunc func(ctx context.Context, cmd *ResponseCommand, s Sender) error

ResponseCommandHandlerFunc defines an action to be executed to a ResponseCommand.

type ResponseCommandPredicate

type ResponseCommandPredicate func(cmd *ResponseCommand) bool

ResponseCommandPredicate defines an expression for checking if the specified ResponseCommand satisfies a condition.

type ResponseCommandReceiver

type ResponseCommandReceiver interface {
	ReceiveResponseCommand(ctx context.Context) (*ResponseCommand, error)
	RespCmdChan() <-chan *ResponseCommand
}

type ResponseCommandSender

type ResponseCommandSender interface {
	SendResponseCommand(ctx context.Context, cmd *ResponseCommand) error
}

type Sender

Sender defines a service for sending envelopes to a remote party.

type Server

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

Server allows the receiving of Lime connections through multiple transport listeners, like TCP and Websockets. It handles the session negotiation and authentication through the handlers defined in ServerConfig. Finally, it allows the definition of handles for receiving envelopes from the clients.

func NewServer

func NewServer(config *ServerConfig, mux *EnvelopeMux, listeners ...BoundListener) *Server

NewServer creates a new instance of the Server type.

func (*Server) Close

func (srv *Server) Close() error

Close stops the server by closing the transport listeners and all active sessions.

func (*Server) ListenAndServe

func (srv *Server) ListenAndServe() error

ListenAndServe starts listening for new connections in the registered transport listeners. This is a blocking call which always returns a non nil error. In case of a graceful closing, the returned error is ErrServerClosed.

type ServerBuilder

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

ServerBuilder is a helper for building instances of Server. Avoid instantiating it directly, use the NewServerBuilder() function instead.

func NewServerBuilder

func NewServerBuilder() *ServerBuilder

NewServerBuilder creates a new ServerBuilder, which is a helper for building Server instances. It provides a fluent interface for convenience.

func (*ServerBuilder) AutoReplyPings

func (b *ServerBuilder) AutoReplyPings() *ServerBuilder

AutoReplyPings adds a RequestCommandHandler handler to automatically reply ping requests from the remote node.

func (*ServerBuilder) Build

func (b *ServerBuilder) Build() *Server

Build creates a new instance of Server.

func (*ServerBuilder) ChannelBufferSize

func (b *ServerBuilder) ChannelBufferSize(bufferSize int) *ServerBuilder

ChannelBufferSize determines the internal envelope buffer size for the channels.

func (*ServerBuilder) CompressionOptions

func (b *ServerBuilder) CompressionOptions(compOpts ...SessionCompression) *ServerBuilder

CompressionOptions defines the compression options to be used in the session negotiation.

func (*ServerBuilder) Domain

func (b *ServerBuilder) Domain(domain string) *ServerBuilder

Domain sets the server's node domain.

func (*ServerBuilder) EnableExternalAuthentication

func (b *ServerBuilder) EnableExternalAuthentication(a ExternalAuthenticator) *ServerBuilder

EnableExternalAuthentication enables the use of key authentication scheme during the authentication of the client sessions. The provided ExternalAuthenticator function is called for authenticating any session with this scheme.

func (*ServerBuilder) EnableGuestAuthentication

func (b *ServerBuilder) EnableGuestAuthentication() *ServerBuilder

EnableGuestAuthentication enables the use of guest authentication scheme during the authentication of the client sessions. The guest authentication scheme do not require any credentials from the clients.

func (*ServerBuilder) EnableKeyAuthentication

func (b *ServerBuilder) EnableKeyAuthentication(a KeyAuthenticator) *ServerBuilder

EnableKeyAuthentication enables the use of key authentication scheme during the authentication of the client sessions. The provided KeyAuthenticator function is called for authenticating any session with this scheme.

func (*ServerBuilder) EnablePlainAuthentication

func (b *ServerBuilder) EnablePlainAuthentication(a PlainAuthenticator) *ServerBuilder

EnablePlainAuthentication enables the use of plain authentication scheme during the authentication of the client sessions. The provided PlainAuthentication function is called for authenticating any session with this scheme.

func (*ServerBuilder) EnableTransportAuthentication

func (b *ServerBuilder) EnableTransportAuthentication() *ServerBuilder

EnableTransportAuthentication enables the use of transport authentication scheme during the authentication of the client sessions. The transport authentication will delegate the authentication to the session transport and the form of passing the credentials may vary depending on the transport type. For instance, in TCP transport connections, the client certificate used during the mutual TLS negotiation is considered the credentials by the server.

func (*ServerBuilder) EncryptionOptions

func (b *ServerBuilder) EncryptionOptions(encryptOpts ...SessionEncryption) *ServerBuilder

EncryptionOptions defines the encryption options to be used in the session negotiation.

func (*ServerBuilder) Established

func (b *ServerBuilder) Established(established func(sessionID string, c *ServerChannel)) *ServerBuilder

Established is called when a session with a node is established.

func (*ServerBuilder) Finished

func (b *ServerBuilder) Finished(finished func(sessionID string)) *ServerBuilder

Finished is called when an established session with a node is finished.

func (*ServerBuilder) Instance

func (b *ServerBuilder) Instance(instance string) *ServerBuilder

Instance sets the server's node instance.

func (*ServerBuilder) ListenInProcess

func (b *ServerBuilder) ListenInProcess(addr InProcessAddr) *ServerBuilder

ListenInProcess adds a new in-process transport listener with the specified configuration. This method can be called multiple times.

func (*ServerBuilder) ListenTCP

func (b *ServerBuilder) ListenTCP(addr *net.TCPAddr, config *TCPConfig) *ServerBuilder

ListenTCP adds a new TCP transport listener with the specified configuration. This method can be called multiple times.

func (*ServerBuilder) ListenWebsocket

func (b *ServerBuilder) ListenWebsocket(addr *net.TCPAddr, config *WebsocketConfig) *ServerBuilder

ListenWebsocket adds a new Websocket transport listener with the specified configuration. This method can be called multiple times.

func (*ServerBuilder) MessageHandler

func (b *ServerBuilder) MessageHandler(handler MessageHandler) *ServerBuilder

MessageHandler allows the registration of a MessageHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) MessageHandlerFunc

func (b *ServerBuilder) MessageHandlerFunc(predicate MessagePredicate, f MessageHandlerFunc) *ServerBuilder

MessageHandlerFunc allows the registration of a function for handling received messages that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) MessagesHandlerFunc

func (b *ServerBuilder) MessagesHandlerFunc(f MessageHandlerFunc) *ServerBuilder

MessagesHandlerFunc allows the registration of a function for handling all received messages. This handler should be the last one to be registered, since it will capture all messages received by the client.

func (*ServerBuilder) Name

func (b *ServerBuilder) Name(name string) *ServerBuilder

Name sets the server's node name.

func (*ServerBuilder) NotificationHandler

func (b *ServerBuilder) NotificationHandler(handler NotificationHandler) *ServerBuilder

NotificationHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) NotificationHandlerFunc

func (b *ServerBuilder) NotificationHandlerFunc(predicate NotificationPredicate, f NotificationHandlerFunc) *ServerBuilder

NotificationHandlerFunc allows the registration of a function for handling received notifications that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) NotificationsHandlerFunc

func (b *ServerBuilder) NotificationsHandlerFunc(f NotificationHandlerFunc) *ServerBuilder

NotificationsHandlerFunc allows the registration of a function for handling all received notifications. This handler should be the last one to be registered, since it will capture all notifications received by the client.

func (*ServerBuilder) Register

func (b *ServerBuilder) Register(register func(ctx context.Context, candidate Node, c *ServerChannel) (Node, error)) *ServerBuilder

Register is called for the client Node address registration. It receives a candidate node from the client and should return the effective node address that will be assigned to the session.

func (*ServerBuilder) RequestCommandHandler

func (b *ServerBuilder) RequestCommandHandler(handler RequestCommandHandler) *ServerBuilder

RequestCommandHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) RequestCommandHandlerFunc

func (b *ServerBuilder) RequestCommandHandlerFunc(predicate RequestCommandPredicate, f RequestCommandHandlerFunc) *ServerBuilder

RequestCommandHandlerFunc allows the registration of a function for handling received commands that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) RequestCommandsHandlerFunc

func (b *ServerBuilder) RequestCommandsHandlerFunc(f RequestCommandHandlerFunc) *ServerBuilder

RequestCommandsHandlerFunc allows the registration of a function for handling all received commands. This handler should be the last one to be registered, since it will capture all commands received by the client.

func (*ServerBuilder) ResponseCommandHandler

func (b *ServerBuilder) ResponseCommandHandler(handler ResponseCommandHandler) *ServerBuilder

ResponseCommandHandler allows the registration of a NotificationHandler. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) ResponseCommandHandlerFunc

func (b *ServerBuilder) ResponseCommandHandlerFunc(predicate ResponseCommandPredicate, f ResponseCommandHandlerFunc) *ServerBuilder

ResponseCommandHandlerFunc allows the registration of a function for handling received commands that matches the specified predicate. Note that the registration order matters, since the receiving process stops when the first predicate match occurs.

func (*ServerBuilder) ResponseCommandsHandlerFunc

func (b *ServerBuilder) ResponseCommandsHandlerFunc(f ResponseCommandHandlerFunc) *ServerBuilder

ResponseCommandsHandlerFunc allows the registration of a function for handling all received commands. This handler should be the last one to be registered, since it will capture all commands received by the client.

type ServerChannel

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

func NewServerChannel

func NewServerChannel(t Transport, bufferSize int, serverNode Node, sessionID string) *ServerChannel

func (ServerChannel) Close

func (c ServerChannel) Close() error

func (*ServerChannel) EstablishSession

func (c *ServerChannel) EstablishSession(
	ctx context.Context,
	compOpts []SessionCompression,
	encryptOpts []SessionEncryption,
	schemeOpts []AuthenticationScheme,
	authenticate func(context.Context, Identity, Authentication) (*AuthenticationResult, error),
	register func(context.Context, Node, *ServerChannel) (Node, error)) error

EstablishSession establishes a server channel with transport options negotiation and authentication.

func (ServerChannel) Established

func (c ServerChannel) Established() bool

func (*ServerChannel) FailSession

func (c *ServerChannel) FailSession(ctx context.Context, reason *Reason) error

func (*ServerChannel) FinishSession

func (c *ServerChannel) FinishSession(ctx context.Context) error

func (ServerChannel) ID

func (c ServerChannel) ID() string

func (ServerChannel) LocalNode

func (c ServerChannel) LocalNode() Node

func (ServerChannel) MsgChan

func (c ServerChannel) MsgChan() <-chan *Message

func (ServerChannel) NotChan

func (c ServerChannel) NotChan() <-chan *Notification

func (ServerChannel) ProcessCommand

func (c ServerChannel) ProcessCommand(ctx context.Context, reqCmd *RequestCommand) (*ResponseCommand, error)

func (ServerChannel) RcvDone

func (c ServerChannel) RcvDone() <-chan struct{}

RcvDone signals when the channel receiver goroutine is done. This usually indicates that the session with the remote node was finished.

func (ServerChannel) RemoteNode

func (c ServerChannel) RemoteNode() Node

func (ServerChannel) ReqCmdChan

func (c ServerChannel) ReqCmdChan() <-chan *RequestCommand

func (ServerChannel) RespCmdChan

func (c ServerChannel) RespCmdChan() <-chan *ResponseCommand

func (ServerChannel) SendMessage

func (c ServerChannel) SendMessage(ctx context.Context, msg *Message) error

func (ServerChannel) SendNotification

func (c ServerChannel) SendNotification(ctx context.Context, not *Notification) error

func (ServerChannel) SendRequestCommand

func (c ServerChannel) SendRequestCommand(ctx context.Context, cmd *RequestCommand) error

func (ServerChannel) SendResponseCommand

func (c ServerChannel) SendResponseCommand(ctx context.Context, cmd *ResponseCommand) error

func (ServerChannel) State

func (c ServerChannel) State() SessionState

type ServerConfig

type ServerConfig struct {
	Node              Node                   // Node represents the server's address.
	CompOpts          []SessionCompression   // CompOpts defines the compression options to be used in the session negotiation.
	EncryptOpts       []SessionEncryption    // EncryptOpts defines the encryption options to be used in the session negotiation.
	SchemeOpts        []AuthenticationScheme // SchemeOpts defines the authentication schemes that should be presented to the clients during session establishment.
	Backlog           int                    // Backlog defines the size of the listener's pending connections queue.
	ChannelBufferSize int                    // ChannelBufferSize determines the internal envelope buffer size for the channels.

	// Authenticate is called for authenticating a client session.
	// It should return an AuthenticationResult instance with DomainRole different of DomainRoleUnknown for a successful authentication.
	Authenticate func(ctx context.Context, identity Identity, a Authentication) (*AuthenticationResult, error)
	// Register is called for the client Node address registration.
	// It receives a candidate node from the client and should return the effective node address that will be assigned
	// to the session.
	Register func(ctx context.Context, candidate Node, c *ServerChannel) (Node, error)
	// Established is called when a session with a node is established.
	Established func(sessionID string, c *ServerChannel)
	// Finished is called when an established session with a node is finished.
	Finished func(sessionID string)
}

ServerConfig define the configurations for a Server instance.

func NewServerConfig

func NewServerConfig() *ServerConfig

NewServerConfig creates a new instance of ServerConfig with the default configuration values.

type Session

type Session struct {
	Envelope
	// State informs or changes the state of a session.
	// Only the server can change the session state, but the client can request
	// the state transition.
	State SessionState
	// EncryptionOptions represent the options provided by the server during the session negotiation.
	EncryptionOptions []SessionEncryption
	// Encryption represents the encryption option selected for the session.
	// This property is provided by the client in the  negotiation and by the
	// server in the confirmation after that.
	Encryption SessionEncryption
	// Compression options provided by the server during the session negotiation.
	CompressionOptions []SessionCompression
	// The compression option selected for the session.
	// This property is provided by the client in the negotiation and by the
	// server in the confirmation after that.
	Compression SessionCompression
	// List of available authentication schemas for session authentication provided
	// by the server.
	SchemeOptions []AuthenticationScheme
	// The authentication scheme option selected for the session.
	// This property must be present if the property authentication is defined.
	Scheme AuthenticationScheme
	// Authentication data, related To the selected schema.
	// Information like password sent by the client or round-trip data sent by the server.
	Authentication Authentication
	// In cases where the client receives a session with failed state,
	// this property should provide more details about the problem.
	Reason *Reason
}

The Session envelope is used for the negotiation, authentication and establishment of the communication channel between the client and a server.

func (*Session) MarshalJSON

func (s *Session) MarshalJSON() ([]byte, error)

func (*Session) SetAuthentication

func (s *Session) SetAuthentication(a Authentication)

func (*Session) UnmarshalJSON

func (s *Session) UnmarshalJSON(b []byte) error

type SessionCompression

type SessionCompression string

SessionCompression Defines the valid session compression values.

type SessionEncryption

type SessionEncryption string

SessionEncryption Defines the valid session encryption values.

type SessionState

type SessionState string

SessionState Defines the supported session states

func (SessionState) MarshalText

func (s SessionState) MarshalText() ([]byte, error)

func (SessionState) Step

func (s SessionState) Step() int

func (*SessionState) UnmarshalText

func (s *SessionState) UnmarshalText(text []byte) error

func (SessionState) Validate

func (s SessionState) Validate() error

type StdoutTraceWriter

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

StdoutTraceWriter Implements a TraceWriter that uses the standard output for writing send and received envelopes.

func (StdoutTraceWriter) ReceiveWriter

func (t StdoutTraceWriter) ReceiveWriter() *io.Writer

func (StdoutTraceWriter) SendWriter

func (t StdoutTraceWriter) SendWriter() *io.Writer

type TCPConfig

type TCPConfig struct {
	ReadLimit   int64       // ReadLimit defines the limit for buffered data in read operations.
	TraceWriter TraceWriter // TraceWriter sets the trace writer for tracing connection envelopes
	TLSConfig   *tls.Config
	ConnBuffer  int
}

type TextDocument

type TextDocument string

TextDocument represents a plain document.

func (TextDocument) MediaType

func (d TextDocument) MediaType() MediaType

type TraceWriter

type TraceWriter interface {
	SendWriter() *io.Writer    // SendWriter returns the sendWriter for the transport send operations
	ReceiveWriter() *io.Writer // ReceiveWriter returns the sendWriter for the transport receive operations
}

TraceWriter Enable request tracing for network transports.

func NewStdoutTraceWriter

func NewStdoutTraceWriter() TraceWriter

type Transport

type Transport interface {
	io.Closer
	Send(ctx context.Context, e envelope) error                     // Send sends an envelope to the remote node.
	Receive(ctx context.Context) (envelope, error)                  // Receive receives an envelope from the remote node.
	SupportedCompression() []SessionCompression                     // SupportedCompression enumerates the supported compression options for the transport.
	Compression() SessionCompression                                // Compression returns the current transport compression option.
	SetCompression(ctx context.Context, c SessionCompression) error // SetCompression defines the compression mode for the transport.
	SupportedEncryption() []SessionEncryption                       // SupportedEncryption enumerates the supported encryption options for the transport.
	Encryption() SessionEncryption                                  // Encryption returns the current transport encryption option.
	SetEncryption(ctx context.Context, e SessionEncryption) error   // SetEncryption defines the encryption mode for the transport.
	Connected() bool                                                // Connected indicates if the transport is connected.
	LocalAddr() net.Addr                                            // LocalAddr returns the local endpoint address.
	RemoteAddr() net.Addr                                           // RemoteAddr returns the remote endpoint address.
}

Transport defines the basic features for a Lime communication mean

func DialInProcess

func DialInProcess(addr InProcessAddr, bufferSize int) (Transport, error)

DialInProcess creates a new in process transport connection to the specified path.

func DialTcp

func DialTcp(ctx context.Context, addr net.Addr, config *TCPConfig) (Transport, error)

DialTcp opens a TCP transport connection with the specified URI.

func DialWebsocket

func DialWebsocket(ctx context.Context, urlStr string, requestHeader http.Header, tls *tls.Config) (Transport, error)

type TransportAuthentication

type TransportAuthentication struct {
}

TransportAuthentication defines a transport layer authentication scheme.

func (*TransportAuthentication) GetAuthenticationScheme

func (a *TransportAuthentication) GetAuthenticationScheme() AuthenticationScheme

type TransportListener

type TransportListener interface {
	io.Closer
	Listen(ctx context.Context, addr net.Addr) error // Listen start listening for new transport connections.
	Accept(ctx context.Context) (Transport, error)   // Accept a new transport connection.
}

TransportListener Defines a listener interface for the transports.

func NewInProcessTransportListener

func NewInProcessTransportListener(addr InProcessAddr) TransportListener

func NewTCPTransportListener

func NewTCPTransportListener(config *TCPConfig) TransportListener

func NewWebsocketTransportListener

func NewWebsocketTransportListener(config *WebsocketConfig) TransportListener

type URI

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

URI defines a Lime resource identifier. It can be represented in the short form (like '/presence') or in the absolute form, that includes the URI scheme and resource owner identity (like 'lime://name@domain/presence').

func ParseLimeURI

func ParseLimeURI(s string) (*URI, error)

func (*URI) MarshalText

func (u *URI) MarshalText() ([]byte, error)

func (*URI) Owner

func (u *URI) Owner() *Identity

func (*URI) Path

func (u *URI) Path() string

func (*URI) String

func (u *URI) String() string

func (*URI) URL

func (u *URI) URL() *url.URL

URL returns the raw URL associated with the Lime URI.

func (*URI) UnmarshalText

func (u *URI) UnmarshalText(text []byte) error

type WebsocketConfig

type WebsocketConfig struct {
	TLSConfig         *tls.Config
	TraceWriter       TraceWriter // TraceWriter sets the trace writer for tracing connection envelopes
	EnableCompression bool
	ConnBuffer        int

	// CheckOrigin returns true if the request Origin header is acceptable. If
	// CheckOrigin is nil, then a safe default is used: return false if the
	// Origin request header is present and the origin host is not equal to
	// request Host header.
	//
	// A CheckOrigin function should carefully validate the request origin to
	// prevent cross-site request forgery.
	CheckOrigin func(r *http.Request) bool
}

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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