1 // vim: noet sw=4 ts=4:
3 ==================================================================================
4 Copyright (c) 2020 Nokia
5 Copyright (c) 2020 AT&T Intellectual Property.
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
11 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
22 **************************************************************************
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.
39 * Author: E. Scott Daniels
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 **************************************************************************
48 #include "sisetup.h" // get the setup stuff
49 #include "sitransport.h"
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
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
66 ibuf = (char *) malloc( 2048 );
68 gptr->sierr = SI_ERR_SHUTD;
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
75 gptr->sierr = SI_ERR_HANDLE;
77 if( gptr->magicnum != MAGICNUM ) { // if not a valid ginfo block
78 fprintf( stderr, ">>> wait: bad magic on entry????\n" );
83 timeout.tv_usec = 500000; // pop every 500ms to ensure we pick up new outbound connections in list
85 do { // main wait/process loop
87 SIbldpoll( gptr ); // build the fdlist for poll
88 pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds, &gptr->execpfds, &timeout );
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
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
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
104 if( FD_ISSET( tpptr->fd, &gptr->execpfds ) ) {
105 ; // sunos seems to set the except flag for unknown reasons; ignore it
107 if( FD_ISSET( tpptr->fd, &gptr->readfds ) ) { // ready to read
111 if( tpptr->flags & TPF_LISTENFD ) { // new session request
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
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
127 SIterm( gptr, tpptr );
132 } // if still good fd
135 } while( gptr->tplist != NULL && !(gptr->flags & GIF_SHUTDOWN) );
138 if( gptr->tplist == NULL ) // indicate all fds closed
139 gptr->sierr = SI_ERR_NOFDS;
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
146 status = SI_OK; // user can continue to process