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 gptr->sierr = SI_ERR_HANDLE; // set errno before we fail
62 if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block
65 gptr->sierr = SI_ERR_SESSID; // set errno before we fail
66 for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid;
67 tpptr = tpptr->next ); // find transport block
69 return SI_ERROR; // signal bad block
71 uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
72 addrlen = sizeof( *uaddr );
74 gptr->sierr = SI_ERR_SHUTD; // set errno before we fail
75 if( ! (gptr->flags & GIF_SHUTDOWN) )
76 { // 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
80 FD_ZERO( &execpfds ); // clear select info
81 FD_SET( tpptr->fd, &execpfds ); // set to check read status
83 if( delay >= 0 ) // user asked for a fininte time limit
85 tptr = &time; // point at the local struct
86 tptr->tv_sec = 0; // setup time for select call
87 tptr->tv_usec = delay;
90 gptr->sierr = SI_ERR_TP;
91 if( (select( tpptr->fd + 1, &readfds, NULL, &execpfds, tptr ) < 0 ) )
92 gptr->flags |= GIF_SHUTDOWN; // we must shut on error or signal
94 { // poll was successful - see if data ?
95 gptr->sierr = SI_ERR_TIMEOUT;
96 if( FD_ISSET( tpptr->fd, &execpfds ) ) // session error?
98 SIterm( gptr, tpptr ); // clean up our end of things
99 gptr->sierr = SI_ERR_SESSID; // set errno before we fail
103 if( (FD_ISSET( tpptr->fd, &readfds )) )
104 { // process data if no signal
105 gptr->sierr = SI_ERR_TP;
106 if( tpptr->type == SOCK_DGRAM ) // raw data received
108 status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen );
111 SIaddress( uaddr, (void **) &acbuf, AC_TODOT ); // address returns pointer to buf now rather than filling
112 strcpy( abuf, acbuf ); // must be back compat with old versions
115 if( status < 0 ) // session terminated?
116 SIterm( gptr, tpptr ); // so close our end
118 else // cooked data received
120 status = RECV( sid, buf, buflen, 0 ); // read data into user buf
121 if( status < 0 ) // session terminated?
122 SIterm( gptr, tpptr ); // so close our end
124 } // end event was received
125 else // no event was received
126 status = 0; // status is just ok
127 } // end else - not in shutdown mode after poll
128 } // end else pole was successful
129 } // end if not already signal shutdown
131 if( gptr->flags & GIF_SHUTDOWN && gptr->tplist != NULL )
132 { // shutdown received but sessions not cleaned up
134 status = SI_ERROR; // indicate failure on return
135 } // end if shut but not clean
138 return status; // send back the status