128c1a7ecf4b15355fe1f8186e4506a5e5a45a78
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / siwait.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 *  Mnemonic: SIwait
24 *  Abstract: This  routine will wait for an event to occur on the
25 *            connections in tplist. When an event is received on a fd
26 *            the status of the fd is checked and the event handled, driving
27 *            a callback routine if necessary. The system call poll is usd
28 *            to wait, and will be interrupted if a signal is caught,
29 *            therefore the routine will handle any work that is required
30 *            when a signal is received. The routine continues to loop
31 *            until the shutdown flag is set, or until there are no open
32 *            file descriptors on which to wait.
33 *  Parms:    gptr - Pointer to the global information block
34 *  Returns:  SI_OK if the caller can continue, SI_ERROR if all sessions have been
35 *            stopped, or the interface cannot proceed. When SI_ERROR is
36 *            returned the caller should cleanup and exit immediatly (we
37 *            have probably received a sigter or sigquit.
38 *  Date:     28 March 1995
39 *  Author:   E. Scott Daniels
40 *
41 *  Modified: 11 Apr 1995 - To pass execption to select when no keyboard
42 *            19 Apr 1995 - To call do key to do better keyboard editing
43 *            18 Aug 1995 - To init kstat to 0 to prevent key hold if
44 *                          network data pending prior to entry.
45 *                       31 Jul 2016 - Major formatting clean up in the main while loop.
46 **************************************************************************
47 */
48 #include  "sisetup.h"     //  get the setup stuff 
49 #include "sitransport.h"
50 #include        <sys/wait.h>
51
52 /*
53         The select timeout is about 300 mu-sec. This is fast enough to add a new
54         outbound connection to the poll list before the other side responds,
55         but slow enough so as not to consume excess CPU when idle.
56 */
57 #define SI_SELECT_TIMEOUT 300000
58
59 extern int SIwait( struct ginfo_blk *gptr ) {
60         int fd;                                                 //  file descriptor for use in this routine 
61         int ((*cbptr)());                               //  pointer to callback routine to call 
62         int status = SI_OK;                             //  return status 
63         int addrlen;                                    //  length of address from recvfrom call 
64         int i;                                                  //  loop index 
65         struct tp_blk *tpptr;                   //  pointer at tp stuff 
66         struct tp_blk *nextone;                 //  point at next block to process in loop 
67         int pstat;                                              //  poll status 
68         struct timeval  timeout;                //  delay to use on select call
69         char *buf;
70         char *ibuf;
71
72         ibuf = (char *) malloc( 2048 );
73
74         if( gptr->flags & GIF_SHUTDOWN ) {                              //  cannot do if we should shutdown 
75                 free( ibuf );
76                 return SI_ERROR;                                                        //  so just get out 
77         }
78
79         if( gptr->magicnum != MAGICNUM ) {                              //  if not a valid ginfo block 
80                 rmr_vlog( RMR_VL_CRIT, "SI95: wait: bad global info struct magic number is wrong\n" );
81                 return SI_ERROR;
82         }
83
84         do {                                                                    // spin until a callback says to stop (likely never)
85                 timeout.tv_sec = 0;                                     // must be reset on every call!
86                 timeout.tv_usec = SI_SELECT_TIMEOUT;
87
88                 SIbldpoll( gptr );                                      // poll list is trashed on each pop; must rebuild
89                 pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds, &gptr->execpfds, &timeout );
90
91                 if( (pstat < 0 && errno != EINTR)  ) {
92                         gptr->fdcount = 0;                              //  prevent trying to look at a session 
93                         gptr->flags |= GIF_SHUTDOWN;    //  cause cleanup and exit at end 
94                 }
95
96                 if( pstat > 0  &&  (! (gptr->flags & GIF_SHUTDOWN)) ) {
97                         tpptr = gptr->tplist; 
98                         while( tpptr != NULL ) { 
99                                 nextone = tpptr->next;                          //  prevent issues if we delete the block during loop 
100
101                                 if( tpptr->fd >= 0 ) {
102                                         if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) ) {
103                                                 SIsend( gptr, tpptr );                  //  send if clear to send 
104                                         }
105         
106                                         if( FD_ISSET( tpptr->fd, &gptr->execpfds ) ) {
107                                                         ;                               // sunos seems to set the except flag for unknown reasons; ignore it
108                                         } else {
109                                                 if( FD_ISSET( tpptr->fd, &gptr->readfds ) ) {                   // ready to read
110                                                         fd = tpptr->fd;
111                                                         tpptr->rcvd++;
112         
113                                                         if( tpptr->flags & TPF_LISTENFD ) {                                     // new session request
114                                                                 errno=0;
115                                                                 status = SInewsession( gptr, tpptr );                   // accept connection
116                                                         } else  {                                                                                       //  data received on a regular port (we support just tcp now
117                                                                 status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 );   //  read data 
118                                                                 if( status > 0  &&  ! (tpptr->flags & TPF_DRAIN) ) {
119                                                                         if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL ) {
120                                                                                 status = (*cbptr)( gptr->cbtab[SI_CB_CDATA].cbdata, fd, gptr->rbuf, status );
121                                                                                 SIcbstat( gptr, status, SI_CB_CDATA );  //  handle cb status 
122                                                                         }
123                                                                 } else {                                                                                // no bites, but read flagged indicates disconnect
124                                                                         if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL ) {
125                                                                                 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
126                                                                                 SIcbstat( gptr, status, SI_CB_DISC );   //  handle status 
127                                                                         }
128                                                                         SIterm( gptr, tpptr );                  // close FD and mark block for deletion
129                                                                 }
130                                                         }
131                                                 }
132                                         }
133                                 }                                                               //  if still good fd 
134
135                                 tpptr = nextone;
136                         }
137                 }
138         } while( gptr->tplist != NULL && !(gptr->flags & GIF_SHUTDOWN) );
139
140         free( ibuf );
141         if( gptr->tplist == NULL )                                      //  indicate all fds closed 
142
143         if( gptr->flags & GIF_SHUTDOWN ) {                      //  we need to stop for some reason 
144                 status = SI_ERROR;                                              //  status should indicate to user to die 
145                 SIshutdown( gptr );                                             //  clean things up 
146         } else {
147                 status = SI_OK;                                                 //  user can continue to process 
148         }
149
150         return status;
151 }