HP OpenVMS Systems Documentation

Content starts here

VMS DECwindows Transport Manual


Previous Contents Index

  1. Determine which free queue this XTCB came from, based on the XTCB$B_SUBTYPE field of the XTCB.
  2. Store the address of the connection structure in the XTCB and then initiate an asynchronous read $QIO into the XTCB. The FREE_INPUT_AST read-completion AST routine is called with the address of the XTCB when the I/O operation completes. The FREE_INPUT_AST routine is described in Section 8.2.8.
  3. If the $QIO service failed, perform failure recovery. Return the XTCB to the correct free queue, mark the connection as dying, and store the failure status code in the XTCC with the XTCC_STATUS macro.
    In either case, return the result of the $QIO service as the return value.

8.2.8 Sample FREE_INPUT_AST Routine

The FREE_INPUT_AST routine is the $QIO read-completion AST routine.

Note

In prior versions of the DECwindows transport-common layer, each specific transport had to perform its own read-completion processing. The transport-common DECW$XPORT_READ_COMPLETE routine has been implemented to perform read-completion processing.

Specific transports that support an AST interface should call the transport-common DECW$XPORT_READ_COMPLETE routine to perform the read completion and initiate additional reads. See the description of the DECW$XPORT_READ_COMPLETE routine in Chapter 5 for more informaton.

Example 8-8 shows a sample implementation of the FREE_INPUT_AST routine.

Example 8-8 Sample FREE_INPUT_AST Routine

   .
   .
   .
ROUTINE free_input_ast( xtcb : REF $BBLOCK ) : NOVALUE =

    BEGIN
    BIND
        iosb = xtcb [xtcb$w_iosb] : VECTOR [4,WORD,UNSIGNED],
        tcc = .xtcb [xtcb$l_rflink] : $BBLOCK ;

    LOCAL
        itcc : REF $BBLOCK,
        status : INITIAL(.iosb [0]) ;

    (1)VALIDATE_XTCC( tcc, itcc ) ;

    (2)xtcb [xtcb$l_length] = .iosb [1] ;

    (3)status = DECW$XPORT_READ_COMPLETE(.itcc, .xtcb, .status) ;

    RETURN ;
    END ;

   .
   .
   .
  1. The connection-context address is stored in the XTCB, which is user-modifiable. Call the VALIDATE_XTCC macro to confirm that the address is uncorrupted and to get the address of the IXTCC. If the XTCC ID is known and is valid, VALIDATE_XTCC returns the previously registered address of the IXTCC data structure in the ixtcc argument.
  2. The number of bytes read by the just-completed I/O is in the second word of the IOSB (.iosb [1]). Use this number to set the length field of the XTCB. DECW$XPORT_READ_COMPLETE requires this field to be valid.
  3. Call DECW$XPORT_READ_COMPLETE to place the XTCB on the input work queue. If a free buffer is available, DECW$XPORT_READ_COMPLETE calls the routine identified by the XTFT$A_FREE_INPUT_BUFFER field in the XTFT to start the next read.

8.2.9 Sample PARSE_INTERNET_ADDRESS Routine

The PARSE_INTERNET_ADDRESS routine converts an ASCII Internet Standard Format address (nnn.nnn.nnn.nnn) into the binary, 32-bit Network Standard Format address. This entails converting numeric fields separated by periods into 1-byte values and then packing these bytes into a longword with the first-encountered field converted and inserted into the rightmost byte of the longword. For example, the address 130.180.40.44 would be converted to the longword value 2C28B48216.

If there are too few fields or any nonnumeric characters seen (other than the field separator), then the routine returns a bad parameter status. If the conversion is successful, the Network Standard Format address is built in the sockaddrin structure.

Example 8-9 shows a sample implementation of the PARSE_INTERNET_ADDRESS routine.

Example 8-9 Sample PARSE_INTERNET_ADDRESS

   .
   .
   .
