Code Monkey home page Code Monkey logo

juno's Introduction

juno

Yes.
It really is an IRC daemon.
It's written in Perl.

...

You can breathe again.
There. Very good.

Introduction

This is juno, a seriously modern IRC daemon written from scratch in Perl. Really.

Perl is the right language for IRC. IRC is chock full of various strings and other what not, all of which is easily parsed by Perl, where the C IRC daemons jump through all kinds of hoops and have really nasty looking code (have you ever looked at the Undernet IRC daemon?) Whereas this is, in my opinion, very clean.

This software will hopefully surprise you with its novel features and functionality. It's super easy to install and even comes with a working configuration, so go ahead and try it already.

Come chat with us at #k on irc.notroll.net too.

Features

There are a lot! But here are some things that make juno stand out.

You can

  • Upgrade an entire network from IRC without restarting servers or dropping connections.
  • Check out the latest version from git via IRC.
  • Configure servers directly from IRC.
  • Link a complex network of various IRCds and services packages spanning multiple server protocols.
  • Write modules for the easy-to-use event-based module API.
  • Or rather, beg for the features you want.

Plus, juno

  • Is free and open-source.
  • Is written in Perl, making it fun and easy to tinker with.
  • Is extensively documented.
  • Is excessively configurable.
  • Despite that, ships with a working configuration and runs out-of-the-box.
  • Consists entirely of modules and therefore can be as minimal or as bloated as you're comfortable with.
  • Supports the latest IRCv3 standards.
  • Supports multiple linking protocols, including several TS variants and a custom user-extensible protocol.
  • Supports Atheme, PyLink and probably other IRC services packages.

Concepts

  • Eventedness: The core unifying policy of juno is the excessive use of events. Just about any operation that occurs is represented as an event. This is made possible by Evented::Object, the base of every class within the IRCd.
# if it's a server, add the $PROTO_message events
if (my $server = $connection->server) {
    my $proto = $server->{link_type};
    push @events, [ $server, "${proto}_message"        => $msg ],
                  [ $server, "${proto}_message_${cmd}" => $msg ];
    $msg->{_physical_server} = $server;
}

# fire the events
my $fire = $connection->prepare(@events)->fire('safe');
  • Extensibility: Through the use of events and other mechanisms, extensibility is another important guideline around which juno is designed. It should not be assumed that any commands, modes, prefixes, etc. are fixed or finite. They should be changeable, replaceable, and unlimited.
[ modes: channel ]
    no_ext        = [ mode_normal, 'n' ]    # no external channel messages
    protect_topic = [ mode_normal, 't' ]    # only ops can set the topic
    ban           = [ mode_list,   'b' ]    # ban
    except        = [ mode_list,   'e' ]    # ban exception
    limit         = [ mode_pset,   'l' ]    # user limit
    forward       = [ mode_pset,   'f' ]    # channel forward mode
    key           = [ mode_key,    'k' ]    # keyword for entry
  • Modularity: By responding to events, modules add new features and functionality. Without them, juno is made up of under thirty lines of code. Modules work together to create a single functioning body whose parts can be added, removed, and modified dynamically. This is made possible by the Evented::API::Engine, a class that manages modules and automatically tracks their events.
Ban::TS6 10.6
   TS6 ban propagation
   TS6 CAPABILITIES
       BAN, KLN, UNKLN
   TS6 COMMANDS
       BAN, ENCAP_DLINE, ENCAP_KLINE, ENCAP_NICKDELAY
       ENCAP_RESV, ENCAP_UNDLINE, ENCAP_UNKLINE
       ENCAP_UNRESV, KLINE, RESV, UNKLINE, UNRESV
   OUTGOING TS6 COMMANDS
       BAN, BANDEL, BANINFO
  • Upgradability: The beauty of Perl's malleable symbol table makes it possible for an entire piece of software to be upgraded or reloaded without restarting it. With the help of the Evented::API::Engine and with modularity as a central principle, juno aims to do exactly that. With just one command, you can jump up one or one hundred versions, all without your users disconnecting.
*** Update: k.notroll.net git repository updated to version 12.88 (juno12-mihret-209-g269c83c)
*** Reload: k.notroll.net upgraded from 12.48 to 12.88 (up 88 versions since start)
[ listen: 0.0.0.0 ]
    port    = [6667..6669, 7000]
    sslport = [6697]
    ts6port = [7050]

