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

📄 en_sock.c

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