pete@mck-csc.UUCP (Peter Gaston) (01/11/90)
I would like to use a DDP level socket in some code I'm writing. For this I need to do a DDP socket listener. Does anyone have any hints on doing this from LSC? I have working samples in MPW, but I'd like to keep everything in LSC for ease of maintenence. For example, How is ReadRest called? What about multifinder (i.e. if the listener is called at a bad time, A5 may be incorrect...)? Any help would be appreciated. Thanks. Peter Gaston
tim@hoptoad.uucp (Tim Maroney) (01/12/90)
In article <338@mck-csc.UUCP> pete@mck-csc.UUCP (Peter Gaston) writes: >I would like to use a DDP level socket in some code I'm writing. For >this I need to do a DDP socket listener. Does anyone have any hints >on doing this from LSC? I have working samples in MPW, but I'd like >to keep everything in LSC for ease of maintenence. > >For example, How is ReadRest called? What about multifinder (i.e. if >the listener is called at a bad time, A5 may be incorrect...)? I've written several, though all in MPW Assembler and Lisa Assembler. Unfortunately, the interface is very badly designed, so you can't write it in anything but assembly language (in-line assembler in THINK C). The MPW Assembler samples ought to work just about as well in THINK C in-line assembler; most assemblers are pretty similar. However, if it involves any of MPW's fancy data structure definitions or structured macros, you may have to do a significant amount of conversion. I do have a few hints; make sure you know that section of the documentation backwards and forwards before you start, be prepared to crash your machine repeatedly, work on an isolated network with a Mac dedicated to Peek attached, and put DC.W $A9FF breakpoints in your code to watch what's happening whenever things don't seem to be making sense. Notice that because of the timing involved, these breakpoints will prevent the code from working if you call ReadRest or ReadPacket after the breakpoint, and may very well crash your machine outright if you try to continue normal execution. Such is the price of success. As for A5, there's not really any choice. You have to stash it in code relative space before you start, then use that when you're called from the DDP driver. That is, you have to use a DC.L . This is nasty and possibly incompatible with future systems, but I've been asking Apple for an alternative for years and there still isn't one. ReadRest is called by offset from a4, i.e., jsr 2(a4) The arguments are in A3 (buffer address) and D3 (buffer size), as documented. You should keep a queue of pre-allocated buffers, dequeue the header when you get a packet, and use that buffer to read in the packet, then enqueue the buffer onto a reception queue. (Or put it back on the free queue if things fail). Be sure you always call ReadRest. Be sure to check error returns from ReadPacket and ReadRest by using the Z bit directly; don't do your own tests on D3, it's not always correct. For instance, to call ReadPacket and test for error, jsr (a4) bne.s error DON'T do this: jsr (a4) tst.w d3 bne.s error You will get puzzling crashes if you do. Sometimes d3 is zero even though there was an error. Hope this helps. Socket listeners and protocol handlers are weird and frustrating, but it feels so good when you can stop working on them. -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com "In science it often happens that scientists say, 'You know that's a really good argument; my position is mistaken,' and then they actually change their minds and you never hear that old view from them again. They really do it. It doesn't happen as often as it should, because scientists are human and change is sometimes painful. But it happens every day. I cannot recall the last time something like that happened in politics or religion." -- Carl Sagan, 1987 CSICOP keynote address