📄 en_sock.c
字号:
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** Must delete the attached comm buff
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
EnCdMessage.PacketBuf->pCb = NULL;
}
PktBufFree( EnCdMessage.PacketBuf );
}
continue;
}
/* /*
** ** Now check for a misdirected originated message
** *//*
** if ( ( psEce->sEid.u.type == ECE_TYPE_INBOUND ) &&
** ( EnCdMessage.PacketBuf->sEncap.sHdr.alEncaph_context[ 0 ] == list_target_data.sS.s_sock.lSin_addr ) )
** {
** DBLN("Misdirected originated message");
** if ( EnCdMessage.PacketBuf != NULL )
** {
** if ( EnCdMessage.Command == SENDCOMMBUF )
** {
** /*
** ** Must delete the attached comm buff
** *//*
**
** CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
** EnCdMessage.PacketBuf->pCb = NULL;
** }
** PktBufFree( EnCdMessage.PacketBuf );
** }
** continue;
** }
*/
/*
** Get the sock_wdesc ready for the send. Form the iov's for sendmessage
*/
EnCdMessage.PacketBuf->sEncap.sHdr.lEncaph_session = psEce->lSid;
en_cd_FormatIOV( EnCdMessage.PacketBuf, &sWriteDesc );
/*
** Write to the socket. Check for a possible
** error. Close down the connection if the
** error is not one of the flow control
** errors.
*/
do
{
if ( en_cd_TCPSend( lSockFd, &sWriteDesc, 0, &nStatus ) == OE_ERROR )
{
if ( ( nStatus != EWOULDBLOCK ) && ( nStatus != ENOBUFS ) )
{
/*
** Handle the error by sending a high priority message
** to this task forcing an organized shutdown
*/
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** Must delete the attached comm buff
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
EnCdMessage.PacketBuf->pCb = NULL;
}
PktBufFree( EnCdMessage.PacketBuf );
}
nShutdown = TRUE; /* Go into shutdown mode */
EnCdMessage.Command = CLOSECONNECTION;
EnCdMessage.PacketBuf = NULL;
/*
** Notice that the OE_MsgQSend below and the one above to the temporary
** queue specify a NO_WAIT option. It is possible that the queue gets filled
** when there is extremely heavy traffic and no room exists to add any more messages.
** In these cases the task sending to the queue with a wait forever option
** will wait until there is room in the queue. However, since this task is the only
** task taking messages out of the queue, if it waits forever to put messages into the
** queue we end up with a deadlock.
**
** The send below is only necessary to get this task off the wait at the top of the loop.
** If there are already messages in the queue it is really not necessary. Setting the
** shutdown flag will take care of the rest
*/
OE_MsgQSend( sSendTaskMsgQueue,
( char * ) &EnCdMessage.Command,
sizeof EnCdMessage,
NO_WAIT,
MSG_PRI_URGENT ); /* Front of queue */
} /* nErr = controlled */
} /* Received error from send */
/*
** If the write had completed,
** free the write buffer and clear the
** write state in the psEce entry. Clear the lSockfd from the write lSockfd
** map. Otherwise, Return with w_state of ECE_WS_PARTIAL ( set up
** when the transfer was started ) if the entire message wasn't sent.
*/
} while ( ( nShutdown == FALSE ) && ( sWriteDesc.lW_length != 0 ) ); /* end do */
sWriteDesc.lW_state = ECE_WS_EMPTY;
sWriteDesc.psW_msg = ( PKTBUF_P ) NULL;
OE_TaskDelay(NO_WAIT); /* move to end of ready queue */
if ( EnCdMessage.PacketBuf != NULL )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** Must delete the attached comm buff
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
}
} /* End if not null packet */
break;
case CLOSECONNECTION:
/*
** Close this session, free any resources
** First, close any CIP connections that may have been opened on this socket
*/
pTrrbl = GS_NewTrrbl( CD_PacketTrrblType );
/*
** Multipurpose, can be used to close any connections that
** are opened on this session
*/
pTrrbl->eRequest = TREQ_RX_IM_ALIVE;
pTrrbl->xReturnQueue = GS_NO_QUEUE;
pTrrbl->iPort = CD_ETHERNET_PORT;
pTrrbl->pComBuf = NULL;
pTrrbl->xCdHandle = ( void * ) psEce->lSid;
GS_PutTrrbl( CM_xQid, pTrrbl );
/*
** Close the socket, this will also get recv task off the select
*/
closesocket( lSockFd );
/*
** We need to clear out any more messages in our queue lest we
** loose the memory attached
*/
do
{
/*
** Wait 10 seconds to make sure all messages clear
*/
nStatus = OE_MsgQReceive( sSendTaskMsgQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
MSEC2TICKS(10000) );
if (( nStatus != 0 ) && ( nStatus != OE_ERROR ) && ( EnCdMessage.PacketBuf != NULL ) )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** Must delete the attached comm buff
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
} /* End if message with memory to free */
} while (( nStatus != 0 ) && ( nStatus != OE_ERROR )); /* Do until no more messages */
/*
** Delete the Queue used by Send Task
*/
OE_MsgQDelete( sSendTaskMsgQueue );
/*
** check if we still have the temporary queue for
** storing outgoing messages
*/
if ( sTempMsgQueue != NULL )
{
do
{
/*
** We need to clear out any messages in our temporary queu also
*/
nStatus = OE_MsgQReceive( sTempMsgQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
NO_WAIT );
if (( nStatus != 0 ) && ( nStatus != OE_ERROR ) && ( EnCdMessage.PacketBuf != NULL ) )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** Must delete the attached comm buff
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
} /* End if message with memory to free */
} while (( nStatus != 0 ) && ( nStatus != OE_ERROR ));/* Do until no more messages */
/*
** Delete the Queue used by Send Task
*/
OE_MsgQDelete( sTempMsgQueue );
}
GS_DeleteTask( 0 );
break; /* End if close message */
case SENDSID:
/*
** The outgoing encap session has been created and we have just received a
** message verifying it
*/
lSid = EnCdMessage.Sid; /* Save the lSid of the new session */
break;
} /* End switch */
} /* End forever */
} /* end en_cd_EncapSendTask( ) */
/*---------------------------------------------------------------------------
** en_cd_EncapRecvTask( )
**---------------------------------------------------------------------------
*/
TASKRETURN en_cd_EncapRecvTask( ECE * psEce )
{
/*
** AS currently implemented this task handles all the communication
** for a TCP socket. Currently there can be multiple instances of
** this same task each handling there own socket. We need to
** evaluate the performance and resources to determine if this is the
** best route to take wrt architecture.
**
** This task is spwned from the en_cd_PassiveWaitTask task in the Passive.c
** module.
*/
UINT32 lBufferSize;
UINT32 lBufferIndex;
INT32 lBytesReceived;
INT32 lBytesRequested;
struct
{
INT32 lBytesReceived;
INT32 lMessageLength;
} sIncomingMsg;
UINT32 nFlush;
UINT32 nErr;
EnCdMessageType EnCdMessage;
ENCAPH *psEncapHdr;
struct linger sLinger;
PKTBUF *psPacketBuf;
GS_TaskSeedType sSeed;
INT32 nStatus;
UINT32 lSendTaskId;
OE_Q_ID sSendTaskMsgQueue;
UINT32 nSendTaskPriority;
UINT32 lSockFd;
UINT8 achTaskName[32];
char buf[1024];
/*
** Original thoughts were to create a pipe to this task to receive
** internal communication. Pipes are a requirement because when
** sitting on a select, the only way to get off is via a descriptor
** comming true. Due to the number of problems with pipes ( allocate
** memory up front, and can not be deleted, slower performance ) we
** try to craft the communications to get rid of pipes where ever
** possible. This means setting up a send and receive task. The
** send task sitting on a message queue, the receive task being made
** such that it requires no internal communication.
*/
sprintf(buf,"en_cd_EncapRecvTask()开始. tid = %d",GetCurrentThreadId());
CHECKPOINT(buf);
sSendTaskMsgQueue = psEce->sOutputQ;
lECE_connects++; /* Inc current connection count */
lTotal_lECE_connects++; /* Inc the total number of all connections */
if ( psEce->sEid.u.type == ECE_TYPE_INBOUND )
{
/*
** We are not originating this connection
**
** Name is combo of IP address and 2 letter designation of direction
*/
lSockFd = psEce->lSockFd;
sprintf( achTaskName, "IS%08x", psEce->sAddr.sin_addr.s_addr );
/*
** The priority of the response sending task will be the 2nd highest
** of the socket tasks. This will get information out reasonably
** efficiently, but will favor our requests that need to be sent
*/
lECE_connects_in++;
nSendTaskPriority = IN_SEND_TASK_PRIO;
} /* End we are not originating */
else
{
lECE_connects_out++;
psEce->lSid = 0;
/*
** attempt to connect Server specified by to psEce->sAddr on
** open socket specified by lSockFd
*/
#if defined( WIN32 )
nt_Suspend( );
#endif
nStatus = en_cd_TcpConnect( &psEce->sAddr,
&lSockFd,
&nErr );
#if defined( WIN32 )
nt_Resume( );
#endif
if ( nStatus == OE_ERROR )
{
sprintf(buf,"与%s建立连接失败\n",inet_ntoa(psEce->sAddr.sin_addr));
OutputDebugString(buf);
/*
** Event already posted in the TCP Connect routine
** We need to clear out any messages in our queue lest we loose the memory
** attached
*/
/*
** jjw 02/27/01 added statements to zero fields in ECE. Fields were
** not being zeroed resulting in en_cd_MngOutgoingEncapTask thinking
** the socket is open for output, when it isn't
*/
psEce->sOutputQ = 0;
psEce->lRecvTaskID = 0;
do
{
nStatus = OE_MsgQReceive( sSendTaskMsgQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
NO_WAIT );
if (( nStatus != 0 ) && ( nStatus != OE_ERROR ) && ( EnCdMessage.PacketBuf != NULL ) )
{
if ( EnCdMessage.Command == SENDCOMMBUF )
{
/*
** jjw 02/06/01 added the delete combuf call
** This has an attached combuffer, delete our interest
*/
CB_DeleteComBuf( EnCdMessage.PacketBuf->pCb );
}
PktBufFree( EnCdMessage.PacketBuf );
}
} while (( nStatus != 0 ) && ( nStatus != OE_ERROR )); /* Do until no more messages */
/*
** jjw, eventually, delete messages used to prime queue
*/
OE_MsgQDelete( sSendTaskMsgQueue );
lECE_connects_out--;
lECE_connects--;
GS_DeleteTask( 0 );
}
psEce->sEid.u.idx = lSockFd; /* Form the handle, idx is socket # */
psEce->lSockFd = lSockFd;
psEce->lState = ECE_STATE_CONNECTED; /* We are connec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -