Add dynamic route table update to SI95 support
[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 extern int SIwait( struct ginfo_blk *gptr ) {
54         int fd;                                                 //  file descriptor for use in this routine 
55         int ((*cbptr)());                               //  pointer to callback routine to call 
56         int status = SI_OK;                             //  return status 
57         int addrlen;                                    //  length of address from recvfrom call 
58         int i;                                                  //  loop index 
59         struct tp_blk *tpptr;                   //  pointer at tp stuff 
60         struct tp_blk *nextone;                 //  point at next block to process in loop 
61         int pstat;                                              //  poll status 
62         struct timeval  timeout;                //  delay to use on select call
63         char *buf;
64         char *ibuf;
65
66         ibuf = (char *) malloc( 2048 );
67
68         gptr->sierr = SI_ERR_SHUTD;
69
70         if( gptr->flags & GIF_SHUTDOWN ) {                              //  cannot do if we should shutdown 
71                 fprintf( stderr, ">>> wait: shutdown on entry????\n" );
72                 return SI_ERROR;                                                        //  so just get out 
73         }
74
75         gptr->sierr = SI_ERR_HANDLE;
76
77         if( gptr->magicnum != MAGICNUM ) {                              //  if not a valid ginfo block 
78                 fprintf( stderr, ">>> wait: bad magic on entry????\n" );
79                 return SI_ERROR;
80         }
81
82         timeout.tv_sec = 0;
83         timeout.tv_usec = 500000;                               // pop every 500ms to ensure we pick up new outbound connections in list
84
85         do {                                                                    // main wait/process loop 
86
87                 SIbldpoll( gptr );                                      // build the fdlist for poll 
88                 pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds, &gptr->execpfds, &timeout );
89
90                 if( (pstat < 0 && errno != EINTR)  ) {
91                         gptr->fdcount = 0;                              //  prevent trying to look at a session 
92                         gptr->flags |= GIF_SHUTDOWN;    //  cause cleanup and exit at end 
93                 }
94
95                 if( pstat > 0  &&  (! (gptr->flags & GIF_SHUTDOWN)) ) {
96                         for( tpptr = gptr->tplist; tpptr != NULL; tpptr = nextone ) {
97                                 nextone = tpptr->next;                          //  prevent issues if we delete the block during loop 
98
99                                 if( tpptr->fd >= 0 ) {
100                                         if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) ) {
101                                                 SIsend( gptr, tpptr );                  //  send if clear to send 
102                                         }
103         
104                                         if( FD_ISSET( tpptr->fd, &gptr->execpfds ) ) {
105                                                         ;                               // sunos seems to set the except flag for unknown reasons; ignore it
106                                         } else {
107                                                 if( FD_ISSET( tpptr->fd, &gptr->readfds ) ) {                   // ready to read
108                                                         fd = tpptr->fd;
109                                                         tpptr->rcvd++;
110         
111                                                         if( tpptr->flags & TPF_LISTENFD ) {                                     // new session request
112                                                                 errno=0;
113                                                                 status = SInewsession( gptr, tpptr );                   // accept connection
114                                                         } else  {                                                                                       //  data received on a regular port (we support just tcp now
115                                                                 status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 );   //  read data 
116                                                                 //fprintf( stderr, ">>>>> wait popped status =%d\n", status );
117                                                                 if( status > 0  &&  ! (tpptr->flags & TPF_DRAIN) ) {
118                                                                         if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL ) {
119                                                                                 status = (*cbptr)( gptr->cbtab[SI_CB_CDATA].cbdata, fd, gptr->rbuf, status );
120                                                                                 SIcbstat( gptr, status, SI_CB_CDATA );  //  handle cb status 
121                                                                         }
122                                                                 } else {                                                                                // no bites, but read flagged indicates disconnect
123                                                                         if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL ) {
124                                                                                 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
125                                                                                 SIcbstat( gptr, status, SI_CB_DISC );   //  handle status 
126                                                                         }
127                                                                         SIterm( gptr, tpptr );
128                                                                 }
129                                                         }
130                                                 }
131                                         }
132                                 }                                                               //  if still good fd 
133                         }
134                 }
135         } while( gptr->tplist != NULL && !(gptr->flags & GIF_SHUTDOWN) );
136
137         free( ibuf );
138         if( gptr->tplist == NULL )                                      //  indicate all fds closed 
139                 gptr->sierr = SI_ERR_NOFDS;
140
141         if( gptr->flags & GIF_SHUTDOWN ) {                      //  we need to stop for some reason 
142                 gptr->sierr = SI_ERR_SHUTD;                             //  indicate error exit status 
143                 status = SI_ERROR;                                              //  status should indicate to user to die 
144                 SIshutdown( gptr );                                             //  clean things up 
145         } else {
146                 status = SI_OK;                                                 //  user can continue to process 
147         }
148
149         return status;
150 }