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.
Fork of UIPEthernet by
UIPUdp.cpp
00001 /* 00002 UIPUdp.cpp - Arduino implementation of a UIP wrapper class. 00003 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> 00004 All rights reserved. 00005 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 #include "UIPEthernet.h" 00020 #include "UIPUdp.h" 00021 #include "Dns.h" 00022 00023 extern "C" 00024 { 00025 #include "utility/uip-conf.h" 00026 #include "utility/uip.h" 00027 #include "utility/uip_arp.h" 00028 } 00029 #if UIP_UDP 00030 #define UIP_ARPHDRSIZE 42 00031 #define UDPBUF ((struct uip_udpip_hdr*) &uip_buf[UIP_LLH_LEN]) 00032 00033 // Constructor 00034 UIPUDP::UIPUDP(void) : 00035 _uip_udp_conn(NULL) { 00036 memset(&appdata, 0, sizeof(appdata)); 00037 } 00038 00039 // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 00040 uint8_t UIPUDP::begin(uint16_t port) { 00041 if (!_uip_udp_conn) { 00042 _uip_udp_conn = uip_udp_new(NULL, 0); 00043 } 00044 00045 if (_uip_udp_conn) { 00046 uip_udp_bind(_uip_udp_conn, htons(port)); 00047 _uip_udp_conn->appstate = &appdata; 00048 return 1; 00049 } 00050 00051 return 0; 00052 } 00053 00054 // Finish with the UDP socket 00055 void UIPUDP::stop(void) { 00056 if (_uip_udp_conn) { 00057 uip_udp_remove(_uip_udp_conn); 00058 _uip_udp_conn->appstate = NULL; 00059 _uip_udp_conn = NULL; 00060 uIPEthernet.network.freeBlock(appdata.packet_in); 00061 uIPEthernet.network.freeBlock(appdata.packet_next); 00062 uIPEthernet.network.freeBlock(appdata.packet_out); 00063 memset(&appdata, 0, sizeof(appdata)); 00064 } 00065 } 00066 00067 // Sending UDP packets 00068 // Start building up a packet to send to the remote host specific in ip and port 00069 00070 // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 00071 int UIPUDP::beginPacket(IPAddress ip, uint16_t port) { 00072 uIPEthernet.tick(); 00073 if (ip && port) { 00074 uip_ipaddr_t ripaddr; 00075 uip_ip_addr(&ripaddr, ip); 00076 #ifdef UIPETHERNET_DEBUG_UDP 00077 printf("udp beginPacket, "); 00078 #endif 00079 if (_uip_udp_conn) { 00080 _uip_udp_conn->rport = htons(port); 00081 uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); 00082 } 00083 else { 00084 _uip_udp_conn = uip_udp_new(&ripaddr, htons(port)); 00085 if (_uip_udp_conn) 00086 { 00087 #ifdef UIPETHERNET_DEBUG_UDP 00088 printf("new connection, "); 00089 #endif 00090 _uip_udp_conn->appstate = &appdata; 00091 } 00092 else 00093 { 00094 #ifdef UIPETHERNET_DEBUG_UDP 00095 printf("failed to allocate new connection\r\n"); 00096 #endif 00097 return 0; 00098 } 00099 } 00100 00101 #ifdef UIPETHERNET_DEBUG_UDP 00102 printf("rip: %s, port: %d\r\n", ip.asString(), port); 00103 #endif 00104 } 00105 00106 if (_uip_udp_conn) { 00107 if (appdata.packet_out == NOBLOCK) { 00108 appdata.packet_out = uIPEthernet.network.allocBlock(UIP_UDP_MAXPACKETSIZE); 00109 appdata.out_pos = UIP_UDP_PHYH_LEN; 00110 if (appdata.packet_out != NOBLOCK) 00111 return 1; 00112 #ifdef UIPETHERNET_DEBUG_UDP 00113 else 00114 printf("failed to allocate memory for packet\r\n"); 00115 #endif 00116 } 00117 00118 #ifdef UIPETHERNET_DEBUG_UDP 00119 else 00120 printf("previous packet on that connection not sent yet\r\n"); 00121 #endif 00122 } 00123 00124 return 0; 00125 } 00126 00127 // Start building up a packet to send to the remote host specific in host and port 00128 00129 // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 00130 int UIPUDP::beginPacket(const char* host, uint16_t port) { 00131 00132 // Look up the host first 00133 int ret = 0; 00134 DNSClient dns; 00135 IPAddress remote_addr; 00136 00137 dns.begin(uIPEthernet.dnsServerIP()); 00138 ret = dns.getHostByName(host, remote_addr); 00139 if (ret == 1) { 00140 return beginPacket(remote_addr, port); 00141 } 00142 else { 00143 return ret; 00144 } 00145 } 00146 00147 // Finish off this packet and send it 00148 00149 // Returns 1 if the packet was sent successfully, 0 if there was an error 00150 int UIPUDP::endPacket(void) { 00151 if (_uip_udp_conn && appdata.packet_out != NOBLOCK) { 00152 appdata.send = true; 00153 uIPEthernet.network.resizeBlock(appdata.packet_out, 0, appdata.out_pos); 00154 uip_udp_periodic_conn(_uip_udp_conn); 00155 if (uip_len > 0) { 00156 _send(&appdata); 00157 return 1; 00158 } 00159 } 00160 00161 return 0; 00162 } 00163 00164 // Write a single byte into the packet 00165 size_t UIPUDP::write(uint8_t c) { 00166 return write(&c, 1); 00167 } 00168 00169 // Write size bytes from buffer into the packet 00170 size_t UIPUDP::write(const uint8_t* buffer, size_t size) { 00171 if (appdata.packet_out != NOBLOCK) { 00172 size_t ret = uIPEthernet.network.writePacket(appdata.packet_out, appdata.out_pos, (uint8_t*)buffer, size); 00173 appdata.out_pos += ret; 00174 return ret; 00175 } 00176 00177 return 0; 00178 } 00179 00180 // Start processing the next available incoming packet 00181 00182 // Returns the size of the packet in bytes, or 0 if no packets are available 00183 int UIPUDP::parsePacket(void) { 00184 uIPEthernet.tick(); 00185 #ifdef UIPETHERNET_DEBUG_UDP 00186 if (appdata.packet_in != NOBLOCK) { 00187 printf("udp parsePacket freeing previous packet: %d\r\n", appdata.packet_in); 00188 } 00189 #endif 00190 uIPEthernet.network.freeBlock(appdata.packet_in); 00191 00192 appdata.packet_in = appdata.packet_next; 00193 appdata.packet_next = NOBLOCK; 00194 00195 #ifdef UIPETHERNET_DEBUG_UDP 00196 if (appdata.packet_in != NOBLOCK) { 00197 printf("udp parsePacket received packet: %d", appdata.packet_in); 00198 } 00199 #endif 00200 00201 int size = uIPEthernet.network.blockSize(appdata.packet_in); 00202 #ifdef UIPETHERNET_DEBUG_UDP 00203 if (appdata.packet_in != NOBLOCK) { 00204 printf(", size: %d\r\n", size); 00205 } 00206 #endif 00207 return size; 00208 } 00209 00210 // Number of bytes remaining in the current packet 00211 int UIPUDP::available(void) { 00212 uIPEthernet.tick(); 00213 return uIPEthernet.network.blockSize(appdata.packet_in); 00214 } 00215 00216 // Read a single byte from the current packet 00217 int UIPUDP::read(void) { 00218 static unsigned char c; 00219 if (read(&c, 1) > 0) { 00220 return c; 00221 } 00222 00223 return -1; 00224 } 00225 00226 // Read up to len bytes from the current packet and place them into buffer 00227 00228 // Returns the number of bytes read, or 0 if none are available 00229 int UIPUDP::read(unsigned char* buffer, size_t len) { 00230 uIPEthernet.tick(); 00231 if (appdata.packet_in != NOBLOCK) { 00232 memaddress read = uIPEthernet.network.readPacket(appdata.packet_in, 0, buffer, len); 00233 if (read == uIPEthernet.network.blockSize(appdata.packet_in)) { 00234 uIPEthernet.network.freeBlock(appdata.packet_in); 00235 appdata.packet_in = NOBLOCK; 00236 } 00237 else 00238 uIPEthernet.network.resizeBlock(appdata.packet_in, read); 00239 return read; 00240 } 00241 00242 return 0; 00243 } 00244 00245 // Return the next byte from the current packet without moving on to the next byte 00246 int UIPUDP::peek(void) { 00247 uIPEthernet.tick(); 00248 if (appdata.packet_in != NOBLOCK) { 00249 unsigned char c; 00250 if (uIPEthernet.network.readPacket(appdata.packet_in, 0, &c, 1) == 1) 00251 return c; 00252 } 00253 00254 return -1; 00255 } 00256 00257 // Finish reading the current packet 00258 void UIPUDP::flush(void) { 00259 uIPEthernet.tick(); 00260 uIPEthernet.network.freeBlock(appdata.packet_in); 00261 appdata.packet_in = NOBLOCK; 00262 } 00263 00264 // Return the IP address of the host who sent the current incoming packet 00265 IPAddress UIPUDP::remoteIP(void) { 00266 return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress(); 00267 } 00268 00269 // Return the port of the host who sent the current incoming packet 00270 uint16_t UIPUDP::remotePort(void) { 00271 return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0; 00272 } 00273 00274 // UIP callback function 00275 void uipudp_appcall(void) { 00276 if (uip_udp_userdata_t * data = (uip_udp_userdata_t *) (uip_udp_conn->appstate)) { 00277 if (uip_newdata()) { 00278 if (data->packet_next == NOBLOCK) { 00279 uip_udp_conn->rport = UDPBUF->srcport; 00280 uip_ipaddr_copy(uip_udp_conn->ripaddr, UDPBUF->srcipaddr); 00281 data->packet_next = uIPEthernet.network.allocBlock(ntohs(UDPBUF->udplen) - UIP_UDPH_LEN); 00282 00283 //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery 00284 if (data->packet_next != NOBLOCK) { 00285 00286 //discard Linklevel and IP and udp-header and any trailing bytes: 00287 uIPEthernet.network.copyPacket 00288 ( 00289 data->packet_next, 00290 0, 00291 UIPEthernet::in_packet, 00292 UIP_UDP_PHYH_LEN, 00293 uIPEthernet.network.blockSize(data->packet_next) 00294 ); 00295 #ifdef UIPETHERNET_DEBUG_UDP 00296 printf 00297 ( 00298 "udp, uip_newdata received packet: %d, size: %d\r\n", 00299 data->packet_next, 00300 UIPEthernet.network.blockSize(data->packet_next) 00301 ); 00302 #endif 00303 } 00304 } 00305 } 00306 00307 if (uip_poll() && data->send) 00308 { 00309 //set uip_slen (uip private) by calling uip_udp_send 00310 #ifdef UIPETHERNET_DEBUG_UDP 00311 printf 00312 ( 00313 "udp, uip_poll preparing packet to send: %d, size: %d\r\n", 00314 data->packet_out, 00315 UIPEthernet.network.blockSize(data->packet_out) 00316 ); 00317 #endif 00318 UIPEthernet::uip_packet = data->packet_out; 00319 UIPEthernet::uip_hdrlen = UIP_UDP_PHYH_LEN; 00320 uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN)); 00321 } 00322 } 00323 } 00324 00325 /** 00326 * @brief 00327 * @note 00328 * @param 00329 * @retval 00330 */ 00331 void UIPUDP::_send(uip_udp_userdata_t* data) { 00332 uip_arp_out(); //add arp 00333 if (uip_len == UIP_ARPHDRSIZE) { 00334 UIPEthernet::uip_packet = NOBLOCK; 00335 UIPEthernet::packetstate &= ~UIPETHERNET_SENDPACKET; 00336 #ifdef UIPETHERNET_DEBUG_UDP 00337 printf("udp, uip_poll results in ARP-packet\r\n"); 00338 #endif 00339 } 00340 else { 00341 00342 //arp found ethaddr for ip (otherwise packet is replaced by arp-request) 00343 data->send = false; 00344 data->packet_out = NOBLOCK; 00345 UIPEthernet::packetstate |= UIPETHERNET_SENDPACKET; 00346 #ifdef UIPETHERNET_DEBUG_UDP 00347 printf("udp, uip_packet to send: %d\r\n", UIPEthernet::uip_packet); 00348 #endif 00349 } 00350 00351 uIPEthernet.network_send(); 00352 } 00353 #endif 00354
Generated on Tue Jul 12 2022 18:10:58 by
