# API and build change and fix summaries. Doc correctsions
# and/or changes are not mentioned here; see the commit messages.
+2020 April 28; version 4.0.3
+ Fix sonar flagged bugs (RIC-78)
+
2020 April 24; version 4.0.2
Correct bug in SI95 transport header length validation (RIC-341)
set( major_version "4" ) # should be automatically populated from git tag later, but until CI process sets a tag we use this
set( minor_version "0" )
-set( patch_level "2" )
+set( patch_level "3" )
set( install_root "${CMAKE_INSTALL_PREFIX}" )
set( install_inc "include/rmr" )
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The library must be given a route table which maps message
-numbers to endpoint groups such that each time a message of
-type T is sent, the message is delivered to one member of
-each group associated with T. For example, message type 2
-might route to two different groups where group A consists of
-worker1 and worker2, while group B consists only of logger1.
+types (integers) to endpoint groups such that each time a
+message of type T is sent, the message is delivered to one
+member of each group associated with T. For example, message
+type 2 might route to two different groups where group A has
+two members, worker1 and worker2, while group B has only one
+member, logger1.
+
+The route table consists of a start record, one or more table
+entry records, and an end record. All table records contain
+fields separated with vertical bars (|), and allow for
+trailing comments with the standard shell comment symbol
+(hash, #) provided that the start of the comment is separated
+from the last token on the record by one or more spaces.
+Leading and trailing white space in each field is ignored.
+The route table supports two entry types: *rte* and *mse*.
+
+A *rte* entry defines a message type, an optional sender
+application, and the endpoint(s) which accept the indicated
+message type. However, this format is deprecated and may be
+removed in a future version. An example record appears next.
+
+::
+
+ rte | 1 | app10:4560
+
+
+
+The second type of entry is *mse*. This entry defines a
+message type, an optional sender application, a subscription
+ID, and a collection of endpoints. An example record appears
+next.
+
+::
+
+ mse | 1000,forwarder:43086 | 10 | app2:43086
+
+
It is the responsibility of the route table generator to know
which endpoints belong to which groups, and which groups
Route Table Syntax
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The following illustrates the syntax for both the route
-table.
+The following illustrates the syntax for both types of route
+table entries.
::
newrt | start
+ rte | <message-type>[,<sender-endpoint>] | <round-robin-grp>[;<round-robin-grp>]...
mse | <message-type>[,<sender-endpoint>] | <sub-id> | <round-robin-grp>[;<round-robin-grp>]...
newrt | end
A round robin group is one or more endpoints from which one
will be selected to receive the message. When multiple
endpoints are given in a group, they must be separated with a
-comma. An endpoint is the IP address and port (e.g.
-192.158.4.30:8219) or DNS name and port of the application
+comma. An endpoint is an IP address and port (e.g.
+192.158.4.30:8219), or DNS name and port, of the application
that should receive the message type. If multiple round-robin
-groups are given, they must be separated by a semicolon, and
+groups are given, they must be separated by a semicolon.
MEID Map Syntax
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--------------------------------------------------------------------------------------------
+2020 April 28; version 4.0.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Fix sonar flagged bugs (RIC-78)
+
+
+2020 April 24; version 4.0.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Correct bug in SI95 transport header length validation
+(RIC-341)
+
+
+2020 April 22; version 4.0.1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Correct message type constant for Traffic Steering
+predication (RIC-342)
+
+
+2020 April 21; version 4.0.0
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The NNG based libraries are no longer included in the RMR
+packages. This is considered a breaking change as NNG will
+not be supported by default. It is still possible to build
+with RMR-NNG libraries, but that is the exception. The API
+between 3.8.2 and 4.0.0 is the SAME. Upgrading to 4.0.0 only
+means that the underlying transport mechanism is limited only
+to SI95.
+
+The rmr_rcv_specific() function has been deprecated as it was
+necessary only for NNG and Nanomsg support. Its use should be
+discontinued.
+
+
+2020 April 20; version 3.8.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Fix bug which was preventing an instance receiving dynamic
+route table updates. (RIC-336)
+
+
2020 April 20; version 3.8.1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Abstract: These are common functions which work only on the mbuf and
thus (because they do not touch an endpoint or context)
can be agnostic to the underlying transport, or the transport
- layer provides a transport specific function (e.g. payload
+ layer provides a transport specific function (e.g. payload
reallocation).
Author: E. Scott Daniels
if( len > RMR_MAX_MEID ) {
len = RMR_MAX_MEID;
errno = EOVERFLOW;
- }
+ }
hdr = (uta_mhdr_t *) mbuf->header;
memcpy( hdr->meid, src, len );
if( dest != NULL ) {
hdr = msg->header;
- strcpy( dest, hdr->src );
+ strncpy( dest, hdr->src, RMR_MAX_SRC );
}
return dest;
hdr = msg->header;
if( HDR_VERSION( msg->header ) > 2 ) { // src ip was not present in hdr until ver 3
errno = 0;
- strcpy( dest, hdr->srcip );
+ strncpy( dest, hdr->srcip, RMR_MAX_SRC );
rstr = dest;
} else {
errno = 0;
- strcpy( dest, hdr->src ); // reutrn the name:port for old messages
+ strncpy( dest, hdr->src, RMR_MAX_SRC ); // reutrn the name:port for old messages
rstr = dest;
}
}
#include "../include/rmr.h"
-#define ADD_SEP 1
+#define ADD_SEP 1
#define NO_SEP 0
/*
if( src && target ) {
len = strlen( src );
if( (rc = len <= max ? len : 0 ) > 0 ) { // if it fits, add it.
- strcat( target, src );
+ strncat( target, src, len );
}
}
phrase = build_ival( "RMR_ERR_INITFAILED", RMR_ERR_INITFAILED, NO_SEP );
remain -= bang_on( wbuf, phrase, remain );
- strcat( wbuf, " }" );
+ strncat( wbuf, " }", remain );
return strdup( wbuf ); // chop unused space and return
}
v1hdr = (uta_v1mhdr_t *) old_msg->header; // v1 will work to dig header out of any version
switch( ntohl( v1hdr->rmr_ver ) ) {
case 1:
- memcpy( v1hdr, old_msg->header, sizeof( *v1hdr ) ); // copy complete header
+ hdr = nm->header;
+ memcpy( hdr, old_msg->header, sizeof( *v1hdr ) ); // copy complete header
nm->payload = (void *) v1hdr + sizeof( *v1hdr );
break;
* Mnemonic: SIaddress
* Abstract: This routine will convert a sockaddr_in structure to a
* dotted decimal address, or visa versa.
-* If type == AC_TOADDR the src string may be:
+* If type == AC_TOADDR the src string may be:
* xxx.xxx.xxx.xxx.portnumber or host-name.portnumber
* xxx.xxx.xxx.xxx.service[.protocol] or hostname;service[;protocol]
* if protocol is not supplied then tcp is assumed.
* hostname may be something like godzilla.moviemania.com
* Parms: src - Pointer to source buffer
-* dest- Pointer to dest buffer pointer
-* type- Type of conversion AC_TODOT converts sockaddr to human readable. AC_TOADDR
+* dest- Pointer to dest buffer pointer
+* type- Type of conversion AC_TODOT converts sockaddr to human readable. AC_TOADDR
* converts character buffer to sockaddr.
* Returns: Nothing.
* Date: 19 January 1995
* Modified: 22 Mar 1995 - To add support for ipx addresses.
* 18 Oct 2020 - drop old port separator (;)
*
-* CAUTION: The netdb.h header file is a bit off when it sets up the
-* hostent structure. It claims that h_addr_list is a pointer
-* to character pointers, but it is really a pointer to a list
+* CAUTION: The netdb.h header file is a bit off when it sets up the
+* hostent structure. It claims that h_addr_list is a pointer
+* to character pointers, but it is really a pointer to a list
* of pointers to integers!!!
-*
+*
***************************************************************************
*/
-#include "sisetup.h" // get necessary defs and other stuff
+#include "sisetup.h" // get necessary defs and other stuff
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
-/*
+/*
target: buffer with address e.g. 192.168.0.1:4444 :4444 (listen) [::1]4444
- family: PF_INET[6] (let it be 0 to select based on addr in buffer
+ family: PF_INET[6] (let it be 0 to select based on addr in buffer
proto: IPPROTO_TCP IPPROTO_UDP
type: SOCK_STREAM SOCK_DGRAM
returns length of struct pointed to by rap (return addr blockpointer)
*/
extern int SIgenaddr( char *target, int proto, int family, int socktype, struct sockaddr **rap ) {
- struct addrinfo hint; // hints to give getaddrinfo
- struct addrinfo *list = NULL; // list of what comes back
- int ga_flags = 0; // flags to pass to getaddrinfo in hints
+ struct addrinfo hint; // hints to give getaddrinfo
+ struct addrinfo *list = NULL; // list of what comes back
+ int ga_flags = 0; // flags to pass to getaddrinfo in hints
int error = 0;
- int rlen = 0; // length of the addr that rap points to on return
- char *pstr; // port string
- char *dstr; // a copy of the users target that we can destroy
+ int rlen = 0; // length of the addr that rap points to on return
+ char *pstr; // port string
+ char *dstr; // a copy of the users target that we can destroy
char* fptr; // ptr we allocated and need to free (we may adjust dstr)
- fptr = dstr = strdup( (char *) target ); // copy so we can destroy it with strtok
- *rap = NULL; // ensure null incase something breaks
+ fptr = dstr = strdup( (char *) target ); // copy so we can destroy it with strtok
+ *rap = NULL; // ensure null incase something breaks
while( isspace( *dstr ) ) {
dstr++;
}
- if( *dstr == ':' ) { // user passed in :port -- so we assume this is for bind
+ if( *dstr == ':' ) { // user passed in :port -- so we assume this is for bind
pstr = dstr;
*(pstr++) = 0;
}
memset( &hint, 0, sizeof( hint ) );
- hint.ai_family = family; // AF_INET AF_INET6... let this be 0 to select best based on addr
- hint.ai_socktype = socktype; // SOCK_DGRAM SOCK_STREAM
- hint.ai_protocol = proto; // IPPROTO_TCP IPPROTO_UDP
+ hint.ai_family = family; // AF_INET AF_INET6... let this be 0 to select best based on addr
+ hint.ai_socktype = socktype; // SOCK_DGRAM SOCK_STREAM
+ hint.ai_protocol = proto; // IPPROTO_TCP IPPROTO_UDP
hint.ai_flags = ga_flags;
- if( DEBUG )
+ if( DEBUG )
rmr_vlog( RMR_VL_DEBUG, "siaddress: calling getaddrinfo flags=%x sockty=%d proto=%d family=%d target=%s host=%s port=%s\n",
ga_flags, socktype, proto, family, target, dstr, pstr );
if( (error = getaddrinfo( dstr, pstr, &hint, &list )) ) {
- fprintf( stderr, "sigenaddr: error from getaddrinfo: target=%s host=%s port=%s(port): error=(%d) %s\n",
+ fprintf( stderr, "sigenaddr: error from getaddrinfo: target=%s host=%s port=%s(port): error=(%d) %s\n",
target, dstr, pstr, error, gai_strerror( error ) );
} else {
- *rap = (struct sockaddr *) malloc( list->ai_addrlen ); // alloc a buffer and give address to caller
+ *rap = (struct sockaddr *) malloc( list->ai_addrlen ); // alloc a buffer and give address to caller
memcpy( *rap, list->ai_addr, list->ai_addrlen );
rlen = list->ai_addrlen;
-
- freeaddrinfo( list ); // ditch system allocated memory
+
+ freeaddrinfo( list ); // ditch system allocated memory
}
free( fptr );
}
-/*
+/*
Given a source address convert from one form to another based on type constant.
Type const == AC_TODOT Convert source address structure to human readable string.
Type const == AC_TOADDR6 Convert source string (host:port or ipv6 address [n:n...:n]:port) to an address struct
Type const == AC_TOADDR Convert source string (host:port or ipv4 dotted decimal address) to an address struct
*/
extern int SIaddress( void *src, void **dest, int type ) {
- struct sockaddr_in *addr; // pointer to the address
+ struct sockaddr_in *addr; // pointer to the address
struct sockaddr_in6 *addr6; // ip6 has a different layout
- unsigned char *num; // pointer at the address number
+ unsigned char *num; // pointer at the address number
uint8_t* byte; // pointer at the ipv6 address byte values
- char wbuf[256]; // work buffer
- int i;
+ char wbuf[256]; // work buffer
+ int i;
int rlen = 0; // return len - len of address struct or string
switch( type ) {
case AC_TODOT: // convert from a struct to human readable "dotted decimal"
- addr = (struct sockaddr_in *) src;
+ addr = (struct sockaddr_in *) src;
if( addr->sin_family == AF_INET6 ) {
addr6 = (struct sockaddr_in6 *) src; // really an ip6 struct
byte = (uint8_t *) &addr6->sin6_addr;
- sprintf( wbuf, "[%u:%u:%u:%u:%u:%u]:%d",
- *(byte+0), *(byte+1), *(byte+2),
- *(byte+3), *(byte+4), *(byte+5) ,
+ snprintf( wbuf, sizeof( wbuf ), "[%u:%u:%u:%u:%u:%u]:%d",
+ *(byte+0), *(byte+1), *(byte+2),
+ *(byte+3), *(byte+4), *(byte+5) ,
(int) ntohs( addr6->sin6_port ) );
} else {
- num = (char *) &addr->sin_addr.s_addr; // point at the long
- sprintf( wbuf, "%u.%u.%u.%u;%d", *(num+0), *(num+1), *(num+2), *(num+3), (int) ntohs(addr->sin_port) );
+ num = (char *) &addr->sin_addr.s_addr; // point at the long
+ snprintf( wbuf, sizeof( wbuf ), "%u.%u.%u.%u;%d", *(num+0), *(num+1), *(num+2), *(num+3), (int) ntohs(addr->sin_port) );
}
*dest = (void *) strdup( wbuf );
rlen = strlen( *dest );
break;
- case AC_TOADDR6: // from hostname:port string to address for send etc
+ case AC_TOADDR6: // from hostname:port string to address for send etc
return SIgenaddr( src, IPPROTO_TCP, AF_INET6, SOCK_STREAM, (struct sockaddr **) dest );
- case AC_TOADDR: // from dotted decimal to address struct ip4
- //return SIgenaddr( src, AF_INET, IPPROTO_TCP, SOCK_STREAM, (struct sockaddr **) dest );
+ case AC_TOADDR: // from dotted decimal to address struct ip4
return SIgenaddr( src, IPPROTO_TCP, AF_INET, SOCK_STREAM, (struct sockaddr **) dest );
}
* Mnemonic: SIgetaddr
* Abstract: This routine will get the address of the first listening
* block on the tp list and return it in ASCII format to the
-* caller.
+* caller. The dest buffer is assumed to be at least 256 bytes
+* long.
* Parms: gptr - Pointer to the global information block
* buf - Pointer to the buffer to hold the ascii string
* Returns: NI_OK if block found, NI_ERROR if no listen block exists
*
******************************************************************************
*/
-#include "sisetup.h" // get the standard include stuff
+#include "sisetup.h" // get the standard include stuff
extern int SIgetaddr( struct ginfo_blk *gptr, char *buf ) {
- struct tp_blk *tpptr; // Pointer into tp list
- int status = SI_ERROR; // return status
- char *ibuf; // SIaddr now points us at a string, rather than filling ours
+ struct tp_blk *tpptr; // Pointer into tp list
+ int status = SI_ERROR; // return status
+ char *ibuf; // SIaddr now points us at a string, rather than filling ours
- for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags & TPF_LISTENFD);
- tpptr = tpptr->next );
+ for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags & TPF_LISTENFD);
+ tpptr = tpptr->next );
- if( tpptr != NULL )
- {
- SIaddress( tpptr->addr, (void *) &ibuf, AC_TODOT ); // convert to dot fmt
- strcpy( buf, ibuf ); // copy into caller's buffer
+ if( tpptr != NULL )
+ {
+ SIaddress( tpptr->addr, (void *) &ibuf, AC_TODOT ); // convert to dot fmt
+ strncpy( buf, ibuf, 256 ); // copy into caller's buffer
free( ibuf );
- status = SI_OK; // ok status for return
- }
+ status = SI_OK; // ok status for return
+ }
- return status;
-}
+ return status;
+}
-// vim: noet sw=4 ts=4:
+ // vim: noet sw=4 ts=4:
/*
==================================================================================
Copyright (c) 2020 Nokia
* 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)
+* must be a minimum of 64 bytes long.
* 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
*
******************************************************************************
*/
-#include "sisetup.h" // get start up stuff
+#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;
+ 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;
- if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block
- return SI_ERROR;
+ if( gptr->magicnum != MAGICNUM ) { // if not a valid ginfo block
+ return SI_ERROR;
+ }
- for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid;
- tpptr = tpptr->next ); // find transport block
- if( tpptr == NULL )
- return SI_ERROR; // signal bad block
+ for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid; tpptr = tpptr->next ) { // find transport block
+ // no body
+ }
- uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
- addrlen = sizeof( *uaddr );
+ if( tpptr == NULL ) {
+ return SI_ERROR; // signal bad block
+ }
- 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
+ uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) );
+ addrlen = sizeof( *uaddr );
- FD_ZERO( &execpfds ); // clear select info
- FD_SET( tpptr->fd, &execpfds ); // set to check read status
+ 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
- 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;
- }
+ FD_ZERO( &execpfds ); // clear select info
+ FD_SET( tpptr->fd, &execpfds ); // set to check read status
- 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 ?
- if( FD_ISSET( tpptr->fd, &execpfds ) ) // session error?
- {
- SIterm( gptr, tpptr ); // clean up our end of things
- }
- else
- {
- if( (FD_ISSET( tpptr->fd, &readfds )) )
- { // process data if no signal
- 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( 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;
+ }
- 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
+ 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 ?
+ if( FD_ISSET( tpptr->fd, &execpfds ) ) { // session error?
+ SIterm( gptr, tpptr ); // clean up our end of things
+ } else {
+ if( (FD_ISSET( tpptr->fd, &readfds )) ) { // process data if no signal
+ 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
+ strncpy( abuf, acbuf, 64 ); // 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
+ }
+ }
+ } else { // end 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
- free( uaddr );
- return status; // send back the status
-} // SIrcv
+ if( gptr->flags & GIF_SHUTDOWN && gptr->tplist != NULL ) { // shutdown received but sessions not cleaned up
+ SIshutdown( gptr );
+ status = SI_ERROR;
+ }
+
+ free( uaddr );
+ return status; // send back the status
+}
v1hdr = (uta_v1mhdr_t *) old_msg->header; // v1 will work to dig header out of any version
switch( ntohl( v1hdr->rmr_ver ) ) {
case 1:
- memcpy( v1hdr, old_msg->header, sizeof( *v1hdr ) ); // copy complete header
+ hdr = nm->header;
+ memcpy( hdr, old_msg->header, sizeof( *v1hdr ) ); // copy complete header
nm->payload = (void *) v1hdr + sizeof( *v1hdr );
break;