
Show HN: Jackal – XMPP server in Go - ortuman
https://github.com/ortuman/jackal/releases/tag/0.2.0
======
orivej
The principal feature that I consider when evaluating XMPP servers and clients
is their support for reliable message delivery (no message loss on connection
interruptions), and the main method of achieving it is with XEP-0198 ("Stream
Management") [1]. Unfortunately Jackal does not support it, and AFAIK it is
much harder to implement it for an existing server or client than to design
the application with XEP-0198 in mind.

To support reliable message delivery as defined in XEP-0198, the application
needs to:

(1) count and acknowledge stanzas;

(2) buffer unacknowledged stanzas for redelivery in case of stream resumption;

(3) resend delayed stanzas in case of stream not being resumed.

Note that some clients that claim support for XEP-0198 implement
`urn:xmpp:sm:3` (Psi+, Conversations, Gajim with python-nbxmpp>=0.5.6), while
others implement `urn:xmpp:sm:2` (Swift, Gajim with python-nbxmpp<0.5.6). The
revisions differ in how they count stanzas. Ejabberd supports them both
simultaneously.

The level of support also varies. An application may:

(1) just count and acknowledge stanzas;

(2) resend stanzas on stream resumption;

(3) resend stanzas on reconnect without stream resumption;

(4) resend stanzas after the application is restared.

Psi+ supports 1 and 2, does not support 4, and probably does not support 3.
Swift supports only 1. [2]

[1] It is also technically possible for the client to use XEP-0313 ("Message
Archive Management") to retrieve undelivered messages and to discover and
resend unsent messages, but the latter is not described in the XEP, and I'm
not aware of the clients that do so. I have found this suggested by Holger
Weiß at [https://github.com/redsolution/xabber-
android/issues/128#iss...](https://github.com/redsolution/xabber-
android/issues/128#issuecomment-142424907) , together with a clever (currently
abandoned) extension of XEP-0313 with `urn:xmpp:mam:sub` that subsumes
XEP-0280 ("Message Carbons").

[2] To study interactions between Jabber clients and servers, I wrote
[https://github.com/orivej/xmpp-logging-proxy](https://github.com/orivej/xmpp-
logging-proxy) that serves as a Jabber server by relaying communications to
the actual Jabber server while saving the decrypted streams to files.

~~~
defanor
I agree: not to discourage OP, but there is plenty of XMPP implementations (as
well as those for other protocols), yet very few complete (say, in the
XEP-0387 sense) ones, and even fewer reusable (libraries providing C
interface, or something else more or less common and standard) ones. It seems
that it would be more useful to put time/effort into improving those, unless
there are really good reasons for making new ones.

------
sofaofthedamned
I've just checked the Docker image and it's 417mb. How on earth is it this
large?

[https://hub.docker.com/r/ortuman/jackal/tags/](https://hub.docker.com/r/ortuman/jackal/tags/)

~~~
eximius
Why is it even using Docker at all? One of the features of Go is that it is
statically linked with it's dependencies!?

~~~
kiliankoe
Docker has a few more upsides than just bundling an app with its dependencies,
orchestration being one of them. Also, a go app wouldn't have to be cross-
compiled for whatever architecture as long as Docker runs there. Go makes that
easy and effortless, sure, and there's nothing stopping you from doing so.

~~~
chatmasta
Docker containers inherit the architecture of the host system. There is no CPU
virtualization involved. So you still need to cross compile if you want to run
the binary on another architecture, regardless of whether or not the binary is
running inside a docker container.

------
Boulth
This is really interesting. As far as I know there are only two servers that
power the majority of public instances and both of them have weak type
systems.

~~~
lucian1900
Go's is not much stronger either. It hardly makes any difference.

~~~
Thaxll
You don't known what you're talking about, did you even bother search
interface {} in the code?

~~~
erik_seaberg
Here are methods that store and retrieve … something, probably. The author had
to make up method names because map[string]interface{} doesn't have an
interface we could satisfy.

    
    
      func (ctx *Context) SetObject(object interface{}, key string) { … }
      func (ctx *Context) Object(key string) interface{} { … }
    

Here a caller has to provide a method that takes an arbitrary number of …
whatever.

    
    
      type rowScanner interface {
      	Scan(...interface{}) error
      }

------
JepZ
Nice to see someone actually starting a Go powered XMPP server. I hope their
breath is long enough to bring it to a competitive state.

------
0xdeadbeefbabe
It's good to see something written in go.

