Address multi-threading issues in SI95
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / siclose.c
1 // vim: noet sw=4 ts=4:
2 /*
3 ==================================================================================
4     Copyright (c) 2020 Nokia
5     Copyright (c) 2020 AT&T Intellectual Property.
6
7    Licensed under the Apache License, Version 2.0 (the "License");
8    you may not use this file except in compliance with the License.
9    You may obtain a copy of the License at
10
11        http://www.apache.org/licenses/LICENSE-2.0
12
13    Unless required by applicable law or agreed to in writing, software
14    distributed under the License is distributed on an "AS IS" BASIS,
15    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16    See the License for the specific language governing permissions and
17    limitations under the License.
18 ==================================================================================
19 */
20
21 /*
22 ******************************************************************************
23 *
24 *  Mnemonic: SIclose
25 *  Abstract: This routine allows the user application to close a port
26 *            associated with a file descriptor. The port is unbound from
27 *            the transport providor even if it is marked as a listen
28 *            port. If the fd passed in is less than 0 this routine assumes
29 *            that the UDP port opened during init is to be closed (user never
30 *            receives a fd on this one).
31 *  Parms:    gptr - The pointer to the ginfo block (SIHANDLE to the user)
32 *            fd   - FD to close.
33 *  Returns:  SI_OK if all goes well, SI_ERROR with SIerrno set if there is
34 *            a problem.
35 *  Date:     3 February 1995
36 *  Author:   E. Scott Daniels
37 *
38 *  Modified:i   19 Feb 1995 - To set TP blk to drain if output pending.
39 *                               10 May 1995 - To change SOCK_RAW to SOCK_DGRAM
40 *                               22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd
41 ******************************************************************************
42 */
43 #include "sisetup.h"
44
45 extern int SIclose( struct ginfo_blk *gptr, int fd ) {
46         struct tp_blk *tpptr;      //  pointer into tp list 
47         int status = SI_ERROR;     //  status of processing 
48
49         if( gptr != NULL ) {
50                 if( fd >= 0 ) {                                         //  if caller knew the fd number 
51                         if( fd < MAX_FDS ) {                    // straight from map if possible
52                                 tpptr = gptr->tp_map[fd];
53                         } else {
54                                 // future: need to lock the list or switch to gmax hash
55                                 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next );   //  find the tppblock to close
56                         }
57                 } else {  //  user did not know the fd - find first Listener or UDP tp blk 
58                         if( fd == TCP_LISTEN_PORT ) {                   //  close first tcp listen port; else first udp 
59                                 for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next );   
60                         } else {
61                                 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next );
62                         }
63                 }
64
65                 if( tpptr != NULL ) {
66                         if( tpptr->squeue == NULL ) {   //  if nothing is queued to send... 
67                                 tpptr->flags |= TPF_UNBIND;   //  ensure port is unbound from tp 
68                                 tpptr->flags |= TPF_DELETE;
69                                 {
70                                         int x = 1;
71                                         setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ;
72                                 }
73         
74                                 SIterm( gptr, tpptr );          // close the fd and mark the block as deletable
75                         } else {
76                                 tpptr->flags |= TPF_DRAIN;   //  stuff on queue, must drain before closing
77                         }
78         
79                         status = SI_OK;               //  give caller a good status 
80                 }                              //  end if we found a tpptr 
81         }
82
83         return status;                 //  send the status back to the caller 
84 }                                  //  SIclose 
85