X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Frmr%2Fsi%2Fsrc%2Fsi95%2Fsiterm.c;h=ce4874882dfc562ab3c6385b7b1adc3f88dbd834;hb=fcea3951d44de0cc55d33c5e114487abe79d3406;hp=0b74ba0018a3a5dc70ed03866500fc5cf7b87830;hpb=ec88d3c0563eeb6ae5f73427edb0b3c4d7acf299;p=ric-plt%2Flib%2Frmr.git diff --git a/src/rmr/si/src/si95/siterm.c b/src/rmr/si/src/si95/siterm.c index 0b74ba0..ce48748 100644 --- a/src/rmr/si/src/si95/siterm.c +++ b/src/rmr/si/src/si95/siterm.c @@ -20,45 +20,90 @@ /* ************************************************************************** -* Mnemonic: SIterm -* Abstract: This routine will terminate a session based on the tp_blk -* that is passed into the routine. The transport session block -* is released and removed from the ginfo list. The session is -* terminated by issuing a t_unbind call (if the unbind flag is -* on in the tpptr block), and then issuing a t_close. -* Parms: gptr - Pointer to the global information block -* tpptr - Pointer to tp block that defines the open fd. -* Returns: Nothing. -* Date: 18 January 1995 -* Author: E. Scott Daniels +* Mnemonic: SIterm +* Abstract: Manage the transport provider block information relating to +* the need to terminate the session. The block is left in the +* list; it is unsafe to clean the lsit up outside of the SIwait +* thread. When safe, the SIrm_tpb() function can be called to +* do the rest of the work that was originally done by SIterm. +* +* Date: 18 January 1995 +* Author: E. Scott Daniels * ************************************************************************** */ -#include "sisetup.h" // get the setup stuff +#include "sisetup.h" // get the setup stuff #include "sitransport.h" + +/* + Abort the connection in such a way that there is no resulting time-wait state. + This should be used cautiously but is needed for situations like when the Linux + connect() system call manages to connect us to ourselves through the even number + port bug. + + This needs a real file desc as there may not yet be a transport block when + the connection may need to be aborted. For this reason, the function name is + lower case indicating that user programmes are discouraged from using this + function directly. +*/ +extern void siabort_conn( int fd ) { + struct linger opt_val; // value passed as option to set call + + opt_val.l_onoff = 1; // MUST set linger on with a zero len timeout + opt_val.l_linger = 0; + + setsockopt( fd, SOL_SOCKET, SO_LINGER, &opt_val, sizeof( opt_val ) ); // disable linger to prevent time-wait + CLOSE( fd ); // close will now abort and not result in time-wait (do NOT use shutdown() first!) +} + +/* + Close the FD and mark the transport block as unusable/closed. + Removal of the block from the list is safe only from the siwait + thread. If the abort flag is set in the transport block, then the + connection is aborted (reset). +*/ extern void SIterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) { if( tpptr != NULL ) { if( tpptr->fd >= 0 ) { - CLOSE( tpptr->fd ); + if( tpptr->flags & TPF_ABORT ) { + siabort_conn( tpptr->fd ); + } else { + CLOSE( tpptr->fd ); + } + if( tpptr->fd < MAX_FDS ) { gptr->tp_map[tpptr->fd] = NULL; // drop reference } } - if( tpptr->prev != NULL ) { // remove from the list - tpptr->prev->next = tpptr->next; // point previous at the next - } else { - gptr->tplist = tpptr->next; // this was head, make next new head - } + tpptr->fd = -1; // prevent future sends etc. + tpptr->flags |= TPF_DELETE; // signal block deletion needed when safe + } +} - if( tpptr->next != NULL ) { - tpptr->next->prev = tpptr->prev; // point next one back behind this one +/* + It is safe to remove the block from the list; if it was in the list + in the first place. +*/ +extern void SIrm_tpb( struct ginfo_blk *gptr, struct tp_blk *tpptr ) { + + if( tpptr != NULL ) { + if( tpptr->prev != NULL || tpptr->next != NULL ) { // in the list + if( tpptr->prev != NULL ) { // remove from the list + tpptr->prev->next = tpptr->next; // point previous at the next + } else { + gptr->tplist = tpptr->next; // this was head, make next new head + } + + if( tpptr->next != NULL ) { + tpptr->next->prev = tpptr->prev; // point next one back behind this one + } } - free( tpptr->addr ); // release the address bufers + free( tpptr->addr ); // release the address bufers free( tpptr->paddr ); - free( tpptr ); // and release the block + free( tpptr ); // and release the block } }