|
VMS DECwindows Transport Manual
- Test the status from the IO$_ACCESS $QIO.
If the network is shutting down, call DECW$XPORT_ATTACH_LOST to report
that the transport shut down and then call DETACH_AND_POLL to poll for
its return. If it was successful, continue processing to construct a
full connection context.
- Start a named block of code that attempts
to allocate and initialize the resources needed to maintain a
connection. If any part of this setup fails, the code block is exited
and failure processing recovers any allocated resources.
- Allocate an IXTCC and XTPB for this
connection. Store the address of the XTPB in the IXTCC.
- Increment the connection reference count and
store the IXTCC on the XTDB so that it can be found in case of image
rundown before the connection is fully established.
- Call the transport-common
DECW$XPORT_ALLOC_INIT_QUEUES routine to allocate and initialize the
communication queues. DECW$XPORT_ALLOC_INIT_QUEUES allocates a block of
storage for an XTCC, XTCQ, and all of the XTCBs for a connection.
DECW$XPORT_ALLOC_INIT_QUEUES must allocate at least an XTCC; the other
structures are optional. DECW$XPORT_ALLOC_INIT_QUEUES places all of the
XTCBs on the appropriate free queues.
- Convert the Network Standard Format
Internet address of the connection client, which is returned by the
IO$_ACCESS $QIO in the XTDB$T_ACC_INADDR field of the XTDB, into a
dot-format Internet address. For example, the longword value
2C28B48216 would be converted to the ASCII string
130.180.40.44.
- Attempt to perform address-to-nodename
translation of the dot-format Internet address to get the textual name
of the client node. The arguments of the IO$_ACPCONTROL $QIO system
service are as follows:
- P1 is the address of a 2-longword descriptor of a
longword containing the function code INETACP_FUNC$C_GETHOSTBYADDR.
- P2 is the address of the descriptor of the
dot-format Internet address to be translated.
- P3 is the address of a word to receive the length
of the resultant string.
- P4 is the address of a descriptor of an area of
memory to receive the result of the translation.
- The address-to-nodename translation failed
with the status of SS$_ENDOFFILE. This indicates that the dot-address
could not be found in the local host database. The dot-address form of
the client's node address will be used as the node name of the client.
- The address-to-nodename translation
succeeded. Check if the returned node name matches the local node name.
If it does, use the string "0" as the client's node name; otherwise use
the string returned by the translation operation.
- The Internet protocols do not support the
concept of a remote user name. Synthesize this information by
identifying the remote user with the string "?".
- Point the XTCC to the remote-user name and
node fields.
- Copy the channel assigned to the client
connection into the IXTCC and zero this field in the XTDB.
- Mark the connection as active by setting
the flags longword of the XTCC to the constant XTCC$M_ACTIVE and the
connection mode as a remote server (these two operations should be
performed in this order because the mode field is a subfield of the
flags longword).
Initialize the pointer to the XTDB in the IXTCC
and the pointer to the transport function table in the IXTCC. Inherit
the event flag for I/O operations from the XTDB.
- Deliver a user-mode AST to the
TRANSPORT_OPEN_CALLBACK routine (with the IXTCC as the argument) to
complete the connection acceptance in user mode.
TRANSPORT_OPEN_CALLBACK performs the callback to the transport
caller and starts I/O on the connection.
- Executive-mode connection setup completed.
- If any step of the connection setup in the
connect block failed, resource recovery operations are performed here:
channels are deassigned, memory is deallocated, connection structures
are disassociated, reference counts are decremented, and so on.
- Call the transport common
DECW$XPORT_ACCEPT_FAILED routine to generate a report describing the
cause of the failure.
- This is the common exit point. Invoke
TRANSPORT_READ_QUEUE to issue another IO$_ACCESS $QIO to receive
another client connection request.
8.2.19 Sample TRANSPORT_OPEN_CALLBACK Routine
TRANSPORT_OPEN_CALLBACK is invoked as a user-mode AST procedure by
TRANSPORT_READ_AST to complete the creation of a connection. It
performs a callback to the server's connect-request routine and,
depending on the value returned by that routine, completes the
connection by starting the initial read operation.
Example 8-19 shows a sample implementation of the
TRANSPORT_OPEN_CALLBACK routine.
Example 8-19 Sample TRANSPORT_OPEN_CALLBACK
Routine |
.
.
.
ROUTINE transport_open_callback( itcc : REF $BBLOCK ) : NOVALUE =
BEGIN
BUILTIN
REMQTI ;
LOCAL
tcc: REF $BBLOCK INITIAL ( .itcc [ixtcc$a_tcc] ),
free_queue: REF VECTOR[2],
status ;
LABEL
start_reading ;
start_reading:
BEGIN
(1)IF NOT (status = (.tcpip_tdb [xtdb$a_connect_request])( .tcc ))
THEN
LEAVE start_reading ;
(2)xport_in_state_srp( tcc ) ;
xport_out_state_srp( tcc ) ;
xport_in_free_disable( tcc, decw$c_xport_buffer_lrp ) ;
(3)free_queue = .tcc [xtcc$a_ifs_queue] ;
IF .free_queue[0] EQLA 0
THEN
BEGIN
free_queue = .tcc [xtcc$a_ifl_queue] ;
IF .free_queue[0] EQLA 0
THEN
BEGIN
status = DECW$_BADQUEUE ;
LEAVE start_reading ;
END ;
END ;
(4)status = DECW$$TCPIP_EXECUTE_FREE
( .tcc, 0, decw$c_xport_buffer_srp, .free_queue ) ;
IF .status
THEN
RETURN ;
END ;
(5)DECW$XPORT_CLOSE( .tcc ) ;
(6)DECW$XPORT_REFUSED_BY_SERVER ( .status ) ;
RETURN ;
END ;
.
.
.
|
- Invoke the server's connect-request routine
with the address of the XTCC for the connection.
- The transport user accepted the connection.
Force the input and output operations to use small request packets for
startup and disable free-input operations on the input large request
packet free queue.
- Check the small input free queue and, if it
is empty, the large input free queue. If both are empty, the transport
cannot perform a read operation, so return a bad queue status.
- Call the XTFT$A_EXECUTE_FREE routine to put
the buffers on the free queue and return.
- This code is entered only if the callback
procedure returned a failure status. Invoke the transport-common
DECW$XPORT_CLOSE routine to complete the destruction of the connection.
- Call DECW$XPORT_REFUSED_BY_SERVER to format
and deliver a message vector to describe the reason for the connection
refusal. This is constructed on the status code returned by the
callback procedure.
8.2.20 Sample DETACH_AND_POLL Routine
DETACH_AND_POLL starts polling for a transport restart.
Example 8-20 shows a sample implementation of the DETACH_AND_POLL
routine.
Example 8-20 Sample DETACH_AND_POLL
Routine |
.
.
.
ROUTINE detach_and_poll( tdb : REF $BBLOCK ) : NOVALUE =
BEGIN
BUILTIN
EMUL ;
LOCAL
status ;
(1)IF .tdb [xtdb$v_dying]
THEN
RETURN ;
(2)IF .tdb [xtdb$w_chan] NEQ 0
THEN
BEGIN
$CANCEL( CHAN = .tdb [xtdb$w_chan] ) ;
$DASSGN( CHAN = .tdb [xtdb$w_chan] ) ;
tdb [xtdb$w_chan] = 0 ;
END ;
(3)IF .tdb [xtdb$w_acc_chan] NEQ 0
THEN
BEGIN
$CANCEL( CHAN = .tdb [xtdb$w_acc_chan] ) ;
$DASSGN( CHAN = .tdb [xtdb$w_acc_chan] ) ;
tdb [xtdb$w_acc_chan] = 0 ;
END ;
(4)IF .reattach_timer_id EQL 0
THEN
BEGIN
reattach_timer_id = .tdb ;
EMUL( %REF( REATTACH_INTERVAL_SECS ), %REF( -10000000 ), %REF( 0 ),
reattach_timer_delta ) ;
END ;
(5)IF .tcpip_tdb [xtdb$v_dying]
THEN
RETURN ;
(6)status = $SETIMR(
EFN = 31,
DAYTIM = reattach_timer_delta,
ASTADR = reattach_ast,
REQIDT = .reattach_timer_id ) ;
(7)IF NOT .status
THEN
DECW$XPORT_REATTACH_FAILED( .tdb, .status ) ;
RETURN ;
END ;
.
.
.
|
- If the XTDB$V_DYING bit is set, there is no
need to continue.
- Release the channel to the Internet device.
- Release the connection-accept channel.
- If the timer is not identified, associate
the timer with the address of the XTDB.
- Make sure that the transport is still alive.
- Start polling for a network restart at
reattach_timer_delta intervals. (The REATTACH_AST
routine is described in Section 8.2.21.)
- If unable to poll for the restart, report
that the reattach failed.
8.2.21 Sample REATTACH_AST Routine
REATTACH_AST calls DECW$$TCPIP_ATTACH_TRANSPORT to reattach the
transport when the reattach_timer_delta interval has
expired.
Example 8-21 shows a sample implementation of the REATTACH_AST routine.
Example 8-21 Sample REATTACH_AST Routine |
.
.
.
ROUTINE reattach_ast( tdb : REF $BBLOCK ) : NOVALUE =
BEGIN
LOCAL
status;
(1)status = DECW$$TCPIP_ATTACH_TRANSPORT( .tdb ) ;
RETURN ;
END ;
.
.
.
|
- Call DECW$$TCPIP_ATTACH_TRANSPORT to
reattach the transport.
8.2.22 Sample XTFT$A_RUNDOWN Routine
XTFT$A_RUNDOWN is invoked by the common transport when the image in
which the transport is running exits. It is the responsibility of each
transport's rundown procedure to release any resources that might
survive the image exit. ASTs are disabled while XTFT$A_RUNDOWN is
executing.
Example 8-22 shows a sample implementation of the XTFT$A_RUNDOWN
routine.
Example 8-22 Sample XTFT$A_RUNDOWN
Routine |
.
.
.
GLOBAL ROUTINE DECW$$TCPIP_RUNDOWN( tdb : REF $BBLOCK ) : NOVALUE =
BEGIN
BIND
iosb = tdb [xtdb$w_iosb] : VECTOR [4,WORD],
xtpb = .tdb [xtdb$a_tpb] : $BBLOCK ;
LOCAL
itcc : REF $BBLOCK INITIAL( .tdb [xtdb$a_itcc_flink] ),
status ;
(1)tdb [xtdb$v_dying] = 1 ;
(2)WHILE .itcc NEQA tdb [xtdb$a_itcc_flink] DO
BEGIN
BIND
xtcc = .itcc [ixtcc$a_tcc] : $BBLOCK ;
xtcc [xtcc$v_dying] = 1 ;
$CANCEL( CHAN = .itcc [ixtcc$w_chan] ) ;
$DASSGN( CHAN = .itcc [ixtcc$w_chan] ) ;
itcc [ixtcc$w_chan] = 0 ;
itcc = .itcc [xtcc$a_flink] ;
END ;
(3)IF ( .tdb [xtdb$v_mode] AND DECW$M_XPORT_CLIENT ) NEQ 0
THEN
RETURN ;
(4)$CANCEL( CHAN = .tdb [xtdb$w_chan] ) ;
$CANCEL( CHAN = .tdb [xtdb$w_acc_chan] ) ;
$DASSGN( CHAN = .tdb [xtdb$w_acc_chan] ) ;
tdb [xtdb$w_acc_chan] = 0 ;
$DASSGN( CHAN = .tdb [xtdb$w_chan] ) ;
tdb [xtdb$w_chan] = 0 ;
IF .reattach_timer_id NEQ 0
THEN
$CANTIM( REQIDT = .reattach_timer_id ) ;
RETURN ;
END ;
.
.
.
|
- Mark this transport as dying to prevent any
of the routines, such as TRANSPORT_READ_QUEUE, from performing
additional operations.
- Locate each connection known to this
transport and perform any rundown operations necessary. For TCP/IP, the
connection is marked as dying to prevent any per-connection routine
from operating on the connection. Any I/O operation in progress on the
connection is canceled and the communication channel is deassigned.
- If the caller is a client, no more
processing is needed for rundown.
- For servers, cancel any I/O operation on the
listening and accepting channels and deassign the channels.
8.2.23 Sample DECW$TRANSPORT_INIT Routine
The DECW$TRANSPORT_INIT routine initializes and returns the address of
the XTFT. Each specific transport has a global symbol named
DECW$TRANSPORT_INIT. This is the address of the first procedure invoked
in the specific transport during the common transport
DECW$XPORT_ATTACH_TRANSPORT routine and it is responsible for
initializing the fields in the XTFT structure.
The DECW$EXAMPLES:XPORT_EXAMPLE_XFER.MAR module and
DECW$EXAMPLES:DEMO_BUILD.COM procedure ensure that the transfer vector
to the DECW$TRANSPORT_INIT routine is found at the beginning of the
transport-specific shareable image.
Unlike the other transport-specific functions, DECW$TRANSPORT_INIT
returns the address of the XTFT structure as its return value instead
of a VMS condition code.
Example 8-23 shows a sample implementation of the DECW$TRANSPORT_INIT
routine.
Example 8-23 Sample DECW$TRANSPORT_INIT
Routine |
.
.
.
GLOBAL ROUTINE DECW$TRANSPORT_INIT =
BEGIN
LOCAL
tft: REF $BBLOCK ;
tft = tcpip_tft ;
tft[xtft$l_required0] = xtft$k_required0 ;
tft[xtft$l_reserved0] = 0 ;
tft[xtft$a_execute_write] = decw$$tcpip_execute_write ;
tft[xtft$a_write] = decw$$tcpip_write ;
tft[xtft$a_write_user] = decw$$tcpip_write_user ;
tft[xtft$a_execute_free] = decw$$tcpip_execute_free ;
tft[xtft$a_free_input_buffer] = decw$$tcpip_free_input_buffer ;
tft[xtft$a_close] = decw$$tcpip_close ;
tft[xtft$a_open] = decw$$tcpip_open ;
tft[xtft$a_attach_transport] = decw$$tcpip_attach_transport ;
tft[xtft$a_rundown] = decw$$tcpip_rundown ;
tft[xtft$l_xtcc_length] = xtcc$c_tcpip_length ;
tft[xtft$l_xtpb_length] = xtpb$c_tcpip_length ;
tft[xtft$l_xtdb_length] = xtdb$c_tcpip_length ;
tft[xtft$l_ixtcc_length] = ixtcc$c_tcpip_length ;
tft[xtft$l_required1] = xtft$k_required1 ;
.tft
END ;
.
.
.
|
DECW$EXAMPLES:XPORT_EXAMPLE_XFER.MAR generates transfer vectors for the
sample transport. A portion of the XPORT_EXAMPLE_XFER.MAR code follows:
.
.
.
.PSECT $TRANSFER$ PIC,USR,CON,REL,LCL,SHR,EXE,RD,NOWRT,QUAD
TRANSFER DECW$TRANSPORT_INIT
.END
.
.
.
|
The $TRANSFER$ program section points to a program unit, in this case
DECW$TRANSPORT_INIT. The DEMO_BUILD.COM procedure then creates a
cluster and collects the $TRANSFER$ program section in it, as described
in Example 8-24.
8.3 Compiling and Linking Options for the Transport
The DECW$EXAMPLES:DEMO_BUILD.COM procedure supplied with the DECwindows
kit builds the VMS DECwindows example programs, including the sample
TCP/IP transport layer described in this chapter. You can refer to this
procedure for suggestions on compiling and linking a transport layer in
the DECwindows environment.
Example 8-24 shows the transport-specific portion of the
DEMO_BUILD.COM procedure.
Example 8-24 DEMO_BUILD.COM Procedure |
.
.
.
$ ! If Bliss and UCX are installed on the system and DECwindows is installed
$ ! with the common transport shareable image and Bliss programming support,
$ ! then compile and link the example transport.
$ !
$ if f$search("sys$library:ucx$inetdef.r32") .eqs. "" then goto do_fortran
$ if f$search("sys$share:decw$transport_common.exe") .eqs. "" then goto do_fortran
$ define/nolog src$ decw$examples
(1) $ bliss decw$examples:xport_example
$ macro decw$examples:xport_example_xfer
(2) $ link/share=decw$transport_example.exe -
xport_example,-
xport_example_xfer,-
sys$input/opt
(3) gsmatch=lequal,12,12
psect_attr=$code$,pic,shr,exe,nowrt
psect_attr=$plit$,pic,shr,exe,nowrt
psect_attr=$own$,pic,noshr,noexe,wrt
psect_attr=$global$,pic,noshr,noexe,wrt
(4) cluster=transfer_cluster,,,
collect=transfer_cluster,$transfer$
cluster=code_cluster,,,
collect=code_cluster,$code$,$plit$
(5) protect=yes
cluster=own_cluster,,,
collect=own_cluster,$own$,$global$
protect=no
sys$share:decw$transport_common/shareable
.
.
.
|
- Compile the transport-specific code.
The
DECW$EXAMPLES:XPORT_EXAMPLE_XFER.MAR module generates transfer vectors
for the sample transport.
- Link the transport-specific code as a VMS
shareable image that can be accessed by the transport-common component.
Make sure your transport-specific shareable image is in the form
DECW_TRANSPORT_transport_name.EXE. (Transport names
that do not contain a $ character are reserved for third-party and
customer transport images.) When called by either Xlib or the server,
DECW$XPORT_ATTACH_TRANSPORT attempts to locate and activate an image
with a name in this form.
- Prevent image activation of incompatible
transport versions.
Set program section attributes appropriately
for shareable images.
- Create a cluster for the transfer vector
and place the named program section, in this case $transfer$, in it.
The $transfer$ program section points to the DECW$TRANSPORT_INIT
routine, as described in Section 8.2.23. The transfer vector must be at
the beginning of the image (in the first cluster) or the transport
common will not activate it.
- OWN and global variables are protected from
user-mode writing.
8.3.1 Installing the Transport-Specific Shareable Image
You must install your transport-specific image as a protected image in
the SYS$SHARE directory in order for the transport-common layer to
access it. To do this, perform the following steps:
Note
Because the common transport uses only executive-mode logical names,
the logical name SYS$SHARE cannot be redefined.
|
- Log in to the system manager account.
- Copy the transport image to the SYS$SHARE directory.
$COPY DECW_TRANSPORT_transport_name.EXE SYS$SHARE:/PROT=W:RE
|
- Add the following line to SYS$MANAGER:SYSTARTUP_V5.COM:
$ INSTALL CREATE SYS$SHARE:DECW_TRANSPORT_transport_name/OPEN /SHARED /HEADER_RES /PROTECTED
|
- If you have not already done so, copy
SYS$MANAGER:DECW$PRIVATE_SERVER_SETUP.TEMPLATE to *.COM
. Then, modify the DECW$SERVER_TRANSPORTS symbol to include your
transport. For example, DECW$SERVER_TRANSPORTS could translate to
"DECNET,LOCAL,TCPIP,FOO".
$ DECW$SERVER_TRANSPORTS == "DECNET,LOCAL,TCPIP,FOO"
|
Note
If you write your own transport layer based on TCP/IP, do not include
the Digital-supplied TCPIP transport name in the
DECW$SERVER_TRANSPORTS symbol. The X11 protocol convention for TCP/IP
is that server number 0 listens on port 6000, server number 1 listens
on port 6001, and so forth. The Digital-supplied
TCPIP transport attaches to port 6000 and will
conflict with your own TCP/IP transport.
|
The server uses the symbol DECW$SERVER_TRANSPORTS to determine
which transports to attach and initialize and calls the
DECW$XPORT_ATTACH_TRANSPORT routine for each transport identified by
the symbol. The transport_name argument specifies the
transport, such as FOO.
- Manually execute the install command you added to
SYS$MANAGER:SYSTARTUP_V5.COM.
- Enter the following command to restart DECwindows:
Answer "yes" to the confirmation question.
- Customize security as described in the Using DECwindows Motif for OpenVMS for TCP/IP,
but use the transport name transport_name instead of
TCPIP.
- Create a DECterm window on the workstation and enter the following
command:
$SET DISPLAY /CREATE /NODE=your_node /TRANSPORT=transport_name
|
Substitute the node name of your workstation for
your_node. Enclose your_node in quotes if your
transport distinguishes lowercase node names.
- Run any DECwindows application from the DECterm window. The
application will now use your transport to establish the connection.
8.3.2 Installing the Example Transport Shareable Image
If you have installed the UCX software, you can install and use the
example transport by doing the following:
Note
The Digital-supplied TCPIP transport attaches to port
6000 and will conflict with the example transport, which also attaches
to port 6000. If you want to use the example transport, do not include
the Digital-supplied TCPIP transport name in the
DECW$SERVER_TRANSPORTS symbol.
|
- Log into the system manager account.
- Copy the example transport to the SYS$SHARE directory as follows:
$COPY DECW$EXAMPLES:DECW$TRANSPORT_EXAMPLE.EXE SYS$SHARE:/PROT=W:RE
|
- Add the following line to SYS$MANAGER:SYSTARTUP_V5.COM:
$ INSTALL CREATE SYS$SHARE:DECW$TRANSPORT_EXAMPLE /OPEN /SHARED /HEADER_RES /PROTECTED
|
- If you have not already done so, copy
SYS$MANAGER:DECW$PRIVATE_SERVER_SETUP.TEMPLATE to *.COM
. Then, modify the DECW$SERVER_TRANSPORTS symbol to include the example
transport.
$ DECW$SERVER_TRANSPORTS == "DECNET,LOCAL,EXAMPLE"
|
- Manually execute the install command.
- Enter the following command to restart DECwindows:
Answer "yes" to the confirmation question.
- Customize security as described in the Using DECwindows Motif for OpenVMS for TCP/IP,
but use the transport name EXAMPLE instead of TCPIP.
- Create a DECterm window on the workstation and enter the following
command:
$SET DISPLAY /CREATE /NODE=your_node /TRANSPORT=EXAMPLE
|
Substitute the node name of your workstation for
your_node. Enclose your_node in quotes if the
Internet node name contains lowercase characters.
- Run any DECwindows application from the DECterm window. The
application will now use the example transport to establish the
connection.
|