Code Monkey home page Code Monkey logo

cr-xmpp's Introduction

Crystal XMPP

CI GitHub release Docs

Pure Crystal XMPP Shard, focusing on simplicity, simple automation, and IoT.

The goal is to make simple to write simple XMPP clients and components. It features:

  • Fully OOP
  • Aims at being XMPP compliant
  • Event Based
  • Easy to extend
  • For automation (like for example monitoring of an XMPP service),
  • For building connected "things" by plugging them on an XMPP server,
  • For writing simple chatbot to control a service or a thing,
  • For writing XMPP servers components.

You can basically do everything you want with cr-xmpp. It fully supports XMPP Client and components specification, and also a wide range of extensions (XEPs). And it's very easy to extend :)

This Shard does not have any other dependencies.

Supported specifications

Clients

Components

XEP Extensions

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      cr-xmpp:
        github: naqvis/cr-xmpp
  2. Run shards install

Usage

require "cr-xmpp"

config = XMPP::Config.new(
  host: "localhost",
  jid: "test@localhost",
  password: "test",
  log_file: STDOUT,   # Capture all out-going and in-coming messages
  # Order of SASL Authentication Mechanism, first matched method supported by server will be used
  # for authentication. Below is default order that will be used if `sasl_auth_order` param is not set.
  sasl_auth_order: [XMPP::AuthMechanism::SCRAM_SHA_512, XMPP::AuthMechanism::SCRAM_SHA_256,
                    XMPP::AuthMechanism::SCRAM_SHA_1, XMPP::AuthMechanism::DIGEST_MD5,
                    XMPP::AuthMechanism::PLAIN, XMPP::AuthMechanism::ANONYMOUS]
)

router = XMPP::Router.new

# router.on "presence" do |_, p|  # OR
router.presence do |_, p|
  if (msg = p.as?(XMPP::Stanza::Presence))
    puts msg
  else
    puts "Ignoring Packet: #{p}"
  end
end

# router.when "chat" do |s, p| # OR
router.message do |s, p|
  handle_message(s, p)
end

# OR
# router.on "message", ->handle_message(XMPP::Sender, XMPP::Stanza::Packet)

client = XMPP::Client.new config, router
# If you pass the client to a connection manager, it will handle the reconnect policy
# for you automatically
sm = XMPP::StreamManager.new client
sm.run


def handle_message(s : XMPP::Sender, p : XMPP::Stanza::Packet)
  if (msg = p.as?(XMPP::Stanza::Message))
    puts "Got message: #{msg.body}"
    reply = XMPP::Stanza::Message.new
    reply.to = msg.from
    reply.body = "#{msg.body}"
    s.send reply
  else
    puts "Ignoring Packet: #{p}"
  end
end

Refer to examples for more usage details.

Development

XMPP stanzas are basic and extensible XML elements. Stanzas (or sometimes special stanzas called 'nonzas') are used to leverage the XMPP protocol features. During a session, a client (or a component) and a server will be exchanging stanzas back and forth.

At a low-level, stanzas are XML fragments. However, this shard provides the building blocks to interact with stanzas at a high-level, providing a Crystal-friendly API.

The XMPP::Stanza module provides support for XMPP stream parsing, encoding and decoding of XMPP stanza. It is a bridge between high-level Crystal classes and low-level XMPP protocol.

Parsing, encoding and decoding is automatically handled by Crystal XMPP client shard. As a developer, you will generally manipulates only the high-level classes provided by the XMPP::Stanza module.

The XMPP protocol, as the name implies is extensible. If your application is using custom stanza extensions, you can implement your own extensions directly.

Custom Stanza Support

Below example show how to implement a custom extension for your own client, without having to modify or fork Crystal XMPP shard.

class CustomExtension < Extension
    include IQPayload
    class_getter xml_name : XMLName = XMLName.new("my:custom:payload query")
    property node : String = ""

    def self.new(node : XML::Node)
      raise "Invalid node(#{node.name}, expecting #{@@xml_name.to_s}" unless (node.namespace.try &.href == @@xml_name.space) &&
                                                                             (node.name == @@xml_name.local)
      cls = new()
      node.children.select(&.element?).each do |child|
      case child.name
        when "item" then cls.node = child.content
        end
      end
      cls
    end

    def to_xml(elem : XML::Builder)
      elem.element(@@xml_name.local, xmlns: @@xml_name.space) do
        elem.element("node") { elem.text node } unless node.blank?
      end
    end

    def namespace : String
      @@xml_name.space
    end

    def name : String
      @@xml_name.local
    end
  end

  Registry.map_extension(PacketType::IQ, XMLName.new("my:custom:payload", "query"), CustomExtension)

Contributing

  1. Fork it (https://github.com/naqvis/cr-xmpp/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

cr-xmpp's People

Contributors

naqvis avatar robdavid avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

iraamaro robdavid

cr-xmpp's Issues

SCRAM-SHA-1-PLUS + SCRAM-SHA-256-PLUS + SCRAM-SHA-512-PLUS + SCRAM-SHA3-512(-PLUS) supports

Dear @naqvis,

In first, I wish you a Happy New Year!

After

  • SCRAM-SHA-1
  • SCRAM-SHA-256
  • SCRAM-SHA-512

Can you add supports of :

  • SCRAM-SHA-1-PLUS
  • SCRAM-SHA-256-PLUS
  • SCRAM-SHA-512-PLUS
  • SCRAM-SHA3-512
  • SCRAM-SHA3-512-PLUS

You can add too:

  • SCRAM-SHA-224
  • SCRAM-SHA-224-PLUS
  • SCRAM-SHA-384
  • SCRAM-SHA-384-PLUS

"When using the SASL SCRAM mechanism, the SCRAM-SHA-256-PLUS variant SHOULD be preferred over the SCRAM-SHA-256 variant, and SHA-256 variants [RFC7677] SHOULD be preferred over SHA-1 variants [RFC5802]".

https://xmpp.org/extensions/inbox/hash-recommendations.html

-PLUS variants:

IMAP:

LDAP:

  • RFC5803: Lightweight Directory Access Protocol (LDAP) Schema for Storing Salted: Challenge Response Authentication Mechanism (SCRAM) Secrets: https://tools.ietf.org/html/rfc5803

HTTP:

2FA:

IANA:

Linked to:

RFC 9266: Channel Bindings for TLS 1.3 support

Dear @naqvis,

Can you add the support of RFC 9266: Channel Bindings for TLS 1.3?

Little details, to know easily:

  • tls-unique for TLS =< 1.2
  • tls-server-end-point
  • tls-exporter for TLS = 1.3

I think that you have seen the jabber.ru MITM and Channel Binding is the solution:

Thanks in advance.

Linked to:

Support SCRAM-SHA-1, SCRAM-SHA-256 and SCRAM-SHA-512 ๐Ÿ”

First of all: thank you so much for your work! ๐Ÿ™

It would be nice if those authentication methods would be supported:

See also XMPP wiki

PS: Just to be sure: the strongest variants should obviously be preferred because SHA-1 (see RFC 4270 and RFC 6194) and MD5 (RFC 6331) are considered obsolete

PPS: I'm not sure whether it's worth anything but Kafka and MongoDB also use SCRAM for authentication. Therefore the Ruby Kafka client and the Ruby MongoDB driver could be used as an inspiration.

XEPs and RFCs support page with version

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.