So, I have a node on HECnet, named NICHTS. HECnet is a world wide DECnet network, made possible and managed by Johnny Billquist. I connected my PiDP-11/70 to it and it's been handy for sharing files with other DEC enthusuaists. I'd like to see it take more advantage of being connected to HECnet, rather than just sharing files.
I used to write lots of what I'll call, for want of a better term, client-server programs on VAX/VMS. In that environment, it's pretty trivial to put something like that together, due to the relatively tight integration of DECnet with the rest of VMS.
But, I haven't had the opportunity to write any programs that use the features of DECnet on RSX. In order to experiment with it and learn how to do DECnet task to task communications on RSX systems, I decided to write a (again, for want of a better term) "chat" program - possibly the only program more trite and contrived than "Hello World" or Clock programs.
DECnet-RSX comes with a "talk" program, and a "phone" program - similar programs for terminal to terminal communication. Talk is limited to one conversation between two users at a time. Phone supports up to 5 users. I decided to make mine multi user - larger than 5 users - a middlin' large number of users (currently 32 - can be increased by changing variable MAXCON in MTALKS.MAC) can converse in the same conversation at a time, each one seeing what all the other users type. In this high tech, nuclear powered, rocket propelled space age 21st century world, where you can argue with millions of people everywhere from your phone in fractions of a second, I don't see a lot of real use for this utility. But, it serves as a learning tool, and could be used as the skeleton for writing some useful program that uses DECnet.
I couldn't stand to call it "Chat", since that is so early 80's 8-bit micro hobbyist cute. I named it "MTALK" - for Multiuser Multinode Talk. Architecture wise, it's pretty simple. There's a server task called "MTASKS" (for Multitalk Server), located on some known node. You INStall it on the node you want to be the "server" node. When a client task tries to connect to it, DECnet starts MTASKS for you - no need to run it manually. When MTASKS starts, it opens a connection to DECnet using the OPNW$S call. Then, for each possible connection from a client, it assigns a unique LUN to the NS device (a network pseudo device). It then uses SPA$ to specify that whenever a Network message comes in, it would like to receive an AST in order to invoke routines to deal with it (Network messages are connect, interrupt, disconnect, user abort and network abort notifications, not the messages that the users type to each other).
Then, MTASKS does my favorite thing in the whole world - nothing. It suspends execution by calling SPND$S. All activities from then on are triggered by ASTs.
MTALKC (Mtalk Client) is started by the user, and it initializes somewhat like MTALKS. It opens a connection to DECnet using OPNW$S, and specifies an AST to deal with incoming network messages. It then uses CONW$S to connect to MTASKS.
That generates an incoming CONNECT network message for MTASK, which wakes it up from being suspended. Routine NETAST does a GNDW$S to read the network message. It then allocates an MTALK control block for the client that caused the request, and stores some info from the network request received in it. Then, it sends a message to all already connected users, that new user so-and-so from node such-and-such is now online. MTASKS then accepts the connection request via ACCW$S. It posts an intial read on the network channel, and (what else) requests an AST when the read comes in. Whenever that AST is triggered by a receive for that user (or any already connected user), it loops through the connection blocks and sends the received message out to all the other users. What could be simpler?
So, MTALKC has opened a connection to the server, and it's been accepted. Now MTALKC posts a read to the user's terminal, to accept input to be sent to all the other users. After posting the read, MTALKC, like MTALKS, suspends execution by SPND$S. When a complete line is read from the terminal, the QIO causes an AST to be generated. The AST formats the line and sends it to MTALKS, using SNDW$S.
When MTALKS gets the user's message from MTALKC, it loops through all of the connections and sends the message to each one.
Commands are typed in to the MTALKC prompt, just like a message. Commands begin with a ":" character. So far, there is only one command, :W. This stands for "WHO", and causes a list of connected users to be printed out for you.
That's pretty much it. Here's what it looks like. This user typed return to the NUP prompt, taking the defaults. This is user GLEASON's session, on node NICHTS. A :W command shows that user SYSTEM on node NIMBUS is already connected. While waiting for GLEASON to type a line, the arrival of user JONES on node NADA is announced. A few lines of text are communicated and then user SYSTEM on node NIMBUS disconnects. GLEASON types contro-Z and exits back to MCR.
>MTK
MTALK - Multi Node, Multi User Talk program
Version X01A02 2-JUL-2026
Control-G Consultants
lee.gleason@gmail.com
Default Node, app username and app password are NICHTS,MTALK,RIALTO
Press enter at the NUP> prompt to use these defaults.
Or, enter alternate values at the NUP (Node Username Password) prompt
Thusly...NUP>/nod:CASTOR/nam:username/pas:password
Where node is the DECnet node name of the MTALK server,
And username and password are the MTALK server task's (not yours!)
NUP>
MTK>:w
MTK>
List of connected users (if any)
MTK>
NIMBUS::SYSTEM
MTK>
User Joined NADA::JONES
MTK>
NADA::JONES>hello there
MTK>Hi good to here from you
MTK>
NADA::JONES>RSX11 is good, nicht wahr?
MTK>
NADA::JONES>Ganz genau!
MTK>
MTK>Richtig!
NIMBUS::SYSTEM>Alright, bye
MTK>
User Left NIMBUS::SYSTEM
MTK>^Z
>
OK, here's the sources and build command files. I absolutely guarantee that there are bugs in this code. And the server, MTALKS, still has a lot of debug print statements in it. But, they're kinda vanilla programs, no kernel mode or APR remapping, so they should be pretty benign. If you're on HECnet, give MTALKC a try using the default settings - it should connect to my PiDP-11 running MTALKS
To build, execute the command files. The command files also install the programs, and purge previous versions. After you build the programs once, you can just install them.
Install MTALKS on a node you want to be the server
>INS MTALKS
Install MTALKC on an end user's system
>INS MTALKC
Start MTALKC by typing MTK
>MTK
Lee, i’m looking forward to reading through your code, I always learn something new when I do. DECnet programming in Macro-11 on RSX is not something I’ve done since 1982 so I don’t remember much about it. It will be fun to re-learn the basics.
ReplyDeleteAh thanks. I should have mentioned, that the ^R problem I was having, I solved using two of your suggestions - setting the terminal /FDX, and inserting some CRs and LFs in the output strings.
ReplyDeleteFun that you are doing stuff, as always.
ReplyDeleteJust a couple of comments.
First of all, PHONE actually do allow more than two people to talk. The limit is five. Mostly just because screen estate, I'd say. But anyway, PHONE under RSX kindof sucks, so I don't normally use it anyway.
Second, I'd usually recommend STOP$ over SPND$. The difference being about how the task might be shuffled around. RSX is more relaxed around a stopped task, and can move it around more freely.
Anyway, ASTs are maybe the most beautiful thing there is, and it does make a lot of things really easy when used right. Totally agree with you on that.
Thanks for the correction on PHONE. I've corrected its mention in the post. I've always used SPND$, but I've always been in big memory RSX environments where checkpointing and shuffling almost never happened, with competition for memory. We always had plenty of memory, we needed more compute power. I'll be interested to do some experiments and see the difference.
DeleteOh, and I'm a really big fan of ASTs. It's amazing what can be done with what I've heard described as basically a thread-and-a-half. I had to work on RSTS/e for 3 years after working on IAS for my first 6 years. RSTS/e had the RSX run time system, which made much of what I knew useful...but no ASTs. That was painful. I hear that more recent versions of RSTS have AST support - I'll have to have another look at it.
DeleteAs far as I can remember, RSTS/E did finally get asynchronous I/O, but it's not as flexible as under RSX. But it's been a while since I even looked at it.
DeleteThe RSX runtime system under RSTS/E have ASTs just like in RSX. It's just that things aren't happening asynchronously. If you do a QIO (without wait) it will still wait under RSTS/E, and the AST will be called as the next thing, when the I/O completes. So the AST happens as you might expect. But anything you might have wanted to run meanwhile will not happen, which also means you can't really field multiple I/O requests in parallel, and so everything becomes harder compared to actual RSX.