[ ssl ]
    cert = 'etc/ssl/cert.pem'   
    key  = 'etc/ssl/key.pem'    
  • Efficiency: Modern IRC servers have a higher per-user load and therefore must be prompt at fulfilling requests. Utilizing the wonderful IO::Async framework, juno is quite reactive.

Setup and operation

Installation

Before installing juno, install the tools for a common building environment (a compiler, make, etc.) Below is an example on a Debian-based distribution. Also install a few Perl modules from the CPAN:

sudo apt-get install build-essential # or similar
cpanm --sudo IO::Async IO::Socket::IP Socket::GetAddrInfo JSON JSON::XS DBD::SQLite

Once you've installed the appropriate Perl packages, clone the repository:

git clone --recursive https://github.com/cooper/juno.git
# OR (whichever is available on your git)
git clone --recurse-submodules https://github.com/cooper/juno.git

If your git does not support recursive cloning, or if you forgot to specify, run git submodule update --init to check out the submodules.

Next, pick a release. The default branch is master which is the development branch and might be broken at any given moment.

git checkout juno13-ava

Now set up SSL if you want or skip to the configuration.

SSL setup

If you wish to use SSL on the server, install libssl and the following Perl module:

sudo apt-get install libssl-dev
cpanm --sudo IO::Async::SSL

You will now need to run ./juno genssl to generate your self-signed SSL certificate.

In the configuration, use the sslport key in your listen block(s) to specify the port(s) on which to listen for secure connections. If you're setting up connect blocks with the ssl option enabled, you will also need to listen on more port(s) using the format: <protocol name>sslport; e.g. ts6sslport.

Configuration

juno comes with a working example configuration. So if you want to try it with next to no effort, just copy etc/ircd.conf.example to etc/ircd.conf. The password for the default oper account admin is k.

The configuration is, for the most part, self-explanatory. Anything that might be questionable probably has a comment that explains it. Explanations of all options are available in the configuration spec.

Note that, because juno ships with a configuration suitable for fiddling, the default values in the limit block are rather low. A production IRC server will likely require less strict limits on connection and client count, for example.

Operation

Most actions for managing the IRC server are committed with the juno script.

usage: ./juno [action]
    start       start juno IRCd
    forcestart  attempt to start juno under any circumstances
    stop        terminate juno IRCd
    debug       start in NOFORK mode with printed output
    forever     run continuously
    foreverd    run continuously in debug mode
    rehash      rehash the server configuration file
    mkpasswd    runs the password generator
    dev         various developer actions (./juno dev help)
    help        print this information
  • start: Runs the server in the background as a daemon.

  • forcestart: Runs the server in the background, ignoring the PID file if it appears to already be running.

  • stop: Terminates the IRCd if it is currently running.

  • debug: Runs the IRCd in the foreground, printing the logging output.

  • forever: Runs the IRCd continuously in the background. In other words, if it is stopped for any reason (such as a crash or exploit or SHUTDOWN), it will immediately start again. Don't worry though, it will not stress out your processor if it fails over and over.

  • foreverd: Runs the IRCd continuously in the foreground, printing the logging output.

  • rehash: Notifies the currently-running server to reload its configuration file.

  • mkpasswd: Runs the script for generating encrypted passwords for use in oper and connect blocks in the server configuration.

  • dev: Includes a number of subcommand tools for developers; see ./juno dev help.

On Windows, start juno with juno-start.bat.

Upgrading

To upgrade an existing repository, run the following commands:

git pull origin master
git submodule update --init
git checkout <desired release tag>

OR (from IRC with the Git module loaded)

  1. UPDATE
  2. CHECKOUT <desired release tag>
  3. RELOAD

Information

Contact

Go to #k on irc.notroll.net.

If you discover a reproducible bug, please file an issue.

Author

Mitchell Cooper, [email protected]

juno was my first project in Perl — ever. Scary, right? Luckily it's been through more than 10 years of improvement, including a few rewrites; and I am awfully proud of the current codebase.

License

This is free software released under the ISC license.

juno's People

Contributors

cooper avatar gitter-badger avatar mattwb65 avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar

juno's Issues

