Add SI95 transport support
[ric-plt/lib/rmr.git] / src / rmr / si / src / si95 / sircv.c
diff --git a/src/rmr/si/src/si95/sircv.c b/src/rmr/si/src/si95/sircv.c
new file mode 100644 (file)
index 0000000..2202629
--- /dev/null
@@ -0,0 +1,139 @@
+// vim: noet sw=4 ts=4:
+/*
+==================================================================================
+    Copyright (c) 2020 Nokia
+    Copyright (c) 2020 AT&T Intellectual Property.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+*/
+
+/* X
+*****************************************************************************
+*
+*  Mnemonic: SIrcv
+*  Abstract: This routine allows the user program to receive data on a
+*            session without using the callback structure of the library.
+*            It is the caller's responsibility to provide a buffer large
+*            enough to handle the received data.
+*  Parms:    gptr - The SIHANDLE that the user received on init call
+*            sid  - The session id that the user wants to check
+*            buf  - Pointer to buffer to receive data in
+*            abuf - Pointer to buffer to return address of UDP sender in (!null)
+*            buflen-Length of the receive buffer
+*            delay- Value to pass to poll (time out) -1 == block until data
+*  Returns:  SI_ERROR - (SIerrno will contain reason) if failure, else the
+*            number of bytes read. If the number read is 0 SIerrno will indicate
+*            why: time out exceeded, signal received.
+*  Date:     26 March 1995
+*  Author:   E. Scott Daniels
+*  Mods:     26 Mar 20001 - Changed to support UDP reads
+*
+******************************************************************************
+*/
+#include "sisetup.h"    //  get start up stuff 
+#include "sitransport.h"
+
+extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ) {
+ //extern int sigflags;           //  signal flags 
+ int status = SI_ERROR;         //  assume the worst to return to caller 
+ struct tp_blk *tpptr;          //  pointer to transport provider info 
+ int flags = 0;                 //  receive flags 
+ int remainder;                 //  # of bytes remaining after rcv if more 
+ fd_set readfds;                //  special set of read fds for this call 
+ fd_set execpfds;               //  special set of read fds for this call 
+ struct timeval *tptr = NULL;   //  time info for select call 
+ struct timeval time;
+ struct sockaddr *uaddr;       //  pointer to udp address 
+       char    *acbuf;         //  pointer to converted address 
+ int addrlen;
+
+ gptr->sierr = SI_ERR_HANDLE;              //  set errno before we fail 
+ if( gptr->magicnum != MAGICNUM )     //  if not a valid ginfo block 
+  return SI_ERROR;
+
+ gptr->sierr = SI_ERR_SESSID;             //  set errno before we fail 
+ for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid;
+      tpptr = tpptr->next );      //  find transport block 
+ if( tpptr == NULL )
+  return SI_ERROR;                      //  signal bad block 
+
+ uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
+ addrlen = sizeof( *uaddr );
+
+ gptr->sierr = SI_ERR_SHUTD;               //  set errno before we fail 
+ if( ! (gptr->flags & GIF_SHUTDOWN) )
+  {                        //  if not in shutdown and no signal flags  
+   FD_ZERO( &readfds );               //  clear select info 
+   FD_SET( tpptr->fd, &readfds );     //  set to check read status 
+
+   FD_ZERO( &execpfds );               //  clear select info 
+   FD_SET( tpptr->fd, &execpfds );     //  set to check read status 
+
+   if( delay >= 0 )                //  user asked for a fininte time limit 
+    {
+     tptr = &time;                 //  point at the local struct 
+     tptr->tv_sec = 0;             //  setup time for select call 
+     tptr->tv_usec = delay;
+    }
+
+   gptr->sierr = SI_ERR_TP;
+   if( (select( tpptr->fd + 1, &readfds, NULL, &execpfds, tptr ) < 0 ) )
+    gptr->flags |= GIF_SHUTDOWN;     //  we must shut on error or signal 
+   else
+    {                                //  poll was successful - see if data ? 
+     gptr->sierr = SI_ERR_TIMEOUT;
+     if( FD_ISSET( tpptr->fd, &execpfds ) )   //  session error? 
+      {
+       SIterm( gptr, tpptr );                 //  clean up our end of things 
+       gptr->sierr = SI_ERR_SESSID;               //  set errno before we fail 
+      }
+     else
+      {
+       if( (FD_ISSET( tpptr->fd, &readfds )) )
+        {                                       //  process data if no signal 
+               gptr->sierr = SI_ERR_TP;
+               if( tpptr->type == SOCK_DGRAM )        //  raw data received 
+               {
+                       status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen );
+                       if( abuf )
+                       {
+                               SIaddress( uaddr, (void **) &acbuf, AC_TODOT ); //  address returns pointer to buf now rather than filling 
+                               strcpy( abuf, acbuf );                  //  must be back compat with old versions 
+                               free( acbuf );
+                       }
+                       if( status < 0 )                        //  session terminated? 
+                               SIterm( gptr, tpptr );                   //  so close our end 
+               }
+               else                                      //  cooked data received 
+               {
+                       status = RECV( sid, buf, buflen, 0 );   //  read data into user buf 
+                       if( status < 0 )                        //  session terminated? 
+                               SIterm( gptr, tpptr );                 //  so close our end 
+               }
+        }                                         //  end event was received 
+       else                                       //  no event was received  
+        status = 0;                               //  status is just ok 
+      }                       //  end else - not in shutdown mode after poll 
+    }                     //  end else pole was successful 
+  }                                 //  end if not already signal shutdown 
+
+ if( gptr->flags & GIF_SHUTDOWN  &&  gptr->tplist != NULL )
+  {             //  shutdown received but sessions not cleaned up 
+   SIshutdown( gptr );
+   status = SI_ERROR;                //  indicate failure on return 
+  }                                  //  end if shut but not clean 
+
+ free( uaddr );
+ return status;          //  send back the status 
+}                           //  SIrcv