2012-12-19
Inferno OS IRC client with persistent connections
I've written before about how Inferno makes it easy to share resources across devices and networks. In this post I show how to use IRC from within Inferno and then how to run the IRC connection handling on a server and the GUI on a client machine. The server can stay connected giving a persistent IRC connection similar to how IRC proxies and bouncers are used.
The IRC client I'm using for Inferno is written by mjl. A large number of useful Inferno and Plan 9 utilities with source is available at mjl's bitbucket repository. The one that provides IRC capability is ircfs. This is written in a manner that exposes IRC connections as a file system using the 9p2000 protocol. The GUI communicates with IRC via the file system.
Building
Building from within Inferno requires a couple of environment variables to be set. ROOT
is the path to the root of the Inferno system and SYSHOST
should be set to 'Inferno':
% cd ircfs
% ROOT=/
% SYSHOST=Inferno
% mk install
cd module ; mk install
mk: 'install' is up to date
cd appl ; mk install
cd cmd ; mk install
rm -f /dis/testirc.dis && cp testirc.dis /dis/testirc.dis
rm -f /dis/ircfs.dis && cp ircfs.dis /dis/ircfs.dis
cd wm ; mk install
mk: 'install' is up to date
cd lib ; mk install
mk: 'install' is up to date
cd man ; mk install
mk: 'install' is up to date
This installs ircfs
into the standard Inferno application and command locations. It may not be desirable to clutter the existing system locations with additional programs like this. If you prefer you can create local directories to hold the installed programs and bind
this over the system directories using a union file system. ircfs
installs a useful man
page which is worth reading to find out all the options.
Running ircfs
When ircfs
is executed it creates a directory structure that contains the files that allow clients to send and receive data to the service. To run it we first create a directory underneath /mnt/irc
for the server we want to connect to, then run ircfs
passing this directory name:
% mkdir -p /mnt/irc/freenode
% mount {ircfs freenode} /mnt/irc/freenode
% ls /mnt/irc/freenode
/mnt/irc/freenode/0
/mnt/irc/freenode/ctl
/mnt/irc/freenode/event
/mnt/irc/freenode/nick
/mnt/irc/freenode/pong
/mnt/irc/freenode/raw
The example above shows the files that exist after running and mounting the ircfs
service. The mount
command uses the variant that runs and mounts a 9p service.
The running ircfs
hasn't connected to any IRC server yet. Connections and controlling of the IRC server is managed via writing or reading from the files under /mnt/irc/freenode
. The protocol is explained in the ircfs
man page. For example, writing to ctl
allows us to connect to a server. Reading from nick
gives the current nickname used by the connected user.
Ensure that ndb/cs
is running to allow network connections from Inferno before continuing.
Running the IRC GUI
The GUI for ircfs
is run with the command wm/irc
, optionally passing the path to the ircfs
directory structure as an argument:
% wm/irc /mnt/irc/freenode
On the left of the wm/irc
screen is a list of the servers and channels. Currently there is status
and (freenode)
. The (freenode)
window is for sending commands to the irc server once we're connected. To connect to irc.freenode.net
enter the following in the (freenode)
area:
/connect irc.freenode.net mynick
The status messages from the server should now appear. The commands that ircfs
understands are documented in the /ctl
section of the ircfs man page. Standard IRC client commands like /join
, etc work and the channels will appear on the list in the left of the client window. The ircfs
server remains running and connected if the GUI is closed. Running the GUI again with the path to the ircfs
directory will display the existing channels connected and you can continue where you left off before it was closed.
GUI commands
The GUI knows some special commands that can be passed to it using /win
. These are explained in the main page for wm/irc
.
add
can be used to add new ircfs
directories to a running GUI. If you start wm/irc
without passing it a directory for example you can type the following in the status
window to connect to one:
/win add /mnt/irc/freenode
del
removes the current ircfs
directory so the GUI no longer displays informatation about it. You can use add
to get the GUI to redisplay it. Note that these two commands don't affect the actual IRC connection. That remains managed by ircfs
. It only affects what is displayed in the GUI:
/win del
The windows
command gives a list of all the windows for the current ircfs
connection and their control number. This number can be used to close and open channel windows in the GUI:
/win windows
open:
(freenode) (0)
#inferno (1)
not open:
/win close
/win windows
open:
(freenode) (0)
not open:
#inferno (1)
/win open 1
/win windows
open:
(freenode) (0)
#inferno (1)
not open:
away
can be used to mark the user as away or back on all servers. exit
will exit the GUI but leave ircfs
connections intact.
Persistent connections
I prefer to have a persistent IRC connection on a server and connect to it from a client so I can catch up with channel logs and activity while I've been away. This allows other users to leave me messages when I'm disconnected. It also allows connecting using multiple devices and keeping my conversation active. This approach usually requires running IRSSI in a screen session on a server, or running an IRC proxy or bouncer.
A similar approach can be done using ircfs
by running the ircfs
server on a remote machine and on the client mounting the ircfs
filesystem. The connection can be encrypted and authenticated.
The following is a simple setup. Install Inferno on the remote server and build and install ircfs
as described previously. Run ircfs
to run the server. In this example I also add a command line switch to log the IRC connection so I can have channel logs:
; mkdir -p /mnt/irc/freenode
; mount {ircfs -t -l /usr/myuser/irclogs freenode} /mnt/irc/freenode
; styxlisten net!*!16667 {export /mnt/irc}
On the client we mount this exported filesystem using encryption (replace example.com
with the hostname of the server):
% mount -C sha1/rc4_256 net!example.com!16667 /mnt/irc
% ls /mnt/irc/freenode
/mnt/irc/freenode/0
/mnt/irc/freenode/ctl
/mnt/irc/freenode/event
/mnt/irc/freenode/nick
/mnt/irc/freenode/pong
/mnt/irc/freenode/raw
The directory and files shown are those from the remote server. Running wm/irc
will now use the servers ircfs
files:
% wm/irc /mnt/irc/freenode
You can now connect to the irc.freenode.net server, join channels then close the IRC window and shut down the client. Next time you restart the client, mount
the remote filesystem again and continue where you left off.
Conclusion
The man pages for ircfs
and wm/irc
have more detail on the commands and keys that can be used. There are other things that can be done with ircfs
other than GUI IRC programs. It's possible to write IRC bots and programs by utilising the control files and directories of an ircfs
session.
The ircfs
source is written in Limbo and is quite easy to follow. It's a good example of mapping an existing protocol onto Inferno's "everything is a file" metaphor and making use of the tools to share resources. One use of this is having Inferno on other devices, like a phone, so you can connect to IRC connections running on a local machine if you temporarily need to be mobile.