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 *****************************************************************************
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 * buflen-Length of the receive buffer
34 * delay- Value to pass to poll (time out) -1 == block until data
35 * Returns: SI_ERROR - (SIerrno will contain reason) if failure, else the
36 * number of bytes read. If the number read is 0 SIerrno will indicate
37 * why: time out exceeded, signal received.
39 * Author: E. Scott Daniels
40 * Mods: 26 Mar 20001 - Changed to support UDP reads
42 ******************************************************************************
44 #include "sisetup.h" // get start up stuff
45 #include "sitransport.h"
47 extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
48 //extern int sigflags; // signal flags
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
57 struct sockaddr *uaddr; // pointer to udp address
58 char *acbuf; // pointer to converted address
61 if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block
64 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid;
65 tpptr = tpptr->next ); // find transport block
67 return SI_ERROR; // signal bad block
69 uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
70 addrlen = sizeof( *uaddr );
72 if( ! (gptr->flags & GIF_SHUTDOWN) )
73 { // if not in shutdown and no signal flags
74 FD_ZERO( &readfds ); // clear select info
75 FD_SET( tpptr->fd, &readfds ); // set to check read status
77 FD_ZERO( &execpfds ); // clear select info
78 FD_SET( tpptr->fd, &execpfds ); // set to check read status
80 if( delay >= 0 ) // user asked for a fininte time limit
82 tptr = &time; // point at the local struct
83 tptr->tv_sec = 0; // setup time for select call
84 tptr->tv_usec = delay;
87 if( (select( tpptr->fd + 1, &readfds, NULL, &execpfds, tptr ) < 0 ) )
88 gptr->flags |= GIF_SHUTDOWN; // we must shut on error or signal
90 { // poll was successful - see if data ?
91 if( FD_ISSET( tpptr->fd, &execpfds ) ) // session error?
93 SIterm( gptr, tpptr ); // clean up our end of things
97 if( (FD_ISSET( tpptr->fd, &readfds )) )
98 { // process data if no signal
99 if( tpptr->type == SOCK_DGRAM ) // raw data received
101 status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen );
104 SIaddress( uaddr, (void **) &acbuf, AC_TODOT ); // address returns pointer to buf now rather than filling
105 strcpy( abuf, acbuf ); // must be back compat with old versions
108 if( status < 0 ) // session terminated?
109 SIterm( gptr, tpptr ); // so close our end
111 else // cooked data received
113 status = RECV( sid, buf, buflen, 0 ); // read data into user buf
114 if( status < 0 ) // session terminated?
115 SIterm( gptr, tpptr ); // so close our end
117 } // end event was received
118 else // no event was received
119 status = 0; // status is just ok
120 } // end else - not in shutdown mode after poll
121 } // end else pole was successful
122 } // end if not already signal shutdown
124 if( gptr->flags & GIF_SHUTDOWN && gptr->tplist != NULL )
125 { // shutdown received but sessions not cleaned up
127 status = SI_ERROR; // indicate failure on return
128 } // end if shut but not clean
131 return status; // send back the status