void vMBTCPPortClose( ) { /* Shutdown any open client sockets. */ prvvMBPortReleaseClient( pxPCBClient ); /* Shutdown or listening socket. */ prvvMBPortReleaseClient( pxPCBListen ); /* Release resources for the event queue. */ vMBPortEventClose( ); }
BOOL xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength ) { BOOL bFrameSent = FALSE; if( pxPCBClient ) { /* Make sure we can send the packet. */ assert( tcp_sndbuf( pxPCBClient ) >= usTCPLength ); if( tcp_write( pxPCBClient, pucMBTCPFrame, ( u16_t ) usTCPLength, NETCONN_COPY ) == ERR_OK ) { #ifdef MB_TCP_DEBUG prvvMBTCPLogFrame( "MBTCP-SENT", &aucTCPBuf[0], usTCPLength ); #endif /* Make sure data gets sent immediately. */ ( void )tcp_output( pxPCBClient ); bFrameSent = TRUE; } else { /* Drop the connection in case of an write error. */ prvvMBPortReleaseClient( pxPCBClient ); } } return bFrameSent; }
void vMBTCPPortDisable( void ) { /* Close all client sockets. */ if( xClientSocket != SOCKET_ERROR ) { prvvMBPortReleaseClient( ); } }
/* Called in case of an unrecoverable error. In any case we drop the client * connection. */ void prvvMBTCPPortError( void *pvArg, err_t xErr ) { struct tcp_pcb *pxPCB = pvArg; if( pxPCB != NULL ) { #ifdef MB_TCP_DEBUG vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", "Error with client connection! Droping it.\r\n" ); #endif prvvMBPortReleaseClient( pxPCB ); } }
void vMBTCPPortClose( ) { // Close all client sockets. if( xClientSocket != SOCKET_ERROR ) { prvvMBPortReleaseClient( ); } // Close the listener socket. if( xListenSocket != SOCKET_ERROR ) { close( xListenSocket ); } }
err_t prvxMBTCPPortAccept( void *pvArg, struct tcp_pcb *pxPCB, err_t xErr ) { err_t error; if( xErr != ERR_OK ) { return xErr; } /* We can handle only one client. */ if( pxPCBClient == NULL ) { /* Register the client. */ pxPCBClient = pxPCB; /* Set up the receive function prvxMBTCPPortReceive( ) to be called when data * arrives. */ tcp_recv( pxPCB, prvxMBTCPPortReceive ); /* Register error handler. */ tcp_err( pxPCB, prvvMBTCPPortError ); /* Set callback argument later used in the error handler. */ tcp_arg( pxPCB, pxPCB ); /* Reset the buffers and state variables. */ usTCPBufPos = 0; #ifdef MB_TCP_DEBUG vMBPortLog( MB_LOG_DEBUG, "MBTCP-ACCEPT", "Accepted new client %d.%d.%d.%d\r\n", ip4_addr1( &( pxPCB->remote_ip ) ), ip4_addr2( &( pxPCB->remote_ip ) ), ip4_addr3( &( pxPCB->remote_ip ) ), ip4_addr4( &( pxPCB->remote_ip ) ) ); #endif error = ERR_OK; } else { prvvMBPortReleaseClient( pxPCB ); error = ERR_OK; } return error; }
BOOL xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength ) { BOOL bFrameSent = FALSE; BOOL bAbort = FALSE; int res; int iBytesSent = 0; int iTimeOut = MB_TCP_READ_TIMEOUT; do { res = send( xClientSocket, &pucMBTCPFrame[iBytesSent], usTCPLength - iBytesSent, 0 ); switch ( res ) { case -1: if( iTimeOut > 0 ) { iTimeOut -= MB_TCP_READ_CYCLE; usleep( MB_TCP_READ_CYCLE ); } else { bAbort = TRUE; } break; case 0: prvvMBPortReleaseClient( ); bAbort = TRUE; break; default: iBytesSent += res; break; } } while( ( iBytesSent != usTCPLength ) && !bAbort ); bFrameSent = iBytesSent == usTCPLength ? TRUE : FALSE; return bFrameSent; }
err_t prvxMBTCPPortReceive( void *pvArg, struct tcp_pcb *pxPCB, struct pbuf *p, err_t xErr ) { USHORT usLength; err_t error; if( xErr != ERR_OK ) { return xErr; } /* If pbuf is NULL then remote end has closed connection. */ if( p == NULL ) { prvvMBPortReleaseClient( pxPCB ); return ERR_OK; } /* Acknowledge that we have received the data bytes. */ tcp_recved( pxPCB, p->len ); /* Check for internal buffer overflow. In case of an error drop the * client. */ if( ( usTCPBufPos + p->len ) >= MB_TCP_BUF_SIZE ) { prvvMBPortReleaseClient( pxPCB ); error = ERR_OK; } else { memcpy( &aucTCPBuf[usTCPBufPos], p->payload, p->len ); usTCPBufPos += p->len; /* If we have received the MBAP header we can analyze it and calculate * the number of bytes left to complete the current request. If complete * notify the protocol stack. */ if( usTCPBufPos >= MB_TCP_FUNC ) { /* Length is a byte count of Modbus PDU (function code + data) and the * unit identifier. */ usLength = aucTCPBuf[MB_TCP_LEN] << 8U; usLength |= aucTCPBuf[MB_TCP_LEN + 1]; /* Is the frame already complete. */ if( usTCPBufPos < ( MB_TCP_UID + usLength ) ) { } else if( usTCPBufPos == ( MB_TCP_UID + usLength ) ) { #ifdef MB_TCP_DEBUG prvvMBTCPLogFrame( "MBTCP-RECV", &aucTCPBuf[0], usTCPBufPos ); #endif ( void )xMBPortEventPost( EV_FRAME_RECEIVED ); } else { #ifdef MB_TCP_DEBUG vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", "Received to many bytes! Droping client.\r\n" ); #endif /* This should not happen. We can't deal with such a client and * drop the connection for security reasons. */ prvvMBPortReleaseClient( pxPCB ); } } } pbuf_free( p ); return error; }
void vMBTCPPortDisable( void ) { prvvMBPortReleaseClient( pxPCBClient ); }