Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xmpp-go

An XMPP library for Go supporting both client and server roles, with a plugin architecture and building blocks for 50+ XEPs.

Project status

The client and server work end to end and are covered by integration tests (real client ↔ real server over TCP, WebSocket, and BOSH):

  • Connection: full stream negotiation over TCP (<stream:stream>), WebSocket (RFC 7395 <open/> framing), and BOSH (XEP-0124/0206 HTTP long-polling, Client.WithBOSH + Server.BOSHHandler), plus STARTTLS and resource binding.
  • Authentication: SASL SCRAM-SHA-1/256/512 and their -PLUS channel-binding variants (client and server; tls-server-end-point, RFC 5929, negotiated automatically over TLS), PLAIN (refused over cleartext unless explicitly overridden), ANONYMOUS, and EXTERNAL on both sides — the server maps a verified TLS client certificate to a local identity (WithServerClientCertAuth). Auth failures surface as a typed *AuthError.
  • Federation (s2s): server-to-server streams authenticated with XEP-0220 Server Dialback (WithServerS2S); stanzas to remote domains are routed over authenticated s2s streams, and inbound s2s streams are verified via a dialback callback to the originating server.
  • Routing & services: message/presence/IQ routing; service IQs for disco#info/#items, XEP-0199 ping, XEP-0092 version, and RFC 6121 roster get/set; clients auto-answer pings.
  • Presence (RFC 6121): the subscribe/subscribed/unsubscribe state machine with roster updates, roster pushes, and presence broadcast to subscribed contacts.
  • Plugins: an inbound-handler framework routes incoming stanzas to plugins by payload namespace. On the client the disco, ping, version, and roster plugins respond to and issue requests (Client.SendIQ). On the server, WithServerPluginFactory gives each session its own plugin instances with inbound IQ dispatch.
  • Stream Management (XEP-0198): enable/enabled, inbound counting, r/a acknowledgement (delivery confirmation via Session.RequestSMAck), and resumption — a dropped session is parked for a resumption window, stanzas addressed to it are buffered, and Client.Resume restores the bound resource and replays unacknowledged stanzas.
  • BOSH robustness (XEP-0124): request acknowledgements (ack), retransmission recovery via a per-rid response cache (§14.2), pipelined requests with forward-gap ordering, and hold-release so a send is never stalled behind an idle long-poll. The bundled client keeps a concurrent long-poll (requests='2') and retransmits failed requests.
  • JIDs: RFC 7622 normalization — IDNA A-labels for domains, PRECIS UsernameCaseMapped localparts, OpaqueString resources. Stanza extensions round-trip without corruption.

The core RFCs (6120/6121/7622), all three transports (TCP, WebSocket, BOSH), the full SASL mechanism set, Stream Management with resumption, and s2s dialback federation are implemented and integration-tested. Higher-level XEPs beyond the core (MUC, PubSub, MAM, OMEMO, Jingle, …) are provided as plugin building blocks under plugins/; see the feature checklist below.

Features

  • Unified client/server Session type
  • Plugin architecture with dependency resolution
  • Streaming XML parser optimized for XMPP
  • Multiple transports: TCP, WebSocket, BOSH
  • Full SASL support: PLAIN, SCRAM-SHA-1/256/512 (+PLUS), EXTERNAL, ANONYMOUS
  • STARTTLS with certificate verification
  • Stanza multiplexer with middleware support
  • DNS SRV and host-meta resolution
  • Pluggable storage backends: Memory, File, SQLite, PostgreSQL, MySQL, MongoDB, Redis

Installation

go get github.com/meszmate/xmpp-go

Docker / Compose

This repo ships a ready-to-run server binary in cmd/xmppd with Docker and Compose support.

Quick start (self-signed TLS, file storage, default accounts):

docker compose --profile xmpp up --build

The default config lives in docker/xmppd.env. Common overrides:

  • XMPP_DOMAIN (default example.com)
  • XMPP_STORAGE (file|sqlite|postgres|mysql|mongodb|redis|memory)
  • XMPP_STORAGE_DSN (for DB backends)
  • XMPP_PLUGINS (comma list or all)
  • XMPP_DEFAULT_ACCOUNTS (user:pass,user2:pass)
  • XMPP_TLS_SELF_SIGNED=true (auto-generate certs)

Server-side XEP-0077 registration is supported and configurable via:

  • XMPP_REGISTRATION_POLICY (open|closed|invite|admin)
  • XMPP_REGISTRATION_FIELDS (comma list, e.g. username,password,email)
  • XMPP_REGISTRATION_INVITES (comma list of invite tokens)
  • XMPP_REGISTRATION_ADMIN_TOKENS (comma list)
  • XMPP_REGISTRATION_RATE_LIMIT (requests per window)
  • XMPP_REGISTRATION_RATE_WINDOW (Go duration, e.g. 1m)
  • XMPP_REGISTRATION_SCRAM_ITERATIONS (default 4096)
  • XMPP_REGISTRATION_DATAFORM (true|false)

