Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetNetIf mbed
porttcp.cpp
00001 /* 00002 * FreeModbus Libary: mbed Port 00003 * Copyright (C) 2006 Christian Walter <wolti@sil.at> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 * 00019 * File: $Id: porttcp.c,v 1.1 2006/08/30 23:18:07 wolti Exp $ 00020 */ 00021 /* ----------------------- System includes ----------------------------------*/ 00022 #include <stdio.h> 00023 #include <string.h> 00024 00025 #include "port.h" 00026 00027 /* ----------------------- mbed includes ------------------------------------*/ 00028 #include "mbed.h" 00029 #include "EthernetNetIf.h" 00030 #include "TCPSocket.h" 00031 00032 /* ----------------------- Modbus includes ----------------------------------*/ 00033 #include "mb.h" 00034 #include "mbport.h" 00035 00036 /* ----------------------- MBAP Header --------------------------------------*/ 00037 #define MB_TCP_UID 6 00038 #define MB_TCP_LEN 4 00039 #define MB_TCP_FUNC 7 00040 00041 /* ----------------------- Defines -----------------------------------------*/ 00042 #define MB_TCP_DEFAULT_PORT 502 /* TCP listening port. */ 00043 #define MB_TCP_BUF_SIZE ( 256 + 7 ) /* Must hold a complete Modbus TCP frame. */ 00044 00045 /* ----------------------- Prototypes ---------------------------------------*/ 00046 void prvvMBPortReleaseClient( ); 00047 BOOL prvbMBPortAcceptClient( ); 00048 BOOL prvMBTCPGetFrame( ); 00049 void onListeningTCPSocketEvent(TCPSocketEvent e); 00050 void onConnectedTCPSocketEvent(TCPSocketEvent e); 00051 00052 /* ----------------------- Static variables ---------------------------------*/ 00053 static UCHAR aucTCPBuf[MB_TCP_BUF_SIZE]; 00054 static USHORT usTCPBufPos; 00055 static USHORT usTCPFrameBytesLeft; 00056 00057 static TCPSocket ListeningSock; 00058 static TCPSocket* pConnectedSock; // for ConnectedSock 00059 static Host client; 00060 00061 /* ----------------------- Begin implementation -----------------------------*/ 00062 BOOL 00063 xMBTCPPortInit( USHORT usTCPPort ) 00064 { 00065 BOOL bOkay = FALSE; 00066 USHORT usPort; 00067 00068 if( usTCPPort == 0 ) 00069 { 00070 usPort = MB_TCP_DEFAULT_PORT; 00071 } 00072 else 00073 { 00074 usPort = ( USHORT ) usTCPPort; 00075 } 00076 pConnectedSock=NULL; 00077 00078 // Set the callbacks for Listening 00079 ListeningSock.setOnEvent(&onListeningTCPSocketEvent); 00080 00081 // bind and listen on TCP 00082 if( ListeningSock.bind(Host(IpAddr(), usPort)) ) 00083 { 00084 // Failed to bind 00085 bOkay = FALSE; 00086 } 00087 else if( ListeningSock.listen() ) 00088 { 00089 // Failed to listen 00090 bOkay = FALSE; 00091 } 00092 else 00093 { 00094 #ifdef MB_TCP_DEBUG 00095 vMBPortLog( MB_LOG_DEBUG, "MBTCP-ACCEPT", "Protocol stack ready.\r\n" ); 00096 #endif 00097 bOkay = TRUE; 00098 } 00099 00100 return bOkay; 00101 } 00102 00103 void 00104 vMBTCPPortClose( ) 00105 { 00106 /* Shutdown any open client sockets. */ 00107 prvvMBPortReleaseClient(); 00108 00109 /* Shutdown or listening socket. */ 00110 ListeningSock.close(); 00111 00112 /* Release resources for the event queue. */ 00113 // vMBPortEventClose( ); 00114 } 00115 00116 void 00117 vMBTCPPortDisable( void ) 00118 { 00119 prvvMBPortReleaseClient( ); 00120 } 00121 00122 BOOL 00123 xMBTCPPortGetRequest( UCHAR ** ppucMBTCPFrame, USHORT * usTCPLength ) 00124 { 00125 *ppucMBTCPFrame = &aucTCPBuf[0]; 00126 *usTCPLength = usTCPBufPos; 00127 00128 /* Reset the buffer. */ 00129 usTCPBufPos = 0; 00130 usTCPFrameBytesLeft = MB_TCP_FUNC; 00131 return TRUE; 00132 } 00133 00134 BOOL 00135 xMBTCPPortSendResponse( const UCHAR * pucMBTCPFrame, USHORT usTCPLength ) 00136 { 00137 BOOL bFrameSent = FALSE; 00138 00139 if( pConnectedSock ) 00140 { 00141 if(pConnectedSock->send((char *)pucMBTCPFrame, usTCPLength)>=0) 00142 { 00143 bFrameSent = TRUE; 00144 printf("sent %d bytes\n",usTCPLength); 00145 } 00146 else 00147 { 00148 /* Drop the connection in case of an write error. */ 00149 printf("sent error!\n"); 00150 prvvMBPortReleaseClient( ); 00151 } 00152 } 00153 return bFrameSent; 00154 } 00155 00156 void 00157 prvvMBPortReleaseClient( ) 00158 { 00159 if(pConnectedSock){ 00160 IpAddr clientIp = client.getIp(); 00161 #ifdef MB_TCP_DEBUG 00162 vMBPortLog( MB_LOG_DEBUG, "MBTCP-CLOSE", "Closed connection to %d.%d.%d.%d.\r\n", 00163 clientIp[0], clientIp[1], clientIp[2], clientIp[3]); 00164 #endif 00165 pConnectedSock->close(); 00166 pConnectedSock=NULL; 00167 } 00168 } 00169 00170 00171 BOOL prvbMBPortAcceptClient( ) 00172 { 00173 // Accepts connection from client and gets connected socket. 00174 00175 if (ListeningSock.accept(&client, &pConnectedSock)) { 00176 return FALSE; //Error in accept, discard connection 00177 } 00178 // Setup the new socket events 00179 pConnectedSock->setOnEvent(&onConnectedTCPSocketEvent); 00180 // We can find out from where the connection is coming by looking at the 00181 // Host parameter of the accept() method 00182 IpAddr clientIp = client.getIp(); 00183 00184 #ifdef MB_TCP_DEBUG 00185 vMBPortLog( MB_LOG_DEBUG, "MBTCP-ACCEPT", "Accepted new client %d.%d.%d.%d\r\n", 00186 clientIp[0], clientIp[1], clientIp[2], clientIp[3]); 00187 #endif 00188 00189 usTCPBufPos = 0; 00190 usTCPFrameBytesLeft = MB_TCP_FUNC; 00191 00192 return TRUE; 00193 } 00194 00195 00196 BOOL 00197 prvMBTCPGetFrame( ) 00198 { 00199 BOOL bOkay = TRUE; 00200 USHORT usLength; 00201 int iRes; 00202 /* Make sure that we can safely process the next read request. If there 00203 * is an overflow drop the client. 00204 */ 00205 00206 if( ( usTCPBufPos + usTCPFrameBytesLeft ) >= MB_TCP_BUF_SIZE ) 00207 { 00208 // buffer overrun 00209 return FALSE; 00210 } 00211 00212 while (iRes = pConnectedSock->recv((char *)&aucTCPBuf[usTCPBufPos], MB_TCP_BUF_SIZE-usTCPBufPos) ) { 00213 usTCPBufPos+=iRes; 00214 usTCPFrameBytesLeft-=iRes; 00215 } 00216 00217 /* If we have received the MBAP header we can analyze it and calculate 00218 * the number of bytes left to complete the current request. If complete 00219 * notify the protocol stack. 00220 */ 00221 if( usTCPBufPos >= MB_TCP_FUNC ) 00222 { 00223 /* Length is a byte count of Modbus PDU (function code + data) and the 00224 * unit identifier. */ 00225 usLength = aucTCPBuf[MB_TCP_LEN] << 8U; 00226 usLength |= aucTCPBuf[MB_TCP_LEN + 1]; 00227 00228 /* Is the frame already complete. */ 00229 if( usTCPBufPos < ( MB_TCP_UID + usLength ) ) 00230 { 00231 usTCPFrameBytesLeft = usLength + MB_TCP_UID - usTCPBufPos; 00232 } 00233 /* The frame is complete. */ 00234 else if( usTCPBufPos == ( MB_TCP_UID + usLength ) ) 00235 { 00236 #ifdef MB_TCP_DEBUG 00237 prvvMBTCPLogFrame( "MBTCP-RECV", &aucTCPBuf[0], usTCPBufPos ); 00238 #endif 00239 ( void )xMBPortEventPost( EV_FRAME_RECEIVED ); 00240 } 00241 else 00242 { 00243 #ifdef MB_TCP_DEBUG 00244 vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", 00245 "Received too many bytes! Droping client.[%d>%d]\r\n" ,usTCPBufPos, MB_TCP_UID + usLength); 00246 #endif 00247 /* This should not happen. We can't deal with such a client and 00248 * drop the connection for security reasons. 00249 */ 00250 prvvMBPortReleaseClient( ); 00251 } 00252 } 00253 return bOkay; 00254 } 00255 00256 00257 void onListeningTCPSocketEvent(TCPSocketEvent e) 00258 { 00259 switch(e) 00260 { 00261 case TCPSOCKET_ACCEPT: 00262 if(!prvbMBPortAcceptClient()) 00263 { 00264 #ifdef MB_TCP_DEBUG 00265 vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", "Error with client connection! Droping it.\r\n" ); 00266 #endif 00267 ListeningSock.close(); 00268 } 00269 break; 00270 00271 default: 00272 #ifdef MB_TCP_DEBUG 00273 vMBPortLog( MB_LOG_DEBUG, "MBTCP-ERROR", "Unexpeted condition!.\r\n" ); 00274 #endif 00275 ListeningSock.close(); 00276 break; 00277 }; 00278 } 00279 00280 void onConnectedTCPSocketEvent(TCPSocketEvent e) 00281 { 00282 switch(e) 00283 { 00284 case TCPSOCKET_READABLE: 00285 if(!prvMBTCPGetFrame())prvvMBPortReleaseClient(); 00286 break; 00287 case TCPSOCKET_CONNECTED: 00288 case TCPSOCKET_WRITEABLE: 00289 break; 00290 00291 case TCPSOCKET_CONTIMEOUT: 00292 case TCPSOCKET_CONRST: 00293 case TCPSOCKET_CONABRT: 00294 case TCPSOCKET_ERROR: 00295 case TCPSOCKET_DISCONNECTED: 00296 prvvMBPortReleaseClient(); 00297 break; 00298 default: 00299 break; 00300 } 00301 }
Generated on Tue Jul 12 2022 21:23:57 by
