Documentation ¶
Overview ¶
Package imap implements all three node types a pluto setup consists of: distributor, worker, and storage.
Handler functions for the various implemented IMAP commands usually return a boolean value indicating whether correct communication between pluto and connected clients was achieved but not whether commands were handled correctly according to IMAP semantics. This means that if a fatal error occurred during handling e.g. a LOGIN request which prevents the system with a high probability from handling future commands correctly as well, the responsible handler function will return false. But in case an user error occurred such as a missing name and/or password accompanying the LOGIN command and pluto was able to send back a useful error message to the client, this function returns true because communication went according to planned handling pipeline.
Please refer to https://tools.ietf.org/html/rfc3501#section-3 for full documentation on the states and https://tools.ietf.org/html/rfc3501 for the full IMAP v4 rev1 RFC.
Index ¶
- Variables
- func ParseFlags(recv string) (map[string]struct{}, error)
- func ParseSeqNumbers(recv string, lenMailboxContents int) ([]int, error)
- type Connection
- func (c *Connection) Error(msg string, err error)
- func (c *Connection) InternalReceive(inc bool) (string, error)
- func (c *Connection) InternalSend(inc bool, text string) error
- func (c *Connection) Receive(inc bool) (string, error)
- func (c *Connection) Send(inc bool, text string) error
- func (c *Connection) SignalAwaitingLiteral(inc bool, awaiting int) error
- func (c *Connection) SignalSessionDone(inc bool) error
- func (c *Connection) SignalSessionStart(inc bool) error
- func (c *Connection) SignalSessionStartFailover(inc bool, recvClientID string, origWorker string) error
- func (c *Connection) Terminate() error
- type Distributor
- func (distr *Distributor) Capability(c *Connection, req *Request) bool
- func (distr *Distributor) HandleConnection(conn net.Conn)
- func (distr *Distributor) Login(c *Connection, req *Request) bool
- func (distr *Distributor) Logout(c *Connection, req *Request) bool
- func (distr *Distributor) Proxy(c *Connection, rawReq string) bool
- func (distr *Distributor) Run() error
- func (distr *Distributor) StartTLS(c *Connection, req *Request) bool
- type FailoverWorker
- type IMAPConnection
- type IMAPNode
- func (node *IMAPNode) Append(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) ApplyCRDTUpd(applyChan chan string, doneChan chan struct{})
- func (node *IMAPNode) Create(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) Delete(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) Expunge(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) List(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) Select(c *IMAPConnection, req *Request, syncChan chan string) bool
- func (node *IMAPNode) Store(c *IMAPConnection, req *Request, syncChan chan string) bool
- type IMAPState
- type PlainAuthenticator
- type Request
- type Storage
- type Worker
Constants ¶
This section is empty.
Variables ¶
var SupportedCommands = map[string]bool{ "CAPABILITY": true, "LOGOUT": true, "STARTTLS": true, "LOGIN": true, "SELECT": true, "CREATE": true, "DELETE": true, "LIST": true, "APPEND": true, "EXPUNGE": true, "STORE": true, }
SupportedCommands is a quick access map for checking if a supplied IMAP command is supported by pluto.
Functions ¶
func ParseFlags ¶
ParseFlags takes in the string representation of a parenthesized list of IMAP flags and returns a map containing all found flags.
Types ¶
type Connection ¶
type Connection struct { IncConn *tls.Conn IncReader *bufio.Reader OutConn *tls.Conn OutReader *bufio.Reader IntlTLSConfig *tls.Config IntlConnRetry int OutAddr string ClientID string UserName string }
Connection carries all information specific to one observed connection on its way through a pluto node that only authenticates and proxies IMAP connections.
func (*Connection) Error ¶
func (c *Connection) Error(msg string, err error)
Error makes use of Terminate but provides an additional error message before terminating.
func (*Connection) InternalReceive ¶ added in v0.2.0
func (c *Connection) InternalReceive(inc bool) (string, error)
InternalReceive is used by nodes in the pluto system receive an incoming message and filter out all prior received ping message.
func (*Connection) InternalSend ¶ added in v0.2.0
func (c *Connection) InternalSend(inc bool, text string) error
InternalSend is used by nodes of the pluto system to successfully transmit a message to another node or fail definitely if no reconnection is possible. This prevents further handler advancement in case a link failed.
func (*Connection) Receive ¶
func (c *Connection) Receive(inc bool) (string, error)
Receive wraps the main io.Reader function that awaits text until an IMAP newline symbol and deletes the symbols after- wards again. It returns the resulting string or an error.
func (*Connection) Send ¶
func (c *Connection) Send(inc bool, text string) error
Send takes in an answer text from a node as a string and writes it to the connection to the client. In case an error occurs, this method returns it to the calling function.
func (*Connection) SignalAwaitingLiteral ¶
func (c *Connection) SignalAwaitingLiteral(inc bool, awaiting int) error
SignalAwaitingLiteral is used by workers to indicate a proxying distributor node that they are awaiting literal data from a client. The amount of awaited data is sent along this signal.
func (*Connection) SignalSessionDone ¶
func (c *Connection) SignalSessionDone(inc bool) error
SignalSessionDone is either used by the distributor to signal the worker that a client logged out or by any node to indicated that the current operation is done.
func (*Connection) SignalSessionStart ¶ added in v0.2.0
func (c *Connection) SignalSessionStart(inc bool) error
SignalSessionStart is used by the distributor node to signal an involved worker node context about future requests.
func (*Connection) SignalSessionStartFailover ¶ added in v0.2.0
func (c *Connection) SignalSessionStartFailover(inc bool, recvClientID string, origWorker string) error
SignalSessionStartFailover is used by a failover worker node to signal the storage node context about future requests.
func (*Connection) Terminate ¶
func (c *Connection) Terminate() error
Terminate tears down the state of a connection. This includes closing contained connection items. It returns nil or eventual errors.
type Distributor ¶
type Distributor struct { Socket net.Listener IntlTLSConfig *tls.Config AuthAdapter PlainAuthenticator Connections map[string]*tls.Conn Config *config.Config // contains filtered or unexported fields }
Distributor struct bundles information needed in operation of a distributor node.
func InitDistributor ¶
func InitDistributor(logger log.Logger, config *config.Config, auth PlainAuthenticator) (*Distributor, error)
InitDistributor listens for TLS connections on a TCP socket opened up on supplied IP address and port as well as initializes connections to involved worker nodes. It returns those information bundled in above Distributor struct.
func (*Distributor) Capability ¶
func (distr *Distributor) Capability(c *Connection, req *Request) bool
Capability handles the IMAP CAPABILITY command. It outputs the supported actions in the current state.
func (*Distributor) HandleConnection ¶
func (distr *Distributor) HandleConnection(conn net.Conn)
HandleConnection acts as the main loop for requests targeted at IMAP functions implemented in distributor node. It parses incoming requests and executes command specific handlers matching the parsed data.
func (*Distributor) Login ¶
func (distr *Distributor) Login(c *Connection, req *Request) bool
Login performs the authentication mechanism specified as part of the distributor config.
func (*Distributor) Logout ¶
func (distr *Distributor) Logout(c *Connection, req *Request) bool
Logout correctly ends a connection with a client. Also necessarily created management structures will get shut down gracefully.
func (*Distributor) Proxy ¶
func (distr *Distributor) Proxy(c *Connection, rawReq string) bool
Proxy forwards one request between the distributor node and the responsible worker node.
func (*Distributor) Run ¶
func (distr *Distributor) Run() error
Run loops over incoming requests at distributor and dispatches each one to a goroutine taking care of the commands supplied.
func (*Distributor) StartTLS ¶
func (distr *Distributor) StartTLS(c *Connection, req *Request) bool
StartTLS states on IMAP STARTTLS command that current connection is already encrypted.
type FailoverWorker ¶
type FailoverWorker struct { Name string MailSocket net.Listener IntlTLSConfig *tls.Config Connections map[string]*tls.Conn Config *config.Config ShutdownChan chan struct{} // contains filtered or unexported fields }
FailoverWorker represents a reduced IMAPNode that simply writes through traffic to storage node.
func InitFailoverWorker ¶
func InitFailoverWorker(config *config.Config, workerName string) (*FailoverWorker, error)
InitFailoverWorker initializes a worker node that acts as a passthrough-failover of the worker node specified via workerName. This results in a "dumb" proxy node that forwards all received traffic from distributor directly to storage node.
func (*FailoverWorker) HandleFailover ¶
func (failWorker *FailoverWorker) HandleFailover(conn net.Conn)
HandleFailover is the function new IMAP connections incoming at a failover worker node are dispatched into in. It takes care of message forwarding to storage and reply return to distributor.
func (*FailoverWorker) RunFailover ¶
func (failWorker *FailoverWorker) RunFailover() error
RunFailover is the main method called when starting a failover worker node. It accepts IMAP connections and dispatches them into own goroutines.
type IMAPConnection ¶ added in v0.2.0
type IMAPConnection struct { *Connection IMAPState IMAPState UserCRDTPath string UserMaildirPath string SelectedMailbox string }
IMAPConnection contains additional elements needed for performing the actual IMAP operations for an authenticated client.
func (*IMAPConnection) UpdateClientContext ¶ added in v0.2.0
func (c *IMAPConnection) UpdateClientContext(clientIDRaw string, CRDTLayerRoot string, MaildirRoot string) (string, error)
UpdateClientContext expects the initial client information string sent when the proxying node opened a connection to a worker node. It updates the existing connection with the contained information.
type IMAPNode ¶
type IMAPNode struct { MailSocket net.Listener SyncSocket net.Listener Connections map[string]*tls.Conn MailboxStructure map[string]map[string]*crdt.ORSet MailboxContents map[string]map[string][]string CRDTLayerRoot string MaildirRoot string Config *config.Config ShutdownChan chan struct{} // contains filtered or unexported fields }
IMAPNode unifies needed management elements for nodes types worker and storage. This allows for one single place to define behaviour of handling IMAP as well as CRDT update requests.
func (*IMAPNode) Append ¶
func (node *IMAPNode) Append(c *IMAPConnection, req *Request, syncChan chan string) bool
Append puts supplied message into specified mailbox.
func (*IMAPNode) ApplyCRDTUpd ¶
ApplyCRDTUpd receives strings representing CRDT update operations from receiver and executes them.
func (*IMAPNode) Create ¶
func (node *IMAPNode) Create(c *IMAPConnection, req *Request, syncChan chan string) bool
Create attempts to create a mailbox with name taken from payload of request.
func (*IMAPNode) Delete ¶
func (node *IMAPNode) Delete(c *IMAPConnection, req *Request, syncChan chan string) bool
Delete attempts to remove an existing mailbox with all included content in CRDT as well as file system.
func (*IMAPNode) Expunge ¶
func (node *IMAPNode) Expunge(c *IMAPConnection, req *Request, syncChan chan string) bool
Expunge deletes messages permanently from currently selected mailbox that have been flagged as Deleted prior to calling this function.
func (*IMAPNode) List ¶
func (node *IMAPNode) List(c *IMAPConnection, req *Request, syncChan chan string) bool
List allows clients to learn about the mailboxes available and also returns the hierarchy delimiter.
func (*IMAPNode) Select ¶
func (node *IMAPNode) Select(c *IMAPConnection, req *Request, syncChan chan string) bool
Select sets the current mailbox based on supplied payload to user-instructed value. A return value of this function does not indicate whether the command was successfully handled according to IMAP semantics, but rather whether a fatal error occurred or a complete answer could been sent. So, in case of an user error (e.g. a missing mailbox to select) but otherwise correct handling, this function would send a useful message to the client and still return true.
type IMAPState ¶
type IMAPState int
IMAPState represents the integer value associated with one of the implemented IMAP states a connection can be in.
type PlainAuthenticator ¶ added in v0.4.1
type PlainAuthenticator interface { // GetWorkerForUser allows us to route an IMAP request to the // worker node responsible for a specific user. GetWorkerForUser(workers map[string]config.Worker, id int) (string, error) // AuthenticatePlain will be implemented by each of the // authentication methods of type PLAIN to perform the // actual part of checking supplied credentials. AuthenticatePlain(username string, password string, clientAddr string) (int, string, error) }
PlainAuthenticator defines the methods required to perform an IMAP AUTH=PLAIN authentication in order to reach authenticated state (also LOGIN).
type Request ¶
Request represents the parsed content of a client command line sent to pluto. Payload will be examined further in command specific functions.
func ParseRequest ¶
ParseRequest takes in a raw string representing a received IMAP request and parses it into the defined request structure above. Any error encountered is handled useful to the IMAP protocol.
type Storage ¶
Storage struct bundles information needed in operation of a storage node.
func InitStorage ¶
InitStorage listens for TLS connections on a TCP socket opened up on supplied IP address. It returns those information bundeled in above Storage struct.
func (*Storage) HandleConnection ¶
HandleConnection is the main storage routine where all incoming requests against this storage node have to go through.
type Worker ¶
type Worker struct { *IMAPNode Name string SyncSendChan chan string // contains filtered or unexported fields }
Worker struct bundles information needed in operation of a worker node.
func InitWorker ¶
InitWorker listens for TLS connections on a TCP socket opened up on supplied IP address and port as well as connects to involved storage node. It returns those information bundeled in above Worker struct.
func (*Worker) HandleConnection ¶
HandleConnection is the main worker routine where all incoming requests against worker nodes have to go through.