alex af15e0698b Codebase
git-svn-id: svn://10.65.10.50/trunk@4679 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-06-16 13:01:08 +00:00

2058 lines
53 KiB
C
Executable File

/* c4com.c (c)Copyright Sequiter Software Inc., 1988-1996. All rights reserved. */
/* CONNECTION4::connectionFailure indicates an irrecoverable connection error.
In the case of only a CODE4::errorCode condition, communications will still
operate normally */
#include "d4all.h"
#ifndef S4UNIX
#ifdef __TURBOC__
#pragma hdrstop
#endif /* __TUROBC__ */
#endif /* S4UNIX */
/* cannot be inline due to DLL CODE4 structure potential mismatches */
/* available whether or not communications are available */
long S4FUNCTION code4timeout( CODE4 *c4 )
{
#ifdef E4PARM_LOW
if ( c4 == 0 )
return error4( 0, e4parm_null, E91006 ) ;
#endif
return c4->timeout ;
}
/* available whether or not communications are available */
void S4FUNCTION code4timeoutSet( CODE4 *c4, long val )
{
#ifdef E4PARM_LOW
if ( c4 == 0 )
{
error4( 0, e4parm_null, E91007 ) ;
return ;
}
#endif
c4->timeout = val ;
}
#ifndef S4OFF_COMMUNICATIONS
/*#include <conio.h>*/
#ifndef S4SERVER
#ifndef S4UNIX
#include <sys\timeb.h>
#else
#ifndef S4NO_FTIME
#include <sys/timeb.h>
#else
#include <sys/time.h>
#endif
#endif
#endif
#ifdef S4COM_PRINT
static void s4connectionPrint( const int ) ;
#endif
#ifndef E4OFF_STRING
extern long error4seek( long ) ;
#endif
#ifdef E4PARM_LOW
static long packet4len( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->dataLen ;
}
static int packet4setLen( PACKET4 *packet, const long int dataLen )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
packet->dataLen = dataLen ;
return 0 ;
}
static void packet4setStatus( PACKET4 *packet, int status )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->status = status ;
}
static void packet4setType( PACKET4 *packet, const int type )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->type = type ;
}
static int packet4status( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->status ;
}
static long packet4errCode2( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->errCode2 ;
}
static int packet4setErrCode2( PACKET4 *packet, const long code2 )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
packet->errCode2 = code2 ;
return 0 ;
}
static int packet4type( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->type ;
}
static long packet4serverId( const PACKET4 *packet )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return 0 ;
}
return packet->serverDataId ;
}
static long packet4clientId( const PACKET4 *packet )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return 0 ;
}
return packet->clientDataId ;
}
static int packet4didUnlock( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->didUnlock ;
}
static int packet4readLock( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->readLock ;
}
static int packet4unlockAuto( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->unlockAuto ;
}
static void packet4setClientId( PACKET4 *packet, const long id )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->clientDataId = id ;
}
static void packet4setServerId( PACKET4 *packet, const long id )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->serverDataId = id ;
}
static void packet4setReadLock( PACKET4 *packet, const int readLock )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->readLock = readLock ;
}
static void packet4setRequestLockedInfo( PACKET4 *packet, const int val )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->requestLockedInfo = val ;
}
int packet4requestLockedInfo( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->requestLockedInfo ;
}
void packet4setDidUnlock( PACKET4 *packet, const int didUnlock )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->didUnlock = didUnlock ;
}
static void packet4setUnlockAuto( PACKET4 *packet, const int unlockAuto )
{
if ( packet == 0 )
{
error4( 0, e4parm_null, E90159 ) ;
return ;
}
packet->unlockAuto = unlockAuto ;
}
static int packet4partNo( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->partNo ;
}
static int packet4numParts( const PACKET4 *packet )
{
if ( packet == 0 )
return error4( 0, e4parm_null, E90159 ) ;
return packet->numParts ;
}
long connection4clientId( const CONNECTION4 *connection )
{
#ifdef E4PARM_LOW
if ( connection == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return 0 ;
}
#endif
if ( connection->message == 0 )
return 0 ;
return packet4clientId( connection->message->packet ) ;
}
S4CONST char * connection4data( const CONNECTION4 *connection )
{
return connection4dataOffset( connection, 0 ) ;
}
#endif
/* if a single linked message only (case of a receive), then can return parts */
#ifdef S4UTILS
S4CONST char * S4FUNCTION connection4dataOffset( const CONNECTION4 *connection, const unsigned int offset )
#else
S4CONST char *connection4dataOffset( const CONNECTION4 *connection, const unsigned int offset )
#endif
{
MESSAGE4DATA *data ;
#ifdef E4PARM_LOW
if ( connection == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return 0 ;
}
#endif
if ( connection->messageData.nLink != 1 )
{
#ifdef E4ANALYZE
error4( connection->cb, e4info, E90160 ) ;
#endif
return 0 ;
}
data = (MESSAGE4DATA *)l4first( &connection->messageData ) ;
if ( data == 0 )
return 0 ;
return data->data + offset + connection->adjustForLocked ;
}
int connection4disconnect( CONNECTION4 *connection )
{
int rc ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
if ( connection->connected != 0 )
{
#ifdef E4ANALYZE
if ( connection->net == 0 )
return error4( connection->cb, e4struct, E90160 ) ;
#endif
rc = connection4netDisconnect( connection->net ) ;
if ( rc < 0 )
return error4stack( connection->cb, (short)rc, E90160 ) ;
connection->connected = 0 ;
rc = connection4netFree( connection->net ) ;
connection->net = 0 ;
#ifdef S4SERVER
l4remove( &connection->socket->connections, connection ) ;
#endif
return rc ;
}
else
return 0 ;
}
int connection4init( CONNECTION4 *connection, SOCKET4 *socket )
{
#ifdef E4PARM_LOW
if ( socket == 0 || connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
memset( connection, 0, sizeof( CONNECTION4 ) ) ;
connection->cb = socket->cb ;
connection->socket = socket ;
return 0 ;
}
int connection4initUndo( CONNECTION4 *connection )
{
int rc ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
#ifdef E4ANALYZE
connection->initUndone = 1 ;
#endif
rc = connection4disconnect( connection ) ;
connection4clear( connection ) ;
if ( connection->net != 0 )
{
connection4netInitUndo( connection->net ) ;
connection4netFree( connection->net ) ;
connection->net = 0 ;
}
if ( connection->message != 0 )
{
message4free( connection->cb, connection->message ) ;
connection->message = 0 ;
}
return rc ;
}
#ifdef E4PARM_LOW
int connection4free( CONNECTION4 *connection )
{
if ( connection == 0 )
return 0 ;
#ifdef E4ANALYZE
if ( connection->initUndone != 1 )
return error4( connection->cb, e4info, E90160 ) ;
#endif
mem4free( connection->cb->connectionMemory, connection ) ;
return 0 ;
}
/* if connection is null, it means dealing with a system file, so return 0L */
long connection4id( const CONNECTION4 *connection )
{
if ( connection == 0 )
return 0L ;
return connection4netId( connection->net ) ;
}
int connection4didUnlock( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4didUnlock( connection->message->packet ) ;
}
int connection4readLock( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4readLock( connection->message->packet ) ;
}
int connection4unlockAuto( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4unlockAuto( connection->message->packet ) ;
}
#endif /* E4PARM_LOW -- i.e. inline */
static int connection4messageAlloc( CONNECTION4 *connection )
{
if ( connection->message == 0 )
{
connection->message = message4alloc( connection->cb, (unsigned int)connection4netMessageLen( connection->net ) ) ;
if ( connection->message == 0 )
return error4( connection->cb, e4memory, E90160 ) ;
}
return 0 ;
}
static MESSAGE4DATA *connection4allocateData( CONNECTION4 *connection, const unsigned allocLen, const int doAlloc, const int insert )
{
CODE4 *c4 ;
int rc ;
MESSAGE4DATA *messageLink ;
c4 = connection->cb ;
rc = connection4messageAlloc( connection ) ;
if ( rc != 0 )
{
#ifdef E4STACK
error4stack( c4, (short)rc, E90160 ) ;
#endif
return 0 ;
}
if ( c4->messageLinkMemory == 0 )
{
c4->messageLinkMemory = mem4create( c4, 20, sizeof( MESSAGE4DATA ), 10, 0 ) ;
if ( c4->messageLinkMemory == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90160 ) ;
#endif
return 0 ;
}
}
messageLink = 0 ;
if ( doAlloc == 1 ) /* check with local list first */
if ( allocLen <= COM4DEFAULT_MESSAGE_LEN ) /* if <= 512, try to get from local list to avoid allocate/deallocate sequence */
messageLink = (MESSAGE4DATA *)l4pop( &c4->availDataMessages ) ;
if ( messageLink == 0 )
{
messageLink = (MESSAGE4DATA *)mem4alloc( c4->messageLinkMemory ) ;
if ( messageLink == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90160 ) ;
#endif
return 0 ;
}
}
if ( doAlloc == 1 )
{
if ( messageLink->allocLen == 0 )
{
if ( allocLen <= COM4DEFAULT_MESSAGE_LEN )
{
messageLink->allocatedData = (char *)u4allocEr( c4, (long)COM4DEFAULT_MESSAGE_LEN ) ;
if ( messageLink->allocatedData != 0 )
messageLink->allocLen = COM4DEFAULT_MESSAGE_LEN ;
}
else
{
messageLink->allocatedData = (char *)u4allocEr( c4, (long)allocLen ) ;
}
if ( messageLink->allocatedData == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90160 ) ;
#endif
return 0 ;
}
messageLink->data = messageLink->allocatedData ;
messageLink->didAlloc = 1 ;
}
}
else
messageLink->didAlloc = 0 ;
messageLink->len = allocLen ;
if ( insert == 1 )
l4addBefore( &connection->messageData, l4first( &connection->messageData ), messageLink ) ;
else
l4add( &connection->messageData, messageLink ) ;
connection->totalDataLen += allocLen ;
return messageLink ;
}
/* a null data paramater means that the space should be allocated but none inserted */
/* a return code of '1' means that the data was repositioned */
int connection4insertData( CONNECTION4 *connection, const void *data, const unsigned dataLen, const int doAlloc, const int insert )
{
MESSAGE4DATA *messageLink ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
if ( connection->connectionFailure < 0 )
return connection->connectionFailure ;
if ( dataLen == 0 )
return 0 ;
messageLink = connection4allocateData( connection, dataLen, doAlloc, insert ) ;
if ( messageLink == 0 )
return error4stack( connection->c4, e4memory, E90160 ) ;
if ( doAlloc == 1 )
memcpy( messageLink->allocatedData, data, dataLen ) ;
else
messageLink->data = (char *)data ;
return 0 ;
}
CONNECTION4 *connection4alloc( SOCKET4 *socket )
{
int rc ;
CONNECTION4 *connection ;
CODE4 *c4 ;
#ifdef E4PARM_LOW
if ( socket == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return 0 ;
}
#endif
c4 = socket->cb ;
if ( c4->connectionMemory == 0 )
{
#ifdef S4SERVER
c4->connectionMemory = mem4create( c4, 10, sizeof( CONNECTION4 ), 5, 0 ) ;
#else
c4->connectionMemory = mem4create( c4, 2, sizeof( CONNECTION4 ), 1, 0 ) ;
#endif
if ( c4->connectionMemory == 0 )
return 0 ;
}
connection = (CONNECTION4 *)mem4alloc( c4->connectionMemory ) ;
if ( connection == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90160 ) ;
#endif
return 0 ;
}
connection->cb = c4 ;
rc = connection4init( connection, socket ) ;
if ( rc < 0 )
{
#ifdef E4STACK
error4stack( c4, (short)rc, E90160 ) ;
#endif
return 0 ;
}
return connection ;
}
/* sets up basic required info, and clears the data connectionmunication set */
#ifdef S4UTILS
int S4FUNCTION connection4assign( CONNECTION4 *connection, const int type, const long clientId, const long serverId )
#else
int connection4assign( CONNECTION4 *connection, const int type, const long clientId, const long serverId )
#endif
{
int rc ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
if ( connection->connectionFailure < 0 )
return connection->connectionFailure ;
if ( connection->net != 0 ) /* the default server will have a null net */
{
rc = connection4messageAlloc( connection ) ;
if ( rc < 0 )
{
connection->connectionFailure = rc ;
return error4stack( connection->cb, (short)rc, E90160 ) ;
}
}
#ifdef E4ANALYZE
if ( connection->message == 0 )
{
connection->connectionFailure = e4struct ;
return error4( connection->cb, e4struct, E90160 ) ;
}
#endif
#ifndef S4SERVER
connection->cb->lockedLockItem = -2L ;
connection->cb->lockedFileName = 0 ;
connection->cb->lockedUserId = 0 ;
connection->cb->lockedNetId = 0 ;
connection->adjustForLocked = 0 ;
if ( connection->message != 0 )
connection4setRequestLockedInfo( connection, 0 ) ;
#endif
packet4setType( connection->message->packet, type ) ;
packet4setStatus( connection->message->packet, 0 ) ;
packet4setClientId( connection->message->packet, clientId ) ;
packet4setServerId( connection->message->packet, serverId ) ;
#ifndef S4SERVER
packet4setReadLock( connection->message->packet, connection->cb->readLock ) ;
packet4setUnlockAuto( connection->message->packet, code4unlockAuto( connection->cb ) ) ;
#endif
return connection4clear( connection ) ;
}
int connection4clear( CONNECTION4 *connection )
{
MESSAGE4DATA *link ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->cb == 0 )
{
#ifdef S4SERVER
if ( connection->messageData.nLink != 0 )
#endif
return error4( 0, e4parm, E90160 ) ;
}
#endif
/* WARNING: do not modify this function without making appropriate changes
to connection4repeat() which emulates portions of this function */
connection->totalDataLen = 0L ;
for ( ;; )
{
link = (MESSAGE4DATA *)l4first( &connection->messageData ) ;
if ( link == 0 )
break ;
l4remove( &connection->messageData, link ) ;
if ( link->didAlloc == 1 )
{
if ( link->allocLen == COM4DEFAULT_MESSAGE_LEN )
l4add( &connection->cb->availDataMessages, link ) ;
else
{
u4free( link->allocatedData ) ;
link->didAlloc = 0 ;
mem4free( connection->cb->messageLinkMemory, link ) ;
}
}
else
mem4free( connection->cb->messageLinkMemory, link ) ;
}
return 0 ;
}
#define packet4connectionId( p ) ( (p)->connectionId )
static MESSAGE4 *connection4returnMessage( CONNECTION4 *connection, const CONNECTION4ID id, const int partNo )
{
MESSAGE4 *message ;
for ( message = 0 ;; )
{
message = (MESSAGE4 *)l4next( &connection->receivedMessages, message ) ;
if ( message == 0 )
return 0 ;
if ( packet4connectionId( message->packet ) == id && packet4partNo( message->packet ) == partNo )
{
l4remove( &connection->receivedMessages, message ) ;
return message ;
}
}
}
#ifndef S4SERVER
static int code4unlockSet( CODE4 *c4 )
{
DATA4FILE *data ;
LOCK4LINK *lock ;
#ifdef E4PARM_LOW
if ( c4 == 0 )
return error4( 0, e4parm_null, E90155 ) ;
#endif
for( data = 0 ;; )
{
data = (DATA4FILE *)l4next( &c4->dataFileList, data ) ;
if ( data == 0 )
return 0 ;
data->numRecs = -1 ;
#ifdef S4CLIENT
data->appendLock = 0 ;
data->fileLock = 0 ;
#endif
for( ;; )
{
lock = (LOCK4LINK *)l4first( &data->lockedRecords ) ;
if ( lock == 0 )
break ;
l4remove( &data->lockedRecords, lock ) ;
mem4free( c4->lockLinkMemory, lock ) ;
}
}
}
#endif
#ifndef S4SERVER
#ifdef S4UTILS
int S4FUNCTION connection4receive( CONNECTION4 *connection )
#else
int connection4receive( CONNECTION4 *connection )
#endif
{
int rc, len, totLen, conLen; /*, hundredths ;*/
long totalHundredths, countHundredths ;
const char *ptr ;
CODE4 *c4 ;
CONNECTION4 *messageConnection ;
#ifdef S4NO_FTIME
struct timeval oldTime, newTime ;
#else
struct timeb oldTime, newTime ;
#endif
#ifdef S4TIMEOUT_HOOK
int count, elapsedHundredths ;
struct timeb origTime ;
#endif
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
c4 = connection->cb ;
#ifdef E4ANALYZE
if ( c4 == 0 )
return error4( 0, e4struct, E90160 ) ;
#endif
if ( connection->connectionFailure < 0 )
return connection->connectionFailure ;
if ( connection->message != 0 )
{
connection4clear( connection ) ;
message4free( c4, connection->message ) ;
connection->message = 0 ;
}
connection->totalDataLen = 0 ;
#ifndef S4NO_FTIME
ftime( &oldTime) ;
#else
gettimeofday(&oldTime, NULL ) ;
#endif
totalHundredths = code4timeout( c4 ) ;
if ( totalHundredths > 0 )
totalHundredths *= 100 ;
#ifdef S4TIMEOUT_HOOK
ftime( &origTime) ;
for( count = 0 ;; )
#else
for( ;; )
#endif
{
messageConnection = socket4receiveMessage( connection->socket ) ;
if ( messageConnection != 0 )
{
if ( connection4didUnlock( connection ) == 1 )
rc = code4unlockSet( c4 ) ;
else
{
rc = 0 ;
if ( connection4type( connection ) == CON4DISCONNECT )
{
connection->connectionFailure = e4connection ;
return error4( c4, e4connection, E80220 ) ;
}
}
connection->adjustForLocked = 0 ;
if ( connection4requestLockedInfo( connection ) == 1 )
if ( connection4status( connection ) == r4locked )
{
conLen = (int)connection4len( connection ) ;
totLen = sizeof( c4->lockedLockItem ) ;
if ( conLen < totLen + 3 )
return error4( c4, e4packetLen, E90160 ) ;
ptr = connection4data( connection ) ;
c4->lockedLockItem = *((long *)ptr ) ;
ptr += sizeof( c4->lockedLockItem ) ;
len = strlen( ptr ) ;
totLen += len + 1 ;
if ( conLen < totLen )
return error4( c4, e4packetLen, E90160 ) ;
c4->lockedFileName = ptr ;
ptr += (len + 1) ;
len = strlen( ptr ) ;
totLen += len + 1 ;
if ( conLen < totLen )
return error4( c4, e4packetLen, E90160 ) ;
c4->lockedUserId = ptr ;
ptr += (len + 1) ;
len = strlen( ptr ) ;
totLen += len + 1 ;
if ( conLen < totLen )
return error4( c4, e4packetLen, E90160 ) ;
c4->lockedNetId = ptr ;
connection->adjustForLocked = totLen ;
}
return rc ;
}
if ( error4code( c4 ) < 0 )
return error4stack( c4, error4code( c4 ), E90160 ) ;
if ( totalHundredths != -1 )
{
#ifndef S4NO_FTIME
ftime( &newTime ) ;
countHundredths = ((newTime.time - oldTime.time)*100 ) + (( (int)newTime.millitm - (int)oldTime.millitm ) / 10 ) ;
#else
gettimeofday(&newTime, NULL ) ;
countHundredths = ((newTime.tv_sec-oldTime.tv_sec)*100) + (( (int)newTime.tv_usec - (int)oldTime.tv_usec ) / 10000 ) ;
#endif
if ( countHundredths > totalHundredths )
{
#ifdef S4TIMEOUT_HOOK
elapsedHundredths = (int)( ((newTime.time - origTime.time)*100 ) + (( (int)newTime.millitm - (int)origTime.millitm ) / 10 ) ) ;
rc = code4timeoutHook( c4, count, elapsedHundredths ) ;
if ( rc != 0 )
return rc ;
count++ ;
ftime( &oldTime ) ;
#else
return error4( c4, e4timeOut, E81006 ) ;
#endif
}
}
connection4yield( connection ) ;
}
}
#endif /* S4SERVER */
CONNECTION4 * socket4receiveMessage( SOCKET4 *socket )
{
MESSAGE4 *message, *partialMessage, *returnMessage ;
MESSAGE4DATA *messageData = 0 ;
CONNECTION4ID connectionId ;
int partNo ;
int offset = 0 ;
unsigned int numParts, i ;
CONNECTION4 *connection ;
CODE4 *c4 ;
#ifdef S4SERVER
SERVER4CLIENT *client ;
#endif
#ifdef E4PARM_LOW
if ( socket == 0 )
{
error4( 0, e4parm_null, E90161 ) ;
return 0 ;
}
#endif
#ifdef E4ANALYZE
if ( socket->cb == 0 )
{
error4( 0, e4struct, E90161 ) ;
return 0 ;
}
#endif
c4 = socket->cb ;
#ifndef S4SERVER
connection = socket->connect ;
#endif
for( ;; )
{
message = socket4receive( socket ) ;
if ( message == 0 )
return 0 ;
#ifdef S4SERVER
client = server4client( c4->server, message->packet->connectionId ) ;
if ( client == 0 ) /* could be a crashed client, so just delete message */
{
message4free( c4, message ) ;
return 0 ;
}
connection = client->connection ;
#endif
if ( message != 0 ) /* is this the complete message? */
{
/* if a disconnect message received, any pending messages for the client are deleted
and the disconnect message is forwarded */
if ( packet4type( message->packet ) == CON4DISCONNECT )
{
for ( ;; )
{
partialMessage = (MESSAGE4 *)l4first( &connection->receivedMessages ) ;
if ( partialMessage == 0 )
break ;
l4remove( &connection->receivedMessages, partialMessage ) ;
message4free( c4, partialMessage ) ;
}
if ( connection->message != 0 )
{
message4free( c4, connection->message ) ;
connection->message = 0 ;
}
#ifdef E4ANALYZE
if ( packet4numParts( message->packet ) != 1 ) /* disconnect cannot span parts */
{
error4( c4, e4info, E90160 ) ;
return 0 ;
}
#endif
}
#ifdef E4ANALYZE
if ( connection->message != 0 )
{
error4( c4, e4info, E90160 ) ;
return 0 ;
}
#endif
#ifdef S4DISTRIBUTED
if ( packet4connectionId( message->packet ) != connection4netSourceId( connection->net ) )
{
/* message from another server, maybe a disconnect. */
/* error for now */
error4( c4, e4connection, "connection4receive() - invalid message received" ) ;
return 0 ;
}
#endif
numParts = (unsigned int)packet4numParts( message->packet ) ;
if ( numParts == 1 )
{
connection->message = message ;
connection4addData( connection, (char *)(((char *)message->packet) + message->packet->packetDataOffset), message->packet->packetDataLen, 0 ) ;
return connection ;
}
connectionId = packet4connectionId( message->packet ) ;
numParts-- ;
/* check if we can complete a message with available parts */
if ( connection->receivedMessages.nLink < numParts ) /* insufficient supply of parts */
{
l4add( &connection->receivedMessages, message ) ;
partialMessage = 0 ;
}
else
for ( partialMessage = 0 ;; )
{
partialMessage = (MESSAGE4 *)l4next( &connection->receivedMessages, partialMessage ) ;
if ( partialMessage == 0 ) /* can't complete... */
{
l4add( &connection->receivedMessages, message ) ;
break ;
}
if ( packet4connectionId( partialMessage->packet ) == connectionId )
{
numParts-- ;
if ( numParts == 0 ) /* should be able to create a complete message */
break ;
}
}
if ( partialMessage == 0 ) /* get an additional message */
continue ;
numParts = packet4numParts( message->packet ) ;
partNo = packet4partNo( message->packet ) ;
returnMessage = 0 ;
for ( i = 1 ; i <= numParts ; i++ )
{
if ( (unsigned int)partNo == i )
partialMessage = message ;
else /* need to get the message */
partialMessage = connection4returnMessage( connection, connectionId, i ) ;
if ( partialMessage == 0 )
{
if ( returnMessage != 0 && message != returnMessage )
message4free( c4, returnMessage ) ;
if ( message != 0 )
message4free( c4, message ) ;
connection->message = 0 ;
error4( c4, e4message, E90160 ) ;
return 0 ;
}
if ( i == 1 )
{
connection->message = partialMessage ;
returnMessage = partialMessage ;
#ifdef E4ANALYZE
if ( connection4len( connection ) > UINT_MAX )
{
error4( c4, e4info, E90160 ) ;
return 0 ;
}
#endif
messageData = connection4allocateData( connection, (unsigned int)connection4len( connection ), 1, 0 ) ;
if ( messageData == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90160 ) ;
#endif
return 0 ;
}
#ifdef E4ANALYZE
if ( messageData->len < partialMessage->packet->packetDataLen )
{
error4( c4, e4info, E90160 ) ;
return 0 ;
}
#endif
memcpy( messageData->allocatedData, (char *)(((char *)partialMessage->packet) + partialMessage->packet->packetDataOffset), partialMessage->packet->packetDataLen ) ;
offset = partialMessage->packet->packetDataLen ;
}
else
{
#ifdef E4ANALYZE
if ( messageData->len < partialMessage->packet->packetDataLen + offset )
{
error4( c4, e4info, E90160 ) ;
return 0 ;
}
#endif
memcpy( messageData->allocatedData + offset, (char *)(((char *)partialMessage->packet) + partialMessage->packet->packetDataOffset), partialMessage->packet->packetDataLen ) ;
offset += partialMessage->packet->packetDataLen ;
}
if ( i != 1 )
{
if ( message == partialMessage )
message = 0 ;
message4free( c4, partialMessage ) ;
}
}
#ifdef S4COM_PRINT
if ( partNo == 1 && returnMessage != 0 )
{
printf( "Received Message: " ) ;
s4connectionPrint( packet4type( returnMessage->packet ) ) ;
}
#endif
return connection ;
}
return 0 ;
}
}
/* return code of 1 means done. input len is amount available for writing, startPos is where to start writing */
static int connection4placeData( CONNECTION4 *connection, unsigned short int *dataPos, unsigned short int len, unsigned short int startLen, MESSAGE4DATA **dataIn )
{
MESSAGE4DATA *data ;
data = *dataIn ;
if ( data == 0 )
data = (MESSAGE4DATA *)l4first( &connection->messageData ) ;
if ( data == 0 )
return 1 ;
while ( ( data->len - *dataPos ) <= len )
{
memcpy( ((char *)connection->message->packet) + startLen, data->data + *dataPos, data->len - (long)*dataPos ) ;
len -= (unsigned short)( data->len - *dataPos ) ;
startLen += (unsigned short)( data->len - *dataPos ) ;
data = (MESSAGE4DATA *)l4next( &connection->messageData, data ) ;
*dataPos = 0 ;
if ( data == 0 )
{
*dataIn = data ; /* changed */
return 1 ;
}
if ( len == 0 )
{
*dataIn = data ;
return 0 ;
}
}
memcpy( ((char *)connection->message->packet) + startLen, data->data + *dataPos, len ) ;
*dataPos += len ;
*dataIn = data ;
return 0 ;
}
#ifndef S4SERVER
/* performs a send/receive loop as long as return code is loopCode numRepeat times (or
forever if numRepeat == - 1 )
assigning -2 to numRepeat, or -1 to delayHundredths or loopCode results in their taking
default appropriate CODE4 values */
int connection4repeat( CONNECTION4 *connection, const int numRepeat, const int loopCodeIn, const int delayHundredthsIn, DATA4 *d4 )
{
int rc, loop, delayHundredths, loopCode, saveAdjustedLen ;
MESSAGE4 *saveMessage, *saveMessage2 ;
PACKET4 savePacketInfo ;
LIST4 saveData, saveData2 ;
unsigned long int saveTotal, saveTotal2 ;
CODE4 *c4 ;
#ifdef S4LOCK_HOOK
int count ;
#endif
#ifdef E4PARM_LOW
if ( connection == 0 || numRepeat < -2 )
return error4( 0, e4parm, E90160 ) ;
#endif
c4 = connection->cb ;
loop = numRepeat ;
if ( loop == 0 )
loop = 1 ;
if ( loop == -2 )
loop = c4->lockAttempts ;
if ( loopCodeIn == -1 )
loopCode = r4locked ;
else
loopCode = loopCodeIn ;
if ( delayHundredthsIn == -1 )
delayHundredths = c4->lockDelay ;
else
delayHundredths = delayHundredthsIn ;
saveMessage = connection->message ;
memcpy( &saveData, &connection->messageData, sizeof( LIST4 ) ) ;
memcpy( &savePacketInfo, connection->message->packet, sizeof( PACKET4 ) ) ;
saveTotal = connection->totalDataLen ;
#ifdef S4LOCK_HOOK
for ( count = 0 ;; count++ )
#else
for ( ;; )
#endif
{
if ( loop != numRepeat )
{
connection->message = saveMessage ;
memcpy( &connection->messageData, &saveData, sizeof( LIST4 ) ) ;
memcpy( connection->message->packet, &savePacketInfo, sizeof( PACKET4 ) );
}
if ( loop > 0 )
loop-- ;
c4->lockedLockItem = -2L ;
c4->lockedFileName = 0 ;
c4->lockedUserId = 0 ;
c4->lockedNetId = 0 ;
connection->adjustForLocked = 0 ;
connection->totalDataLen = saveTotal ;
#ifndef S4LOCK_HOOK
/* in the case of lock hook, always set, otherwise only set just before return */
if ( loop == 0 ) /* will return next call, so get lock info if r4locked */
#endif
connection4setRequestLockedInfo( connection, 1 ) ;
connection4send( connection ) ;
connection->message = 0 ;
memset( &connection->messageData, 0, sizeof( LIST4 ) ) ;
connection->totalDataLen = 0 ;
rc = connection4receive( connection ) ;
if ( rc < 0 )
break ;
#ifndef S4STAND_ALONE
if ( d4 != 0 )
if ( packet4didUnlockData( connection->message->packet ) == 1 )
d4unlockClientData( d4 ) ;
#endif
rc = connection4status( connection ) ;
if ( loop == 0 ) /* get receive return if loop == 0 */
break ;
if ( rc != loopCode )
break ;
#ifdef S4LOCK_HOOK
rc = code4lockHook( c4, c4->lockedFileName, c4->lockedUserId, c4->lockedNetId, c4->lockedLockItem, count ) ;
if ( rc != 0 )
break ;
#endif
if ( connection->message != 0 )
{
connection4clear( connection ) ;
message4free( c4, connection->message ) ;
connection->message = 0 ;
}
u4delayHundredth( delayHundredths ) ;
}
saveMessage2 = connection->message ;
saveAdjustedLen = connection->adjustForLocked ;
if ( saveMessage2 != 0 )
{
memcpy( &saveData2, &connection->messageData, sizeof( LIST4 ) ) ;
saveTotal2 = connection->totalDataLen ;
}
if ( saveMessage != 0 )
{
connection->message = saveMessage ;
memcpy( &connection->messageData, &saveData, sizeof( LIST4 ) ) ;
memcpy( connection->message->packet, &savePacketInfo, sizeof( PACKET4 ) );
connection->totalDataLen = saveTotal ;
connection4clear( connection ) ;
message4free( c4, connection->message ) ;
connection->message = 0 ;
}
if ( saveMessage2 != 0 )
{
connection->message = saveMessage2 ;
memcpy( &connection->messageData, &saveData2, sizeof( LIST4 ) ) ;
connection->totalDataLen = saveTotal2 ;
connection->adjustForLocked = saveAdjustedLen ;
}
return rc ;
}
#endif /* S4SERVER */
#ifdef S4UTILS
int S4FUNCTION connection4send( CONNECTION4 *connection )
#else
int connection4send( CONNECTION4 *connection )
#endif
{
int rc, numParts, partNo ;
unsigned short int messageSendLen, incLen, dataPos, startLen ;
long int connectionLen ;
PACKET4HEADER *header ;
CONNECTION4ID id ;
MESSAGE4DATA *data ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
#ifdef E4ANALYZE
if ( connection->cb == 0 )
return error4( 0, e4struct, E90160 ) ;
if ( connection->message == 0 )
{
connection->connectionFailure = e4struct ;
return error4( 0, e4struct, E90160 ) ;
}
#endif
if ( connection->connectionFailure < 0 )
return connection->connectionFailure ;
rc = connection4setLen( connection, connection->totalDataLen ) ;
if ( rc < 0 )
{
connection->connectionFailure = rc ;
return error4stack( connection->cb, (short)rc, E90160 ) ;
}
#ifdef S4COM_PRINT
printf( "Sending Message: " ) ;
s4connectionPrint( connection4type( connection ) ) ;
#endif
messageSendLen = connection4netMessageLen( connection->net ) ;
#ifdef E4ANALYZE
if ( messageSendLen < sizeof( PACKET4 ) )
{
connection->connectionFailure = e4info ;
return error4( connection->cb, e4info, E90160 ) ;
}
#endif
connectionLen = connection4len( connection ) ;
if ( connectionLen < 0 )
{
connection->connectionFailure = (short)connectionLen ;
return error4stack( connection->cb, (short)connectionLen, E90160 ) ;
}
startLen = messageSendLen - sizeof( PACKET4 ) ;
if ( connectionLen < (long)startLen )
startLen = (unsigned short int)connectionLen ;
incLen = messageSendLen - sizeof( PACKET4HEADER ) ;
numParts = (int) ( ( ( connectionLen - startLen ) + ( incLen - 1 ) ) / incLen + 1 ) ;
id = connection4netDestId( connection->net ) ;
memcpy( &connection->message->packet->connectionId, &id, sizeof( CONNECTION4ID ) ) ;
header = (PACKET4HEADER *)(connection->message->packet) ;
header->numParts = numParts ;
#ifndef S4SERVER
packet4setDidUnlock( connection->message->packet, 0 ) ;
packet4setDidUnlockData( connection->message->packet, 0 ) ;
#endif
dataPos = 0 ;
for( partNo = 1 ; partNo <= numParts ; partNo++ )
{
if ( partNo == 1 )
{
data = 0 ;
connection4placeData( connection, &dataPos, startLen, sizeof( PACKET4 ), &data ) ;
header->packetDataLen = startLen ;
header->packetDataOffset = sizeof( PACKET4 ) ;
}
else
{
if ( partNo == numParts )
incLen = (unsigned short int)(connectionLen - startLen - ( ( numParts - 2 ) * incLen ) ) ;
connection4placeData( connection, &dataPos, incLen, sizeof( PACKET4HEADER ), &data ) ;
header->packetDataLen = incLen ;
header->packetDataOffset = sizeof( PACKET4HEADER ) ;
}
header->partNo = partNo ;
rc = connection4netSend( connection->net, connection->message ) ;
if ( rc < 0 )
{
connection->connectionFailure = rc ;
return error4stack( connection->cb, (short)rc, E90160 ) ;
}
}
return 0 ;
}
int connection4setStatus( CONNECTION4 *connection, const int status )
{
int rc ;
#ifdef E4PARM_LOW
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
#endif
rc = connection4messageAlloc( connection ) ;
if ( rc < 0 )
return error4stack( connection->cb, (short)rc, E90160 ) ;
#ifdef E4ANALYZE
if ( connection->message == 0 )
return error4( connection->cb, e4parm_null, E90160 ) ;
#endif
packet4setStatus( connection->message->packet, status ) ;
#ifdef E4OFF_STRING
return packet4setErrCode2( connection->message->packet, connection->cb->errorCode2 ) ;
#else
return packet4setErrCode2( connection->message->packet, error4number2( connection->cb->errorCode2 ) ) ;
#endif
}
int connection4errorDescribeExecute( const CONNECTION4 *connection, CODE4 *c4, int c1, long c2, const char *s1, const char *s2, const char *s3 )
{
long cErr ;
if ( connection->message == 0 )
cErr = c2 ;
else
{
cErr = connection4errCode2( connection ) ;
if ( c2 != 0 && ( cErr > 90000 || cErr == 0 ) )
cErr = c2 ;
#ifndef E4OFF_STRING
else
cErr = error4seek( cErr ) ; /* convert the long value to the appropriate positional value */
#endif
}
return error4describeExecute( c4, c1, cErr, s1, s2, s3 ) ;
}
#ifdef E4PARM_LOW
long connection4serverId( const CONNECTION4 *connection )
{
if ( connection == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return 0 ;
}
if ( connection->message == 0 )
{
error4( 0, e4struct, E90160 ) ;
return 0 ;
}
return packet4serverId( connection->message->packet ) ;
}
long int connection4len( const CONNECTION4 *connection )
{
if ( connection == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return 0 ;
}
if ( connection->message == 0 )
{
error4( 0, e4struct, E90160 ) ;
return 0 ;
}
return ( packet4len( connection->message->packet ) - connection->adjustForLocked ) ;
}
int connection4setLen( CONNECTION4 *connection, const long int dataLen )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4setLen( connection->message->packet, dataLen ) ;
}
void connection4setRequestLockedInfo( CONNECTION4 *connection, int val )
{
if ( connection == 0 )
{
error4( 0, e4parm_null, E90160 ) ;
return ;
}
if ( connection->message == 0 )
{
error4( 0, e4struct, E90160 ) ;
return ;
}
packet4setRequestLockedInfo( connection->message->packet, val ) ;
}
int connection4status( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4status( connection->message->packet ) ;
}
long connection4errCode2( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4errCode2( connection->message->packet ) ;
}
int connection4type( const CONNECTION4 *connection )
{
if ( connection == 0 )
return error4( 0, e4parm_null, E90160 ) ;
if ( connection->message == 0 )
return error4( 0, e4struct, E90160 ) ;
return packet4type( connection->message->packet ) ;
}
#endif /* E4PARM_LOW -- i.e. inline */
SOCKET4 *socket4alloc( CODE4 *c4 )
{
SOCKET4 *socket ;
#ifdef E4PARM_LOW
if ( c4 == 0 )
{
error4( 0, e4parm_null, E90161 ) ;
return 0 ;
}
#endif
socket = (SOCKET4 *)u4allocFree( c4, (long)sizeof( SOCKET4 ) ) ;
if ( socket == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90161 ) ;
#endif
return 0 ;
}
socket->cb = c4 ;
socket->net = socket4netAlloc( socket ) ;
if ( socket->net == 0 )
{
#ifdef E4STACK
error4stack( c4, e4memory, E90161 ) ;
#endif
u4free( socket ) ;
return 0 ;
}
return socket ;
}
int socket4connect( SOCKET4 *socket, const char *serverName, const char *processId )
{
int rc ;
CODE4 *c4 ;
#ifndef S4SERVER
int len ;
#endif
#ifdef E4PARM_LOW
if ( socket == 0 )
return error4( 0, e4parm_null, E90161 ) ;
#ifndef S4SERVER
if ( serverName == 0 )
return error4( socket->cb, e4parm_null, E90161 ) ;
#endif
#endif
c4 = socket->cb ;
#ifdef E4ANALYZE
if ( socket->connect != 0 )
return error4( c4, e4connection, E80101 ) ;
#endif
for ( rc = 0 ;; )
{
socket->connect = connection4alloc( socket ) ;
if ( socket->connect == 0 )
{
rc = e4connection ;
break ;
}
#ifndef S4SERVER
len = strlen( serverName ) ;
len = len < sizeof( socket->serverName ) ? len : sizeof( socket->serverName ) - 1 ;
memcpy( socket->serverName, serverName, len ) ;
c4upper( socket->serverName ) ;
#endif
if ( socket->connect->net != 0 )
{
rc = e4socket ;
break ;
}
socket->connect->net = connection4netAlloc( socket->net ) ;
if ( socket->connect->net == 0 )
{
rc = error4code( c4 ) ;
if ( rc == 0 )
rc = e4memory ;
}
else
rc = connection4netInit( socket->connect->net, socket->net ) ;
if ( rc < 0 )
break ;
#ifdef S4SERVER
rc = socket4netConnectClient( socket->net, socket->connect, socket->connect->net ) ;
#else
rc = socket4netConnectServer( socket->net, socket->connect->net, socket->serverName, processId ) ;
if ( rc < 0 )
break ;
rc = connection4receive( socket->connect ) ;
if ( rc < 0 )
break ;
if ( connection4type( socket->connect ) != CON4ACK )
rc = error4( c4, e4connection, E80229 ) ;
#endif
break ;
}
if ( rc < 0 )
{
if ( error4code( c4 ) < 0 )
return error4code( c4 ) ;
return error4( c4, (short int)rc, E90161 ) ;
}
#ifndef S4SERVER
socket->connect->connected = 1 ;
#ifdef S4DISTRIBUTED
l4add( &c4->servers, socket ) ;
#endif
#endif
return 0 ;
}
CODE4 * S4FUNCTION socket4codeBase( SOCKET4 *socket )
{
return socket->cb ;
}
#ifdef S4SERVER
int socket4verifyConnections( SOCKET4 *socket )
{
SERVER4CLIENT *client, *nextClient ;
for ( nextClient = (SERVER4CLIENT *)l4first( &socket->cb->server->clients ) ;; )
{
client = nextClient ;
nextClient = (SERVER4CLIENT *)l4next( &socket->cb->server->clients, client ) ;
if ( client == 0 )
break ;
if ( client->connection != 0 )
if ( client->connection->connected )
if ( connection4netDisconnected( client->connection->net ) == 1 )
server4disconnect( client->server, client ) ;
}
return 0 ;
}
int socket4connected( SOCKET4 *socket )
{
int rc ;
CONNECTION4 *connection ;
#ifdef E4PARM_LOW
if ( socket == 0 )
return error4( 0, e4parm_null, E90161 ) ;
#endif
#ifdef E4ANALYZE
if ( socket->connect == 0 || socket->net == 0 )
return error4( socket->cb, e4struct, E90161 ) ;
#endif
rc = socket4netConnected( socket->net ) ;
if ( rc == 1 )
{
if ( socket->connect->net == 0 )
return error4( 0, e4info, E90161 ) ;
socket4verifyConnections( socket ) ; /* make sure existing connections are all valid */
socket->connect->connected = 1 ;
l4add( &socket->connections, socket->connect ) ;
connection = socket->connect ;
socket->connect = 0 ;
/* and send the acknowledgement message */
connection4assign( connection, CON4ACK, 0L, 0L ) ;
rc = connection4send( connection ) ;
if ( connection->message != 0 )
{
connection4clear( connection ) ;
message4free( socket->cb, connection->message ) ;
connection->message = 0 ;
}
if ( rc < 0 )
return error4stack( socket->cb, rc, E90161 ) ;
return 1 ;
}
return rc ;
}
#endif
#ifdef E4PARM_LOW
int socket4free( SOCKET4 *socket )
{
if ( socket == 0 )
return 0 ;
#ifdef E4ANALYZE
if ( socket->initUndone != 1 )
return error4( 0, e4info, E90161 ) ;
#endif
u4free( socket ) ;
return 0 ;
}
int socket4init( SOCKET4 *socket, CODE4 *c4, const char *socketName, const char *processId )
{
#ifdef E4PARM_LOW
if ( socket == 0 || c4 == 0 )
return error4( c4, e4parm_null, E90161 ) ;
#ifdef S4SERVER
if ( socketName == 0 )
return error4( c4, e4parm_null, E90161 ) ;
#endif
#endif
socket->cb = c4 ;
if ( processId == 0 )
processId = DEF4PROCESS_ID ;
#ifdef S4SERVER
return socket4netInitServer( socket->net, socketName, processId ) ;
#else
return 0 ;
#endif
}
#ifdef S4SERVER
int socket4shutdownAdvertising( SOCKET4 *socket )
{
return socket4netShutdownAdvertising( socket->net ) ;
}
#endif
#endif /* E4PARM_LOW -- i.e. inline */
int socket4initUndo( SOCKET4 *socket )
{
int rc, save_rc ;
#ifdef S4SERVER
CONNECTION4 *connection ;
#endif
#ifdef E4PARM_LOW
if ( socket == 0 )
return error4( 0, e4parm_null, E90161 ) ;
#endif
#ifdef E4ANALYZE
socket->initUndone = 1 ;
#endif
save_rc = 0 ;
if ( socket->connect != 0 )
{
rc = connection4initUndo( socket->connect ) ;
connection4free( socket->connect ) ;
socket->connect = 0 ;
if ( rc != 0 )
save_rc = rc ;
}
#ifdef S4SERVER
for( ;; )
{
connection = (CONNECTION4 *)l4first( &socket->connections ) ;
if ( connection == 0 )
break ;
rc = connection4initUndo( connection ) ;
if ( rc != 0 )
save_rc = rc ;
rc = connection4free( connection ) ;
if ( rc != 0 )
save_rc = rc ;
}
#endif
if ( socket->net != 0 )
{
rc = socket4netInitUndo( socket->net ) ;
socket4netFree( socket->net ) ;
socket->net = 0 ;
if ( rc != 0 )
save_rc = rc ;
}
return save_rc ;
}
MESSAGE4 *socket4receive( SOCKET4 *socket )
{
MESSAGE4 *message ;
#ifdef E4PARM_LOW
if ( socket == 0 )
{
error4( 0, e4parm_null, E90161 ) ;
return 0 ;
}
#endif
message = socket4netReceive( socket->net ) ;
#ifdef S4COM_PRINT
if ( message != 0 )
{
printf( "Received Message: " ) ;
s4connectionPrint( packet4type( message->packet ) ) ;
}
#endif
return message ;
}
#ifdef S4COM_PRINT
static void s4connectionPrint( const int type )
{
char *out ;
switch( type )
{
#ifndef S4SINGLE
case CON4LOCK:
out = "CON4LOCK" ;
break ;
case CON4UNLOCK:
out = "CON4UNLOCK" ;
break ;
#endif
case CON4WRITE:
out = "CON4WRITE" ;
break ;
case CON4GO:
out = "CON4GO" ;
break ;
case CON4SKIP:
out = "CON4SKIP" ;
break ;
case CON4SEEK:
out = "CON4SEEK" ;
break ;
case CON4SEEK_DBL:
out = "CON4SEEK_DBL" ;
break ;
case CON4START:
out = "CON4START" ;
break ;
case CON4COMMIT:
out = "CON4COMMIT" ;
break ;
case CON4COMPLETE:
out = "CON4COMPLETE" ;
break ;
case CON4ROLLBACK:
out = "CON4ROLLBACK" ;
break ;
case CON4OPEN:
out = "CON4OPEN" ;
break ;
case CON4CLOSE:
out = "CON4CLOSE" ;
break ;
case CON4RECCOUNT:
out = "CON4RECCOUNT" ;
break ;
#ifndef S4SINGLE
case CON4LOCK_CONFIRM:
out = "CON4LOCK_CONFIRM" ;
break ;
case CON4LOCK_GROUP:
out = "CON4LOCK_GROUP" ;
break ;
#endif
case CON4CONNECT:
out = "CON4CONNECT" ;
break ;
case CON4DISCONNECT:
out = "CON4DISCONNECT" ;
break ;
case CON4PACK:
out = "CON4PACK" ;
break ;
case CON4ZAP:
out = "CON4ZAP" ;
break ;
case CON4CREATE:
out = "CON4CREATE" ;
break ;
case CON4CANCEL:
out = "CON4CANCEL" ;
break ;
case CON4RELATE_INIT:
out = "CON4RELATE_INIT" ;
break ;
case CON4RELATE_TOP:
out = "CON4RELATE_TOP" ;
break ;
case CON4RELATE_BOTTOM:
out = "CON4RELATE_BOTTOM" ;
break ;
case CON4RELATE_DO:
out = "CON4RELATE_DO" ;
break ;
case CON4RELATE_DO_ONE:
out = "CON4RELATE_DO_ONE" ;
break ;
case CON4RELATE_FREE:
out = "CON4RELATE_FREE" ;
break ;
#ifndef S4SINGLE
case CON4RELATE_LOCK:
out = "CON4RELATE_LOCK" ;
break ;
case CON4RELATE_UNLOCK:
out = "CON4RELATE_UNLOCK" ;
break ;
#endif
case CON4RELATE_SKIP:
out = "CON4RELATE_SKIP" ;
break ;
case CON4INDEX_CREATE:
out = "CON4INDEX_CREATE" ;
break ;
case CON4INDEX_OPEN:
out = "CON4INDEX_OPEN" ;
break ;
case CON4INDEX_CLOSE:
out = "CON4INDEX_CLOSE" ;
break ;
case CON4POSITION:
out = "CON4POSITION" ;
break ;
case CON4POSITION_SET:
out = "CON4POSITION_SET" ;
break ;
case CON4REINDEX:
out = "CON4REINDEX" ;
break ;
case CON4CHECK:
out = "CON4CHECK" ;
break ;
case CON4TOP:
out = "CON4TOP" ;
break ;
case CON4BOTTOM:
out = "CON4BOTTOM" ;
break ;
case CON4APPEND:
out = "CON4APPEND" ;
break ;
case CON4MEMO_COMPRESS:
out = "CON4MEMO_COMPRESS" ;
break ;
case CON4MEMO:
out = "CON4MEMO" ;
break ;
case CON4INFO:
out = "CON4INFO" ;
break ;
case CON4UNIQUE_SET:
out = "CON4UNIQUE_SET" ;
break ;
case CON4PASSWORD:
out = "CON4PASSWORD" ;
break ;
case CON4TRANS_INIT:
out = "CON4TRANS_INIT" ;
break ;
case CON4RELATE_OPT:
out = "CON4RELATE_OPT" ;
break ;
case CON4SYSTEM:
out = "CON4SYSTEM" ;
break ;
case CON4TAG_SYNCH:
out = "CON4TAG_SYNCH" ;
break ;
case CON4DATE_FORMAT:
out = "CON4DATE_FORMAT" ;
break ;
case CON4TRAN_EOF:
out = "CON4TRAN_EOF" ;
break ;
case CON4TRAN_EOF_HALT:
out = "CON4TRAN_EOF_HALT" ;
break ;
case CON4TRAN_RESTART:
out = "CON4TRAN_RESTART" ;
break ;
case CON4INDEX_FORMAT:
out = "CON4INDEX_FORMAT" ;
break ;
default:
out = "INVALID MESSAGE" ;
break ;
}
printf( "%s\n", out ) ;
}
#endif
#endif /* S4OFF_COMMUNICATIONS */