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 poll the sockets that are open for
25 * an event and return after the delay period has expired, or
26 * an event has been processed.
27 * Parms: gptr - Pointer to the global information block
28 * msdelay- 100ths of seconds to delay
29 * Returns: SI_OK if the caller can continue, SI_ERROR if all sessions have been
30 * stopped, or the interface cannot proceed. When SI_ERROR is
31 * returned the caller should cleanup and exit immediatly (we
32 * have probably received a sigter or sigquit.
34 * Author: E. Scott Daniels
36 **************************************************************************
38 #include "sisetup.h" // get the setup stuff
39 #include "sitransport.h"
43 extern int SIpoll( struct ginfo_blk *gptr, int msdelay )
45 //extern int deaths; // number of children that died and are zombies
46 //extern int sigflags; // flags set by the signal handler routine
48 int fd; // file descriptor for use in this routine
49 int ((*cbptr)()); // pointer to callback routine to call
50 int status = SI_OK; // return status
51 int addrlen; // length of address from recvfrom call
52 char *buf; // work buffer pointer
55 struct tp_blk *tpptr; // pointer at tp stuff
56 struct tp_blk *nextone; // pointer at next block to process
57 int pstat; // poll status
58 int kstat; // keyboard status
59 struct timeval delay; // delay to use on select call
60 struct sockaddr *uaddr; // pointer to udp address
62 gptr->sierr = SI_ERR_SHUTD;
64 if( gptr->flags & GIF_SHUTDOWN ) // cannot do if we should shutdown
65 return( SI_ERROR ); // so just get out
68 gptr->sierr = SI_ERR_HANDLE;
70 if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block
73 delay.tv_sec = msdelay/100; // user submits 100ths, cvt to seconds and milliseconds
74 delay.tv_usec = (msdelay%100) * 10;
77 SIbldpoll( gptr ); // build the fdlist for poll
78 pstat = 0; // ensure good code
80 if( gptr->fdcount > 0 )
81 pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds,
82 &gptr->execpfds, &delay );
84 if( (pstat < 0 && errno != EINTR) )
85 { // poll fail or termination signal rcvd
86 gptr->fdcount = 0; // prevent trying to look at a session
87 gptr->flags |= GIF_SHUTDOWN; // cause cleanup and exit at end
88 //deaths = 0; // dont need to issue waits on dead child
89 //sigflags = 0; // who cares about signals now too
93 while( deaths > 0 ) // there have been death(s) - keep the dead
94 { // from being zombies - send them to heaven
95 wait( NULL ); // issue wait on child
97 } // end while dead children to send to heaven
101 if( sigflags && // if signal received and processing them
102 (cbptr = gptr->cbtab[SI_CB_SIGNAL].cbrtn) != NULL )
104 while( sigflags != 0 )
106 i = sigflags; // hold for call
107 sigflags = 0; // incase we are interrupted while away
108 status = (*cbptr)( gptr->cbtab[SI_CB_SIGNAL].cbdata, i );
109 SIcbstat( gptr, status, SI_CB_SIGNAL ); // handle status
114 if( pstat > 0 && (! (gptr->flags & GIF_SHUTDOWN)) )
116 if( FD_ISSET( 0, &gptr->readfds ) ) // check for keybd input
118 fgets( ibuf, 1024, stdin ); // get the stuff from keyboard
119 if( (cbptr = gptr->cbtab[SI_CB_KDATA].cbrtn) != NULL )
121 status = (*cbptr)( gptr->cbtab[SI_CB_KDATA].cbdata, ibuf );
122 SIcbstat( gptr, status, SI_CB_KDATA ); // handle status
123 } // end if call back was defined
126 // for( tpptr = gptr->tplist; tpptr != NULL; tpptr = tpptr->next )
127 for( tpptr = gptr->tplist; tpptr != NULL; tpptr = nextone )
129 nextone = tpptr->next; // prevent coredump if we delete the session
131 if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) )
132 SIsend( gptr, tpptr ); // send if clear to send
134 if( FD_ISSET( tpptr->fd, &gptr->execpfds ) )
136 ; // sunos seems to set except for unknown reasons; ignore
139 if( FD_ISSET( tpptr->fd, &gptr->readfds ) ) // read event pending?
141 fd = tpptr->fd; // quick ref to the fd
143 if( tpptr->flags & TPF_LISTENFD ) // listen port setup by init?
144 { // yes-assume new session req
145 status = SInewsession( gptr, tpptr ); // make new session
147 else // data received on a regular port
148 if( tpptr->type == SOCK_DGRAM ) // udp socket?
150 uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
151 status = RECVFROM( fd, gptr->rbuf, MAX_RBUF, 0, uaddr, &addrlen );
152 if( status >= 0 && ! (tpptr->flags & TPF_DRAIN) )
153 { // if good status call cb routine
154 if( (cbptr = gptr->cbtab[SI_CB_RDATA].cbrtn) != NULL )
156 SIaddress( uaddr, (void **) &buf, AC_TODOT );
157 status = (*cbptr)( gptr->cbtab[SI_CB_RDATA].cbdata, gptr->rbuf, status, buf );
158 SIcbstat( gptr, status, SI_CB_RDATA ); // handle status
160 } // end if call back was defined
161 } // end if status was ok
165 { // else receive on tcp session
166 status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 ); // read data
168 if( status > SI_OK && ! (tpptr->flags & TPF_DRAIN) )
170 if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL )
172 status = (*cbptr)( gptr->cbtab[SI_CB_CDATA].cbdata, fd, gptr->rbuf, status );
173 SIcbstat( gptr, status, SI_CB_CDATA ); // handle cb status
174 } // end if call back was defined
175 } // end if status was ok
176 else // sunos seems to send 0 bytes as indication of disc
178 if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL )
180 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
181 SIcbstat( gptr, status, SI_CB_DISC ); // handle status
183 SIterm( gptr, tpptr );
186 } // end if event on this fd
187 } // end for each fd in the list
188 } // end if not in shutdown
191 if( gptr->flags & GIF_SHUTDOWN ) // we need to stop for some reason
193 gptr->sierr = SI_ERR_SHUTD; // indicate error exit status
194 status = SI_ERROR; // status should indicate to user to die
195 SIshutdown( gptr ); // clean things up
198 status = SI_OK; // user can continue to process
200 return( status ); // send status back to caller