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

📄 en_encap.c

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