Complex PRIVMSGs not yet supported

  • Complex PRIVMSG
    a status character ('@'/'+') followed by a channel name, to send to users
    with that status or higher only.
    capab: CHW
    propagation: all servers with -D users with appropriate status
  • Complex PRIVMSG
    '=' followed by a channel name, to send to chanops only, for cmode +z.
    capab: CHW and EOPMOD
    propagation: all servers with -D chanops
  • Complex PRIVMSG
    a user@server message, to send to users on a specific server. The exact
    meaning of the part before the '@' is not prescribed, except that "opers"
    allows IRC operators to send to all IRC operators on the server in an
    unspecified format.
    propagation: one-to-one
  • Complex PRIVMSG
    a message to all users on server names matching a mask ('$$' followed by mask)
    propagation: broadcast
    Only allowed to IRC operators.
  • Complex PRIVMSG
    a message to all users with hostnames matching a mask ('$#' followed by mask).
    Note that this is often implemented poorly.
    propagation: broadcast
    Only allowed to IRC operators.

Oper notices and server notice replies are often repetitive

Need to make a utils function which combines $user->server_notice() and notice() and another which uses gnotice(). The functions will send out server notice as normal except, if the provided user is not opered and/or does not have the notice flag, he will still receive the notice. For opers it will appear like notice(), e.g. *** Notice: Reload: ...; but for non-opers it will appear like ->server_notice(), e.g. *** Reload: ....

SASL is broken

SASL only ever worked with the built in account mechanisms. It needs to be supported in a more generic way that would work for modules implementing accounts as well as external services.

JELP channel creation is sloppy

JELP sends out channel creation as two messages, JOIN and then CMODE. We should do it the way TS does, use the same command as during burst. CUM is analogous to SJOIN; we can use that and eliminate the join_with_modes outgoing command (and use the channel_burst for channel creation).

TS6 definitions are very repetitive

default.conf is getting enormous due to copy+pasted TS6 mode and prefix definitions. Need to make some sort of base set or to move these definitions to modules/TS6/TS6.module/modes.conf.

Remote global commands are sometimes sent multiple times

This is caused by storing which servers we've checked rather than to which locations we've sent. But we have to do that because JELP RELOAD uses SIDs rather than server masks. I think I need to send out a single RELOAD with a server mask or maybe with a list of SIDs. And of course, only send it to the matching server(s).

No deaf user support

  • Add mode block and definitions
  • Do not send channel messages to deaf users
  • Do not send channel PRIVMSG messages to servers unless there is at least one non-deaf user

Multi-target commands are sloppy, dealt with inconsistently, and not configurable

Problem

There is no global limit for how many targets a multi-target command can have. Each command currently implements this differently: some have no limit, some have hardcoded limits, and some do not even support more than one target when they should.

Desired behavior

The target limit needs to be universal among all multi-target commands and configurable by limit:target. It should be reflected in RPL_ISUPPORT as MAXTARGETS (Currently, this is hardcoded to one, for compatibility with the commands which do not properly support multiple targets). Excess targets should be ignored.

Implementation

I think this should be implemented in the parameter parser. As it presently exists, commands with a single channel target use the channel parameter type. We could add channels which will look up a comma-separated list of channels and push an array reference of channel objects to the parameter list. If a channel does not exist, send out ERR_NOSUCHCHANNEL and skip it. If the target limit as specified by limit:target is reached, ignore the remainder of the list. The opt flag should be manually handled to indicate that an empty arrayref is permitted.

JSON module manifests are disregarded; UPDATE ignores them

What's the point of including Evented::API::Engine manifests in git when the UPDATE command disregards them? Usually when there's a conflict, it's caused by one of the modules which is tied to the IRCd version at the time of last update.

One idea is to not allow any module versions to rely on IRCd version except for the core. The manifests for the ircd module and its submodules should be added to gitignore. The rest will use the auto-increment mechanism.

JOIN 0 is propagated as several PARTs

  • Move PART logic to channel.pm rather than just in UserCommands.
  • Make a second new method in user.pm for parting all channels (universal JOIN 0 handler)
  • Make channel.pm JOIN 0 handler fire out a part_all
  • Add outgoing part_all in JELP
  • Add outgoing part_all in TS6
  • Handle JOIN 0 in JELP
  • Handle JOIN 0 in TS6

JELP needs dynamic mode negotiation