To use a database, enable the matching profile and set XMPP_STORAGE + XMPP_STORAGE_DSN:

docker compose --profile xmpp --profile postgres up --build

GHCR image publishing is wired via .github/workflows/docker.yml and publishes to ghcr.io/meszmate/xmpp-go.

CI notes:

  • No GoReleaser is used. Docker publishing is handled by GitHub Actions and pushes to GHCR on main and tags.
  • docker-compose.yml uses ghcr.io/meszmate/xmpp-go:latest by default.

Pull from GHCR (after CI pushes):

docker pull ghcr.io/meszmate/xmpp-go:latest

Quick Start

package main

import (
    "context"
    "log"

    xmpp "github.com/meszmate/xmpp-go"
    "github.com/meszmate/xmpp-go/jid"
    "github.com/meszmate/xmpp-go/stanza"
    "github.com/meszmate/xmpp-go/plugins/disco"
    "github.com/meszmate/xmpp-go/plugins/roster"
)

func main() {
    client, err := xmpp.NewClient(
        jid.MustParse("user@example.com"),
        "password",
        xmpp.WithPlugins(disco.New(), roster.New()),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    ctx := context.Background()
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }

    msg := stanza.NewMessage(stanza.MessageChat)
    msg.To = jid.MustParse("friend@example.com")
    msg.Body = "Hello from xmpp-go!"
    _ = client.Send(ctx, msg)
}

In-Band Registration (XEP-0077)

xmpp-go provides a standalone registration flow in plugins/register for account creation before authentication. The helper functions automatically handle stream setup, STARTTLS upgrade, classic register fields, and data-form registration.

package main

import (
    "context"
    "fmt"
    "log"
    "time"

    "github.com/meszmate/xmpp-go/plugins/register"
)

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    form, err := register.FetchRegistrationForm(ctx, "example.com", 5222)
    if err != nil {
        log.Fatal(err)
    }

    fields := map[string]string{
        "username": "newuser",
        "password": "strong-password",
        "email":    "newuser@example.com",
    }

    result, err := register.SubmitRegistration(
        ctx,
        "example.com",
        5222,
        fields,
        form.IsDataForm,
        form.FormType,
    )
    if err != nil {
        log.Fatal(err)
    }
    if !result.Success {
        log.Fatal(result.Error)
    }

    fmt.Println("Registered JID:", result.JID)
}

For data-form registration, include all required fields from the fetched form in fields (including hidden fields and CAPTCHA answers when requested).

Feature Checklist

Core (RFC 6120/6121/7622)

  • JID parsing and validation (RFC 7622)
  • JID escaping (XEP-0106)
  • XML stream reader/writer
  • Stream error conditions
  • STARTTLS negotiation
  • SASL authentication
  • Resource binding
  • Stanza types: Message, Presence, IQ
  • Stanza error conditions
  • Roster management (RFC 6121)
  • Presence management (RFC 6121)

Transports

  • TCP transport
  • WebSocket transport (RFC 7395)
  • BOSH transport (XEP-0124/0206)

SASL Mechanisms

  • PLAIN
  • SCRAM-SHA-1 / SCRAM-SHA-1-PLUS
  • SCRAM-SHA-256 / SCRAM-SHA-256-PLUS
  • SCRAM-SHA-512 / SCRAM-SHA-512-PLUS
  • EXTERNAL
  • ANONYMOUS

Service Discovery & Capabilities

  • XEP-0030: Service Discovery
  • XEP-0115: Entity Capabilities

Messaging

  • XEP-0085: Chat State Notifications
  • XEP-0184: Message Delivery Receipts
  • XEP-0280: Message Carbons
  • XEP-0308: Last Message Correction
  • XEP-0313: Message Archive Management
  • XEP-0333: Chat Markers
  • XEP-0334: Message Processing Hints
  • XEP-0359: Unique/Stable Stanza IDs
  • XEP-0393: Message Styling
  • XEP-0424: Message Retraction
  • XEP-0444: Message Reactions

Group Chat

  • XEP-0045: Multi-User Chat
  • XEP-0249: Direct MUC Invitations
  • XEP-0369: MIX Core
  • XEP-0403/0405/0406/0407: MIX extensions
  • XEP-0425: Message Moderation

Stream Management

  • XEP-0198: Stream Management

PubSub & Storage

  • XEP-0004: Data Forms
  • XEP-0060: Publish-Subscribe
  • XEP-0163: Personal Eventing Protocol
  • XEP-0402: PEP Native Bookmarks

