📄 en_sock.c
字号:
sWriteDesc.lW_state = ECE_WS_EMPTY;
sWriteDesc.psW_msg = ( PKTBUF_P ) NULL;
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;
/*
** The UDP socket should never be closed, to do so indicates a
** programming error somewhere
*/
case CLOSECONNECTION:
GS_LogEvent( CD_UNSUPPORTED_CONFIG_REQUEST,
OE_SOCKET_ERRNO,
0,
FATAL );
break;
/*
** UDP sockets do not get session ID's assigned. Socket type checked
** when session established. To get this far is a programming error
*/
case SENDSID:
GS_LogEvent( EN_SESS_OPEN_ERR,
OE_SOCKET_ERRNO,
0,
FATAL );
break;
} /* End switch */
} /* End forever */
} /* end en_cd_UDPEncapSendTask( ) */
/*---------------------------------------------------------------------------
** en_cd_TCPSend( )
**---------------------------------------------------------------------------
*/
UINT32 en_cd_TCPSend( UINT32 lSockfd,
SOCK_WDESC * psWriteDesc,
UINT32 lFlags,
UINT32 * nErr )
{
struct msghdr sWriteMsg;
UINT32 nBytes;
UC_SetMem( ( caddr_t ) &sWriteMsg, 0, sizeof( sWriteMsg ) );
sWriteMsg.msg_iov = psWriteDesc->psW_iov;
sWriteMsg.msg_iovlen = psWriteDesc->lW_iovlen;
if ( ( nBytes = sendmsg( lSockfd, &sWriteMsg, lFlags ) ) == OE_ERROR )
{
*nErr = OE_SOCKET_ERRNO;
return ( OE_ERROR );
}
else
{
/*
** Update write length and check for partial write. Update
** write descriptor to reflect the data that was just
** written. The vector pointer and length are untouched if
** the entire write completed.
*/
psWriteDesc->lW_length -= nBytes;
if ( ( psWriteDesc->lW_length ) && ( nBytes ) )
{
register INT32 lWriteBytes = nBytes;
register struct iovec *iov = psWriteDesc->psW_iov;
register INT32 lVBytes;
while ( lWriteBytes )
{
lVBytes = min( lWriteBytes, iov->iov_len );
if ( lVBytes )
{
iov->iov_base += lVBytes;
iov->iov_len -= lVBytes;
}
if ( iov->iov_len == 0 )
{
psWriteDesc->lW_iovlen--;
iov++;
}
lWriteBytes -= lVBytes;
} /* while lWriteBytes */
psWriteDesc->psW_iov = iov;
} /* if not all sent */
return ( OK );
}
} /* end en_cd_TCPSend( ) */
/**---------------------------------------------------------------------------
** en_cd_FormatIOV( )
**---------------------------------------------------------------------------
**/
void en_cd_FormatIOV( PKTBUF_P psMsg, SOCK_WDESC * psWriteDesc )
{
UINT32 lTotal;
register struct iovec *iov = &psWriteDesc->asW_iovec[0];
register UINT32 lCount = 0;
ENCAPH *psEncapHdr = ( ENCAPH * ) ( &psMsg->sEncap.sHdr );
psEncapHdr->iEncaph_length = 0;
lTotal = 0;
/*
** Set up write descriptor to write out the message
*/
UC_SetMem( ( caddr_t ) psWriteDesc, 0, sizeof( *psWriteDesc ) );
psWriteDesc->psW_msg = psMsg;
psWriteDesc->psW_iov = iov;
/*
** Create vector entry to write out the header.
*/
iov->iov_base = ( caddr_t ) & psMsg->sEncap.sHdr;
iov->iov_len = ENCAP_HDR_SIZE;
iov++;
lCount++;
/*
** If the packet has data transfer parameters present, convert the
** tag and create a vector for the tag.
*/
if ( psMsg->sEncap.lValid & PKTBUF_ENCAPV_DT )
{
iov->iov_base = ( caddr_t ) ( &psMsg->sEncap.sDt_hdr );
iov->iov_len = ENCAP_DT_HDR_SIZE;
ENCAP_CVT_PS( psMsg->sEncap.sDt_hdr.iDt_timeout );
psEncapHdr->iEncaph_length += ENCAP_DT_HDR_SIZE;
iov++;
lCount++;
}
/*
** If an object lCount is present, convert the lCount and create a
** vector for the field.
*/
if ( psMsg->sEncap.lValid & PKTBUF_ENCAPV_OBJ )
{
iov->iov_base = ( caddr_t ) ( &psMsg->sEncap.sObj_list );
iov->iov_len = ENCAP_OBJ_LIST_SIZE;
ENCAP_CVT_PS( psMsg->sEncap.sObj_list.iO_count );
psEncapHdr->iEncaph_length += ENCAP_OBJ_LIST_SIZE;
iov++;
lCount++;
}
/*
** If an address tag is present, convert the tag and create a vector
** for the tag.
*/
if ( psMsg->sEncap.lValid & PKTBUF_ENCAPV_ADR )
{
iov->iov_base = ( caddr_t ) ( &psMsg->sEncap.sAdr_tag );
iov->iov_len = psMsg->sEncap.sAdr_tag.sTag.iTag_length + CPF_TAG_SIZE;
psEncapHdr->iEncaph_length += psMsg->sEncap.sAdr_tag.sTag.iTag_length + CPF_TAG_SIZE;
ENCAP_CVT_PS( psMsg->sEncap.sAdr_tag.sTag.iTag_type );
ENCAP_CVT_PS( psMsg->sEncap.sAdr_tag.sTag.iTag_length );
iov++;
lCount++;
}
/*
** If a packet tag is present, convert the tag and create a vector
** for the tag. Note that the PKTBUF length accounts for the actual
** data described by the packet tag.
*/
if ( psMsg->sEncap.lValid & PKTBUF_ENCAPV_PKT )
{
iov->iov_base = ( caddr_t ) ( &psMsg->sEncap.sPkt_tag );
iov->iov_len = CPF_TAG_SIZE;
psEncapHdr->iEncaph_length += CPF_TAG_SIZE;
/*
** The tag is specified in the data portion and will
** be added to the header there
*/
ENCAP_CVT_PS( psMsg->sEncap.sPkt_tag.sTag.iTag_type );
ENCAP_CVT_PS( psMsg->sEncap.sPkt_tag.sTag.iTag_length );
iov++;
lCount++;
}
/*
** Create a vector for the data portion of the packet. Note that the
** ENCAP header length specifies the lTotal lSize of the message.
*/
iov->iov_base = ( caddr_t ) psMsg->pData;
iov->iov_len = psMsg->lLength;
psEncapHdr->iEncaph_length += psMsg->lLength;
iov++;
lCount++;
/*
** Adjust the last vector to account for any additional data in the
** packet. The additional tags follow the packet data so only the
** length needs to be adjusted.
*/
if ( psMsg->sEncap.lValid & PKTBUF_ENCAPV_ADD )
{
iov->iov_base = ( caddr_t ) ( psMsg->pAdd );
iov->iov_len = psMsg->lAdd_len;
psEncapHdr->iEncaph_length += psMsg->lAdd_len;
iov++;
lCount++;
}
/*
** Convert fields in the fixed lSize header
*/
lTotal = psEncapHdr->iEncaph_length;
ENCAP_CVT_HS( psEncapHdr->iEncaph_command );
ENCAP_CVT_HS( psEncapHdr->iEncaph_length );
ENCAP_CVT_HL( psEncapHdr->lEncaph_status );
ENCAP_CVT_HL( psEncapHdr->lEncaph_opt );
psWriteDesc->lW_length = lTotal + ENCAP_HDR_SIZE;
psWriteDesc->lW_iovlen = lCount;
psWriteDesc->lW_state = ECE_WS_PARTIAL;
} /* end en_cd_FormatIOV( ) */
/*---------------------------------------------------------------------------
** en_cd_EncapSendTask( )
**---------------------------------------------------------------------------
*/
TASKRETURN en_cd_EncapSendTask( ECE * psEce )
{
EnCdMessageType EnCdMessage;
UINT32 nShutdown = FALSE;
OE_Q_ID sSendTaskMsgQueue;
UINT32 lSockFd;
UINT32 lSid = 0;
INT32 nStatus;
CD_PacketTrrblType *pTrrbl;
SOCK_WDESC sWriteDesc;
OE_Q_ID sTempMsgQueue = NULL;
sSendTaskMsgQueue = psEce->sOutputQ;
lSockFd = psEce->lSockFd;
if ( psEce->sEid.u.type == ECE_TYPE_OUTBOUND )
{
/*
** We can not send out any CIP messages until we have
** connected and established an Encap session with the host.
** In the meantime the client can be sending messages to us.
** We need to create a temporary queue to store the client
** originated messages until we have completed the connection
** process. Then we can send the client requests, delete the
** temporary queue and continue nrmal processing
*/
sTempMsgQueue = OE_MsgQCreate( 100, /* Number of messages, */
sizeof( EnCdMessageType ),
MSG_Q_FIFO );
} /* End if outbound */
while ( 1 )
{
if ( ( psEce->sEid.u.type == ECE_TYPE_OUTBOUND ) &&
( psEce->lState == ECE_STATE_ACTIVE ) &&
( sTempMsgQueue != NULL ) )
{
/*
** We have just connected with a recent message. We need to send the
** messages that have been queued in the temporary queue, then we can
** go back to the main queue
*/
/*
** All messages comming here of the same form
** Don't wait, if message isn't there we've sent them all
*/
nStatus = OE_MsgQReceive( sTempMsgQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
NO_WAIT );
/*
** if error delete the Queue, Get the next message in the normal queue.
** Note that some operating systems return an error (VxWorks) if there is nothing left in
** the queue, while others will return 0 bytes (NT).
*/
if (( nStatus == 0) || ( nStatus == OE_ERROR ))
{
OE_MsgQDelete( sTempMsgQueue );
sTempMsgQueue = NULL;
continue;
}
} /* End outgoing with messages ready to send */
else
{
if( sSendTaskMsgQueue == 0 )
{
nShutdown = TRUE;
}
else
{
nStatus = OE_MsgQReceive( sSendTaskMsgQueue,
( char * ) &EnCdMessage,
sizeof EnCdMessage,
WAIT_FOREVER );
}
}
/*
** Overide all actions with a shutdown
*/
if ( nShutdown == TRUE )
{
EnCdMessage.Command = CLOSECONNECTION;
}
switch ( EnCdMessage.Command )
{
case SENDINCORPMESSAGE:
case SENDCOMMBUF:
if ( EnCdMessage.PacketBuf != NULL )
{
/*
** Before we can send that first message, we
** must send the list list services and the
** register request
*/
if ( ( psEce->sEid.u.type == ECE_TYPE_OUTBOUND ) &&
( psEce->lState != ECE_STATE_ACTIVE ) &&
( EnCdMessage.PacketBuf->sEncap.sHdr.iEncaph_command != ENCAP_CMD_LISTSERVICES ) &&
( EnCdMessage.PacketBuf->sEncap.sHdr.iEncaph_command != ENCAP_CMD_REGISTERSESSION ) )
{
/*
** Not yet registered, we need to queue this message. Do Not wait, lest the queue be
** filled and we hang here permanently. If we loose the message because the buffer is
** filled the timer will go off and notify the application
*/
OE_MsgQSend( sTempMsgQueue,
( char * ) &EnCdMessage.Command,
sizeof EnCdMessage,
NO_WAIT,
MSG_PRI_NORMAL );
continue; /* Get the next message in the queue */
}
/*
** Verify that all outbound messages have either our
** IP address in the context field (unconnected) or
** 0 indicating they are truly originated by us and not
** a misdirected reply
*/
if ( ( psEce->sEid.u.type == ECE_TYPE_OUTBOUND ) &&
( EnCdMessage.PacketBuf->sEncap.sHdr.alEncaph_context[ 0 ] != list_target_data.sS.s_sock.lSin_addr ) &&
( EnCdMessage.PacketBuf->sEncap.sHdr.alEncaph_context[ 0 ] != 0 ) )
{
DBLN("Misdirected reply message");
if ( EnCdMessage.PacketBuf != NULL )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -