Whilst I was at university, I had my first real taste of the Internet on a fast (at that time) connection. I read a few web pages about how stuff worked and discovered RFCs. There were so many fun things around then, which seem quite mundane now. I learnt my first bits of Perl by writing a very basic HTTP server, and remember being surprised to realise there's nothing special about it - it's not something you have to have privileges for, or be super clever to write.
Moving back to RISC OS I began writing a few little things to see what sort of stuff I could make. At the time there was an archive of many RISC OS Internet applications on an Internet server - I forget where it was originally but it eventually moved to Barnet college, generously provided by 'doormouse'. There were all sorts of little things on there, from simple programs, through decent daemons and clients for some common things all the way to the FreeNet stack that someone (I forget who - sorry) had ported.
Lots and lots of exciting stuff to play with and learn about. In the second year of University, Chris Johns and I shared a house. We had dial-up Internet via University that we used occasionally, and that top notch networking protocol - Econet!
I began to write !TelnetD for Econet - and I don't even remember much
about it back then, just that I wrote it to be an Econet telnet server.
It would control a
remote machine through a TaskWindow, and would do some very rudimentary
negotiation. I remember being very confused
by the patterns, and using !FreeTerm to connect to it didn't help
because it too was a bit flakey on some things. I have a feeling that later
I got !ANTTerm to try and it did a few bits quite differently.
It also wasn't helped by the early Telnet RFCs all referring to terms that weren't in common use now, either because technology moved on or because a different usage was more commonly used. Made it kind of fun to work through, though.
The !TelnetD application handled the telnet negotiation and the initial login
prompt, validating your user name and password with a Users module
which used a '
passwd' file we kept in the application. I spoke to
Nick Smith at ANT and he suggested using the common
passwd file inside
InetDBase: instead; I'm pretty sure I started work towards that but
never completed it.
Once logged in (password accepted, and ready to start a shell), a
special module would be invoked to start the shell. The main reason
that this was necessary was that it wasn't possible to exit a shell
prompt based TaskWindow (that is, one it managed itself) by typing
quit'. This meant that all telnet connections had to be ended by closing the
connection, which isn't very nice. The CLIPrompt module that I knocked
up had some very simple handling for command invocation. Looking at it
now I cringe, as it only sets up environment handlers for error and
exit. Don't run a utility that aborts, or you'll find that the module
leaks memory (and it terminates your telnet session as well).
CLIPrompt shell would only be used as a default - any
shell could be configured in the
passwd file for the user, and would
be invoked - I had a few simple 'shells' provided, which gave little
games when you connected to them. Chris Johns' '
Ideal' and my old
StopTheCab' games were in there.
!TelnetD supported more than just a single telnet connection, though.
The application allowed you to configure a number of ports, within its
which was akin to the '
inetd.conf' on modern Linux systems (or similar,
if you used a different service starting system).
Every service could be associated with a program, and connecting to
the specified port would start up a TaskWindow and run the command.
TelnetDTab I've got here has:
Each was a very simple little program - all BASIC, except for the
qotd' which was C that just took input and wrote stuff out. On
the program exiting, the connection was closed. Because of problems
with the buffering of TaskWindow input, there was a limit to the
usefulness of these clients - in particular sending large amounts
of data to the client could cause data to be dropped silently.
This is a general failing of the TaskWindow protocol - the lack of
a Source Quench type option (to use the ICMP terminology), which
means that if data is coming in too quickly for it to be consumed,
the TaskWindow has no way to communicate that the sender should
back off for a bit. I revisited this in later years, with a proposal to
Pace for a change to the TaskWindow protocol to allow this, when I did some
work on the !WebServe application.
The NNTP implementation I remember was pretty rudimentary. Looks
like it supported article retrieval (in a few forms), group
NEXTarticle information, group listing,
posting articles, and the
NEWGROUPS commands as well.
Rather than supporting
control messages, I used
X-CREATE to create a new group. I'm pretty
sure that this was a stopgap whilst I worked out the control
messages, but then abandoned it - it was never really that useful!
It did use SysLog session logs, though, which was quite rare - I've only seen a handful of programs do that (David Thomas' !NetPlex springs to mind).
Having written a Telnet server (which was surprisingly usable and
useful given its inherent insecurity!), I wanted to try something
a little more interesting. !DNServer was the first UDP based Internet
service that I'd written. It was an authoritative, non-recursive DNS
server which supported only the
QUERY operation, and host transfers
are not supported. I make a big deal in the !Help file about the
fact that the
IQUERY requests are not supported - citing the RFC
that they're not required.
Apparently it also supports Chaos net 'but is useless really...'
(so my instructions tell me) .
It doesn't appear to support
SRV entries, which is not surprising as
it claims to conform to RFC 1034. It had many different SysLog levels,
which would be useful to debug it, although I'm pretty certain I never
really used it for anything of note. I might have used it when I had
the two A5000s connected via serial at home - the family A5000 was the
gateway to the Internet at that time.
It doesn't appear to support domain name compression for responses. From the look (and I'm not sure about this) it doesn't appear to handle compressed requests either, which makes me surprised that it works - maybe the resolvers I was using at the time didn't support them either.
A lot of the people who worked on the freely available Internet software
at the time could be found on IRC in
#acorn. Most were at
University or had left recently, but there was quite a range of ages and
skills on the channel, and some who had found their way there through
friends or family. It was quite a nice community most of the time. Later,
as people drifted away and had differences it became a less fun place to
be, but at the time it was really quite nice to chat to people and help
one another with stuff. It was far more immediate than Usenet, which helped
for a lot of development and testing things.
Matthew Godbolt had written the IRC client for RISC OS at the time. The first versions were pretty decent but then Matthew decided that he needed it to be scriptable. It was really quite over-engineered in some respects. It was an IRC client, yes. It also had an object oriented, garbage collected, overloadable, dynamically typed BASIC interpreter built in. The implementation that was supplied with the application was useful, and provided a multi-channel, multi-window IRC client. Matthew had included some useful hooks, and a few people wrote little plug-in modules to provide some extra functions. I went a step further and added a whole range of new things.
These started by just doing simple operations like caching and filtering user lists in a more useful way, adding in Notify messages, making modules more configurable and easier to control through the command line. Matthew and I went back and forth with different versions - mostly since I'd found that the limitation of not being able to address memory on a byte by byte basis made things harder, and I'd had to emulate it by accessing through words.
I remember that I even adding External Edit support to the libraries that it provided support for, although I don't really remember what for - it is possible that the external edit was how emails were composed. It was pretty much a random collection of things that I threw in and wasn't well thought out by me.
!IRClient gained many strange modules which did odd things - colouring text was pretty simple, but there was also the ability to compose mail from within the client, to browse basic web pages in text form (simpler than lynx, but at the time still reasonably functional), play sounds, control the CD player, supported upload and download to FTP servers and had its own !StrongHelp manual to provide its help. Matthew extended the object oriented system and a lot of the code was rewritten to take advantage of this. Instead of just managing memory and lists themselves, the modules where changed to use objects that provided the binary trees, lists and other structures. This made the code a little stranger, but meant that implementation details could be forgotten - changing a list to a binary tree was easy.
The entire library was overloadable and a dependency system allowed each library to be loaded in the correct orders so that overloads worked properly. It wasn't my first dependency library that I'd written, but it was the first to be completely relied on by a well used application.
Part of the problem with such a radical change was that getting the other module authors to adopt it was harder. By that time more IRC clients were around so there was less need for people to use !IRClient. Also, its look was a little dated, and could have done with an overhaul - which hadn't been helped by my efforts to add silly things like the web browser to it.
During the time that !IRClient was being developed, there were other IRC clients - of which !iXRC was one of the forerunners at the time. Others like !iChat, !g0irc and (of course) !LIRC also spring to mind. Amusingly, Thomas Olsson's !LIRC was also a scriptable IRC client, using BASIC. Instead of providing its own home grown interpreter, its scripts were skeletons which were wrapped into Wimp applications and run independently through the native BASIC interpreter.
The vast bulk of the 'cleverness' of !IRClient is Matthew's - his decision to use BASIC as a scripting language opened it up a lot for people hacking about at that time. Whilst it was limited in some ways, they were not areas that mattered to an IRC client. The addition of overloading and object oriented operations was just genius .
Trying to work with !IRClient whilst using dial-up was expensive. My parents didn't restrict me too much on my phone usage, although I'd already had run ins because of other issues with that in the past so I tried to keep my usage to sensible amounts. It's a little amusing in these days of always connected Internet access, even for mobile devices, that at that time 56k baud connections were the limit - and in our area the connection could be a bit variable. I would be online in the evenings when the phone calls were cheaper, trying to keep the costs down but still aware that there were costs, even if I didn't pay the bills.
There were also technical limitations. The use of such a slow connection
with a large server network like Efnet meant that doing a
command to get a list of all the active channels could actually kick you
from the server. The time taken to receive all the data was longer than the
server ping time, and so the server thought that you were dead and disconnected
You cannot test an IRC client if you don't have an IRC server. That's hopefully obvious. Initially I was testing whilst running it live - so many times I'd be chatting and seemingly ignore people, because the client had crashed and I was fixing it and reconnecting. This was tedious, so I began to write !IRServer. As an IRC server it was never intended to be particularly robust or featureful. It was just intended to be a way to test !IRClient. In particular, BASIC's 256 character string length limitation meant that it was difficult to process some messages.
The server did have copious logging at a lot of different log levels through SysLog. Each session was logged to a Session log, which meant that there was a lot more information collected, but it might be difficult to associate problems between sessions. The server also had its own flood protection to prevent clients drowning the server in data, and it could kick clients who sent data too quickly.
I started to add support for connecting multiple instances of !IRServer together to provide a network. The implementation is not able to connect to other RFC compliant servers, so you couldn't use it to connect to a larger network of Linux servers. The system was also very slow like this, having to process many messages, and generating a lot of logs (unless debug was disabled). Still, it did work, so could be used to test some more obscure cases. Netsplits weren't really supported, but could be simulated to show the they did something like the right thing in the IRC client.
I think some of the IRC client authors used !IRServer as their test system for their applications, but as time went on there were more instances of people using University or home networks that were permanently connected to the Internet. It was less necessary to use !IRServer.
I really enjoyed working with !IRServer. As well as the obvious advantages of being able to test IRC clients, it was also educational to implement another 'standard' protocol and see it work with other clients - it was tested with the RISC OS clients, and mIRC, and the much maligned Comic Chat, and worked quite well. I mention the Microsoft Comic Chat not only because it was tested with it, but because I believe it to be a really neat bit of software, and something that I felt that could benefit IRC in general.
Sadly, because it tended to spam users who weren't using Comic Chat with client noise, it was generally disliked. That 'noise' included the information about comic character and mood of the thing being said, some of which was inferred from the text and some from the mood ring which could be set by the user. This was then presented to the user in the form of a automatically generated comic, together with strange avatars positioned appropriately for the text being spoken and speech bubbles that tended to work out pretty well for reasonably short lines.
Early on I wrote a display library which I intended to use for a simple client. The client became !JFTerm - a 'simple terminal connection client' which supported multiple protocols. The library was intended to be a basic line based display window, where lines would be added to the bottom. Later versions added colouring, controlling individual lines, fonts, and selection and clipboard operations.
!JFTerm used the display library for all its rendering, leaving it to worry about the actual connection and processing. Initially !JFTerm provided a line based connection using different protocols. Each protocol was implemented as a separate BASIC library and could have different processing that it performed on the input. The first was the talker protocol which supported simple colour sequences, for use with talkers - mostly Egham Hills.
There was also a special '
ttylink' protocol which would listen
for connections on port 87 - simply telnetting to that port would let you
talk to me. Because my system was regularly online and had port forwarding
enabled on the server (or was directly connected in the early days), it
was a simple matter to get hold of me.
I added IRC support as a protocol to show that the protocol handling was able to deal with such things. This gave me an opportunity to attach a side pane showing a list of users. The list also forced me to add support for context specific menus over those users as well. None of the other protocols had anything like that, because all the other protocols were very simple.
!JFTerm was one of the main ways I stayed in touch with people, using the talker and IRC protocols. Because it was mostly for my own use, it focused on how I worked - in particular it only supported a single IRC channel at any time. This was intentional, as I found that having more than a single channel was distracting and therefore detrimental to both real work and - more importantly to me - staying in touch with people. I'd found that if I split my attention over more channels and sources of chat, the result was that I might as well use none, as I didn't pay enough attention to any of them. This caused a few people to use other clients which did support multiple channels, and I was always happy with that .
The development of the Display Library for !JFTerm meant that it could be used elsewhere - most of the TaskWindow based applications that I developed later (the conversions tools for Doom, and controlling applications like !BCTD) all used it as part of their display of the output. As it supported fonts, colours, and handled selections and clipboard with very little extra code it made developing such things very easy. Part of the design work for it stemmed from conversations with Chris Johns whilst we were at University. He had decided to write an IRC client called Torque, and some of the things that he put into its display library were later added to my library as they helped performance and usability.
I experimented with adding SOCKS 5 support to !JFTerm but found that it was actually easier to add the support within the Socket library that the application used. SOCKS 5 is a proxying protocol that allows systems to request connections to external sites, or to listen on a given port. Network Address Translation has pretty much supplanted the use of SOCKS 5 for connection based external access. For listening on public interfaces, the Universal Plug and Play (as an 'Internet Gateway Device') has mostly replaced SOCKS 5. However, like SOCKS 5, the Universal Plug and Play needs to be provided by the application, so it is less flexible. Whilst I had started working on support for UPnP, I never got to the point of having a working system I was happy with.
Anyhow, the SOCKS 5 system needs to be supported by the application (or
some library which the application uses). As such, my
SocketLib could be used to connect through such SOCKS 5
systems. The configuration was pretty inflexible - a number of
SOCKS$* variables - and the code I have in
appears to still have debugging in it, so I guess it was never completed
to my satisfaction.
It has even still got my old 'face' in the users pane!
There were a few IRC clients popping up, !IRClient and !JFTerm being just two that I was working on. Each had their own features and quite regularly a factor that determined whether the client was suitable for some users was the support for DCC. Direct Client Connection ('DCC') was a special form of message which allowed two clients on IRC to connect directly, outside of the IRC network. This had the advantage of being more secure (it wasn't passing through many other IRC servers on the way), lower latency (as it only had to traverse the direct route between clients, not go via intermediate servers) and allowed faster communication (because the connection was not throttled at servers and you wouldn't be kicked for large amounts of data). In addition it offered the ability to transfer files to a remote user - which was the usual big draw for the feature.
DCC itself is one of a family of commands known as CTCP - Client To Client
Protocol. This was a method of transferring messages to a user which were
not spoken. The protocol's support is required by most clients which are
not 'bots', as the
ACTION CTCP command is used to implement
user actions (aka '
CLIENTINFO- a list of supported CTCP commands.
VERSION- information about the client itself, maybe including a URL link.
FINGER- information about the user.
PING- respond immediately, to gauge the round-trip time.
!IRClient had a pretty good implementation of DCC transfers, but to get to a good implementation it went through a few revisions and this also had an impact on other clients. Other clients wouldn't have the support or might do things in a way that !IRClient didn't like. I didn't want to write another DCC handler inside !JFTerm - I am heavily in favour of modular systems which can be reused. I wanted to make it easier to write the CTCP commands and provide some more interesting interactions between users.
I designed and implemented a very simple Wimp protocol ('WimpCTCP') which allowed other applications to provide the support for CTCP commands, rather than their being implemented within the IRC client. This meant that the individual CTCP handlers could be implemented independently of the clients, allowing them to be shared between other IRC clients. Although you might change your basic client, the CTCP plug-ins could retain the same functionality - or you could replace the CTCP plug-ins without changing your client. It also allowed the CTCP code to be developed whilst the user is on IRC using them.
Each command (or multiple commands, depending on the implementation) could be provided in a different application. This meant that memory usage was higher, but the isolation of functionality meant that a broken CTCP client would not kill an IRC client. Nor would the CTCP client take up space if it wasn't required - all the WimpCTCP clients were loaded on demand.
The protocol had its limitations, like being restricted to a single Wimp message - so limited to about 200 characters as part of the CTCP data, and had fixed lengths of user names and the like. But it made a the process of writing a IRC client that supported CTCP a lot easier. I wrote a bunch of clients for the basic protocols, the information ones.
The DCC client was pretty simple, but supported the RISC OS extensions that a few of the IRC client authors. The client handles sending and receiving files and can be configured to improve performance in a compatible way to mIRC and LIRC.
!IRCGraf I wanted more than just the basic CTCP operations when I created the WimpCTCP protocol. I wanted to extend the IRC experience so that it was more interesting. One of the tools I wanted to create was an interactive whiteboard. This had many uses, from being fun to play 'noughts and crosses' to being able to explain with pictures. The '
JFGRAPHICS' command was a way to make that
work with the IRC. It wasn't very advanced, or clever really, but I only
wanted to create it as a way to show that WimpCTCP could do some
useful things, and that creating a useful collaborative application
wasn't really that hard.
My impressive drawing skills. Each user would appear in a different colour to distinguish them, but it wasn't possible to erase except by disconnecting. It was actually useful on a couple of occasions to explain things that would otherwise have taken a few minutes in text. Admittedly those times it took a few minutes to make sure that other parties actually had the right bits to make it all work, but it did work .
I wanted to add DrawFile import at some point, so that already created diagrams could be drawn and annotated collaboratively. Similarly, being able to save out the diagrams would have been useful. The tool was in limited use, so I never spend much time adding those sorts of features.
!IRCURL There were a few informational plug-ins as well, one of which was the URL plug-in which allowed users to query a URL from a rudimentary database of keywords. The idea was that instead of asking where something was, you could ask the client and it would respond. The client was able to be configured with a list of keywords together with descriptions and their URL. Anyone requesting a URL by the keyword would have the URL returned to them.
It really wasn't very difficult to do - it's just a simple list of data for each keyword which can be looked up and returned on request. The interface allowed the user to configure keywords individually to map to their URLs. As usual, the interface used the Filer library I'd written to present the URL links in a simple manner. It's nice when the writing of things becomes easier because you've written some decent reusable code.
IRC is still quite impersonal, even with customisable nicknames and even colours in some clients. I wanted to do something a little more with it, to make people more recognisable. Anyone who was at Picsel will know that I'm strongly in favour of associating online identities with pictures of people. It makes the remote people a little more real and helps to make the process of relating to them a little easier. At least that's my view. Plus it also stops any embarrassment when you find out that the person you've been talking to is a different sex to that you expected - which had happened once or twice on #acorn.
Anyhow, that was the idea with the 'Faces', which predated the changes to the Picsel Review System by quite a few years. I wanted to compress the data required to show a face within the IRC client to that which could be transmitted over DCC. A 16x16 sprite in 16 colour greyscale takes 128 bytes, and encoding it with Base64 increases that to 170 characters, which is within the limits imposed by the WimpCTCP protocol (and far fewer than the IRC protocol limit of 512 characters, less a little for protocol overheads).
These images could be displayed in the IRC client. !JFTerm showed them beside user icons to make the window a little more friendly - see the image of !JFTerm and !IRServer above for an example with my face shown.
Within the !IRCFace application, you could show all the faces of people who had responded. Clearly the number of people who had, at some point, used the client was more than I remember!
The images were pretty poor really, and in some cases it just wasn't possible to see what they were meant to be - whether they were even a face at all. A few people did mention this but I couldn't see an easy way of increasing the resolution without breaking WimpCTCP - which was a flaw in WimpCTCP, and that made it more frustrating.
!IRCSED There were other WimpCTCP plug-ins as well. The '
plug-in supported Simple Encrypted Data, albeit in a non-standard
way. I'm pretty sure you could set up different keys for each user,
although the 'encryption' was a very rudimentary EOR with the
characters of the key. But it at least kept the messages from any
!IRCMP3 The '
MP3' client would provide information on what was
playing with AMPlayer, which wasn't that exciting,
but was amusing now and then.
!IRCSound The '
DJF' command would launch
!DJF-JRF and could play little tunes at
the request of others. It really was just about as annoying as the
Sound' plug-in, which would play
files (which were stored locally).
There was one other WimpCTCP client that was written by someone else - there was a Chess game which used the protocol which Dennis Ranke wrote. I can feel slightly vindicated that they thought it was interesting enough to write for. That said, part of the problem with something like this is that I'd written many of the interesting clients already, so there wasn't so much scope to grow. Ah well; it was all fun at the time!