📄 en_encap.c
字号:
#undef TCP_PORT_DELIM
} /* end en_cd_GetOutboundAddress( ) */
/*---------------------------------------------------------------------------
** en_cd_MngOutgoingEncapTask( )
**---------------------------------------------------------------------------
*/
#if EN_MAX_OUTGOING_CONNECTIONS
TASKRETURN en_cd_MngOutgoingEncapTask( TASKPARAM )
{
UINT32 nAvailable;
ECE *ece;
UINT8 chHostName[ MAXHOSTNAMELEN + 1 ];
UINT8 chHostNameTmp[ MAXHOSTNAMELEN + 1 ];
static sHostCount = 0;
static ECE sHostList[ EN_MAX_OUTGOING_CONNECTIONS ];
UINT32 i;
struct sockaddr_in sIP_Server; /* IP address of the server */
/*
** List of all possible outbound hosts hosts
*/
EnCdMessageType EnCdMessage;
UINT16 nPort;
UINT32 nRetryFlag;
GS_TaskSeedType sSeed;
OE_Q_ID sSendTaskMsgQueue;
UINT32 nStatus;
UINT32 lTaskId;
UINT8 chTaskName[ 32 ];
MngOutgoingEncapQueue = OE_MsgQCreate( 100,
sizeof( EnCdMessageType ),
MSG_Q_FIFO );
/*
** Zero out the list, this also fills in with unmatching IP's
*/
UC_SetMem( sHostList, 0, sizeof sHostList );
while ( 1 )
{
nRetryFlag = 0;
/*
** Queue to wait at
*/
nStatus = OE_MsgQReceive( MngOutgoingEncapQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
WAIT_FOREVER );
/* Difficult to tell when we will actually give up control of the hostname field, depends on if
** transmit task is still running, Whether we retry the connection etc. Rather than send the
** message to the transmit task then delete the buffer lets make a local copy now and delete it immediately.
** Less likely to forget then
*/
nPort = htons( lEncapServerPort ); /* Default value */
/*
** The hostname is not necessarily null terminated. Copy it to a temporary
** buffer space and null terminate it. First verify that the name will
** fit in the allocated buffers.
*/
if ( EnCdMessage.pcbDestHost->iDataSize + 1 < sizeof ( chHostNameTmp ) )
{
UC_SetMem( chHostNameTmp, 0, sizeof ( chHostNameTmp ) );
UC_CopyMem( chHostNameTmp,
EnCdMessage.pcbDestHost->pData,
EnCdMessage.pcbDestHost->iDataSize );
nStatus = en_cd_GetOutboundAddress( chHostNameTmp, chHostName, &nPort );
}
else
{
/*
** Name will not fit in buffer. Fail now and handle later.
*/
nStatus = OE_ERROR;
}
if ( nStatus == OE_ERROR )
{
/*
** Could not decode host/port combination
*/
GS_LogEvent( EN_UNKNOWN_HOST,
0,
0,
TRIVIAL );
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** This has an attached combuffer, delete our interest
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
}
CB_DeleteComBuf( EnCdMessage.pcbDestHost );
/*
** Go back to the do while 1 and let the application time out
*/
continue;
} /* end if nStastus == OE_ERROR */
CB_DeleteComBuf( EnCdMessage.pcbDestHost ); /* Delete our interest */
do
{
/*
** The do guarantees we go through the loop at least once. If the
** final send to the tx task for the host fails we'll try
** re-establishing the connection and re-sending the message
**
** First thing we need to do is match up the name ( or ip
** address ) of the destination with our currently opened
** sockets. If we already have a socket open to the device we
** can send the request. If not we will have to open the
** socket and send the request
*/
UC_SetMem( ( char * ) &sIP_Server, 0, sizeof( sIP_Server ) );
sIP_Server.sin_family = AF_INET;
sIP_Server.sin_port = nPort;
#ifndef WIN32
sIP_Server.sin_len = sizeof( struct sockaddr_in );
#endif
/*
** Look up the host and do anything required to connect
*/
nStatus = en_cd_LookupHost( chHostName, &sIP_Server.sin_addr );
if ( nStatus == OE_ERROR )
{
/*
** Could not find host in host file, or using DNS if enable
*/
GS_LogEvent( EN_UNKNOWN_HOST,
0,
0,
TRIVIAL );
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** This has an attached combuffer, delete our interest
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
}
/*
** Nothing more we can do, break out of the do and go back and wait for
** another message
*/
break;
}
/*
** We now have a hostname / Internet address. We need to
** look through our list of connections to determine if there
** is currently an open connection to that host
*/
ece = NULL; /* Default to not found */
nAvailable = ~0;
for ( i = 0; i < sizeof sHostList / sizeof sHostList[ 0 ]; i++ )
{
/*
** search the list, for now linear search
*/
if ( sHostList[ i ].sOutputQ == NULL )
{
if ( nAvailable == ~0 ) /* Grow the list from 0 up */
nAvailable = i;
continue; /* No use checking anything else */
}
if ( en_cd_HostCompare( &sIP_Server, &sHostList[ i ] ) == 0 )
{
/*
** We have a match. Verify it still exists. Because the Send task
** is spawned from the receive task it may not yet be created.
** Therefore only check the receive task. Also check the queue which
** is the first thing created to make sure it is still there.
*/
if ( ( OE_MsgQNumMsgs( sHostList[ i ].sOutputQ ) != OE_ERROR ) &&
( OE_TaskIdVerify( sHostList[ i ].lRecvTaskID ) != OE_ERROR ) )
{
ece = &sHostList[ i ];
break; /* Break out of the i loop */
}
else
{
/*
** Zero out the ece for this host
*/
UC_SetMem( &sHostList[ i ], 0, sizeof sHostList[ i ] );
sHostCount -= 1; /* one less host for now */
}
} /* End we have a match */
} /* End for i */
if ( ece == NULL )
{
/*
** No sockets are opened to this host, need to create one
** First check to make sure room is still available in the list to
** create a new outgoing connection
*/
if ( ( nAvailable == ~0 ) ||
( MAX_TCP_SOCKETS <= lECE_connects ) )
{
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** This has an attached combuffer, delete our interest
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
}
/* Break out of the do loop, go to the top and wait for another message.
** The timer on the request will signal the requesting app of the failure
*/
break;
} /* End if nAvailable = ~0 */
ece = &sHostList[ nAvailable ];
UC_SetMem( &sHostList[ nAvailable ], 0, sizeof sHostList[ 0 ] );
ece->lState = ECE_STATE_CONNECTING; /* We are connected */
/*
** The actual connection will be done in the receive task, This is
** because of the extended time it might take to actually get a
** connection, or a failure
*/
/*
** Transfer the socket address
** Assign an outbound connection id
*/
ece->sAddr = sIP_Server;
ece->sEid.u.type = ECE_TYPE_OUTBOUND;
memcpy( ece->achName,
chHostName,
strlen( chHostName ) < MAXHOSTNAMELEN ?
strlen( chHostName ) : MAXHOSTNAMELEN );
/*
** We are going to create the queue for the
** transmission task now. The idea is that we will
** post the message that needs to be sent at the
** queue. The send task will wait for an ENCAP session
** to be established before it sends the message.
*/
sSendTaskMsgQueue = OE_MsgQCreate( 100, /* Number of messages, */
sizeof( EnCdMessageType ),
MSG_Q_FIFO );
ece->sOutputQ = sSendTaskMsgQueue;
/*
** Now we are going to start the ball rolling.
** ListService request is going to queue a message to
** the queue created above. After we receive a listservicerequest
** response from the host we will automatically send
** a register session request. When we receive that
** response we will tell the send task that were
** registered and it will begin sending the messages
** queued for our local client
*/
en_cd_ListServicesRequest( ece );
/*
** We are going to create the receive task first.
** Name is combo of IP address and 2 letter designation of direction
*/
sprintf( chTaskName, "OR%08x", ece->sAddr.sin_addr.s_addr );
/*
** The originating reception task will have the 2nd lowest priority
** of all the socket tasks. This is to prevent it from tying up
** the system should its peer go awry and hit it with high traffic
*/
sSeed.pRoutine = ( OE_pTaskFuncType ) en_cd_EncapRecvTask;
sSeed.pParameter = ( void * ) ece;
sSeed.pStack = NULL;
sSeed.iStackSize = EN_SOCKET_STACK_SIZE;
sSeed.nPrio = ORG_RECV_TASK_PRIO;
sSeed.pTaskName = chTaskName;
/* The following create call uses the OE_CreateTask call because it can be deleted. As of this
** writting there is no GS_DeleteTask routine in the GS_Utils library. Because the GS_NewTask
** create call allocates timers that must be deleted, we are short circuiting the GS_NewTask
** call with the OE_CreateTask which is delete-able and has no associated timers.
*/
lTaskId = OE_CreateTask( &sSeed );
if ( lTaskId == 0 )
{
/* Couldn't spawn a new originator. Warn only, don't
** affect other connections already established. They
** should not be affected by this
*/
GS_LogEvent( EN_TASK_SP_ERR,
OE_SOCKET_ERRNO,
0,
WARNING );
/*
** Spawning failed, break out of the do
** loop and go back for another message
*/
break;
}
ece->lRecvTaskID = lTaskId; /* Id of task for receiving replies */
sHostCount += 1;
} /* If need to establish new connection */
/*
** Now we can really send the message
*/
nStatus = OE_MsgQSend( ece->sOutputQ,
( char * ) &EnCdMessage.Command,
sizeof EnCdMessage,
WAIT_FOREVER,
MSG_PRI_NORMAL );
if ( nStatus == OE_ERROR )
{
/*
** Xmit task for this host went away
** Zero out the ece for this host
*/
UC_SetMem( ece, 0, sizeof *ece );
sHostCount -= 1;
if ( nRetryFlag == 0 )
{
/*
** have not retried this yet, set the flag
** Go back to the start of the do, and open a new connection this loop
*/
nRetryFlag = 1;
continue;
}
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** This has an attached combuffer, delete our interest
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
/*
** We retried 2 times and failed both times, get
** rid of the attached buffers and exit
*/
PktBufFree( EnCdMessage.PacketBuf );
}
break;
} /* end if nStatus == OE_ERROR */
} while ( 0 ); /* End do */
} /* End while 1 */
} /* end en_cd_MngOutgoingEncapTask( ) */
#endif
/*---------------------------------------------------------------------------
** en_cd_PktbufAlloc( )
**---------------------------------------------------------------------------
*/
PKTBUF_P en_cd_PktbufAlloc( void )
{
PKTBUF_P psPktbuf;
psPktbuf = ( PKTBUF_P ) GS_Malloc( sizeof( PKTBUF ) );
if ( ( psPktbuf != NULL ) )
{
/*
** Initialize packet buffer fields
*/
UC_SetMem( psPktbuf, 0, sizeof( PKTBUF ) );
psPktbuf->pData = &psPktbuf->abData[ 0 ];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -