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

📄 en_encap.c

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

}                                       /* end en_cd_PktbufAlloc( ) */



/*---------------------------------------------------------------------------
** en_cd_PktbufFree( )
**---------------------------------------------------------------------------
*/

void
en_cd_PktbufFree( PKTBUF_P psPktbuf )
{

   /*
   ** Since the buffer is being released, there should be no pending I/O
   ** operations.
   */

   psPktbuf->lFlags &= ( ~PKTBUF_F_PENDING );

   /*
   ** Delete pktbuf which was allocated as a combuf
   */

   gs_Free_FL( ( void * ) psPktbuf,__FILE__,__LINE__ );
}                                       /* end en_cd_PktbufFree( ) */



#undef PROC
#define PROC	"en_cd_CloseEce"

/*---------------------------------------------------------------------------
** en_cd_CloseEce( )
**---------------------------------------------------------------------------
*/

void en_cd_CloseEce( OE_Q_ID OutputQ )
{

   EnCdMessageType EnCdMessage;         /* Message to be sent out via tcpip */

   /*
   ** Command to the write task to close the connection
   */

   EnCdMessage.Command = CLOSECONNECTION;
   OE_MsgQSend( OutputQ,
            ( char * ) &EnCdMessage.Command,
            sizeof EnCdMessage,
            WAIT_FOREVER,
            MSG_PRI_NORMAL );

}                                       /* end en_cd_CloseEce( ) */




/*---------------------------------------------------------------------------
** en_cd_CheckAndGetServices( )
**---------------------------------------------------------------------------
*/

INT32 en_cd_CheckAndGetServices( void *data, INT32 lLen, ENCAP_SERVICE * psServices )
{

   ENCAP_OBJ_LIST  *psObjList;
   ENCAP_OBJ_HDR   *psObjHdr;
   ENCAP_SERVICE   *psEncapService;
   INT32           nObjCount;
   INT32           nObjLen;
   INT32           i;
   INT32           nValid = FALSE;

   do
   {
      /*
      ** Must have at least a standard object list header
      */

      if ( lLen < ENCAP_OBJ_LIST_SIZE )
         break;

      psObjList = data;
      nObjCount = ENCAP_TO_HS( psObjList->iO_count );

      lLen -= ENCAP_OBJ_LIST_SIZE;
      psObjHdr = ( ENCAP_OBJ_HDR * ) ( ( INT32 ) psObjList + ENCAP_OBJ_LIST_SIZE );
      psEncapService = ( ENCAP_SERVICE * ) NULL;

      for ( i = 0; i < nObjCount; i++ )
      {

         /*
         ** Check the length to make sure a standard object header exists.
         ** Extract the object length, and make sure that it is consistent with
         ** the remaining length.
         */

         if ( lLen < ENCAP_OBJ_HDR_SIZE )
            break;

         nObjLen = ENCAP_TO_HS( psObjHdr->iObj_length );
         lLen -= ENCAP_OBJ_HDR_SIZE;

         if ( lLen < nObjLen )
            break;

         /*
         ** The desired object is COMMSERVICE
         */

         if ( psObjHdr->iObj_type == ENCAP_VALUE_SHORT( ENCAP_OBJTYPE_SERVICE_COMM ) )
         {
            psEncapService = ( ENCAP_SERVICE * ) & ( ( ( ENCAP_OBJ_TARGET * ) psObjHdr )->sS );
            break;
         }

         else
         {
            psObjHdr = ( ENCAP_OBJ_HDR * ) ( ( INT32 ) psObjHdr + ENCAP_OBJ_HDR_SIZE + nObjLen );
            lLen -= nObjLen;
         }
      }

      /*
      ** Check version and flags in any COMMSERVICE object which was found
      */

      if ( psEncapService )
      {
         ENCAP_CVT_HS( psEncapService->iS_version );
         if ( psEncapService->iS_version != ENCAP_COMMSERVICE_VERSION )
         {
            sEncapStats.lErrUnSupportedRev++;
            break;
         }
         ENCAP_CVT_HS( psEncapService->iS_flags );
         if ( ( psEncapService->iS_flags & ENCAP_COMMSERVICE_CIP_DIRECT ) == 0 )
            break;

         *psServices = *psEncapService;
         nValid = TRUE;
      }
   } while ( 0 );

   return ( nValid );

}                                       /* end en_cd_CheckAndGetServices( ) */