ROUTINE parse_internet_address( str_desc: REF $BBLOCK [DSC$C_S_BLN],
                                address: REF VECTOR [4,BYTE,UNSIGNED] ) =

     BEGIN

     LOCAL
     string : REF VECTOR [,BYTE],
     strlen,
     p ;


     (1)string = .str_desc [DSC$A_POINTER] ;
     strlen = .str_desc [DSC$W_LENGTH] ;
     p = 0 ;


     INCR i FROM 0 TO 3
     DO
         BEGIN

         (2)address [.i] = 0 ;

         (3)IF .strlen EQL 0
         THEN
            RETURN SS$_BADPARAM ;
         IF .string [.p] EQL %C'.'
         THEN
             RETURN SS$_BADPARAM ;

         (4)WHILE ( .string [.p] GEQU %C'0' ) AND ( .string [.p] LEQU %C'9' )
         DO
             BEGIN
             address [.i] = .address [.i] * 10 + ( .string [.p] - %C'0' ) ;
             p = .p + 1 ;
             strlen = .strlen - 1 ;
             IF .strlen EQL 0
             THEN
                 EXITLOOP ;
             END ;

         (5)IF .strlen NEQ 0
         THEN
             BEGIN
             IF .string [.p] NEQ %C'.'
             THEN
                RETURN SS$_BADPARAM ;
             p = .p + 1 ;
             strlen = .strlen - 1 ;
             IF .strlen EQL 0
             THEN
                 RETURN SS$_BADPARAM ;
             END;
         END ;

     RETURN SS$_NORMAL ;
     END ;

   .
   .
   .
  1. Initialize the string variables to point to the beginning of the string.
  2. Initialize the next address byte to zero.
  3. Make sure each number contains at least one digit.
  4. Accumulate each digit until we reach a nondigit.
  5. Make sure the numbers terminate in a dot (except the last number).

8.2.10 Sample XTFT$A_CLOSE Routine

The XTFT$A_CLOSE routine initiates a series of operations that disconnect a connection and release the data structures associated with the link. Example 8-10 shows a sample implementation of the XTFT$A_CLOSE routine.

Example 8-10 Sample XTFT$A_CLOSE Routine

   .
   .
   .
GLOBAL ROUTINE DECW$$TCPIP_CLOSE( itcc : REF $BBLOCK VOLATILE) =

BEGIN

LOCAL
    tcc : REF $BBLOCK INITIAL( .itcc [ixtcc$a_tcc] ),
    status ;

(1)tcc [xtcc$v_dying] = 1 ;

(2)$CANCEL(           CHAN = .itcc [ixtcc$w_chan] ) ;
$DASSGN(           CHAN = .itcc [ixtcc$w_chan] ) ;
itcc [ixtcc$w_chan]  = 0 ;

(3)status = $DCLAST(  ASTADR = close_and_deallocate_ast,
                   ASTPRM = .itcc ) ;
.status
END ;
   .
   .
   .
  1. Mark the connection as dying, both to prevent the caller from requesting operations on this connection and to prevent the various completion AST routines from attempting to perform additional work.
  2. Cancel I/O and deassign the channel to the connection. This action completes all outstanding I/O operations to the connection and queues all completion ASTs. Further references to the channel are not permitted.
  3. Declare an AST to the CLOSE_AND_DEALLOCATE_AST routine that is executed after the completion ASTs. This routine performs the final cleanup operations such as structure invalidation and deallocation.

8.2.11 Sample CLOSE_AND_DEALLOCATE_AST Routine

The CLOSE_AND_DEALLOCATE_AST routine completes the connection close initiated by XTFT$A_CLOSE. Once this procedure executes, it is assumed that neither the transport caller nor any part of the transport will refer to this connection again. It is also assumed that all XTCBs have been returned to the communication queue structure (XTCQ).

Example 8-11 shows a sample implementation of the CLOSE_AND_DEALLOCATE_AST routine.

Example 8-11 Sample CLOSE_AND_DEALLOCATE_AST Routine

   .
   .
   .
ROUTINE close_and_deallocate_ast( itcc : REF $BBLOCK ) : NOVALUE =

BEGIN
BUILTIN
    REMQUE ;

LOCAL
    tdb : REF $BBLOCK INITIAL( .itcc [ixtcc$a_tdb] ),
    tpb : REF $BBLOCK INITIAL( .itcc [ixtcc$a_tpb] ),
    status ;

(1)REMQUE( .itcc, itcc ) ;
tdb [xtdb$l_ref_count] = .tdb [xtdb$l_ref_count] - 1 ;
(2)DECW$XPORT_DEALLOC_QUEUES( .itcc ) ;

(3)itcc [ixtcc$a_xport_table] = 0 ;

(4)DECW$XPORT_DEALLOC_PMEM( .itcc ) ;
DECW$XPORT_DEALLOC_PMEM( .tpb ) ;
END ;
   .
   .
   .
  1. Remove the IXTCC from the IXTCC queue in the XTDB and decrement the reference count in the XTDB.
  2. Deallocate the storage previously allocated for the connection queues.
  3. Zero the IXTCC$A_XPORT_TABLE field in the IXTCC to catch any subsequent references to the connection.
  4. Deallocate the IXTCC and XTPB connection structures. At this point, the connection is completely run down.

8.2.12 Sample XTFT$A_OPEN Routine

The XTFT$A_OPEN routine is invoked in executive mode to establish a connection to an X server.

Connections are usually established in inner mode. However, if your specific transport indicates (by an explicit return status of DECW$_STALL) that it is necessary to wait for a connection to be established across a network, DECW$XPORT_OPEN can wait in user mode for the open to complete. Waiting in user mode allows a user to press Ctrl/Y to exit the application in the event of a problem.

You can write your transport-specific XTFT$A_OPEN routine to either wait in executive mode (via a $QIOW call) or in user mode (via an asynchronous $QIO call) and use the return status of DECW$_STALL to tell the DECW$XPORT_OPEN routine which way to proceed. However, waiting in executive mode is discouraged. This example waits in user mode.

XTFT$A_OPEN uses three executive-mode ASTs to complete the connection sequence asynchronously. The last $QIO AST completion routine, OPEN_AST3, calls the transport-common DECW$$XPORT_OPEN_COMPLETE routine.

When DECW$XPORT_OPEN resumes, it drops back to user mode and then checks the status returned by XTFT$A_OPEN, as follows:

  • If XTFT$A_OPEN does return DECW$_STALL, DECW$XPORT_OPEN knows that the connection is not completely set up and calls the $SYNCH system service to wait. DECW$XPORT_OPEN uses an event flag and IOSB for this purpose.

    Note

    If your transport layer opens connections asynchronously, it is possible that multiple connection requests could be in progress at one time; that is, while one connection is waiting to complete, another connection could be initiated.
    If your application-specific routines were to allocate connection-specific variables, such as the IOSB used to hold the connection status, in an OWN program section, those variables could be overwritten by another connection.
    To prevent overwriting, the example XTFT$A_OPEN routine uses space on the IXTCC data structure to hold connection-specific variables such as the IOSB.
    Your specific transport can use the extra_context_length and extra_context_address arguments of the DECW$XPORT_ALLOC_INIT_QUEUES routine to allocate additional space. It is recommended that the IXTCC$Q_XPORT_RESERVED field be used to point to data in this area.

    When the connection is completely established, DECW$$XPORT_OPEN_COMPLETE sets the event flag and the IOSB to complete the wait.
  • If XTFT$A_OPEN does not return DECW$_STALL but does not return a failure status, DECW$XPORT_OPEN continues. This code path allows DECW$XPORT_OPEN to handle the case where XTFT$A_OPEN completes synchronously and therefore does not return DECW$_STALL.

For either case, as long XTFT$A_OPEN did not fail, DECW$XPORT_OPEN marks the connection as active in the XTCC.

Example 8-12 shows a sample implementation of the XTFT$A_OPEN routine.

Example 8-12 Sample DECW$$TCPIP_OPEN Routine

      .
      .
      .
    GLOBAL ROUTINE DECW$$TCPIP_OPEN( workstation : REF $BBLOCK, server, itcc : REF
    $BBLOCK ) =

    BEGIN
    BUILTIN
        REMQUE,
        INSQUE ;

    BIND
        tpb = .itcc [ixtcc$a_tpb] : $BBLOCK ;

    LOCAL
        socktype : INITIAL( (UCX$C_STREAM ^ 16) + UCX$C_TCP ),
        status,
        saved_wkstn_space,
        tcc : REF $BBLOCK,
        saved_wkstn_name : REF $BBLOCK,
        sockaddrin : $BBLOCK [SIN$S_SOCKADDRIN] PRESET(
            [SIN$W_FAMILY] = INET$C_AF_INET,
        (1)[SIN$W_PORT] = 0,
            [SIN$L_ADDR]  = swap_long( INET$C_INADDR_ANY ) ),
        sin_desc : VECTOR [2] INITIAL( %ALLOCATION( sockaddrin ), sockaddrin ),

    LABEL
        connect ;

   itcc [ixtcc$l_server_number] = .server;

(2) connect:
   BEGIN
       BEGIN
       !
       ! Check for node "0"
       !
    (3) IF .workstation [DSC$W_LENGTH] EQL 1 AND .(.workstation [DSC$A_POINTER])<0,8,0> EQL %C'0'
       THEN
           workstation = lnn_desc ;
       !
       ! Allocate the user modifiable memory...
       !
(4) status = DECW$XPORT_ALLOC_INIT_QUEUES( .itcc,
       .tcpip_tft[xtft$l_xtcc_length],
       .tpb [xtpb$w_srp_size],
       .tpb [xtpb$w_lrp_size],
       .tpb [xtpb$w_i_srp_count],
       .tpb [xtpb$w_i_lrp_count],
       .tpb [xtpb$w_o_srp_count],
       .tpb [xtpb$w_o_lrp_count],
       .workstation [DSC$W_LENGTH],
       saved_wkstn_space) ;

   IF NOT .status
   THEN
       RETURN .status ;
   tcc = .itcc[ixtcc$a_tcc] ;

(5) INSQUE( .itcc, tcpip_tdb [xtdb$a_itcc_flink] ) ;
   tcpip_tdb [xtdb$l_ref_count] = .tcpip_tdb [xtdb$l_ref_count] + 1 ;



      (6) CH$MOVE(        .workstation [DSC$W_LENGTH],
                   .workstation [DSC$A_POINTER],
                   .saved_wkstn_space ) ;

         saved_wkstn_name = itcc [ixtcc$q_xport_reserved] ;
         saved_wkstn_name [DSC$W_LENGTH]  = .workstation [DSC$W_LENGTH] ;
         saved_wkstn_name [DSC$A_POINTER] = .workstation [DSC$A_POINTER] ;


      (7) IF NOT (status = $assign(  DEVNAM = inet_dev_desc,
                                    CHAN = itcc [ixtcc$w_chan],
                                    ACMODE = psl$c_user ) )
       THEN
          LEAVE connect ;



   (8) status = $QIO(      EFN = .tcpip_tdb [xtdb$w_efn],
                          CHAN = .itcc [ixtcc$w_chan],
                          FUNC = IO$_SETMODE,
                          IOSB = itcc [ixtcc$q_iosb],
                          ASTADR = OPEN_AST1,
                          ASTPRM = .itcc,
                          P1 = socktype,
                          P2 = ( %X'01000000' OR INET$M_LINGER ),
                          P3 = sin_desc ) ;

   (9) XPORT_FAO('Open $QIO status = !XL, iosb = !XL', .status,
                                    .itcc [ixtcc$l_iosb]) ;


      IF NOT .status
      THEN
          LEAVE connect ;

    (10) RETURN DECW$_STALL ;

    (11) END;


    (12) IF .itcc [ixtcc$w_chan] NEQU 0
       THEN
           $DASSGN(        CHAN = .itcc [ixtcc$w_chan] ) ;

       REMQUE( .itcc, itcc ) ;
       tcpip_tdb [xtdb$l_ref_count] = .tcpip_tdb [xtdb$l_ref_count] - 1 ;

       RETURN .status ;
       END ;
      .
      .
      .
  1. Initialize the sockaddrin structure to request an Internet-protocol socket on any available port.
  2. Start a named block of code (connect) that attempts to allocate and initialize the resources needed to maintain a connection. If any part of this setup fails, the code block exits and failure processing recovers any allocated resources.
  3. If the transport caller requested a connection with a node-identifying string of "0", use the Internet name of the host as the node string.
  4. 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.
    Allocate extra space on the end of the IXTCC large enough to hold the workstation's name.
  5. Insert the IXTCC on the XTDB's queue of active connections so that the structure can be found if the rundown routine is invoked before the connection is fully started. Increment the XTDB$L_REF_COUNT field that tracks the number of connections using this transport.
  6. Save the workstation's name in the IXTCC so that the subsequent OPEN _AST routines are able to use the name. Use the IXTCC$Q_XPORT_RESERVED field as a string descriptor to the saved workstation name.
  7. Assign a channel and create a socket to the Internet networking service.
  8. Perform a SETMODE $QIO system service to establish the desired characteristics on the socket.
    ASTPRM is the location of the preallocated IXTCC passed to the XTFT$A_OPEN routine.
    The P1 argument specifies a stream-mode, TCP/IP socket.
    The P2 argument enables the "linger" option on the TCP/IP socket.
    The P3 argument provides port, address, and address-family information for the socket.
    If the $QIO completes successfully, the OPEN_AST1 completion routine continues the connection setup.
  9. Call the XPORT_FAO macro to output the status of the $QIO as a debugging check.
  10. Return the status DECW$_STALL to wait in user mode for the open processing to complete. OPEN_AST1 executes in executive mode when the $QIO completes.
  11. End of block named 'connect'.
  12. We reach here only if we encounter an error during connection setup. Deassign the channel and remove this connection from the list of known connections. The common layer deallocates the user memory allocated by DECW$XPORT_ALLOC_INIT_QUEUES.

8.2.13 Sample OPEN_AST1 Routine

OPEN_AST1 is invoked in executive mode when the IO$_SETMODE $QIO issued by the XTFT$A_OPEN routine completes. OPEN_AST1 continues processing to establish the client connection.

Example 8-13 shows a sample implementation of the OPEN_AST1 completion routine.

Example 8-13 Sample OPEN_AST1 Routine

   .
   .
   .
GLOBAL ROUTINE  OPEN_AST1( itcc : REF $BBLOCK ) : NOVALUE =

    BEGIN
    BUILTIN
        REMQUE;

    LOCAL
        net_addr_desc   : $BBLOCK[DSC$S_DSCDEF1] PRESET (
                                [DSC$W_LENGTH]  = ixtcc$s_server_addr - 1,
                                [DSC$B_CLASS]   = DSC$K_CLASS_S,
                                [DSC$B_DTYPE]   = DSC$K_DTYPE_T,
                                [DSC$A_POINTER] = itcc [ixtcc$t_server_addr] ),
        func_code       : INITIAL( INETACP_FUNC$C_GETHOSTBYNAME ),
        func_code_desc  : VECTOR [2] INITIAL( %ALLOCATION( func_code ), func_code ),
        status ;


    (1)status = .itcc [ixtcc$l_iosb] ;
    IF .status
    THEN

        (2)IF (status = $qio(      EFN = .tcpip_tdb [xtdb$w_efn],
                                CHAN = .itcc [ixtcc$w_chan],
                                FUNC = IO$_ACPCONTROL,
                                IOSB = itcc [ixtcc$q_iosb],
                                ASTADR = OPEN_AST2,
                                ASTPRM = .itcc,
                                P1 = func_code_desc,
                                P2 = itcc [ixtcc$q_xport_reserved],
                                P3 = itcc [ixtcc$l_server_addr_len],
                                P4 = net_addr_desc ) )
        THEN
            !
            ! Let OPEN_AST2 complete the connection setup.
            !
            (3)RETURN ;


    (4)$DASSGN( CHAN = .itcc [ixtcc$w_chan] ) ;

    REMQUE( .itcc, itcc ) ;
    tcpip_tdb [xtdb$l_ref_count] = .tcpip_tdb [xtdb$l_ref_count] - 1 ;

    DECW$$XPORT_OPEN_COMPLETE( .itcc, .status ) ;

    RETURN;
    END ;
   .
   .
   .
  1. Check the status of the SETMODE $QIO operation that just completed.
  2. Get the address of the remote server by attempting to perform a name-to-address conversion with an IO$_ACPCONTROL $QIO system service that queries the UCX host database. The IO$_ACPCONTROL arguments are as follows:
    • P1 specifies the function to be performed by the ACPCONTROL $QIO, which in this case requests a get-host-by-name conversion.
    • P2 is the address of a descriptor of the host name to search for in the host database.
    • P3 is the address to receive the length of the returned address string.
    • P4 is the address of the descriptor of the storage to receive the address found by the search.

    If the $QIO completes successfully, the OPEN_AST2 AST completion routine continues the connection setup.
  3. Dismiss the executive-mode AST. The process will continue to wait in user mode.
  4. An error occurred, either during the SETMODE $QIO or while checking the arguments to the get-host-by-name call. Deassign the channel to UCX, remove the connection from the list of known connections, and call the transport common DECW$$XPORT_OPEN_COMPLETE routine with the failure status. The transport-common layer deallocates the user memory allocated by DECW$XPORT_ALLOC_INIT_QUEUES.

8.2.14 Sample OPEN_AST2 Routine

OPEN_AST2 is invoked in executive mode when the IO$_ACPCONTROL $QIO issued by the OPEN_AST1 routine completes. OPEN_AST2 converts the text result to an address and attempts to connect to the workstation.

Example 8-14 shows a sample implementation of the OPEN_AST2 completion routine.

Example 8-14 Sample OPEN_AST2 Routine

   .
   .
   .
GLOBAL ROUTINE OPEN_AST2( itcc : REF $BBLOCK ) : NOVALUE =

    BEGIN
    BUILTIN
        REMQUE ;

    BIND
        workstation = itcc [ixtcc$q_xport_reserved] : $BBLOCK[DSC$S_DSCDEF1] ;

    LOCAL
        status,
        net_addr_desc   : $BBLOCK[DSC$S_DSCDEF1] PRESET (
                                [DSC$W_LENGTH]  = .itcc [ixtcc$l_server_addr_len],
                                [DSC$B_CLASS]   = DSC$K_CLASS_S,
                                [DSC$B_DTYPE]   = DSC$K_DTYPE_T,
                                [DSC$A_POINTER] = itcc [ixtcc$t_server_addr] ),
        sockaddrin : $BBLOCK [SIN$S_SOCKADDRIN] PRESET(
            [SIN$W_FAMILY]      = INET$C_AF_INET ),
        sin_desc : VECTOR [2] INITIAL( %ALLOCATION( sockaddrin ), sockaddrin ),


    LABEL
         connect;

connect:
    BEGIN

    (1)status = .itcc [ixtcc$l_iosb] ;
    IF NOT .status
    THEN
        IF .status NEQU SS$_ENDOFFILE
        THEN
            LEAVE connect
        (2)ELSE
            BEGIN

            IF .workstation [DSC$W_LENGTH] GEQU ixtcc$s_server_addr

            THEN
                BEGIN
                status = DECW$_INVSRVNAM ;
                LEAVE connect ;
                END ;

            CH$MOVE(    .workstation [DSC$W_LENGTH],
                        .workstation [DSC$A_POINTER],
                        itcc [ixtcc$t_server_addr] ) ;

            net_addr_desc [DSC$W_LENGTH] = .workstation [DSC$W_LENGTH] ;
            END ;


            (3)status = parse_internet_address( net_addr_desc,
                                                 sockaddrin [SIN$L_ADDR] );
            IF NOT .status
            THEN
                BEGIN
                status = DECW$_INVSRVNAM ;
                LEAVE connect ;
                END;


    (4)sockaddrin [SIN$W_PORT] =
        SWAP_SHORT( ( BASE_TCP_PORT + .itcc [ixtcc$l_server_number] ) ) ;

    (5)status = $QIO(      EFN = .tcpip_tdb [xtdb$w_efn],
                        CHAN = .itcc [ixtcc$w_chan],
                        FUNC = IO$_ACCESS,
                        IOSB = itcc [ixtcc$q_iosb],
                        ASTADR = OPEN_AST3,
                        ASTPRM = .itcc,
                        P3 = sin_desc ) ;
    IF NOT .status
    THEN
        LEAVE connect ;

    (6)RETURN ;

    (7)END;

    (8)$DASSGN( CHAN = .itcc [ixtcc$w_chan] ) ;

    REMQUE( .itcc, itcc ) ;
    tcpip_tdb [xtdb$l_ref_count] = .tcpip_tdb [xtdb$l_ref_count] - 1 ;

    DECW$$XPORT_OPEN_COMPLETE( .itcc, .status ) ;

    RETURN;
    END ;
   .
   .
   .


Previous Next Contents Index