home *** CD-ROM | disk | FTP | other *** search
- **************************************************************************
- * NetWorld command rundown... by Paul Jones.
- *
- * These commands have been 'translated' from C to HBASIC.
- *
- * Syntax:
- * FUNCTION (1) mem& (2)=KRmalloc& (3) (size&) (4)
- *
- * (1) Is the command is a FUNCTION or SUB-routine.
- * (2) The size of the return value (and suggested name)
- * (3) The command name
- * (4) The parameters (and size of values of parameters).
- *
- * For any references to the include file's commands, check out the
- * file "INCSPEC.TXT" for more info.
- **************************************************************************
-
- FUNCTION mem&=KRmalloc& (size&)
-
- - Allocate a block of memory from STiK's internal buffer.
- - Returns 0 if sufficient memory is not available.
- - These memory functions are basically the code in K&R 1 pp 174 -
- 177 but there are some minor differences. morecore is *never*
- called. These functions use one block of memory that is Malloc'd
- when the ACC loads. Also, the header size is 8 bytes since
- allocations greater than 2^16 are allowed, therefore memory is
- always allocated in multiples of 8 bytes.
- - Some bits in the headers are checked during KRmalloc() and
- KRfree() to determine if memory corruption has occured.
-
- SUB KRfree (mem&)
-
- - Free a block that was allocated by KRmalloc() or KRrealloc().
- - Currently, KRfree() does *not* check for a 0 address... (but this
- is such a good idea, that I will add the test)
-
- FUNCTION mem&=KRgetfree& (flag%)
-
- - Return the amount of free space left in STiK's internal buffer.
- - If flag is TRUE return the largest block, otherwise return
- total available space.
-
- FUNCTION block&=KRrealloc& (blocksize&, newsize&);
-
- - Change the size of an allocated block. If newsize is greater than
- oldsize, then copy the contents into the new block.
- - If newsize=0 then free the block and return 0.
- - If blocksize=0 then allocate a new block of newsize
- bytes, but zero the contents before returning.
-
- FUNCTION addr&=get_err_text& (code%)
-
- - Returns a pointer to a description of an internal STiK error code.
- The absolute value of code is used to look up the address on the
- start of the string (null terminated). If code is out of range, a
- pointer to "" is returned.
-
- * An easyier way to get an internal STiK string is to use the
- include file's "gerrtxt$ ()" function.
-
- FUNCTION addr&=getvstr& (text&)
-
- - Returns a pointer to the value of a STiK config variable
- set in DEFAULT.CFG The lookup is not case sensitive.
- The pointer is to the first non blank char after the '='.
- - If a variable does not exist, a pointer to "0" is returned.
- - If a variable has no '= value' "1" is returned (present= TRUE)
- - If a variable has '=', but no value, then "0" is returned.
- - To use this command:
-
- text$="EMAIL"+chr$(0)
- email&=getvstr& (varptr(text$))
-
- * An easyier way to get a STiK string is to use the include file's
- "gvstr$ ()" function.
-
- FUNCTION detect%=carrier_detect% (dummy%())
-
- - If the config variable CDVALID is FALSE, then 0 (unknown) is
- returned.
- - Otherwise, returns +1 for carrier, -1 for no carrier.
- - Please note that this command needs an array. Since I don't know
- of a way to make a command with no parameters, I had to use a fake
- array. The array is not used.
-
- FUNCTION cn%=TCP_open% (rhost&, rport%, tos%, obsize&)
-
- - Attempts to open a connection to rhost on rport.
- - tos is Type of Service. I've never experimented with non zero
- values.
- - obsize is the size of the output buffer to allocate.
- TCP_send() places data in this buffer. Size dependant on
- requirements. Bigger is not necessarily better. 500 to 2000
- should be OK.
- - TCP_open() returns a connection handle (0..n) or a a negative
- error code.
- - TCP_open() returns immediately, without waiting for the
- connection to establish.
-
- - Passive opens:-
- - If rhost is 0, then the connection becomes a LISTEN socket, and
- waits for a connection request from a remote host.
- - In this case, rport is the assignment of the local port
- and *not* the remote port...
- - There is no provision for limiting the socket to listen for
- connection from a particular host or port. (ie: always INADDR_ANY)
- - The port must be continually polled for input. There is
- no other way to see if a connection has been made.
- - Sending data to a connection in LISTEN mode is an error.
- - If a remote host makes a connection, the connection will
- no longer be in LISTEN mode. Requests from other hosts
- will be denied. To circumvent this, do another TCP_open(0,...)
- when the first connection is activated. (or have several
- connections passive opened at the same time)
-
- - NOTE To test the current status of the socket, simply
- call CNbyte_count(). If E_LISTEN is returned, then
- the socket is still in TLISTEN state. Any other function
- that has a connection handle as an argument will return
- the same error, except TCP_close().
-
- - Author's apology... It's very rough, but it's really only
- for my own testing. If I don't have time to make something
- better soon, this method should at least be usable. The reason
- that it is so rough is that I never intended having LISTEN
- sockets. Hence, this is a hack.
- * an easyier way to connect to a host is using the include file's
- "tcp_connect ()" function.
-
- FUNCTION er%=TCP_close% (cn%, timeout%)
-
- - Closes a connection. cn is the connection handle.
- - Returns 0 or a negative error code.
- - timeout is the time in seconds to wait for the connection to close.
- TCP_close() must negotiate the close with the remote host, so
- it can take some time if the net is slow. Pending data may need
- to be received and discarded before the connection closes cleanly.
- - Note that TCP_close() *must* be called in order to free memory
- that has been allocated for the connection.
- - A timeout of 0 is acceptable for immediate close.
- - If the ESC key is pressed during the timeout period, TCP_close()
- returns immediately with a E_USERTIMEOUT error code.
-
- FUNCTION er%=TCP_send% (cn%, buf&, len%)
-
- - Send len bytes from buf on the connection cn.
- - Returns E_NORMAL for success, or an error code.
- - Note that the error E_OBUFFULL is *not* a fatal error.
- If E_OBUFFULL is return, you should loop, for your own timeout
- period, waiting for the output buffer to clear. If you have
- defined a buffer that is smaller than the block you are sending,
- it will never clear.
- * buf& is actually an address to the start of the string.
-
- FUNCTION stat%=TCP_wait_state% (cn%, state%, timeout%)
-
- - Wait for timeout seconds for the connection cn, to reach a
- particular TCP state. The primary use for this function is to
- wait for the TESTABLISH state after calling TCP_open() (though
- this is not really necessary).
- - Returns E_NORMAL or an error code.
- - If the ESC key is pressed while this function is waiting, it
- returns E_USERTIMEOUT.
-
- FUNCTION stat%=TCP_ack_wait% (cn%, timeout%)
-
- - Wait for all data in the output buffer to be acknowledged by
- the remote host.
- - Note that the timeout is in milliseconds
- - Returns E_NORMAL regardless of whether the timeout is reached
- or the output buffer clears.
- - This is a kludge that you should probably never use...
-
- FUNCTION cn%=UDP_open% (rhost&, rport%);
-
- - Open a UDP (datagram) connection with rhost on rport.
- - Returns connection handle or error code.
- - Note that there is really no such thing as a UDP `connection'.
- The UDP functions provide a convenient and consistent method
- for communicating with remote hosts using UDP.
- - UDP is used primarily by the domain name resolver.
-
- FUNCTION stat%=UDP_close% (cn%)
-
- - Close the UDP connection cn.
- - Frees the connection handle and any blocks pending in the
- input queue, returns immediately.
-
- FUNCTION stat%=UDP_send% (cn%, buf&, len%);
-
- - Sends len bytes from buf on the connection cn.
- - Returns E_NORMAL or an error code.
- - NOTE that the the data will be sent as a single UDP packet, so
- you should make sure that it is appropriately sized for your MTU.
- * buf& is the address of the start of a string.
-
- FUNCTION stat%=CNkick% (cn%)
-
- - 'kick' the connection cn.
- - If there is data waiting to be sent, then restart the
- retransmission sequence as though it is the first transmission. If
- there is no data waiting, send an ACK packet to the remote host to
- let them know we're still here.
- - In theory this is a pointless function. It is provided so that
- when the user starts bashing the keyboard during a long delay, the
- programmer arrange that something happens as a result. This
- should save lots of valuable Atari hardware. :-))
- - Since the retransmission algorithm uses exponential backoff,
- (ie: timeout doubles at every retransmission) the function is
- probably not entirely pointless.
- - TCP specs state that excessive retransmissions should be avoided.
- - Returns E_NORMAL or an error code if the connection is invalid.
-
- FUNCTION num%=CNbyte_count% (cn%)
-
- - Return the number of bytes waiting in the input queue for
- connection cn, or an error code.
-
- FUNCTION byte%=CNget_char% (cn%)
-
- - Return the next char from the input queue for cn, or
- a negative error code. A return of E_NODATA is *not* fatal.
- - Note that if you are using CNget_char() for data input then
- your loop *must* include CNbyte_count(), or the housekeep()
- function.
-
- FUNCTION addr&=CNget_NDB& (cn%)
-
- - Return a pointer to the next block on the input queue for cn, or 0
- if there are no packets queued.
- - This is potentially the most efficient way of reading the
- input queue, because the NDB contains a point to the actual
- packet that was read in initially. No data has been copied
- up to this point.
- - There is no way defined for CNget_NDB() to return any other
- connection error status.
- - The NDB structure is defined in TRANSPRT.H
- - Since CNget_NDB() unlinks the packet from the input queue,
- you must use KRfree() to free the packet and the NDB structure
- as well. The following code is a guide..
-
- addr&=CNget_NDB& (cn%)
-
- if addr&<>0 then process_block(addr&)
-
- FUNCTION stat%=CNget_block% (cn%, blk&, len%)
-
- - Fills a block starting at blk with len bytes from cn.
- - If the input queue has less than len bytes, then no data will be
- transferred.
- - Returns the number of bytes you requested, or an error code.
- E_NODATA is *not* a fatal error.
-
- SUb housekeep dummy%()
-
- - Performs internal housekeeping duties.
- You don't really need to call this function, but an explanation
- is necessary. housekeep() is called internally by several
- of the other functions listed here. In particular, all
- of the CN input functions call housekeep() *except* CNget_char().
- (otherwise a whole packet could be received every time CNget_char()
- is called!)
-
- - STiK does not do any background or interrupt processing.
- Everything is acheived by polling. housekeep() is the
- central function of STiK that does this polling. It calls
- these functions:-
-
- do_resolve(); Resolver processing, including reading packets
- slip_in(); Reading the serial port
- slip_out(); Writing to the serial port
- tcp_timer(); TCP retransmissions
- frag_ttl_check(); Check time to live in fragment reassembly queue
-
- - Housekeep is now driven by the system_timer interupt. So it runs
- up to a maximum of 50/sec. The event_multi in the .ACC no longer
- calls housekeep(). This avoids several problems with Magic.
-
- - NOTE that the efficiency of STiK relates to this function, but I
- have to admit that housekeep() has not been carefully thought out.
- However, if the functions called by housekeep() have no work
- to do, they return quickly. All the same, they can each be called
- many times each second.
-
- * dummy() is a dummy array.
-
- FUNCTION stat%=resolve% (dn&, rdn&, alist&, lsize%)
-
- - Resolve a domain name into one or more IP addresses.
- dn is the domain name.
- rdn is the real domain name, which is returned if dn is an alias (CNAME).
- alist is a pointer to an array where the IP address(s) are returned.
- lsize is the size of that array.
- - If the information is in local cache, then resolve will return it
- immediately, otherwise an algorithm for query of nameservers
- is initiated. This can take some time, however, the resolver has
- an internal limit on the amout of work it will do in attempting
- to resove a hostname. (Hence the error code `work limit reached')
- - If rdn=0 then no value is assigned to it.
- Otherwise, a pointer to the domain name associated with the addresses
- is assigned to *rdn, even if it is the same as that requested.
- This pointer must be freed using KRfree().
- - If you pass a dotted decimal ip address to resolve, and request the rdn,
- you will just get the dotted decimal ip back. This is a kludge, but
- better than the old manner of just crashing.
- - resolve() returns the number of addresses copied to alist,
- or a negative error code.
- - In retrospect, it might not have been all that smart of me to write
- my own DNS resolver, but it is at least educational :-))
- All the same, it is *not* yet finished. There are some bugs in
- the code at present, and also inefficiency in my algorithm.
- - I'll work on improving it when (if?) I get the chance.
- - NOTE that STiK.ACC will save the dns cache to domain.txt
- every five minutes if AES is active and STiK is enabled.
- * An easyer way of connected to a host is by using the include
- file's "tcp_connect ()" function.
-
- SUB ser_disable dummy%()
-
- - This function disables the serial port prior to disk I/O
- It should only be necessary for combinations of baud rate/
- cpu speed that do not allow DMA and serial I/O to work together.
- Internally, it calls Jan Kriesten's DEVICE.LIB function
- StopReceiver(). This, in turn, calls an IOCTL function
- that might only work with HSMODEM loaded. I'm not sure.
- - In the current version of STiK this (and ser_enable)
- return without doing anything. I'm waiting for bug
- reports before I decide what to do with it.
- - NOTE that if the port is disabled (in later STiK versions)
- it *must* be reenabled immediately after the disk I/O, or
- that is the end of the TCP session :-))
- * dummy() is a dummy array.
-
- SUB ser_enable dummy%()
-
- - See above...
-
- FUNCTION stat%=set_flag% (flag%)
-
- - This calls an assembler routine that sets one of 64 possible
- flags using TAS. The idea is that with proper flag setting
- STiK should function properly in a pre-emptive multitasking
- environment. They could also be used for locking of other
- well defined processes, such as mailers etc.
- - Currently I'm only using the first two of these flags, for
- housekeep() and do_resolve() which are not re-entrant.
- - I've yet to actually do the work which would ensure proper
- function of STiK in a pre-emptive environment, so if it
- does work, that's accidental.
- - set_flag() returns TRUE if the flag was already set
- (ie: Someone else owns the lock) or FALSE if the flag was clear,
- and set_flag() changed it successfully. (ie: the lock is ours).
- (in other words, set_flag() returns the value the flag had
- before this call)
-
- - NOTE that anyone wishing to define a new lock should coordinate
- with me!!!
-
- SUB clear_flag (flag%)
-
- - Clears a flag regardless of it's current status. Returns nothing.
-
- FUNCTION CIB&=CNgetinfo& (cn%);
-
- - Returns a pointer to a CIB structure that has information
- about the connection associated with the handle 'cn'.
- - This includes protocol, remote host, remote port, and
- the local port. The address of the local host can be
- found with stik_cfg->client_ip
- - The pointer is to a live part of the connection information,
- so don't change anything unless you know what you're doing.
- - The definition of a CIB can be found in the `trasnprt.h' file.
-
- FUNCTION stat%=on_port% (port&);
-
- - Returns true if port was succesfully opened
- - This turns a physical port on. It is mainly for use
- by a Dialer.
- - port is the name from the DEV_LIST structure.
-
- - if port is already open this call will return TRUE
- - if port doesn't exist on machine this will return False
-
- SUB off_port (port&)
-
- - Turns a physical port off.
- - port is the name from the DEV_LIST structure.
- - mainly for use with a Dialer.
- - experimentation with this function on an active port will
- probably kill the connection. Play at your own risk!
-
- FUNCTION stat%=setvstr% (vs&, value&)
-
- - sets a value in the cfg->cv array.
- - If the value is already present it changes it.
- > Note it doesn't do the following yet. Right now it only changes
- existing string
- - If the value isn't present then it adds it.
- - returns TRUE if variable was changed/set
- - returns FALSE if array is already full and the variable doesn't exist
-
- FUNCTION stat%=query_port% (port&)
-
- - Checks if a given port is active.
- - returns TRUE if port is active
- - returns FALSE if port is inactive
-
- FUNCTION stat%=g_resolve% (dn&, rdn&, alist&, lsize%)
-
- - The only difference between this and resolve is that the code
- uses an evnt_multi. So it should be non blocking. But it can
- only be used from GEM applications.
-
- FUNCTION stat%=g_TCP_wait_state% (cn%, state%, timeout%)
-
- - This is the GEM version of TCP_wait_state, in all other respects
- it functions the same. May only be called from a GEM application.
-
- *** NOTE g_TCP_wait_state is experimental and not functioning properly
- yet
-
- ------------------------------------------------------------------------
- Extra NetWorld commands
- ------------------------------------------------------------------------
-
- FUNCTION tcp_author& (dummy())
-
- Returns the address to the start of a string which contains the name
- of the author of the transport layer.
-
- FUNCTION tcp_version& (dummy())
-
- Returns the address to the start of a string which contains the
- version number of the transport layer.
-
- FUNCTION tcp_module& (dummy())
-
- Returns the address to the start of a string which contains the
- module information of the transport layer.
-
- FUNCTION netwldver& (dummy())
-
- Returns the address to the start of a string which contains the
- version number of NetWorld.