2202629501f3185bd591b41212f9068e8d830c06
[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 *            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.
38 *  Date:     26 March 1995
39 *  Author:   E. Scott Daniels
40 *  Mods:     26 Mar 20001 - Changed to support UDP reads
41 *
42 ******************************************************************************
43 */
44 #include "sisetup.h"    //  get start up stuff 
45 #include "sitransport.h"
46
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 
56  struct timeval time;
57  struct sockaddr *uaddr;       //  pointer to udp address 
58         char    *acbuf;         //  pointer to converted address 
59  int addrlen;
60
61  gptr->sierr = SI_ERR_HANDLE;              //  set errno before we fail 
62  if( gptr->magicnum != MAGICNUM )     //  if not a valid ginfo block 
63   return SI_ERROR;
64
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 
68  if( tpptr == NULL )
69   return SI_ERROR;                      //  signal bad block 
70
71  uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
72  addrlen = sizeof( *uaddr );
73
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 
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     {
85      tptr = &time;                 //  point at the local struct 
86      tptr->tv_sec = 0;             //  setup time for select call 
87      tptr->tv_usec = delay;
88     }
89
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 
93    else
94     {                                //  poll was successful - see if data ? 
95      gptr->sierr = SI_ERR_TIMEOUT;
96      if( FD_ISSET( tpptr->fd, &execpfds ) )   //  session error? 
97       {
98        SIterm( gptr, tpptr );                 //  clean up our end of things 
99        gptr->sierr = SI_ERR_SESSID;               //  set errno before we fail 
100       }
101      else
102       {
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 
107                 {
108                         status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen );
109                         if( abuf )
110                         {
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 
113                                 free( acbuf );
114                         }
115                         if( status < 0 )                        //  session terminated? 
116                                 SIterm( gptr, tpptr );                   //  so close our end 
117                 }
118                 else                                      //  cooked data received 
119                 {
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 
123                 }
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 
130
131  if( gptr->flags & GIF_SHUTDOWN  &&  gptr->tplist != NULL )
132   {             //  shutdown received but sessions not cleaned up 
133    SIshutdown( gptr );
134    status = SI_ERROR;                //  indicate failure on return 
135   }                                  //  end if shut but not clean 
136
137  free( uaddr );
138  return status;          //  send back the status 
139 }                           //  SIrcv