User Profile

  • XEP-0054: vcard-temp
  • XEP-0084: User Avatar
  • XEP-0092: Software Version
  • XEP-0153: vCard-Based Avatars
  • XEP-0292: vCard4 over XMPP

File Transfer

  • XEP-0047: In-Band Bytestreams
  • XEP-0065: SOCKS5 Bytestreams
  • XEP-0066: Out of Band Data
  • XEP-0234: Jingle File Transfer
  • XEP-0363: HTTP File Upload
  • XEP-0446/0447/0448: Stateless File Sharing

Encryption

Jingle (Voice/Video)

  • XEP-0166: Jingle
  • XEP-0167: Jingle RTP Sessions
  • XEP-0176: Jingle ICE-UDP Transport
  • XEP-0177: Jingle Raw UDP Transport
  • XEP-0320: DTLS-SRTP in Jingle
  • XEP-0353: Jingle Message Initiation

Mobile & Push

  • XEP-0352: Client State Indication
  • XEP-0357: Push Notifications

Server Features

  • XEP-0012: Last Activity
  • XEP-0050: Ad-Hoc Commands
  • XEP-0059: Result Set Management
  • XEP-0077: In-Band Registration
  • XEP-0114: Jabber Component Protocol
  • XEP-0191: Blocking Command
  • XEP-0215: External Service Discovery
  • XEP-0220: Server Dialback
  • XEP-0288: Bidirectional Server-to-Server

Utilities

  • XEP-0082: Date/Time Profiles
  • XEP-0156: DNS/host-meta resolution
  • XEP-0199: XMPP Ping
  • XEP-0202: Entity Time
  • XEP-0203: Delayed Delivery
  • XEP-0231: Bits of Binary
  • XEP-0297: Stanza Forwarding
  • XEP-0300: Cryptographic Hash Functions
  • XEP-0368: SRV records for XMPP over TLS

Modern Authentication

  • XEP-0386: Bind 2
  • XEP-0388: SASL2
  • XEP-0440: SASL Channel-Binding Type Capability
  • XEP-0484: FAST

Storage Backends

xmpp-go includes a pluggable storage layer. All stateful plugins (roster, blocking, vcard, MUC, MAM, PubSub, bookmarks) automatically use the configured backend, falling back to in-memory storage when none is set.

Backend Package External Dependency
Memory storage/memory None
File (JSON) storage/file None
SQLite storage/sqlite github.com/mattn/go-sqlite3
PostgreSQL storage/postgres github.com/jackc/pgx/v5
MySQL storage/mysql github.com/go-sql-driver/mysql
MongoDB storage/mongodb go.mongodb.org/mongo-driver/v2
Redis storage/redis github.com/redis/go-redis/v9
import (
    xmpp "github.com/meszmate/xmpp-go"
    "github.com/meszmate/xmpp-go/storage/memory"
)

server, _ := xmpp.NewServer("example.com",
    xmpp.WithServerStorage(memory.New()),
    // ...
)

Backends with external dependencies live in separate Go modules so the main module stays dependency-free. Install only what you need:

go get github.com/meszmate/xmpp-go/storage/postgres

See the Storage Guide for full details.

OMEMO Encryption

xmpp-go includes a standalone Signal protocol implementation at crypto/omemo/ for OMEMO v2 (XEP-0384) end-to-end encryption. It is a separate Go module with no dependency on the main library.

go get github.com/meszmate/xmpp-go/crypto/omemo

OMEMO works across both the server and client:

  • Server side: The PubSub plugin + storage backend persists device lists and bundles (public key material only). No OMEMO-specific configuration needed -- it uses standard PEP nodes.
  • Client side: The crypto/omemo package handles X3DH key agreement, Double Ratchet encryption, and AES-256-GCM. Private keys and session state are stored locally via the omemo.Store interface.
import "github.com/meszmate/xmpp-go/crypto/omemo"

// Client-side crypto store (private keys, sessions, trust)
store := omemo.NewMemoryStore(myDeviceID)
manager := omemo.NewManager(store)

// Generate bundle (private keys stay local, public parts go to server via PEP)
bundle, _ := manager.GenerateBundle(25)

// After fetching a contact's bundle from the server:
manager.ProcessBundle(addr, remoteBundleParsedFromXML)

// Encrypt for recipient devices
encMsg, _ := manager.Encrypt([]byte("Hello!"), recipientAddresses...)

// Decrypt incoming messages
plaintext, _ := manager.Decrypt(senderAddr, incomingMsg)

See the OMEMO Guide for the full server/client architecture, step-by-step setup, and conversion between XML and crypto types.

Documentation

License

MIT License - see LICENSE for details.

About

A production-grade XMPP library for Go supporting both client and server roles with a plugin architecture covering 50+ XEPs.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages