2058 lines
		
	
	
		
			53 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			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 */
 |