1 // vim: noet sw=4 ts=4:
3 ==================================================================================
4 Copyright (c) 2020-2021 Nokia
5 Copyright (c) 2020-2021 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 int fd; // file descriptor for use in this routine
46 int ((*cbptr)()); // pointer to callback routine to call
47 int status = SI_OK; // return status
48 int addrlen = 0; // length of address from recvfrom call
49 char *buf; // work buffer pointer
52 struct tp_blk *tpptr; // pointer at tp stuff
53 struct tp_blk *nextone = NULL; // pointer at next block to process
54 int pstat; // poll status
55 int kstat; // keyboard status
56 struct timeval delay; // delay to use on select call
57 struct sockaddr *uaddr; // pointer to udp address
59 if( gptr->flags & GIF_SHUTDOWN ) // cannot do if we should shutdown
60 return( SI_ERROR ); // so just get out
63 if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block
66 delay.tv_sec = msdelay/100; // user submits 100ths, cvt to seconds and milliseconds
67 delay.tv_usec = (msdelay%100) * 10;
70 SIbldpoll( gptr ); // build the fdlist for poll
71 pstat = 0; // ensure good code
73 if( gptr->fdcount > 0 )
74 pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds,
75 &gptr->execpfds, &delay );
77 if( pstat < 0 && errno != EINTR )
78 { // poll fail or termination signal rcvd
79 gptr->fdcount = 0; // prevent trying to look at a session
80 gptr->flags |= GIF_SHUTDOWN; // cause cleanup and exit at end
83 if( pstat > 0 && (! (gptr->flags & GIF_SHUTDOWN)) )
85 if( FD_ISSET( 0, &gptr->readfds ) ) // check for keybd input
87 fgets( ibuf, 1024, stdin ); // get the stuff from keyboard
88 if( (cbptr = gptr->cbtab[SI_CB_KDATA].cbrtn) != NULL )
90 status = (*cbptr)( gptr->cbtab[SI_CB_KDATA].cbdata, ibuf );
91 SIcbstat( gptr, status, SI_CB_KDATA ); // handle status
92 } // end if call back was defined
96 while( tpptr != NULL ) {
97 nextone = tpptr->next; // allow for a delete in loop
99 if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) )
100 SIsend( gptr, tpptr ); // send if clear to send
102 if( FD_ISSET( tpptr->fd, &gptr->execpfds ) )
104 ; // sunos seems to set except for unknown reasons; ignore
107 if( FD_ISSET( tpptr->fd, &gptr->readfds ) ) // read event pending?
109 fd = tpptr->fd; // quick ref to the fd
111 if( tpptr->flags & TPF_LISTENFD ) // listen port setup by init?
112 { // yes-assume new session req
113 SInewsession( gptr, tpptr ); // cannot do anything about failure, so ignore status
115 else // data received on a regular port
116 if( tpptr->type == SOCK_DGRAM ) // udp socket?
118 uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
119 status = RECVFROM( fd, gptr->rbuf, MAX_RBUF, 0, uaddr, &addrlen );
120 if( status >= 0 && ! (tpptr->flags & TPF_DRAIN) )
121 { // if good status call cb routine
122 if( (cbptr = gptr->cbtab[SI_CB_RDATA].cbrtn) != NULL )
124 SIaddress( uaddr, (void **) &buf, AC_TODOT );
125 status = (*cbptr)( gptr->cbtab[SI_CB_RDATA].cbdata, gptr->rbuf, status, buf );
126 SIcbstat( gptr, status, SI_CB_RDATA ); // handle status
128 buf = NULL; // just to be safe
129 } // end if call back was defined
130 } // end if status was ok
134 { // else receive on tcp session
135 status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 ); // read data
137 if( status > SI_OK && ! (tpptr->flags & TPF_DRAIN) )
139 if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL )
141 status = (*cbptr)( gptr->cbtab[SI_CB_CDATA].cbdata, fd, gptr->rbuf, status );
142 SIcbstat( gptr, status, SI_CB_CDATA ); // handle cb status
143 } // end if call back was defined
144 } // end if status was ok
145 else // sunos seems to send 0 bytes as indication of disc
147 if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL )
149 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
150 SIcbstat( gptr, status, SI_CB_DISC ); // handle status
152 SIterm( gptr, tpptr );
155 } // end if event on this fd
158 } // end for each fd in the list
159 } // end if not in shutdown
162 if( gptr->flags & GIF_SHUTDOWN ) // we need to stop for some reason
164 status = SI_ERROR; // status should indicate to user to die
165 SIshutdown( gptr ); // clean things up
168 status = SI_OK; // user can continue to process
170 return( status ); // send status back to caller