5309dc557e991322d49ac7b4efcd1d3051604474
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / sircv.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 /* X
22 *****************************************************************************
23 *
24 *  Mnemonic: SIrcv
25 *  Abstract: This routine allows the user program to receive data on a
26 *            session without using the callback structure of the library.
27 *            It is the caller's responsibility to provide a buffer large
28 *            enough to handle the received data.
29 *  Parms:    gptr - The SIHANDLE that the user received on init call
30 *            sid  - The session id that the user wants to check
31 *            buf  - Pointer to buffer to receive data in
32 *            abuf - Pointer to buffer to return address of UDP sender in (!null)
33 *                   must be a minimum of 64 bytes long.
34 *            buflen-Length of the receive buffer
35 *            delay- Value to pass to poll (time out) -1 == block until data
36 *  Returns:  SI_ERROR - (SIerrno will contain reason) if failure, else the
37 *            number of bytes read. If the number read is 0 SIerrno will indicate
38 *            why: time out exceeded, signal received.
39 *  Date:     26 March 1995
40 *  Author:   E. Scott Daniels
41 *  Mods:     26 Mar 20001 - Changed to support UDP reads
42 *
43 ******************************************************************************
44 */
45 #include "sisetup.h"                                    //  get start up stuff
46 #include "sitransport.h"
47
48 extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
49         int status = SI_ERROR;                          //  assume the worst to return to caller
50         struct tp_blk *tpptr;                           //  pointer to transport provider info
51         int flags = 0;                                          //  receive flags
52         int remainder;                                          //  # of bytes remaining after rcv if more
53         fd_set readfds;                                         //  special set of read fds for this call
54         fd_set execpfds;                                        //  special set of read fds for this call
55         struct timeval *tptr = NULL;            //  time info for select call
56         struct timeval time;
57         struct sockaddr *uaddr;                         //  pointer to udp address
58         char    *acbuf;                                         //  pointer to converted address
59         int addrlen;
60
61         if( gptr->magicnum != MAGICNUM ) {      //  if not a valid ginfo block
62                 return SI_ERROR;
63         }
64
65         for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid; tpptr = tpptr->next ) {   //  find transport block
66                 // no body
67         }
68
69         if( tpptr == NULL ) {
70                 return SI_ERROR;                                //  signal bad block
71         }
72
73         uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
74         addrlen = sizeof( *uaddr );
75
76         if( ! (gptr->flags & GIF_SHUTDOWN) ) {                          //  if not in shutdown and no signal flags
77                 FD_ZERO( &readfds );                                                    //  clear select info
78                 FD_SET( tpptr->fd, &readfds );                                  //  set to check read status
79
80                 FD_ZERO( &execpfds );                                                   //  clear select info
81                 FD_SET( tpptr->fd, &execpfds );                                 //  set to check read status
82
83                 if( delay >= 0 ) {                                              //  user asked for a fininte time limit
84                         tptr = &time;                                           //  point at the local struct
85                         tptr->tv_sec = 0;                                       //  setup time for select call
86                         tptr->tv_usec = delay;
87                 }
88
89                 if( (select( tpptr->fd + 1, &readfds, NULL, &execpfds, tptr ) < 0 ) ) {
90                         gptr->flags |= GIF_SHUTDOWN;                                                            //  we must shut on error or signal
91                 } else {                                //  poll was successful - see if data ?
92                         if( FD_ISSET( tpptr->fd, &execpfds ) ) {                                        //  session error?
93                                 SIterm( gptr, tpptr );                                                                  //  clean up our end of things
94                         } else {
95                                 if( (FD_ISSET( tpptr->fd, &readfds )) ) {                               //  process data if no signal
96                                         if( tpptr->type == SOCK_DGRAM ) {                                       //  raw data received
97                                                 status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen );
98                                                 if( abuf ) {
99                                                         SIaddress( uaddr, (void **) &acbuf, AC_TODOT );         //  address returns pointer to buf now rather than filling
100                                                         strncpy( abuf, acbuf, 64 );                                                     //  must be back compat with old versions
101                                                         free( acbuf );
102                                                 }
103                                                 if( status < 0 ) {                                                                      //  session terminated?
104                                                         SIterm( gptr, tpptr );                                                  //  so close our end
105                                                 }
106                                         } else {                                                                                                //  cooked data received
107                                                 status = RECV( sid, buf, buflen, 0 );                           //  read data into user buf
108                                                 if( status < 0 ) {                                                                      //  session terminated?
109                                                         SIterm( gptr, tpptr );                                                  //  so close our end
110                                                 }
111                                         }
112                                 } else {                                //  end event was received
113                                         status = 0;                     //  status is just ok
114                                 }
115                         }                                                       //  end else - not in shutdown mode after poll
116                 }                                                               //  end else pole was successful
117         }                                                                       //  end if not already signal shutdown
118
119         if( gptr->flags & GIF_SHUTDOWN  &&  gptr->tplist != NULL ) {                            //  shutdown received but sessions not cleaned up
120                 SIshutdown( gptr );
121                 status = SI_ERROR;
122         }
123
124         free( uaddr );
125         return status;                          //  send back the status
126 }