/*---------------------------------------------------------------------------
** en_cd_EncapErrorReply( )
**---------------------------------------------------------------------------
*/

void  en_cd_EncapErrorReply( PKTBUF_P psPktBuf, UINT32 lValue,
                     void *data, INT32 nDataLen )
{

   ENCAPH          *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );

   sEncapStats.lRepliesSentErrs++;

   psPktBuf->pData = &psPktBuf->abData[ 0 ];
   psPktBuf->lLength = nDataLen;

   if ( nDataLen )
   {
      UC_CopyMem( ( caddr_t ) &psPktBuf->abData[ 0 ], ( caddr_t ) data,  nDataLen );
   }

   psEncapHdr->iEncaph_length = nDataLen;
   psEncapHdr->lEncaph_status = lValue;
   psPktBuf->sEncap.lValid = 0;

   en_cd_SendEncapCommand( psPktBuf );

}                                       /* end en_cd_EncapErrorReply( ) */



/*---------------------------------------------------------------------------
** en_cd_RegisterRequest( )
**---------------------------------------------------------------------------
*/

PKTBUF_P en_cd_RegisterRequest( ECE * psEce )
{

   PKTBUF_P        psPktBuf;
   ENCAP_RC_DATA   *psRCData;

   if ( psPktBuf = PktBufAlloc( ) )
   {
      psPktBuf->sEncap.sHdr.iEncaph_command = ENCAP_CMD_REGISTERSESSION;
      psPktBuf->sEncap.sHdr.lEncaph_status = 0;
      psPktBuf->sEncap.sHdr.lEncaph_session = 0;
      psPktBuf->sEncap.sHdr.alEncaph_context[ 0 ] = 0;
      psPktBuf->sEncap.sHdr.alEncaph_context[ 1 ] = 0;
      psPktBuf->sEncap.sHdr.iEncaph_length = ENCAP_RC_DATA_SIZE;

      psRCData = psPktBuf->pData;
      psRCData->iRc_version = ENCAP_VALUE_SHORT( ENCAP_PROTOCOL_VERSION );
      psRCData->iRc_flags = 0;

      psPktBuf->sEncap.lValid = 0;
      psPktBuf->lLength = ENCAP_RC_DATA_SIZE;
	   psPktBuf->sOutputQ = psEce->sOutputQ;
   }
   return ( psPktBuf );
}


/*---------------------------------------------------------------------------
** en_cd_ListServicesReceived( )
**---------------------------------------------------------------------------
*/

