#module IPC_COMMON /* ************************************************************************** * Copyright (C) 1990 by * * DIGITAL Equipment Corporation, Maynard, Mass. * * * * This software is furnished under a license and may be used and copied * * only in accordance with the terms of such license and with the * * inclusion of the above copyright notice. This software or any other * * copies thereof may not be provided or otherwise made available to any * * other person. No title to or ownership of the software is hereby * * transferred. * * * * The information in this software is subject to change without notice * * and should not be construed as a commitment by DIGITAL Equipment * * Corporation. * * * * DIGITAL assumes no responsibility for the use or reliability of its * * software on equipment which is not supplied by DIGITAL. * * * ************************************************************************** */ /* * * FACILITY: * * DECnet-Vax OSI IPC Example Programs * * ABSTRACT: * * This module contains common routines to handle IPC network item lists * and the IPCB (InterProcess communication Context Block). It is linked * into both the IPC client (IPC_CLIENT.EXE) and server (IPC_SERVER.EXE) * example images. * * AUTHOR: * * MwD * * CREATION DATE: Dec-1991 * * MODIFICATION HISTORY: * * * X-08 MWD0047 MwD 05-Feb-1993 * findnext should return DATA length, not item length. * * X-07 MWD0045 MwD 11-Jan-1992 * Add item_list__findnext(). * * X-06 LES0074 LES 15-Jul-1992 * Fix edit history * * X-05 LES0070 LES 08-Jun-1992 * Merge gen 4n1 changes with mainline to incorporate * symbol name changes * * X-04N1 LES0070 LES 14-May-1992 * Change structure name IPCBDEF to NET$IPCBDEF * * X-00 MWD0000 MwD Dec-1991 * Creation. * */ #include #include #include "ipc_def.h" /* * * FUNCTIONAL DESCRIPTION: * * Clear an IPCB explictly ( as opposed to allocating it with memset() ). * * FORMAL PARAMETERS: * * INPUT * Ipcb_P : address of IPCB structure * * OUTPUT * * ROUTINE_VALUE: * * None * * SIDE EFFECTS: * * None */ void clear_ipcb( struct NET$IPCBDEF *Ipcb_P ) { Ipcb_P->IPCB$R_IPCBFLAGS.IPCB$L_FLAGS = Ipcb_P->IPCB$L_ASSOCIATIONID = Ipcb_P->IPCB$L_CONNECTIONID = Ipcb_P->IPCB$L_RQSTID = Ipcb_P->IPCB$L_BUFFER_LENGTH = Ipcb_P->IPCB$L_REPLY_LENGTH = Ipcb_P->IPCB$L_ASSOCIATION_CONTEXT = Ipcb_P->IPCB$L_CONNECTION_CONTEXT = 0; Ipcb_P->IPCB$A_BUFFER = Ipcb_P->IPCB$A_REPLY_BUFFER = NULL; Ipcb_P->IPCB$R_INPUTLSTDESC.IPCB$Q_INPUTLST_DESC[ 0 ] = 0; Ipcb_P->IPCB$R_OUTPUTLSTDESC.IPCB$Q_OUTPUTLST_DESC[ 0 ] = 0; Ipcb_P->IPCB$R_TEMPLATELSTDESC.IPCB$Q_TEMPLATELST_DESC[ 0 ] = 0; Ipcb_P->IPCB$R_INPUTLSTDESC.IPCB$Q_INPUTLST_DESC[ 1 ] = 0; Ipcb_P->IPCB$R_OUTPUTLSTDESC.IPCB$Q_OUTPUTLST_DESC[ 1 ] = 0; Ipcb_P->IPCB$R_TEMPLATELSTDESC.IPCB$Q_TEMPLATELST_DESC[ 1 ] = 0; } /* * * FUNCTIONAL DESCRIPTION: * * Allocate an item list and initialize OUR control structure. * * FORMAL PARAMETERS: * * INPUT * Size : Number of bytes to reserve for the item list, EXCLUDING * size of control structure. * * OUTPUT * * ROUTINE_VALUE: * * Address of allocated VM, or 0. ( Returns malloc()'s return value. ) * * SIDE EFFECTS: * * Head of allocated memory contains our control structure. NOT an * item list. As such, this function's returned address CANNOT be passed * to $IPC. See the item_list__to_desc() function. */ void *item_list__new( unsigned int Size ) { IPC_ITEM_LIST_T *ItemList_P; /* * Add room for the control structure, and allocate VM. * If successful, init the control fields. * Return malloc's status. */ ItemList_P = (IPC_ITEM_LIST_T *)malloc(Size + IPC_K_ITEM_CNTRL_LENGTH); if( ItemList_P != NULL ) { ItemList_P->max_length = Size; ItemList_P->cur_length = 0; ItemList_P->next_item = (IPC_ITEM_T *)ItemList_P->list_head; } return( (void *)ItemList_P ); } /* * * FUNCTIONAL DESCRIPTION: * * Add an item to an IPC network item list. * * FORMAL PARAMETERS: * * INPUT * ItemList_P : Address of the list control structure * Length : Length in bytes of this item's data value * Tag : Tag of this item * Value_P : Address of the data value * * OUTPUT * * ROUTINE_VALUE: * * IPC_S_ITEM_SUCCESS, or IPC_S_ITEM_NO_ROOM if it won't fit. * * SIDE EFFECTS: * * None */ int item_list__add( IPC_ITEM_LIST_T *ItemList_P, unsigned short Length, unsigned short Tag, char *Value_P ) { unsigned short int Total_Length; /* * If it fits, add it in and update the control fields. * Remember, an IPC item list LENGTH field contains the length of the * ENTIRE item, including the length and tag fields. We were passed * the length of the data only. * * For example, to add a longword to a list, the caller would pass * Length = 4, but we set the IPC item length field = 8. */ Total_Length = Length + IPC_K_ITEM_HDR_LENGTH; if( Total_Length <= (ItemList_P->max_length - ItemList_P->cur_length) ) { ItemList_P->next_item->length = Total_Length; ItemList_P->next_item->tag = Tag; if( Length != 0 ) memcpy( ItemList_P->next_item->value_buffer, Value_P, Length ); ItemList_P->cur_length += Total_Length; (char *)ItemList_P->next_item += Total_Length; return( IPC_S_ITEM_SUCCESS ); } else return( IPC_S_ITEM_NO_ROOM ); } /* * * FUNCTIONAL DESCRIPTION: * * Return the next item in the list. * * FORMAL PARAMETERS: * * INPUT * ItemList_P : Address of item list control structure * * OUTPUT * Length : Length in bytes of this item's DATA value, * not the item's length * Tag : Tag of this item * Value_P : Address of the data value * * * IMPLICIT * next_item field is used and updated by this routine. * * ROUTINE_VALUE: * * IPC_S_ITEM_SUCCESS, NO_ROOM * * SIDE EFFECTS: * * None */ int item_list__findnext( IPC_ITEM_LIST_T *ItemList_P, unsigned short *Length, unsigned short *Tag, void **Value_P ) { unsigned int Offset; /* * Check that the current item, then its data, both are actually * in the list. */ Offset = (char *)ItemList_P->next_item - ItemList_P->list_head; if ( Offset + IPC_K_ITEM_HDR_LENGTH > ItemList_P->cur_length ) return( IPC_S_ITEM_NO_ROOM ); if ( (Offset + ItemList_P->next_item->length) > ItemList_P->cur_length ) return( IPC_S_ITEM_NO_ROOM ); else { *Length = ItemList_P->next_item->length - IPC_K_ITEM_HDR_LENGTH; *Tag = ItemList_P->next_item->tag; *Value_P = (void *)(ItemList_P->next_item->value_buffer); (char *)ItemList_P->next_item += ItemList_P->next_item->length; } return( IPC_S_ITEM_SUCCESS ); } /* * * FUNCTIONAL DESCRIPTION: * * Walk through an item list and print its contents to sdtout. * * FORMAL PARAMETERS: * * INPUT * ItemList_P : address of item list control structure * * OUTPUT * * ROUTINE_VALUE: * * None * * SIDE EFFECTS: * * None */ void item_list__dump( IPC_ITEM_LIST_T *ItemList_P ) { unsigned char *Eob_P, *Cur_P; IPC_ITEM_T *Item_P; unsigned short Value_Length, I; printf( "Length\tTag\tValue\n------\t---\t-----\n" ); Eob_P = ItemList_P->list_head + ItemList_P->cur_length; Cur_P = ItemList_P->list_head; do { Item_P = (IPC_ITEM_T *)Cur_P; Value_Length = Item_P->length - IPC_K_ITEM_HDR_LENGTH; printf( "%d\t%d\t", Item_P->length, Item_P->tag ); /* * If the length is 1,2, or 4 bytes, interpret the data * as a number. */ switch( Value_Length ) { case 1: printf( "%d - ", *(char *)Item_P->value_buffer ); break; case 2: printf( "%d - ", *(short *)Item_P->value_buffer ); break; case 4: printf( "%d - ", *(int *)Item_P->value_buffer ); break; } /* * Now interpret it as a printable character string. */ I = 0; while( I < Value_Length ) { printf( "%c", Item_P->value_buffer[ I ] ); I++; } printf( "\n" ); Cur_P += Item_P->length; } while( Cur_P < Eob_P ); } /* * * FUNCTIONAL DESCRIPTION: * * Set up an item list descriptor in an IPCB to point to an item list. * If the list's current length is 0, use its max length * ( for output lists descriptors ). * * FORMAL PARAMETERS: * * INPUT * ItemList_P : address of our item list control structure * Desc_P : address of an IPCB (VMS) decriptor * * OUTPUT * * ROUTINE_VALUE: * * None * * SIDE EFFECTS: * * NOTE: Assumption that IPCB descriptor fields overlay VMS descriptor * fields. */ void item_list__to_desc( IPC_ITEM_LIST_T *ItemList_P, struct dsc$descriptor *Desc_P ) { Desc_P->dsc$a_pointer = ItemList_P->list_head; Desc_P->dsc$w_length = (ItemList_P->cur_length == 0) ? ItemList_P->max_length : ItemList_P->cur_length; } /* * * FUNCTIONAL DESCRIPTION: * * Adjust an item list control block after IPC output. Set up the total * length and the next_item field, in preparation for calls to findnext. * * FORMAL PARAMETERS: * * INPUT * ItemList_P : address of item list control structure * Ipcb_P : address of IPCB structure * * OUTPUT * * ROUTINE_VALUE: * * None * * SIDE EFFECTS: * * None */ void item_list__output( IPC_ITEM_LIST_T *ItemList_P, struct NET$IPCBDEF *Ipcb_P ) { ItemList_P->cur_length = Ipcb_P->IPCB$W_RET_OUTPUTLST_LENGTH; ItemList_P->next_item = (IPC_ITEM_T *)ItemList_P->list_head; } /* * * FUNCTIONAL DESCRIPTION: * * Reset an item list control block ( and optionally an IPCB descriptor ). * * FORMAL PARAMETERS: * * INPUT * ItemList_P : address of item list control structure * Desc_P : address of IPCB item list descriptor, or NULL * * OUTPUT * * ROUTINE_VALUE: * * None * * SIDE EFFECTS: * * None */ void item_list__clear( IPC_ITEM_LIST_T *ItemList_P, struct dsc$descriptor *Desc_P ) { ItemList_P->cur_length = 0; ItemList_P->next_item = (IPC_ITEM_T *)ItemList_P->list_head; if( Desc_P != NULL ) { Desc_P->dsc$w_length = 0; Desc_P->dsc$a_pointer = NULL; } } /* * * FUNCTIONAL DESCRIPTION: * * Deallocate memory used for an item list. * * FORMAL PARAMETERS: * * INPUT * ItemListP : address of item list control structure * * OUTPUT * * ROUTINE_VALUE: * * IPC_S_ITEM_SUCCESS, or IPC_S_ITEM_FAILED_FREE if free() fails. * * SIDE EFFECTS: * * None */ int item_list__free( IPC_ITEM_LIST_T *ItemList_P ) { if( free( ItemList_P ) == 0 ) return( IPC_S_ITEM_SUCCESS ); else return( IPC_S_ITEM_FAILED_FREE ); }