RubIRCd is an IRC server written in Ruby.
ldilley / rubircd Goto Github PK
View Code? Open in Web Editor NEW:speech_balloon: An IRC server written in Ruby
Home Page: http://www.dilley.me/rubircd
License: GNU General Public License v3.0
:speech_balloon: An IRC server written in Ruby
Home Page: http://www.dilley.me/rubircd
License: GNU General Public License v3.0
RubIRCd is an IRC server written in Ruby.
Follow the DRY principle.
Allow the use of wildcards in admin and version command arguments to match servers. Similar code will be needed for ban splatting later.
INFO also needs this. grep() can likely be used.
Implement server-to-server linking. This will take some planning...
Note: If using SSL, the connecting server will need new SSL code added to get peer certificate, etc. to initiate the handshake.
If too many clients connect from the same IP address, disconnect any excess over a configurable threshold.
STATUSMSG is currently referenced in the ISUPPORT numeric, but the PRIVMSG and NOTICE functionality is not in place yet.
Handle MODE command and all its various characters and flags for umodes and channel modes.
MODE support is mostly in. The only items remaining are:
1.) Check for access level (admin, founder, chanop) when a user attempts to change channel properties and allow/deny appropriately.
2.) Handle chanflags/prefixes for users.
3.) Handle ban, chanop, and voice adds/removes.
The on_mode() method may also require a rewrite as it is a mess/is long.
Add support for epoll and kqueue using EventMachine.
Note that SSL and TLS are not currently supported when using EventMachine with JRuby. EM was using stub code last I checked for this.
Add nickname and channel registration, etc. Should we use one single bot to handle everything or stick to the ChanServ, NickServ, etc. standard? Should this be integrated into the IRC service with the option to enable/disable it? Should it be a separate thread or remote connection? This will require some planning like the server linking feature request.
Add IRC operator prefix. '!' will be the default. The corresponding channel mode will be +z.
Try to make long methods smaller by reducing the amount of lines required to perform their task. If that is not an option, break the method up into slimmer methods for easier readability and maintenance. The MODE module is a perfect example of this problem.
Add support for NAMESX and UHNAMES in numeric 005 (ISUPPORT). Create a PROTOCTL module which will implement these two subcommands. For example, the client sends:
PROTOCTL NAMESX
Additionally, extend the CAP module to include userhost-in-names (UHNAMES equivalent using CAP instead of PROTOCTL) and multi-prefix (NAMESX).
Only reference NAMESX and UHNAMES in numeric 005 if the PROTOCTL module is loaded.
Add logging severity levels to more easily pick out entries in the log file matching a certain criteria. The following levels should be added:
AUTH - registration events
CRIT - erroneous events that could cause a problem
INFO - informational/generic events (default case)
WARN - events that should not occur, but are not a problem
DBUG - logs extra programming-related information when debug option is turned on in the config
The error below occurs when clients rapidly connect to the server. I suspect it is a thread timing/variable access issue.
RuntimeError: can't add a new key into hash during iteration []= at org/jruby/RubyHash.java:1002 add_channel at /home/ldilley/projects/rubircd/trunk/user.rb:180 synchronize at org/jruby/ext/thread/Mutex.java:149 add_channel at /home/ldilley/projects/rubircd/trunk/user.rb:180 on_join at (eval):130 each at org/jruby/RubyArray.java:1617 on_join at (eval):53 initialize at (eval):24 call at org/jruby/RubyProc.java:255 parse at /home/ldilley/projects/rubircd/trunk/commands.rb:42 main_loop at /home/ldilley/projects/rubircd/trunk/network.rb:373 loop at org/jruby/RubyKernel.java:1489 main_loop at /home/ldilley/projects/rubircd/trunk/network.rb:358 plain_connections at /home/ldilley/projects/rubircd/trunk/network.rb:110
The exception is just caught and ignored for now with seemingly no ill effects (other than the rare case of the server saying you are not in the channel when issuing PART since the channel may have not been added to the User.channels hash.)
There are a number of Rubocop offenses that should be corrected. In fact, there are a few thousand... I am a criminal. Thankfully, Officer Murphy still has some humanity and has given me a chance at redemption if I nullify the majority of the offenses he has cited me for.
Every channel, nickname, and topic should have an associated creation timestamp. This will help defend against channel takeovers and nickname theft during netsplits. The server whose channel has an older timestamp is the dominant one. All modes and the topic from it are used after the servers re-establish connection. After connection is re-established, any non-unique nicknames are collided (we may not necessarily force a disconnect, but rather change the nick via FNICK? to an unused temporary nick and then allow the user to change it afterward.)
Once a G/K/Q/Z line is added, if any targets match locally or globally (for g-lines), then the target should be killed off. Perhaps the server can optionally change the nick of a user matching a q-line to be more friendly.
Create a separate thread that expires G/K/Q/Z lines for any that have a duration other than 0 (zero).
In the whois module, restrict RPL_WHOISACTUALLY numeric to admins, opers, and the user/self. This will hide the IP address from normal users when using hostname cloaking or virtual hosts.
Remove unused channel and user mode constants along with flag character constants since these are already taken care of in ISUPPORT_CHANNEL_MODES, ISUPPORT_PREFIX, etc.
Read in dhparam.pem on start. User can create this file in varying bits (2048 or 4096 for example):
openssl dhparam -out dhparam.pem 4096
Add support for halfops (chanflag %).
Support optional hostname cloaking for users who want to protect their hostname or IP address.
rubircd crashes on startup if logs directory does not exist:
I, [2016-08-21T00:40:01.444000 #733] INFO -- : Celluloid 0.17.3 is running in BACKPORTED mode. [ http://git.io/vJf3J ]
Errno::ENOENT: No such file or directory - logs/celluloid.log
initialize at org/jruby/RubyFile.java:360
open at org/jruby/RubyIO.java:1129
open at org/jruby/RubyKernel.java:305
create_logfile at /opt/jruby-9.1.2.0/lib/ruby/stdlib/logger.rb:711
open_logfile at /opt/jruby-9.1.2.0/lib/ruby/stdlib/logger.rb:705
set_dev at /opt/jruby-9.1.2.0/lib/ruby/stdlib/logger.rb:695
initialize at /opt/jruby-9.1.2.0/lib/ruby/stdlib/logger.rb:635
initialize at /opt/jruby-9.1.2.0/lib/ruby/stdlib/logger.rb:353
class:Cell at /opt/rubircd/cell.rb:44
at /opt/rubircd/cell.rb:41
require at org/jruby/RubyKernel.java:944
(root) at /opt/jruby-9.1.2.0/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:1
require at /opt/jruby-9.1.2.0/lib/ruby/stdlib/rubygems/core_ext/kernel_require.rb:55
at rubircd.rb:26
Add support for SASL via CAP.
Create a Discord module that can bridge chat between various channels.
If too many clients connect from the same IP address in a short period of time, throttle or disconnect them.
After the private and public keys are generated by tools/create_certificate.sh, key.pem should have mode 400 set. The solution is to simply add "chmod 400 key.pem" at the end of the shell script.
The following STATS subcommands are now in place: c (command statistics), d (data transferred), i (admins/opers online with idle time), k (show k-lines), l (list client connections), o (show configured admins/opers), p (show listen ports), q (show q-lines), u (show server uptime), z (show z-lines)
The following STATS subcommands still need to be added: g (show g-lines), m (show memory usage), s (show server links)
Bad and good capabilities returned from CAP ACK and NAK are not using the proper syntax. The CAP subcommands require a leading space before the ':' in the cap.rb module. The problematic lines are as follows:
unless good_extensions.empty? Network.send(user, ":#{Options.server_name} CAP #{user.nick} ACK: #{good_extensions}") end unless bad_extensions.empty? Network.send(user, ":#{Options.server_name} CAP #{user.nick} NAK: #{bad_extensions}") end
Only send admins/opers that have user mode 's' GLINE/KILL/KLINE/QLINE/ZLINE messages, OPER failures, etc. Or have a separate user mode for some of these messages. I am trying to simplify things and avoid the use of SNOMASKs.
Permit the use of asterisks in the host portion of k-lines.
Allow admins to load/unload modules on remote servers.
Add select() as an event-driven alternative to the threaded I/O currently being used. This method will likely perform better on CRuby/MRI.
Only bail on start if the Celluloid gem is not installed and the io_type is set to "cell". Do not require the gem if running in other I/O modes.
Let administrators modify the G/K/Q/Z line YAML files and reload them with REHASH.
Add support for virtual hosts via the VHOST module.
Add support for CHGHOST extension and/or simulate a PART/re-JOIN when VHOST is used to modify a user's hostname.
Read in ca/chain.pem if available on start.
On start, the following message is displayed:
I, [2016-11-06T11:40:26.869000 #15391] INFO -- : Celluloid 0.17.2 is running in BACKPORTED mode. [ http://git.io/vJf3J ]
Update the codebase to prepare for newer versions of Celluloid per https://github.com/celluloid/celluloid/wiki/DEPRECATION-WARNING.
If a client initiates CAP negotiation, they are locked into it per the standard until a CAP END signals completion. Rather than sending absolutely nothing like InspIRCd 2.0.x, I chose to send the following string to make things less ambiguous:
:server 451 CAP :Register first.
In light of cinchrb/cinch#128, this is apparently still too vague for a hint. The solution will be to add a new numeric to blatantly point out that the user must end client capability negotiation to move forward with connecting to the server.
I was hoping to be frugal with custom numerics. If the client adheres to protocol, there should be no problem and only users connecting in raw mode should really see the above. Perhaps a new custom numeric will not be implemented.
If a client is sending too much data in a short amount of time, disconnect them. This can be done by way of the following:
�a) a timer and input counter or
b.) if x messages are received (tracked by an input counter), compare a timestamp from 10 messages ago with the current timestamp. This timestamp information can be held in an array for each user. If the difference is too small, disconnect the user.
Or leave it to bots/channel operators, IRC operators, and IRC administrators to remove the offender. This feature may be too resource intensive for a heavily populated server.
Condition causing the trace below: User "joe" joins channel and quits server. User "jim" then uses NICK to change own nick to "joe".
NoMethodError: undefined method `key_each' for {"#rubircd"=>""}:Hash on_nick at (eval):78 initialize at (eval):24 call at org/jruby/RubyProc.java:271 parse at /apps/rubircd/commands.rb:42 main_loop at /apps/rubircd/network.rb:393 loop at org/jruby/RubyKernel.java:1507 main_loop at /apps/rubircd/network.rb:378 ssl_connections at /apps/rubircd/network.rb:140
After adding support for server-to-server communication, add ziplink support. This can be achieved by the following example:
@require 'zlib'
some_str = Zlib::Deflate.deflate("hello world!")
puts some_str
puts Zlib::Inflate.inflate(some_str)@
So, just need to call Network.send(socket, compressed_data) from the sending server and the server on the receiving end will call the deflate method on the received data to get the original message.
Add an optional module that allows administrators to recommend that garbage collection occur (for both CRuby and JRuby) and report some memory-related statistics.
Check for nil in options.rb for the admins and opers during parsing since these may be blank. The condition occurs when admins: or opers: exists/is not commented and there are no opers or admin entries in opers.yml.
NoMethodError: undefined method `each' for nil:NilClass parse at /apps/rubircd/options.rb:293 each at org/jruby/RubyHash.java:1341 parse at /apps/rubircd/options.rb:279 (root) at rubircd.rb:43
Any data that can be changed (unlike ident for example) should be accessed synchronously while operating in threaded mode. This includes both reads (to prevent "dirty" reads) and writes (to prevent simultaneous writes by 2 or more threads.)
Should the max line length be 80, 100, or 120? I am leaning toward 80 for historical purposes.
Allow clients to initiate TLS connections via STARTTLS using the standard plaintext port.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.