Beef up unit tests for SI95 code
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / sipoll.c
1 // vim: noet sw=4 ts=4:
2 /*
3 ==================================================================================
4     Copyright (c) 2020-2021 Nokia
5     Copyright (c) 2020-2021 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: SIpoll
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.
33 *  Date:     10 April 1995
34 *  Author:   E. Scott Daniels
35 *
36 **************************************************************************
37 */
38 #include  "sisetup.h"     //  get the setup stuff
39 #include "sitransport.h"
40 #include <wait.h>
41
42
43 extern int SIpoll( struct ginfo_blk *gptr, int msdelay )
44 {
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
50  char ibuf[1025];
51  int i;                        //  loop index
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
58
59  if( gptr->flags & GIF_SHUTDOWN )     //  cannot do if we should shutdown
60   return( SI_ERROR );                    //  so just get out
61
62
63  if( gptr->magicnum != MAGICNUM )     //  if not a valid ginfo block
64   return( SI_ERROR );
65
66    delay.tv_sec = msdelay/100;                //  user submits 100ths, cvt to seconds and milliseconds
67    delay.tv_usec = (msdelay%100) * 10;
68
69
70    SIbldpoll( gptr );                 //  build the fdlist for poll
71    pstat = 0;                         //  ensure good code
72
73    if( gptr->fdcount > 0 )
74     pstat = select( gptr->fdcount, &gptr->readfds, &gptr->writefds,
75                                &gptr->execpfds, &delay );
76
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
81     }
82
83    if( pstat > 0  &&  (! (gptr->flags & GIF_SHUTDOWN)) )
84     {
85      if( FD_ISSET( 0, &gptr->readfds ) )       //  check for keybd input
86       {
87        fgets( ibuf, 1024, stdin );   //  get the stuff from keyboard
88        if( (cbptr = gptr->cbtab[SI_CB_KDATA].cbrtn) != NULL )
89         {
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
93       }
94
95         tpptr = gptr->tplist; 
96         while( tpptr != NULL ) {
97                 nextone = tpptr->next;                                  //  allow for a delete in loop
98
99        if( tpptr->squeue != NULL && (FD_ISSET( tpptr->fd, &gptr->writefds )) )
100         SIsend( gptr, tpptr );              //  send if clear to send
101
102        if( FD_ISSET( tpptr->fd, &gptr->execpfds ) )
103         {
104          ; //  sunos seems to set except for unknown reasons; ignore
105         }
106        else
107        if( FD_ISSET( tpptr->fd, &gptr->readfds ) )  //  read event pending?
108         {
109          fd = tpptr->fd;                     //  quick ref to the fd
110
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
114           }
115          else                              //  data received on a regular port
116           if( tpptr->type == SOCK_DGRAM )          //  udp socket?
117            {
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 )
123                {
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
127                                 free( buf );
128                                 buf = NULL;                                             // just to be safe
129                }                              //  end if call back was defined
130              }                                //  end if status was ok
131             free( uaddr );
132            }                                  //  end if udp
133           else
134            {                                //  else receive on tcp session
135             status = RECV( fd, gptr->rbuf, MAX_RBUF, 0 );    //  read data
136
137             if( status > SI_OK  &&  ! (tpptr->flags & TPF_DRAIN) )
138              {
139               if( (cbptr = gptr->cbtab[SI_CB_CDATA].cbrtn) != NULL )
140                {
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
146              {
147               if( (cbptr = gptr->cbtab[SI_CB_DISC].cbrtn) != NULL )
148                {
149                 status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd );
150                 SIcbstat( gptr, status, SI_CB_DISC );    //  handle status
151                }
152               SIterm( gptr, tpptr );
153             }
154            }                                                //  end tcp read
155         }                    //  end if event on this fd
156
157                 tpptr = nextone;
158       }                      //  end for each fd in the list
159     }                        //  end if not in shutdown
160
161
162  if( gptr->flags & GIF_SHUTDOWN )      //  we need to stop for some reason
163   {
164    status = SI_ERROR;                //  status should indicate to user to die
165    SIshutdown( gptr );            //  clean things up
166   }
167  else
168   status = SI_OK;                    //  user can continue to process
169
170  return( status );                //  send status back to caller
171 }                                 //  SIwait