mbed OS5
Fork of UIPEthernet by
Embed:
(wiki syntax)
Show/hide line numbers
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 1.7.2