@@ -5,7 +5,7 @@ LIME - A lightweight messaging library
55![ Go] ( https://github.com/takenet/lime-go/workflows/Go/badge.svg?branch=master )
66
77LIME allows you to build scalable, real-time messaging applications using a JSON-based
8- [ open protocol] ( http://limeprotocol.org ) .
8+ [ open protocol] ( http://limeprotocol.org ) .
99It's ** fully asynchronous** and support persistent transports like TCP or Websockets.
1010
1111You can send and receive any type of document into the wire as long it can be represented as JSON or text (plain or
@@ -49,35 +49,33 @@ import (
4949)
5050
5151func main () {
52- // Message handler that echoes all received messages to the originator
53- msgHandler := func (ctx context.Context , msg *lime.Message , s lime.Sender ) error {
54- return s.SendMessage (ctx, &lime.Message {
55- Envelope: lime.Envelope {ID: msg.ID , To: msg.From },
56- Type: msg.Type ,
57- Content: msg.Content ,
58- })
59- }
60-
61- // Build a server, listening for TCP connections in the 55321 port
62- server := lime.NewServerBuilder ().
63- MessagesHandlerFunc (msgHandler).
64- ListenTCP (&net.TCPAddr {Port: 55321 }, &lime.TCPConfig {}).
65- Build ()
66-
67- // Listen for the OS termination signals
68- sigs := make (chan os.Signal , 1 )
69- signal.Notify (sigs, syscall.SIGINT , syscall.SIGTERM )
70- go func () {
71- <- sigs
72- if err := server.Close (); err != nil {
73- log.Printf (" close: %v \n " , err)
74- }
75- }()
76-
77- // Start listening (blocking call)
78- if err := server.ListenAndServe (); err != lime.ErrServerClosed {
79- log.Printf (" listen: %v \n " , err)
80- }
52+ // Message handler that echoes all received messages to the originator
53+ msgHandler := func (ctx context.Context , msg *lime.Message , s lime.Sender ) error {
54+ echoMsg := &lime.Message {}
55+ echoMsg.SetContent (msg.Content ).SetTo (msg.From )
56+ return s.SendMessage (ctx, echoMsg)
57+ }
58+
59+ // Build a server, listening for TCP connections in the 55321 port
60+ server := lime.NewServerBuilder ().
61+ MessagesHandlerFunc (msgHandler).
62+ ListenTCP (&net.TCPAddr {Port: 55321 }, &lime.TCPConfig {}).
63+ Build ()
64+
65+ // Listen for the OS termination signals
66+ sigs := make (chan os.Signal , 1 )
67+ signal.Notify (sigs, syscall.SIGINT , syscall.SIGTERM )
68+ go func () {
69+ <- sigs
70+ if err := server.Close (); err != nil {
71+ log.Printf (" close: %v \n " , err)
72+ }
73+ }()
74+
75+ // Start listening (blocking call)
76+ if err := server.ListenAndServe (); err != lime.ErrServerClosed {
77+ log.Printf (" listen: %v \n " , err)
78+ }
8179}
8280```
8381
@@ -98,46 +96,44 @@ import (
9896)
9997
10098func main () {
101- done := make (chan bool )
102-
103- // Defines a simple handler function for printing
104- // the received messages to the stdout
105- msgHandler := func (ctx context.Context , msg *lime.Message , s lime.Sender ) error {
106- if txt , ok := msg.Content .(lime.TextDocument ); ok {
107- log.Printf (" Text message received - ID: %v - Type: %v - Content: %v \n " , msg.ID , msg.Type , txt)
108- }
109- close (done)
110- return nil
111- }
112-
113- // Initialize the client
114- client := lime.NewClientBuilder ().
115- UseTCP (&net.TCPAddr {IP: net.IPv4 (127 , 0 , 0 , 1 ), Port: 55321 }, &lime.TCPConfig {}).
116- MessagesHandlerFunc (msgHandler).
117- Build ()
118-
119- // Prepare a simple text message to be sent
120- msg := &lime.Message {
121- Type: lime.MediaTypeTextPlain (),
122- Content: lime.TextDocument (" Hello world!" ),
123- }
124-
125- ctx , cancel := context.WithTimeout (context.Background (), 5 *time.Second )
126- defer cancel ()
127-
128- // Send the message
129- if err := client.SendMessage (ctx, msg); err != nil {
130- log.Printf (" send message: %v \n " , err)
131- }
132-
133- // Wait for the echo message
134- <- done
135-
136- // Close the client
137- err := client.Close ()
138- if err != nil {
139- log.Printf (" close: %v \n " , err)
140- }
99+ done := make (chan bool )
100+
101+ // Defines a simple handler function for printing
102+ // the received messages to the stdout
103+ msgHandler := func (ctx context.Context , msg *lime.Message , s lime.Sender ) error {
104+ if txt , ok := msg.Content .(lime.TextDocument ); ok {
105+ log.Printf (" Text message received - ID: %v - Type: %v - Content: %v \n " , msg.ID , msg.Type , txt)
106+ }
107+ close (done)
108+ return nil
109+ }
110+
111+ // Initialize the client
112+ client := lime.NewClientBuilder ().
113+ UseTCP (&net.TCPAddr {IP: net.IPv4 (127 , 0 , 0 , 1 ), Port: 55321 }, &lime.TCPConfig {}).
114+ MessagesHandlerFunc (msgHandler).
115+ Build ()
116+
117+ // Prepare a simple text message to be sent
118+ msg := &lime.Message {}
119+ msg.SetContent (lime.TextDocument (" Hello world!" ))
120+
121+ ctx , cancel := context.WithTimeout (context.Background (), 5 *time.Second )
122+ defer cancel ()
123+
124+ // Send the message
125+ if err := client.SendMessage (ctx, msg); err != nil {
126+ log.Printf (" send message: %v \n " , err)
127+ }
128+
129+ // Wait for the echo message
130+ <- done
131+
132+ // Close the client
133+ err := client.Close ()
134+ if err != nil {
135+ log.Printf (" close: %v \n " , err)
136+ }
141137}
142138```
143139
@@ -179,21 +175,21 @@ msg.SetContent(lime.TextDocument("Hello from Lime!")).
179175
180176In this example, the document value is the ` Hello from Lime! ` text and its MIME type is ` text/plain ` .
181177
182- This message also have a ` id ` property with value ` 1 ` .
183- The id used to ** correlate notifications** about the message.
184- This means that the message destination and intermediates may send notifications about the message status, using the
185- same id.
186- So, if you are interested to know if a message that was sent by you was delivered or not, you should put a value in the
187- id property.
178+ This message also have a ` id ` property with ` 1 ` value .
179+ The id value is useful to ** correlate notifications** about the message.
180+ When the id is set, the sender may receive notifications (receipts) with message events, which will have the same id.
181+ For instance, you may want to know if a message was received or read by its destination.
182+ In this case, you should provide an id value to the message.
188183
189- The ` to ` property specifies the destination address of the message, and it is used by the server to route the envelope
184+ The ` to ` property sets the destination address of the message, and it is used by the server to route the envelope
190185to the correct destination.
191- The address format is called ** node** and is presented in the ` name@domain/instance ` format, similar to the
192- [ XMPP's Jabber ID] ( https://xmpp.org/rfcs/rfc3920.html#rfc.section.3 ) , but the _ domain_ and _ instance_ portions of the
193- node are optional.
186+ The address format is called ** node** and in its full form is presented in the ` name@domain/instance ` format, similar to
187+ the [ XMPP's Jabber ID] ( https://xmpp.org/rfcs/rfc3920.html#rfc.section.3 ) .
188+ The node's _ domain_ and _ instance_ portions are optional, so the value ` john ` used in the example is a valid node
189+ address.
194190
195- In this example, the content is a simple text but a message can be used to transport any type of document that can be
196- represented as JSON.
191+ In the previous example, the content is a simple text.
192+ But a message can be used to transport any type of document that can be represented as JSON.
197193
198194For instance, to send a generic JSON document you can use the ` application/json ` type:
199195
@@ -219,7 +215,6 @@ msg.SetContent(&lime.JsonDocument{
219215 SetToString (" john" )
220216```
221217
222-
223218You can also can (and probably should) use custom MIME types for representing well-known types from your application
224219domain:
225220
@@ -260,7 +255,7 @@ func init() {
260255}
261256```
262257
263- For instance, to send a message to the " john" addresss you can use the ` SendMessage ` method that is implemented both by
258+ For instance, to send a message to the ` john ` node, you can use the ` SendMessage ` method that is implemented both by
264259the ` lime.Server ` and ` lime.Client ` types:
265260
266261``` go
@@ -317,7 +312,7 @@ if msg.ID != "" {
317312}
318313```
319314
320- Notifications can be sent by the ** destination of the message or by intermediates** - like a server that routes the
315+ Notifications can be emitted by the ** destination of the message or by intermediates** - like a server that route the
321316message.
322317
323318The protocol define the following notification events:
@@ -357,28 +352,33 @@ not := msg.FailedNotification(&lime.Reason{Code: 1, Description: "Destination no
357352
358353### Command
359354
360- The command envelope is used to ** manipulate resources of a remote node** .
361- It provides a REST capable interface, with a URI and methods (verbs), much like the HTTP protocol.
362- It also supports multiplexing, so the connection is not blocked when a request is sent.
355+ The command envelope is used to ** read and write resources of a remote node** .
356+ It provides a REST capable interface, with URI and methods (verbs), similar to the HTTP protocol.
357+ It also supports multiplexing, so the connection is not blocked to wait for a response when a request is sent.
358+
359+ There are two types of commands: a request command - which contains a ` uri ` value - or a response command - with a
360+ ` status ` value.
361+
362+ For instance, you can use commands for managing your contact list or to set your current status (available, busy, away).
363+ Other common use is ** the in-band registration** , where users can create accounts for your service in the protocol
364+ itself.
363365
364- A command can be a request - which haves the ` uri ` value - or a response - with the ` status ` value.
366+ The advantage of using commands is that you can use the ** same existing connection** that is used for messaging for
367+ handling resources, instead of creating out-of-band connections for that.
365368
366- As example, you can use it for managing your contact list or to set your current status (available, busy, away).
367- Other common use is ** the in-band registration** , where users can create Lime accounts in the protocol itself.
369+ In practice, you can avoid having an external HTTP service for handling resources related to your messaging service.
368370
369- The advantage of using commands is that you can use the ** same existing connection** that is used for messaging instead
370- of creating one or more out-of-band connections - like in HTTP for instance.
371- This is more efficient in terms of energy consumption but also is more performatic as well.
372- The session is already established and authenticated, so it avoids the addition overhead of a TLS handshake and
373- authentication that a new connection would require.
371+ This is more efficient in terms of energy consumption but also is usually more performatic as well.
372+ Using a session that is already established and authenticated avoids the additional overhead of a TLS handshake and
373+ authentication that an external connection would require.
374374
375- But there is a limitation: the command interface only supports JSON payloads, so you should avoid use it for
376- transmitting binary or any kind of large content.
375+ But there is a limitation: the command interface only supports JSON payloads, so you should not use it for
376+ transporting binary or any kind of large content.
377377
378- Much like an HTTP service, the URI and methods that you may use in commands depends on what the server implements.
378+ Like in an HTTP service, the URI and methods that you may use in commands depends on what the server implements.
379379
380380For instance, a server could implement a contact management service.
381- In this example, you could be able to send a command like this:
381+ In this example, to retrieve all contacts, you could send a command like this:
382382
383383``` json
384384{
@@ -388,8 +388,7 @@ In this example, you could be able to send a command like this:
388388}
389389```
390390
391- Semantically, this means that you want to retrieve all contacts that are stored in the server.
392- And the server may respond to this request with something like this:
391+ And the server may respond to this request like this:
393392
394393``` json
395394{
0 commit comments