void en_cd_ListServicesReceived( ECE * psEce, PKTBUF_P psPktBuf )
{

   ENCAPH          *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );
   OE_Q_ID        sOutputQ;

   switch ( ECE_TYPE( psEce->sEid ) )
   {

   /*
   ** Process a request from a client for a list of our services
   */

   case ECE_TYPE_INBOUND:

      sEncapStats.lCommandsReceived++;

      /*
      ** Check length of command specific data. There shouldn't be any.
      */

      if ( psEncapHdr->iEncaph_length != 0 )
      {
         sEncapStats.lErrBadData++;
         en_cd_EncapErrorReply( psPktBuf, ENCAP_E_BADDATA, NULL, 0 );
      }

      else
      {
         if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
         {
            UC_CopyMem( ( caddr_t ) &psPktBuf->abData[ 0 ], ( caddr_t ) &list_services_data,
                  sizeof( list_services_data ) );
            psPktBuf->lLength = sizeof( list_services_data );
            psPktBuf->sEncap.sObj_list.iO_count = 1;
            psPktBuf->sEncap.lValid = PKTBUF_ENCAPV_OBJ;

            psEncapHdr->lEncaph_status = 0;
            psEncapHdr->iEncaph_length = ENCAP_OBJ_LIST_SIZE + psPktBuf->lLength;

            sEncapStats.lRepliesSent++;
            en_cd_SendEncapCommand( psPktBuf );
         }
         else
            PktBufFree( psPktBuf );
      }
      break;

   case ECE_TYPE_OUTBOUND:


      /*
      ** Process a ListServices reply.  Parse the reply to
      ** verify that the Communications service is supported, has the correct
      ** version, and supports CIP direct execution. If all of the criteria are
      ** met, then attempt to register with the server.
      */

      {
         INT32           valid = FALSE;

         if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
            sEncapStats.lRepliesReceived++;
         else
            sEncapStats.lRepliesReceivedErrs++;

         do
         {

            /*
            ** Only valid state for the ECE is CONNECTED
            */

            if ( psEce->lState != ECE_STATE_CONNECTED )
               break;

            /*
            ** A non-zero status indicates that the request was not accepted.
            */

            if ( psEncapHdr->lEncaph_status != ENCAP_E_SUCCESS )
               break;

            /*
            ** The ENCAP length must be consistent with remaining data
            */

            if ( psEncapHdr->iEncaph_length != psPktBuf->lLength )
               break;

            /*
            ** Call function to parse the packet and verify that the server
            ** supports the requested function.
            */

            valid = en_cd_CheckAndGetServices( psPktBuf->pData, psPktBuf->lLength, &psEce->sServices );

         } while ( 0 );

         /*
         ** Free the incoming request so that a buffer is available for the
         ** next ENCAP command that we may potentially send.  If all the checks
         ** have passed, then attempt to Register with the server.  Close out
         ** the ECE if the ListServices was incorrect or the Register request
         ** could not be generated.
         */

         sOutputQ = psPktBuf->sOutputQ;
         PktBufFree( psPktBuf );
         if ( valid == FALSE )
            en_cd_CloseEce( sOutputQ );

         else
         {
            PKTBUF_P        psRRequest;

            if ( psRRequest = en_cd_RegisterRequest( psEce ) )
            {
               sEncapStats.lCommandsSent++;
               en_cd_SendEncapCommand( psRRequest );
               if ( psEce->lState == ECE_STATE_CONNECTED )
                  psEce->lState = ECE_STATE_REGISTER;
            }
            else
               en_cd_CloseEce( sOutputQ );
         }
      }
      break;

   /*
   ** Not sure how this could happen, but we should crash on the error.
   */

   default:
      GS_LogEvent( CD_UNSUPPORTED_CONFIG_REQUEST,         /* Incorrect type code specified in ECE */
                   ECE_TYPE( psEce->sEid ),
                   0,
                   FATAL );
      break;
   }
}



#undef PROC
#define PROC "en_cd_ListInterfacesReceived"

/*----------------------------------------------------------------------------
** en_cd_ListInterfacesReceived( )
**---------------------------------------------------------------------------
**/

void en_cd_ListInterfacesReceived( ECE * psEce, PKTBUF_P psPktBuf )
{

   ENCAPH          *psEncapHdr = ( ENCAPH * ) ( &psPktBuf->sEncap.sHdr );

   switch ( ECE_TYPE( psEce->sEid ) )
   {

   /*
   ** Process a request from a client for a list of our services
   */

   case ECE_TYPE_INBOUND:

      sEncapStats.lCommandsReceived++;

      /*
      ** Check length of command specific data. There shouldn't be any.
      */

      if ( psEncapHdr->iEncaph_length != 0 )
      {
         sEncapStats.lErrBadData++;
         en_cd_EncapErrorReply( psPktBuf, ENCAP_E_BADDATA, NULL, 0 );
      }

      else
      {
         if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
         {
            psPktBuf->sEncap.sObj_list.iO_count = 0;   /* Currently not implemented */

            psPktBuf->lLength = psPktBuf->sEncap.sObj_list.iO_count * ENCAP_OBJ_TARGET_SIZE;
            psPktBuf->sEncap.lValid = PKTBUF_ENCAPV_OBJ;
            psEncapHdr->lEncaph_status = 0;
            psEncapHdr->iEncaph_length = ENCAP_OBJ_LIST_SIZE + psPktBuf->lLength;
            sEncapStats.lRepliesSent++;
            en_cd_SendEncapCommand( psPktBuf );
         }
         else
            PktBufFree( psPktBuf );
      }
      break;

   /*
   ** Silently ignore the command...
   */

   case ECE_TYPE_OUTBOUND:

      if ( psEncapHdr->lEncaph_status == ENCAP_E_SUCCESS )
         sEncapStats.lRepliesReceived++;
      else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -