⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 en_sock.c

📁 基于EthernetIP协议的应用程序,可以读取AB公司Controllogix系列Ethernetip协议PLC数据. 此软件代码可用于工业控制.
💻 C
📖 第 1 页 / 共 5 页
字号:

            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 + -