Address multi-threading issues in SI95
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / siclose.c
index cb5cf36..eed11ef 100644 (file)
@@ -18,7 +18,7 @@
 ==================================================================================
 */
 
-/* X
+/*
 ******************************************************************************
 *
 *  Mnemonic: SIclose
 *  Date:     3 February 1995
 *  Author:   E. Scott Daniels
 *
-*  Modified: 19 Feb 1995 - To set TP blk to drain if output pending.
-*            10 May 1995 - To change SOCK_RAW to SOCK_DGRAM
-*              22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd
+*  Modified: 19 Feb 1995 - To set TP blk to drain if output pending.
+*                              10 May 1995 - To change SOCK_RAW to SOCK_DGRAM
+*                              22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd
 ******************************************************************************
 */
 #include "sisetup.h"
 
-extern int SIclose( struct ginfo_blk *gptr, int fd )
-{
-
- struct tp_blk *tpptr;      //  pointer into tp list 
- int status = SI_ERROR;     //  status of processing 
-
- gptr->sierr = SI_ERR_HANDLE;
- if( gptr->magicnum == MAGICNUM )   //  good cookie at the gptr address? 
-  {
-   gptr->sierr = SI_ERR_SESSID;
-
-   if( fd >= 0 )     //  if caller knew the fd number 
-    {
-     for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd;
-          tpptr = tpptr->next );   //  find the tppblock to close 
-    }
-   else  //  user did not know the fd - find first Listener or UDP tp blk 
-   {
-       if( fd == TCP_LISTEN_PORT )                     //  close first tcp listen port; else first udp 
-               for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next );   
-       else
-               for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next );
-   }
+extern int SIclose( struct ginfo_blk *gptr, int fd ) {
+       struct tp_blk *tpptr;      //  pointer into tp list 
+       int status = SI_ERROR;     //  status of processing 
 
-   if( tpptr != NULL )
-    {
-     gptr->sierr = SI_ERR_TP;
+       if( gptr != NULL ) {
+               if( fd >= 0 ) {                                         //  if caller knew the fd number 
+                       if( fd < MAX_FDS ) {                    // straight from map if possible
+                               tpptr = gptr->tp_map[fd];
+                       } else {
+                               // future: need to lock the list or switch to gmax hash
+                               for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next );   //  find the tppblock to close
+                       }
+               } else {  //  user did not know the fd - find first Listener or UDP tp blk 
+                       if( fd == TCP_LISTEN_PORT ) {                   //  close first tcp listen port; else first udp 
+                               for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next );   
+                       } else {
+                               for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next );
+                       }
+               }
 
-     if( tpptr->squeue == NULL )   //  if nothing is queued to send... 
-      {
-       tpptr->flags |= TPF_UNBIND;   //  ensure port is unbound from tp 
-       tpptr->flags |= TPF_DELETE;
-       {
-               int x = 1;
-
-               setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ;
+               if( tpptr != NULL ) {
+                       if( tpptr->squeue == NULL ) {   //  if nothing is queued to send... 
+                               tpptr->flags |= TPF_UNBIND;   //  ensure port is unbound from tp 
+                               tpptr->flags |= TPF_DELETE;
+                               {
+                                       int x = 1;
+                                       setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ;
+                               }
+       
+                               SIterm( gptr, tpptr );          // close the fd and mark the block as deletable
+                       } else {
+                               tpptr->flags |= TPF_DRAIN;   //  stuff on queue, must drain before closing
+                       }
+       
+                       status = SI_OK;               //  give caller a good status 
+               }                              //  end if we found a tpptr 
        }
-       close( tpptr->fd );
-       tpptr->fd = -1;
-       tpptr->type = -1;
-                       //  siterm now called in build poll if tp is marked delete 
-       // SIterm( gptr, gptr, tpptr );*/        /* cleanup and remove from the list 
-      }
-     else                              //  stuff queued to send - mark port to drain 
-      tpptr->flags |= TPF_DRAIN;   //  and we will term the port when q empty 
-
-     status = SI_OK;               //  give caller a good status 
-    }                              //  end if we found a tpptr 
-  }                                //  end if the handle was good 
 
return( status );                 //  send the status back to the caller 
      return status;                 //  send the status back to the caller 
 }                                  //  SIclose 
+