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: mbed mbed-rtos EthernetInterface
mbed_ethernet_channels.cpp
00001 /* 00002 RMCIOS - Reactive Multipurpose Control Input Output System 00003 Copyright (c) 2018 Frans Korhonen 00004 00005 RMCIOS was originally developed at Institute for Atmospheric 00006 and Earth System Research / Physics, Faculty of Science, 00007 University of Helsinki, Finland 00008 00009 Assistance, experience and feedback from following persons have been 00010 critical for development of RMCIOS: Erkki Siivola, Juha Kangasluoma, 00011 Lauri Ahonen, Ella Häkkinen, Pasi Aalto, Joonas Enroth, Runlong Cai, 00012 Markku Kulmala and Tuukka Petäjä. 00013 00014 This file is part of RMCIOS. This notice was encoded using utf-8. 00015 00016 RMCIOS is free software: you can redistribute it and/or modify 00017 it under the terms of the GNU General Public License as published by 00018 the Free Software Foundation, either version 3 of the License, or 00019 (at your option) any later version. 00020 00021 RMCIOS is distributed in the hope that it will be useful, 00022 but WITHOUT ANY WARRANTY; without even the implied warranty of 00023 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00024 GNU General Public License for more details. 00025 00026 You should have received a copy of the GNU General Public Licenses 00027 along with RMCIOS. If not, see <http://www.gnu.org/licenses/>. 00028 */ 00029 00030 #if DEVICE_ETHERNET == 1 00031 00032 #include "EthernetInterface.h" 00033 #include "RMCIOS-functions.h" 00034 00035 extern const struct context_rmcios *module_context ; 00036 00037 ////////////////////////////////////////////////////////////////////// 00038 // Ethernet interface channel 00039 ////////////////////////////////////////////////////////////////////// 00040 EthernetInterface enet ; 00041 EthernetInterface *eth=&enet ; 00042 char eth_configured=0; 00043 00044 void ethernet_class_func(const struct context_rmcios *context, 00045 void *data, int id, int function, 00046 enum type_rmcios paramtype, 00047 union param_rmcios returnv, 00048 int num_params,union param_rmcios param) 00049 { 00050 int iplen ; 00051 int masklen ; 00052 int gwlen ; 00053 switch(function) 00054 { 00055 case help_rmcios: 00056 return_string(context, paramtype,returnv, 00057 "help for ethernet interface channel\r\n" 00058 " setup eth # Configure ethernet with DHCP\r\n" 00059 " setup eth ip_addr ipmask gateway # Manual configuration\r\n" 00060 ) ; 00061 break ; 00062 00063 case setup_rmcios : 00064 // Allocate ethernet interface. 00065 if(eth==NULL) eth = new EthernetInterface ; 00066 if(eth==NULL) break ; 00067 if(eth_configured==1) { 00068 return_string(context, paramtype,returnv, 00069 "Ethernet can only be configured once.") ; 00070 break ; 00071 } 00072 00073 if(num_params<3) { 00074 return_string(context, paramtype,returnv, 00075 "Configuring ethernet with DHCP:") ; 00076 eth_configured=1; 00077 eth->init() ; // dhcp config 00078 eth->connect(); 00079 00080 return_string(context, paramtype,returnv, 00081 "Ethernet configuration:\r\n") ; 00082 return_string(context, paramtype,returnv,"ip:"); 00083 return_string(context, paramtype,returnv,eth->getIPAddress()); 00084 return_string(context, paramtype,returnv,"\r\nipmask:"); 00085 return_string(context, paramtype,returnv,eth->getNetworkMask()); 00086 return_string(context, paramtype,returnv,"\r\ngateway:"); 00087 return_string(context, paramtype,returnv,eth->getGateway()); 00088 return_string(context, paramtype,returnv,"\r\n"); 00089 break ; 00090 } 00091 00092 iplen = param_string_length(context, paramtype, param, 0)+1; 00093 masklen = param_string_length(context, paramtype, param, 1)+1; 00094 gwlen = param_string_length(context, paramtype, param, 2)+1; 00095 { 00096 00097 char ip[iplen] ; 00098 char ipmask[masklen] ; 00099 char gateway[gwlen] ; 00100 param_to_string(context, paramtype, param, 0, iplen, ip); 00101 param_to_string(context, paramtype, param, 1, masklen, ipmask); 00102 param_to_string(context, paramtype, param, 2, gwlen, gateway); 00103 00104 printf("setup manual ip: %s %s %s\r\n", ip, ipmask, gateway) ; 00105 eth_configured=1; 00106 eth->init(ip,ipmask,gateway) ; // manual ip config 00107 eth->connect(); 00108 00109 return_string(context, paramtype,returnv, 00110 "Ethernet configuration:\r\n") ; 00111 return_string(context, paramtype, returnv, "ip:"); 00112 return_string(context, paramtype, returnv, eth->getIPAddress()); 00113 return_string(context, paramtype, returnv, "\r\nipmask:"); 00114 return_string(context, paramtype, returnv, eth->getNetworkMask()); 00115 return_string(context, paramtype, returnv, "\r\ngateway:"); 00116 return_string(context, paramtype, returnv, eth->getGateway()); 00117 return_string(context, paramtype, returnv, "\r\n"); 00118 } 00119 break ; 00120 } 00121 } 00122 00123 //////////////////////////////////////////////////////////////////////// 00124 // TCP Client channel: 00125 //////////////////////////////////////////////////////////////////////// 00126 struct tcp_connection_data { 00127 char host[50] ; 00128 int port ; 00129 TCPSocketConnection socket; 00130 bool closed ; 00131 }; 00132 00133 void tcp_client_class_func(void* data, 00134 const struct context_rmcios *context, 00135 int id, 00136 int function, 00137 enum type_rmcios paramtype, 00138 union param_rmcios returnv, 00139 int num_params, 00140 union param_rmcios param) 00141 { 00142 tcp_connection_data *p_data=(tcp_connection_data *)data ; 00143 int plen ; 00144 switch(function) { 00145 case help_rmcios: 00146 return_string(context, paramtype, returnv, 00147 "help for tcp client channel\r\n" 00148 " create tcp_client newname\r\n" 00149 " setup newname ip port #Open connection\r\n" 00150 " setup newname #Close connection\r\n" 00151 " write newname #Flush all buffers\r\n" 00152 " write newname data #Write data to the connection.\r\n" 00153 " Reconnect if needed\r\n" 00154 " link newname channel # Link received data to channel\r\n" 00155 ) ; 00156 break ; 00157 case create_rmcios : 00158 if(num_params<1) break ; 00159 if(eth==NULL) break ; 00160 00161 // allocate new data 00162 p_data= new struct tcp_connection_data; 00163 00164 // default values 00165 p_data->host[0]=0; 00166 p_data->port=0; 00167 p_data->closed=true ; 00168 00169 create_channel_param(context, paramtype, param, 0, 00170 (class_rmcios)tcp_client_class_func, p_data) ; 00171 00172 break ; 00173 case setup_rmcios : 00174 if(p_data==NULL) break ; 00175 if(num_params<1) { // Close connection 00176 Thread::wait(500); 00177 if(p_data==NULL) break ; 00178 if(p_data->socket.is_connected()) p_data->socket.close(); 00179 break ; 00180 } 00181 if(num_params<2) break ; 00182 param_to_string(context, paramtype, param, 0, 00183 sizeof(p_data->host),p_data->host) ; 00184 p_data->port=param_to_int(context, paramtype,param,1) ; 00185 p_data->closed=true ; 00186 break ; 00187 00188 case write_rmcios : 00189 if(p_data==NULL) break ; 00190 if(num_params<1) { // Close connection 00191 Thread::wait(500); 00192 if(p_data==NULL) break ; 00193 if(p_data->socket.is_connected()) p_data->socket.close(); 00194 break ; 00195 } 00196 00197 /// If socket is not open. Try 3 times to open connection: 00198 if(!p_data->socket.is_connected() || p_data->closed==true ) { 00199 if(p_data->socket.connect(p_data->host,p_data->port)==0) { 00200 p_data->closed=false ; 00201 } 00202 else p_data->closed=false ; 00203 } 00204 if(!p_data->socket.is_connected() || p_data->closed==true ) { 00205 Thread::wait(200); 00206 if(p_data->socket.connect(p_data->host,p_data->port)==0) { 00207 p_data->closed=false ; 00208 } 00209 else p_data->closed=false ; 00210 } 00211 if(!p_data->socket.is_connected() || p_data->closed==true ) { 00212 Thread::wait(200); 00213 if(p_data->socket.connect(p_data->host,p_data->port)==0) { 00214 p_data->closed=false ; 00215 } 00216 else p_data->closed=false ; 00217 } 00218 00219 plen=param_buffer_alloc_size(context, paramtype,param,0) ; 00220 { 00221 char buffer[plen] ; 00222 int retry; 00223 struct buffer_rmcios p ; 00224 p=param_to_buffer(context, paramtype,param, 0, plen, buffer) ; 00225 // retry 3 times 00226 for(retry=0 ; 00227 retry<3 && p_data->socket.send(p.data, p.length )<0 ; 00228 retry++) 00229 { 00230 Thread::wait(200); 00231 } 00232 Thread::wait(100); 00233 } 00234 break ; 00235 } 00236 } 00237 00238 /////////////////////////////////////////////////////// 00239 // TCP server channel 00240 //////////////////////////////////////////////////////// 00241 struct tcpserver_data { 00242 int port ; 00243 TCPSocketServer socket ; 00244 TCPSocketConnection connection; 00245 int linked_channels ; 00246 char buffer[512] ; 00247 int id ; 00248 }; 00249 00250 //! Thread for handling udp reception. 00251 void tcpserver_thread(const void *param) 00252 { 00253 printf("tcp server thread created!\r\n") ; 00254 int n=0 ; 00255 struct tcpserver_data *pthis=(struct tcpserver_data *) param ; 00256 00257 while(pthis->port==0) ; 00258 { 00259 Thread::wait(200); 00260 } 00261 00262 pthis->socket.bind(pthis->port) ; 00263 pthis->socket.listen(); 00264 00265 while(1) { 00266 pthis->socket.accept( pthis->connection ) ; 00267 printf("connection accepted!\r\n") ; 00268 // receive command 00269 while( pthis->connection.is_connected() ) { 00270 n=pthis->connection.receive(pthis->buffer,sizeof( pthis->buffer)-1); 00271 if(n>0) { 00272 if( pthis->linked_channels!=0) { 00273 write_buffer(module_context, pthis->linked_channels, 00274 pthis->buffer,n,pthis->id) ; 00275 } 00276 } 00277 } 00278 } 00279 } 00280 00281 void tcp_server_class_func(struct tcpserver_data *pthis, 00282 const struct context_rmcios *context, 00283 int id, 00284 int function, 00285 enum type_rmcios paramtype, 00286 union param_rmcios returnv, 00287 int num_params, 00288 union param_rmcios param) 00289 { 00290 int plen; 00291 switch(function) { 00292 case help_rmcios: 00293 return_string(context, paramtype, returnv, 00294 "TCP server channel\r\n" 00295 "create tcpserver newname\r\n" 00296 "setup newname port\r\n" 00297 "write newname data\r\n" 00298 "link newname channel\r\n" 00299 ); 00300 break; 00301 00302 case create_rmcios : 00303 if(num_params<1) break ; 00304 pthis= (struct tcpserver_data *) 00305 malloc(sizeof( struct tcpserver_data)) ; 00306 00307 pthis->port=0 ; 00308 pthis->buffer[0]=0; 00309 pthis->socket=TCPSocketServer(); 00310 pthis->connection=TCPSocketConnection(); 00311 00312 pthis->id=create_channel_param(context, paramtype, param, 0, 00313 (class_rmcios)tcp_server_class_func, 00314 pthis); 00315 pthis->linked_channels=linked_channels(context, pthis->id) ; 00316 break; 00317 00318 case setup_rmcios : 00319 if(pthis==NULL) break ; 00320 if(num_params<1) { 00321 if( !pthis->connection.is_connected() ){ 00322 pthis->connection.close() ; 00323 } 00324 break ; 00325 } 00326 pthis->port=param_to_integer(context, paramtype, param,0); 00327 00328 // Start reception thread 00329 new Thread(tcpserver_thread, pthis); 00330 break; 00331 00332 case write_rmcios : 00333 if(pthis==NULL) break ; 00334 if(num_params<1) break ; 00335 plen=param_buffer_alloc_size(context, paramtype, param, 0) ; 00336 { 00337 char buffer[plen] ; 00338 struct buffer_rmcios pbuffer ; 00339 pbuffer = param_to_buffer(context, paramtype,param, 0, 00340 plen , buffer) ; 00341 if(pthis->connection.send(pbuffer.data, pbuffer.length)<0){ 00342 return_int(context, paramtype, returnv, -1) ; 00343 pthis->connection.close() ; 00344 } 00345 } 00346 break; 00347 } 00348 } 00349 00350 /////////////////////////////////////////////////////// 00351 // UDP server channel 00352 //////////////////////////////////////////////////////// 00353 struct udp_server_data { 00354 int id ; 00355 int port ; 00356 UDPSocket socket ; 00357 Endpoint client ; 00358 char txbuffer[100] ; 00359 char buffer[100] ; 00360 int linked_channel ; 00361 } ; 00362 00363 //! Thread for handling udp reception. 00364 void udp_server_thread(const void *param) 00365 { 00366 //printf("udp thread created!\r\n") ; 00367 int n=0 ; 00368 struct udp_server_data *p_data=(struct udp_server_data *) param ; 00369 //printf("waiting for configuration:\r\n") ; 00370 while(p_data->port==0) ; 00371 { 00372 p_data->socket.bind(p_data->port) ; 00373 Thread::wait(200); 00374 } 00375 while(1) { 00376 // receive command 00377 n=p_data->socket.receiveFrom(p_data->client, p_data->buffer, 00378 sizeof(p_data->buffer)-1 ) ; 00379 if(n>0) { 00380 if(p_data->linked_channel!=0){ 00381 write_buffer(module_context, p_data->linked_channel, 00382 p_data->buffer, n, p_data->id) ; 00383 } 00384 } 00385 } 00386 } 00387 00388 void udp_server_class_func(udp_server_data *p_data, 00389 const struct context_rmcios *context, 00390 int id, 00391 int function, 00392 enum type_rmcios paramtype, 00393 union param_rmcios returnv, 00394 int num_params,union param_rmcios param) 00395 { 00396 switch(function) 00397 { 00398 case help_rmcios : 00399 return_string(context, paramtype, returnv, 00400 "help for udp server channel\r\n" 00401 " create udp_server newname\r\n" 00402 " setup newname port \r\n" 00403 " write newname \r\n" 00404 " # flush tansmit buffer)\r\n" 00405 " write newname data \r\n" 00406 " # write data to tansmit buffer.\r\n" 00407 " Flush buffer to ethernet when \\r encountered. \r\n" 00408 " link newname channel \r\n" 00409 " # Link received data to channel\r\n" 00410 ) ; 00411 00412 break ; 00413 case create_rmcios : 00414 if(num_params<1) break ; 00415 if(eth==NULL) break ; 00416 p_data= new struct udp_server_data ; 00417 if(p_data==NULL) break ; 00418 00419 // Default values: 00420 p_data->port=0; 00421 p_data->buffer[0]=0; 00422 p_data->txbuffer[0]=0 ; 00423 00424 // Create the channel 00425 p_data->id=create_channel_param(context, paramtype, param, 0, 00426 (class_rmcios)udp_server_class_func, 00427 p_data) ; 00428 00429 p_data->linked_channel=linked_channels(context,p_data->id); 00430 break ; 00431 case setup_rmcios : 00432 00433 if(p_data==NULL) break ; 00434 if(num_params<1) break ; 00435 else { 00436 p_data->port=param_to_int(context, paramtype, param, 0); 00437 new Thread(udp_server_thread, p_data); 00438 } 00439 break ; 00440 00441 case write_rmcios : 00442 if(p_data==NULL) break ; 00443 if(num_params<1) { // flush buffer 00444 p_data->socket.sendTo(p_data->client, p_data->txbuffer, 00445 strlen(p_data->txbuffer)); 00446 p_data->txbuffer[0]=0 ; 00447 break ; 00448 } 00449 00450 // collect data to buffer 00451 param_to_string(context, paramtype, param, 0, 00452 sizeof(p_data->txbuffer)-strlen(p_data->txbuffer), 00453 p_data->txbuffer+strlen(p_data->txbuffer)) ; 00454 break ; 00455 } 00456 } 00457 00458 void init_mbed_ethernet_channels(const struct context_rmcios *context) 00459 { 00460 module_context=context ; 00461 create_channel_str(context, "eth",(class_rmcios)ethernet_class_func, NULL); 00462 create_channel_str(context, "udp_server", 00463 (class_rmcios)udp_server_class_func, NULL ) ; 00464 00465 // TCP Not usable. (Memory consumption issues.) 00466 // create_channel_str("tcp_client",(channel_func) tcp_client_class_func, 00467 // NULL ) ; 00468 // create_channel_str("tcp_server",(channel_func) tcp_server_class_func, 00469 // NULL ) ; 00470 } 00471 00472 #endif //if DEVICE_ETHERNET == 1 00473 00474
Generated on Wed Jul 13 2022 08:01:14 by
1.7.2