Currently mode definitions are only sent during burst. There is also no mode to remove modes once they're registered. Need to make AUM/ACM commands more dynamic with module loading and stuff. Also need a way to tell servers when modes are no longer available.

    It is now necessary for servers to track which of its own modes are familiar to
    other servers. This way, a server can determine if it needs to send out ADDUMODE,
    ADDCMODE, AUM, or ACM commands when new modes are added.

    Example: a new module was downloaded from the repository. The server configuration
    updated to include the mode provided by the new module. The server is rehashed.

    The server has tracked its own modes and is aware that NO servers are aware of the
    new mode, so it sends an ACM message to all servers. Mode-adding commands should
    be forwarded only if they occur outside of a burst.

Fix mapping status modes owner/admin/etc to op in TS6

I need to consider how I want to handle +qah/etc. forwarding to TS6 servers like charybdis which do not support these statuses.

We cannot assume that anyone with +q or +a or any mode higher than +o has +o in addition to whichever other statuses they have. Therefore it seems essential that a mode change of +q actually translates to +o. It must also be handled properly such that +qo does not translate to +oo and so on.

The question is whether it makes sense to do the opposite, i.e. to translate -o to -q—making ops on charybdis as powerful as owners on juno—or to instead immediately reverse the mode deop if done remotely by someone with a lower status. A third option would be to ignore +q and friends entirely on charybdis, which is the current behavior. The problem with doing that is that some channel actions require ops at a local level and may be ignored by charybdis.

I could also consider making it configure how you want this to behave:

  1. Translate -o to -q
  2. Reverse remote deops from servers without higher statuses
  3. Ignore the existence of these modes altogether

Of course, all of this can be avoided by disabling juno's extra status modes.

Some "global commands" are protocol-oblivious

Configuration::Set, Reload, and Git modules include calls to ->fire_command_data(), which was created back when only one linking protocol was supported. The result is that JELP-encoded commands are sent to servers that do not speak JELP. This method must be removed, and these modules need to use a normal ->fire_command().

Make UPGRADEing easier

Currently upgrading to the latest IRCd is a two-step process. This is far too complicated. Let's make a module that depends on Git and Reload and provides a unified UPGRADE command.

Hidden servers are not hidden

Both server protocols properly recognize when servers are marked as hidden, but they are still visible anyway to clients.

Update ircd.conf dynamically to stay in sync with the Evented::Database

Evented::Database currently stores values semi-permanently if and only if they are updated during runtime to something other than what the legit ircd.conf says. I want the ircd.conf to be in sync with the configuration at all times. So E::D needs to generate a config in Evented::Configuration format in a certain pretty way which is defined by the E::D API. It needs to preserve comments as well.

Dealing with IPv4 mapped addresses

Currently connect blocks and stuff have to have two IP entires, one for normal IPv4 and one for the IPv6 with embedded IPv4. It's hilarious. Net::IP has an ip_get_embedded_ipv4():

<mad> !eval Net::IP::ip_get_embedded_ipv4("0.0.0.0")
<mad> 0.0.0.0
<mad> !eval Net::IP::ip_get_embedded_ipv4("::FFFF:222.1.41.90")
<mad> 222.1.41.90
<mad> !eval Net::IP::ip_get_embedded_ipv4("0:0:0:0:0:FFFF:222.1.41.90")
<mad> 222.1.41.90

But Net::IP is not a core module; it would be an added dependency. I could probably implement this myself.

TS6 bans not implemented

Kline/Dline/etc. are not yet implemented in TS6. The Ban::TS6 module exists and is loaded automatically whenever Ban and TS6 are both loaded.

Some users are missing after channel burst in TS6

I can not find a pattern among them. The users exist on the server but do not join the channel; they seem to be ignored from SJOIN. I checked to make sure all the users are being sent in SJOIN, and they are. They are seemingly ignored.

RELOAD floods opers

Modules with preserve_sym enabled will produce Perl warnings for every time a subroutine is redefined. Unfortunately no warnings 'redefine' cannot be applied because it is reset to normal state by the eval{}. Perhaps a workaround solution would be to temporarily disable all warning notices while reloading, but that could also result in a loss of useful debugging information.

Also, the oper which initiated the reload is sometimes notified that tons of modules have been upgraded to whatever the new IRCd version is. I think this is caused by a separate issue in the UPDATE command which causes disregard of JSON manifests.

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.