mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Committer:
hudakz
Date:
Sun Mar 08 20:26:56 2015 +0000
Revision:
4:d774541a34da
Parent:
2:049ce85163c5
Child:
6:10e42359e217
Version 1.09 (fixed leaking client-data caused by race-condition on remote close)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:5350a66d5279 1 /*
hudakz 0:5350a66d5279 2 UIPClient.cpp - Arduino implementation of a uIP wrapper class.
hudakz 0:5350a66d5279 3 Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
hudakz 0:5350a66d5279 4 All rights reserved.
hudakz 0:5350a66d5279 5
hudakz 4:d774541a34da 6 Modified (ported to mbed) by Zoltan Hudak <hudakz@inbox.com>
hudakz 4:d774541a34da 7
hudakz 0:5350a66d5279 8 This program is free software: you can redistribute it and/or modify
hudakz 0:5350a66d5279 9 it under the terms of the GNU General Public License as published by
hudakz 0:5350a66d5279 10 the Free Software Foundation, either version 3 of the License, or
hudakz 0:5350a66d5279 11 (at your option) any later version.
hudakz 0:5350a66d5279 12
hudakz 0:5350a66d5279 13 This program is distributed in the hope that it will be useful,
hudakz 0:5350a66d5279 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
hudakz 0:5350a66d5279 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
hudakz 0:5350a66d5279 16 GNU General Public License for more details.
hudakz 0:5350a66d5279 17
hudakz 0:5350a66d5279 18 You should have received a copy of the GNU General Public License
hudakz 0:5350a66d5279 19 along with this program. If not, see <http://www.gnu.org/licenses/>.
hudakz 0:5350a66d5279 20 */
hudakz 0:5350a66d5279 21 extern "C"
hudakz 0:5350a66d5279 22 {
hudakz 4:d774541a34da 23 #include "utility/uip-conf.h"
hudakz 4:d774541a34da 24 #include "utility/uip.h"
hudakz 4:d774541a34da 25 #include "utility/uip_arp.h"
hudakz 4:d774541a34da 26 #include "utility/millis.h"
hudakz 0:5350a66d5279 27 #include "string.h"
hudakz 0:5350a66d5279 28 }
hudakz 0:5350a66d5279 29 #include "UIPEthernet.h"
hudakz 0:5350a66d5279 30 #include "UIPClient.h"
hudakz 0:5350a66d5279 31 #include "Dns.h"
hudakz 0:5350a66d5279 32
hudakz 0:5350a66d5279 33 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 0:5350a66d5279 34 #include "HardwareSerial.h"
hudakz 0:5350a66d5279 35 #endif
hudakz 0:5350a66d5279 36 #define UIP_TCP_PHYH_LEN UIP_LLH_LEN + UIP_IPTCPH_LEN
hudakz 0:5350a66d5279 37
hudakz 4:d774541a34da 38 uip_userdata_t UIPClient:: all_data[UIP_CONNS];
hudakz 0:5350a66d5279 39
hudakz 0:5350a66d5279 40 /**
hudakz 0:5350a66d5279 41 * @brief
hudakz 0:5350a66d5279 42 * @note
hudakz 0:5350a66d5279 43 * @param
hudakz 0:5350a66d5279 44 * @retval
hudakz 0:5350a66d5279 45 */
hudakz 0:5350a66d5279 46 UIPClient::UIPClient(void) :
hudakz 4:d774541a34da 47 data(NULL)
hudakz 0:5350a66d5279 48 { }
hudakz 0:5350a66d5279 49
hudakz 0:5350a66d5279 50 /**
hudakz 0:5350a66d5279 51 * @brief
hudakz 0:5350a66d5279 52 * @note
hudakz 0:5350a66d5279 53 * @param
hudakz 0:5350a66d5279 54 * @retval
hudakz 0:5350a66d5279 55 */
hudakz 4:d774541a34da 56 UIPClient::UIPClient(uip_userdata_t* conn_data) :
hudakz 4:d774541a34da 57 data(conn_data)
hudakz 0:5350a66d5279 58 { }
hudakz 0:5350a66d5279 59
hudakz 0:5350a66d5279 60 /**
hudakz 0:5350a66d5279 61 * @brief
hudakz 0:5350a66d5279 62 * @note
hudakz 0:5350a66d5279 63 * @param
hudakz 0:5350a66d5279 64 * @retval
hudakz 0:5350a66d5279 65 */
hudakz 0:5350a66d5279 66 int UIPClient::connect(IPAddress ip, uint16_t port) {
hudakz 4:d774541a34da 67 stop();
hudakz 4:d774541a34da 68
hudakz 0:5350a66d5279 69 uip_ipaddr_t ipaddr;
hudakz 0:5350a66d5279 70 uip_ip_addr(ipaddr, ip);
hudakz 4:d774541a34da 71
hudakz 4:d774541a34da 72 struct uip_conn* conn = uip_connect(&ipaddr, htons(port));
hudakz 4:d774541a34da 73 if(conn)
hudakz 4:d774541a34da 74 {
hudakz 4:d774541a34da 75 #if UIP_CONNECT_TIMEOUT > 0
hudakz 4:d774541a34da 76 int32_t timeout = millis() + 1000 * UIP_CONNECT_TIMEOUT;
hudakz 4:d774541a34da 77 #endif
hudakz 4:d774541a34da 78 while((conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) {
hudakz 0:5350a66d5279 79 UIPEthernet.tick();
hudakz 4:d774541a34da 80 if((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) {
hudakz 4:d774541a34da 81 data = (uip_userdata_t*)conn->appstate;
hudakz 0:5350a66d5279 82 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 83 Serial.print(F("connected, state: "));
hudakz 4:d774541a34da 84 Serial.print(data->state);
hudakz 4:d774541a34da 85 Serial.print(F(", first packet in: "));
hudakz 4:d774541a34da 86 Serial.println(data->packets_in[0]);
hudakz 0:5350a66d5279 87 #endif
hudakz 0:5350a66d5279 88 return 1;
hudakz 0:5350a66d5279 89 }
hudakz 4:d774541a34da 90
hudakz 4:d774541a34da 91 #if UIP_CONNECT_TIMEOUT > 0
hudakz 4:d774541a34da 92 if(((int32_t) (millis() - timeout)) > 0) {
hudakz 4:d774541a34da 93 conn->tcpstateflags = UIP_CLOSED;
hudakz 4:d774541a34da 94 break;
hudakz 4:d774541a34da 95 }
hudakz 4:d774541a34da 96 #endif
hudakz 0:5350a66d5279 97 }
hudakz 0:5350a66d5279 98 }
hudakz 0:5350a66d5279 99
hudakz 0:5350a66d5279 100 return 0;
hudakz 0:5350a66d5279 101 }
hudakz 0:5350a66d5279 102
hudakz 0:5350a66d5279 103 /**
hudakz 0:5350a66d5279 104 * @brief
hudakz 0:5350a66d5279 105 * @note
hudakz 0:5350a66d5279 106 * @param
hudakz 0:5350a66d5279 107 * @retval
hudakz 0:5350a66d5279 108 */
hudakz 0:5350a66d5279 109 int UIPClient::connect(const char* host, uint16_t port) {
hudakz 0:5350a66d5279 110
hudakz 0:5350a66d5279 111 // Look up the host first
hudakz 0:5350a66d5279 112 int ret = 0;
hudakz 0:5350a66d5279 113 #if UIP_UDP
hudakz 0:5350a66d5279 114 DNSClient dns;
hudakz 0:5350a66d5279 115 IPAddress remote_addr;
hudakz 0:5350a66d5279 116
hudakz 4:d774541a34da 117 dns.begin(UIPEthernetClass::_dnsServerAddress);
hudakz 0:5350a66d5279 118 ret = dns.getHostByName(host, remote_addr);
hudakz 0:5350a66d5279 119 if(ret == 1) {
hudakz 0:5350a66d5279 120 return connect(remote_addr, port);
hudakz 0:5350a66d5279 121 }
hudakz 0:5350a66d5279 122 #endif
hudakz 0:5350a66d5279 123 return ret;
hudakz 0:5350a66d5279 124 }
hudakz 0:5350a66d5279 125
hudakz 0:5350a66d5279 126 /**
hudakz 0:5350a66d5279 127 * @brief
hudakz 0:5350a66d5279 128 * @note
hudakz 0:5350a66d5279 129 * @param
hudakz 0:5350a66d5279 130 * @retval
hudakz 0:5350a66d5279 131 */
hudakz 0:5350a66d5279 132 void UIPClient::stop(void) {
hudakz 4:d774541a34da 133 if(data && data->state)
hudakz 4:d774541a34da 134 {
hudakz 4:d774541a34da 135 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 136 Serial.println(F("before stop(), with data"));
hudakz 4:d774541a34da 137 _dumpAllData();
hudakz 4:d774541a34da 138 #endif
hudakz 0:5350a66d5279 139 _flushBlocks(&data->packets_in[0]);
hudakz 4:d774541a34da 140 if(data->state & UIP_CLIENT_REMOTECLOSED) {
hudakz 4:d774541a34da 141 data->state = 0;
hudakz 0:5350a66d5279 142 }
hudakz 0:5350a66d5279 143 else {
hudakz 0:5350a66d5279 144 data->state |= UIP_CLIENT_CLOSE;
hudakz 0:5350a66d5279 145 }
hudakz 0:5350a66d5279 146
hudakz 4:d774541a34da 147 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 148 Serial.println(F("after stop()"));
hudakz 4:d774541a34da 149 _dumpAllData();
hudakz 4:d774541a34da 150 #endif
hudakz 0:5350a66d5279 151 }
hudakz 0:5350a66d5279 152
hudakz 4:d774541a34da 153 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 154 else {
hudakz 4:d774541a34da 155 Serial.println(F("stop(), data: NULL"));
hudakz 4:d774541a34da 156 }
hudakz 4:d774541a34da 157 #endif
hudakz 4:d774541a34da 158 data = NULL;
hudakz 0:5350a66d5279 159 UIPEthernet.tick();
hudakz 0:5350a66d5279 160 }
hudakz 0:5350a66d5279 161
hudakz 0:5350a66d5279 162 /**
hudakz 0:5350a66d5279 163 * @brief
hudakz 0:5350a66d5279 164 * @note
hudakz 0:5350a66d5279 165 * @param
hudakz 0:5350a66d5279 166 * @retval
hudakz 0:5350a66d5279 167 */
hudakz 0:5350a66d5279 168 uint8_t UIPClient::connected(void) {
hudakz 4:d774541a34da 169 return(data && (data->packets_in[0] != NOBLOCK || (data->state & UIP_CLIENT_CONNECTED))) ? 1 : 0;
hudakz 0:5350a66d5279 170 }
hudakz 0:5350a66d5279 171
hudakz 0:5350a66d5279 172 /**
hudakz 0:5350a66d5279 173 * @brief
hudakz 0:5350a66d5279 174 * @note
hudakz 0:5350a66d5279 175 * @param
hudakz 0:5350a66d5279 176 * @retval
hudakz 0:5350a66d5279 177 */
hudakz 0:5350a66d5279 178 bool UIPClient::operator==(const UIPClient& rhs) {
hudakz 4:d774541a34da 179 return data && rhs.data && (data == rhs.data);
hudakz 0:5350a66d5279 180 }
hudakz 0:5350a66d5279 181
hudakz 0:5350a66d5279 182 /**
hudakz 0:5350a66d5279 183 * @brief
hudakz 0:5350a66d5279 184 * @note
hudakz 0:5350a66d5279 185 * @param
hudakz 0:5350a66d5279 186 * @retval
hudakz 0:5350a66d5279 187 */
hudakz 0:5350a66d5279 188 UIPClient::operator bool(void) {
hudakz 0:5350a66d5279 189 UIPEthernet.tick();
hudakz 4:d774541a34da 190 return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK);
hudakz 0:5350a66d5279 191 }
hudakz 0:5350a66d5279 192
hudakz 0:5350a66d5279 193 /**
hudakz 0:5350a66d5279 194 * @brief
hudakz 0:5350a66d5279 195 * @note
hudakz 0:5350a66d5279 196 * @param
hudakz 0:5350a66d5279 197 * @retval
hudakz 0:5350a66d5279 198 */
hudakz 0:5350a66d5279 199 size_t UIPClient::write(uint8_t c) {
hudakz 4:d774541a34da 200 return _write(data, &c, 1);
hudakz 0:5350a66d5279 201 }
hudakz 0:5350a66d5279 202
hudakz 0:5350a66d5279 203 /**
hudakz 0:5350a66d5279 204 * @brief
hudakz 0:5350a66d5279 205 * @note
hudakz 0:5350a66d5279 206 * @param
hudakz 0:5350a66d5279 207 * @retval
hudakz 0:5350a66d5279 208 */
hudakz 0:5350a66d5279 209 size_t UIPClient::write(const uint8_t* buf, size_t size) {
hudakz 4:d774541a34da 210 return _write(data, buf, size);
hudakz 0:5350a66d5279 211 }
hudakz 0:5350a66d5279 212
hudakz 0:5350a66d5279 213 /**
hudakz 0:5350a66d5279 214 * @brief
hudakz 0:5350a66d5279 215 * @note
hudakz 0:5350a66d5279 216 * @param
hudakz 0:5350a66d5279 217 * @retval
hudakz 0:5350a66d5279 218 */
hudakz 4:d774541a34da 219 size_t UIPClient::_write(uip_userdata_t* u, const uint8_t* buf, size_t size) {
hudakz 4:d774541a34da 220 int remain = size;
hudakz 4:d774541a34da 221 uint16_t written;
hudakz 0:5350a66d5279 222 #if UIP_ATTEMPTS_ON_WRITE > 0
hudakz 4:d774541a34da 223 uint16_t attempts = UIP_ATTEMPTS_ON_WRITE;
hudakz 0:5350a66d5279 224 #endif
hudakz 0:5350a66d5279 225 repeat : UIPEthernet.tick();
hudakz 4:d774541a34da 226 if(u && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) {
hudakz 4:d774541a34da 227 uint8_t p = _currentBlock(&u->packets_out[0]);
hudakz 4:d774541a34da 228 if(u->packets_out[p] == NOBLOCK)
hudakz 0:5350a66d5279 229 {
hudakz 0:5350a66d5279 230 newpacket:
hudakz 4:d774541a34da 231 u->packets_out[p] = UIPEthernet.network.allocBlock(UIP_SOCKET_DATALEN);
hudakz 4:d774541a34da 232 if(u->packets_out[p] == NOBLOCK)
hudakz 0:5350a66d5279 233 {
hudakz 0:5350a66d5279 234 #if UIP_ATTEMPTS_ON_WRITE > 0
hudakz 0:5350a66d5279 235 if((--attempts) > 0)
hudakz 0:5350a66d5279 236 #endif
hudakz 0:5350a66d5279 237 #if UIP_ATTEMPTS_ON_WRITE != 0
hudakz 0:5350a66d5279 238 goto repeat;
hudakz 0:5350a66d5279 239 #endif
hudakz 0:5350a66d5279 240 goto ready;
hudakz 0:5350a66d5279 241 }
hudakz 0:5350a66d5279 242
hudakz 0:5350a66d5279 243 u->out_pos = 0;
hudakz 0:5350a66d5279 244 }
hudakz 0:5350a66d5279 245
hudakz 0:5350a66d5279 246 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 247 Serial.print(F("UIPClient.write: writePacket("));
hudakz 4:d774541a34da 248 Serial.print(u->packets_out[p]);
hudakz 4:d774541a34da 249 Serial.print(F(") pos: "));
hudakz 0:5350a66d5279 250 Serial.print(u->out_pos);
hudakz 4:d774541a34da 251 Serial.print(F(", buf["));
hudakz 0:5350a66d5279 252 Serial.print(size - remain);
hudakz 4:d774541a34da 253 Serial.print(F("-"));
hudakz 0:5350a66d5279 254 Serial.print(remain);
hudakz 4:d774541a34da 255 Serial.print(F("]: '"));
hudakz 0:5350a66d5279 256 Serial.write((uint8_t*)buf + size - remain, remain);
hudakz 4:d774541a34da 257 Serial.println(F("'"));
hudakz 0:5350a66d5279 258 #endif
hudakz 4:d774541a34da 259 written = UIPEthernet.network.writePacket
hudakz 4:d774541a34da 260 (
hudakz 4:d774541a34da 261 u->packets_out[p],
hudakz 4:d774541a34da 262 u->out_pos,
hudakz 4:d774541a34da 263 (uint8_t*)buf + size - remain,
hudakz 4:d774541a34da 264 remain
hudakz 4:d774541a34da 265 );
hudakz 0:5350a66d5279 266 remain -= written;
hudakz 0:5350a66d5279 267 u->out_pos += written;
hudakz 0:5350a66d5279 268 if(remain > 0) {
hudakz 4:d774541a34da 269 if(p == UIP_SOCKET_NUMPACKETS - 1)
hudakz 0:5350a66d5279 270 {
hudakz 0:5350a66d5279 271 #if UIP_ATTEMPTS_ON_WRITE > 0
hudakz 0:5350a66d5279 272 if((--attempts) > 0)
hudakz 0:5350a66d5279 273 #endif
hudakz 0:5350a66d5279 274 #if UIP_ATTEMPTS_ON_WRITE != 0
hudakz 0:5350a66d5279 275 goto repeat;
hudakz 0:5350a66d5279 276 #endif
hudakz 0:5350a66d5279 277 goto ready;
hudakz 0:5350a66d5279 278 }
hudakz 0:5350a66d5279 279
hudakz 0:5350a66d5279 280 p++;
hudakz 0:5350a66d5279 281 goto newpacket;
hudakz 0:5350a66d5279 282 }
hudakz 0:5350a66d5279 283
hudakz 0:5350a66d5279 284 ready:
hudakz 4:d774541a34da 285 #if UIP_CLIENT_TIMER >= 0
hudakz 4:d774541a34da 286 u->timer = millis() + UIP_CLIENT_TIMER;
hudakz 4:d774541a34da 287 #endif
hudakz 0:5350a66d5279 288 return size - remain;
hudakz 0:5350a66d5279 289 }
hudakz 0:5350a66d5279 290
hudakz 0:5350a66d5279 291 return -1;
hudakz 0:5350a66d5279 292 }
hudakz 0:5350a66d5279 293
hudakz 0:5350a66d5279 294 /**
hudakz 0:5350a66d5279 295 * @brief
hudakz 0:5350a66d5279 296 * @note
hudakz 0:5350a66d5279 297 * @param
hudakz 0:5350a66d5279 298 * @retval
hudakz 0:5350a66d5279 299 */
hudakz 0:5350a66d5279 300 int UIPClient::available(void) {
hudakz 0:5350a66d5279 301 if(*this)
hudakz 0:5350a66d5279 302 return _available(data);
hudakz 4:d774541a34da 303 return 0;
hudakz 0:5350a66d5279 304 }
hudakz 0:5350a66d5279 305
hudakz 0:5350a66d5279 306 /**
hudakz 0:5350a66d5279 307 * @brief
hudakz 0:5350a66d5279 308 * @note
hudakz 0:5350a66d5279 309 * @param
hudakz 0:5350a66d5279 310 * @retval
hudakz 0:5350a66d5279 311 */
hudakz 0:5350a66d5279 312 int UIPClient::_available(uip_userdata_t* u) {
hudakz 0:5350a66d5279 313 int len = 0;
hudakz 4:d774541a34da 314 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 4:d774541a34da 315 len += UIPEthernet.network.blockSize(u->packets_in[i]);
hudakz 0:5350a66d5279 316 }
hudakz 0:5350a66d5279 317
hudakz 0:5350a66d5279 318 return len;
hudakz 0:5350a66d5279 319 }
hudakz 0:5350a66d5279 320
hudakz 0:5350a66d5279 321 /**
hudakz 0:5350a66d5279 322 * @brief
hudakz 0:5350a66d5279 323 * @note
hudakz 0:5350a66d5279 324 * @param
hudakz 0:5350a66d5279 325 * @retval
hudakz 0:5350a66d5279 326 */
hudakz 0:5350a66d5279 327 int UIPClient::read(uint8_t* buf, size_t size) {
hudakz 0:5350a66d5279 328 if(*this) {
hudakz 4:d774541a34da 329 uint16_t remain = size;
hudakz 4:d774541a34da 330 if(data->packets_in[0] == NOBLOCK)
hudakz 0:5350a66d5279 331 return 0;
hudakz 0:5350a66d5279 332
hudakz 4:d774541a34da 333 uint16_t read;
hudakz 0:5350a66d5279 334 do
hudakz 0:5350a66d5279 335 {
hudakz 4:d774541a34da 336 read = UIPEthernet.network.readPacket(data->packets_in[0], 0, buf + size - remain, remain);
hudakz 4:d774541a34da 337 if(read == UIPEthernet.network.blockSize(data->packets_in[0])) {
hudakz 0:5350a66d5279 338 remain -= read;
hudakz 4:d774541a34da 339 _eatBlock(&data->packets_in[0]);
hudakz 4:d774541a34da 340 if
hudakz 4:d774541a34da 341 (
hudakz 4:d774541a34da 342 uip_stopped(&uip_conns[data->state & UIP_CLIENT_SOCKETS])
hudakz 4:d774541a34da 343 && !(data->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))
hudakz 4:d774541a34da 344 ) data->state |= UIP_CLIENT_RESTART;
hudakz 4:d774541a34da 345 if(data->packets_in[0] == NOBLOCK) {
hudakz 4:d774541a34da 346 if(data->state & UIP_CLIENT_REMOTECLOSED) {
hudakz 4:d774541a34da 347 data->state = 0;
hudakz 4:d774541a34da 348 data = NULL;
hudakz 4:d774541a34da 349 }
hudakz 4:d774541a34da 350
hudakz 0:5350a66d5279 351 return size - remain;
hudakz 4:d774541a34da 352 }
hudakz 0:5350a66d5279 353 }
hudakz 0:5350a66d5279 354 else {
hudakz 4:d774541a34da 355 UIPEthernet.network.resizeBlock(data->packets_in[0], read);
hudakz 0:5350a66d5279 356 break;
hudakz 0:5350a66d5279 357 }
hudakz 0:5350a66d5279 358 } while(remain > 0);
hudakz 0:5350a66d5279 359 return size;
hudakz 0:5350a66d5279 360 }
hudakz 0:5350a66d5279 361
hudakz 0:5350a66d5279 362 return -1;
hudakz 0:5350a66d5279 363 }
hudakz 0:5350a66d5279 364
hudakz 0:5350a66d5279 365 /**
hudakz 0:5350a66d5279 366 * @brief
hudakz 0:5350a66d5279 367 * @note
hudakz 0:5350a66d5279 368 * @param
hudakz 0:5350a66d5279 369 * @retval
hudakz 0:5350a66d5279 370 */
hudakz 0:5350a66d5279 371 int UIPClient::read(void) {
hudakz 0:5350a66d5279 372 uint8_t c;
hudakz 0:5350a66d5279 373 if(read(&c, 1) < 0)
hudakz 0:5350a66d5279 374 return -1;
hudakz 0:5350a66d5279 375 return c;
hudakz 0:5350a66d5279 376 }
hudakz 0:5350a66d5279 377
hudakz 0:5350a66d5279 378 /**
hudakz 0:5350a66d5279 379 * @brief
hudakz 0:5350a66d5279 380 * @note
hudakz 0:5350a66d5279 381 * @param
hudakz 0:5350a66d5279 382 * @retval
hudakz 0:5350a66d5279 383 */
hudakz 0:5350a66d5279 384 int UIPClient::peek(void) {
hudakz 0:5350a66d5279 385 if(*this) {
hudakz 4:d774541a34da 386 if(data->packets_in[0] != NOBLOCK) {
hudakz 0:5350a66d5279 387 uint8_t c;
hudakz 4:d774541a34da 388 UIPEthernet.network.readPacket(data->packets_in[0], 0, &c, 1);
hudakz 0:5350a66d5279 389 return c;
hudakz 0:5350a66d5279 390 }
hudakz 0:5350a66d5279 391 }
hudakz 0:5350a66d5279 392
hudakz 0:5350a66d5279 393 return -1;
hudakz 0:5350a66d5279 394 }
hudakz 0:5350a66d5279 395
hudakz 0:5350a66d5279 396 /**
hudakz 0:5350a66d5279 397 * @brief
hudakz 0:5350a66d5279 398 * @note
hudakz 0:5350a66d5279 399 * @param
hudakz 0:5350a66d5279 400 * @retval
hudakz 0:5350a66d5279 401 */
hudakz 0:5350a66d5279 402 void UIPClient::flush(void) {
hudakz 0:5350a66d5279 403 if(*this) {
hudakz 0:5350a66d5279 404 _flushBlocks(&data->packets_in[0]);
hudakz 0:5350a66d5279 405 }
hudakz 0:5350a66d5279 406 }
hudakz 0:5350a66d5279 407
hudakz 0:5350a66d5279 408 /**
hudakz 0:5350a66d5279 409 * @brief
hudakz 0:5350a66d5279 410 * @note
hudakz 0:5350a66d5279 411 * @param
hudakz 0:5350a66d5279 412 * @retval
hudakz 0:5350a66d5279 413 */
hudakz 4:d774541a34da 414 void uipclient_appcall(void) {
hudakz 4:d774541a34da 415 uint16_t send_len = 0;
hudakz 4:d774541a34da 416 uip_userdata_t* u = (uip_userdata_t*)uip_conn->appstate;
hudakz 0:5350a66d5279 417 if(!u && uip_connected())
hudakz 0:5350a66d5279 418 {
hudakz 0:5350a66d5279 419 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 420 Serial.println(F("UIPClient uip_connected"));
hudakz 4:d774541a34da 421 UIPClient::_dumpAllData();
hudakz 0:5350a66d5279 422 #endif
hudakz 4:d774541a34da 423 u = (uip_userdata_t*)UIPClient::_allocateData();
hudakz 4:d774541a34da 424 if(u) {
hudakz 4:d774541a34da 425 uip_conn->appstate = u;
hudakz 4:d774541a34da 426 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 427 Serial.print(F("UIPClient allocated state: "));
hudakz 4:d774541a34da 428 Serial.println(u->state, BIN);
hudakz 4:d774541a34da 429 #endif
hudakz 4:d774541a34da 430 }
hudakz 0:5350a66d5279 431
hudakz 4:d774541a34da 432 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 433 else
hudakz 4:d774541a34da 434 Serial.println(F("UIPClient allocation failed"));
hudakz 4:d774541a34da 435 #endif
hudakz 0:5350a66d5279 436 }
hudakz 0:5350a66d5279 437
hudakz 0:5350a66d5279 438 if(u) {
hudakz 0:5350a66d5279 439 if(uip_newdata())
hudakz 0:5350a66d5279 440 {
hudakz 0:5350a66d5279 441 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 442 Serial.print(F("UIPClient uip_newdata, uip_len:"));
hudakz 0:5350a66d5279 443 Serial.println(uip_len);
hudakz 0:5350a66d5279 444 #endif
hudakz 4:d774541a34da 445 if(uip_len && !(u->state & (UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED))) {
hudakz 4:d774541a34da 446 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 4:d774541a34da 447 if(u->packets_in[i] == NOBLOCK) {
hudakz 4:d774541a34da 448 u->packets_in[i] = UIPEthernet.network.allocBlock(uip_len);
hudakz 4:d774541a34da 449 if(u->packets_in[i] != NOBLOCK) {
hudakz 4:d774541a34da 450 UIPEthernet.network.copyPacket
hudakz 4:d774541a34da 451 (
hudakz 4:d774541a34da 452 u->packets_in[i],
hudakz 4:d774541a34da 453 0,
hudakz 4:d774541a34da 454 UIPEthernetClass::in_packet,
hudakz 4:d774541a34da 455 ((uint8_t*)uip_appdata) - uip_buf,
hudakz 4:d774541a34da 456 uip_len
hudakz 4:d774541a34da 457 );
hudakz 4:d774541a34da 458 if(i == UIP_SOCKET_NUMPACKETS - 1)
hudakz 4:d774541a34da 459 uip_stop();
hudakz 4:d774541a34da 460 goto finish_newdata;
hudakz 0:5350a66d5279 461 }
hudakz 0:5350a66d5279 462 }
hudakz 0:5350a66d5279 463 }
hudakz 0:5350a66d5279 464
hudakz 4:d774541a34da 465 UIPEthernetClass::packetstate &= ~UIPETHERNET_FREEPACKET;
hudakz 0:5350a66d5279 466 uip_stop();
hudakz 0:5350a66d5279 467 }
hudakz 0:5350a66d5279 468 }
hudakz 0:5350a66d5279 469
hudakz 0:5350a66d5279 470 finish_newdata:
hudakz 0:5350a66d5279 471 if(u->state & UIP_CLIENT_RESTART) {
hudakz 0:5350a66d5279 472 u->state &= ~UIP_CLIENT_RESTART;
hudakz 0:5350a66d5279 473 uip_restart();
hudakz 0:5350a66d5279 474 }
hudakz 0:5350a66d5279 475
hudakz 0:5350a66d5279 476 // If the connection has been closed, save received but unread data.
hudakz 0:5350a66d5279 477 if(uip_closed() || uip_timedout())
hudakz 0:5350a66d5279 478 {
hudakz 0:5350a66d5279 479 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 480 Serial.println(F("UIPClient uip_closed"));
hudakz 4:d774541a34da 481 UIPClient::_dumpAllData();
hudakz 0:5350a66d5279 482 #endif
hudakz 0:5350a66d5279 483 // drop outgoing packets not sent yet:
hudakz 0:5350a66d5279 484
hudakz 4:d774541a34da 485 UIPClient::_flushBlocks(&u->packets_out[0]);
hudakz 0:5350a66d5279 486 if(u->packets_in[0] != NOBLOCK) {
hudakz 4:d774541a34da 487 ((uip_userdata_closed_t*)u)->lport = uip_conn->lport;
hudakz 4:d774541a34da 488 u->state |= UIP_CLIENT_REMOTECLOSED;
hudakz 0:5350a66d5279 489 }
hudakz 4:d774541a34da 490 else
hudakz 4:d774541a34da 491 u->state = 0;
hudakz 0:5350a66d5279 492
hudakz 0:5350a66d5279 493 // disassociate appdata.
hudakz 4:d774541a34da 494 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 495 Serial.println(F("after UIPClient uip_closed"));
hudakz 4:d774541a34da 496 UIPClient::_dumpAllData();
hudakz 4:d774541a34da 497 #endif
hudakz 4:d774541a34da 498 uip_conn->appstate = NULL;
hudakz 4:d774541a34da 499 goto finish;
hudakz 0:5350a66d5279 500 }
hudakz 0:5350a66d5279 501
hudakz 0:5350a66d5279 502 if(uip_acked())
hudakz 0:5350a66d5279 503 {
hudakz 0:5350a66d5279 504 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 505 Serial.println(F("UIPClient uip_acked"));
hudakz 0:5350a66d5279 506 #endif
hudakz 4:d774541a34da 507 UIPClient::_eatBlock(&u->packets_out[0]);
hudakz 0:5350a66d5279 508 }
hudakz 0:5350a66d5279 509
hudakz 0:5350a66d5279 510 if(uip_poll() || uip_rexmit())
hudakz 0:5350a66d5279 511 {
hudakz 0:5350a66d5279 512 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 513 //Serial.println(F("UIPClient uip_poll"));
hudakz 0:5350a66d5279 514 #endif
hudakz 4:d774541a34da 515 if(u->packets_out[0] != NOBLOCK) {
hudakz 0:5350a66d5279 516 if(u->packets_out[1] == NOBLOCK) {
hudakz 4:d774541a34da 517 send_len = u->out_pos;
hudakz 4:d774541a34da 518 if(send_len > 0) {
hudakz 4:d774541a34da 519 UIPEthernet.network.resizeBlock(u->packets_out[0], 0, send_len);
hudakz 0:5350a66d5279 520 }
hudakz 0:5350a66d5279 521 }
hudakz 0:5350a66d5279 522 else
hudakz 4:d774541a34da 523 send_len = UIPEthernet.network.blockSize(u->packets_out[0]);
hudakz 4:d774541a34da 524 if(send_len > 0) {
hudakz 4:d774541a34da 525 UIPEthernetClass::uip_hdrlen = ((uint8_t*)uip_appdata) - uip_buf;
hudakz 4:d774541a34da 526 UIPEthernetClass::uip_packet = UIPEthernet.network.allocBlock(UIPEthernetClass::uip_hdrlen + send_len);
hudakz 4:d774541a34da 527 if(UIPEthernetClass::uip_packet != NOBLOCK) {
hudakz 4:d774541a34da 528 UIPEthernet.network.copyPacket
hudakz 4:d774541a34da 529 (
hudakz 4:d774541a34da 530 UIPEthernetClass::uip_packet,
hudakz 4:d774541a34da 531 UIPEthernetClass::uip_hdrlen,
hudakz 4:d774541a34da 532 u->packets_out[0],
hudakz 4:d774541a34da 533 0,
hudakz 4:d774541a34da 534 send_len
hudakz 4:d774541a34da 535 );
hudakz 4:d774541a34da 536 UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET;
hudakz 0:5350a66d5279 537 }
hudakz 4:d774541a34da 538 }
hudakz 0:5350a66d5279 539
hudakz 4:d774541a34da 540 goto finish;
hudakz 0:5350a66d5279 541 }
hudakz 0:5350a66d5279 542 }
hudakz 0:5350a66d5279 543
hudakz 0:5350a66d5279 544 // don't close connection unless all outgoing packets are sent
hudakz 0:5350a66d5279 545 if(u->state & UIP_CLIENT_CLOSE)
hudakz 0:5350a66d5279 546 {
hudakz 0:5350a66d5279 547 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 548 Serial.println(F("UIPClient state UIP_CLIENT_CLOSE"));
hudakz 4:d774541a34da 549 UIPClient::_dumpAllData();
hudakz 0:5350a66d5279 550 #endif
hudakz 4:d774541a34da 551 if(u->packets_out[0] == NOBLOCK) {
hudakz 4:d774541a34da 552 u->state = 0;
hudakz 4:d774541a34da 553 uip_conn->appstate = NULL;
hudakz 0:5350a66d5279 554 uip_close();
hudakz 4:d774541a34da 555 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 556 Serial.println(F("no blocks out -> free userdata"));
hudakz 4:d774541a34da 557 UIPClient::_dumpAllData();
hudakz 4:d774541a34da 558 #endif
hudakz 0:5350a66d5279 559 }
hudakz 4:d774541a34da 560 else {
hudakz 0:5350a66d5279 561 uip_stop();
hudakz 4:d774541a34da 562 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 563 Serial.println(F("blocks outstanding transfer -> uip_stop()"));
hudakz 4:d774541a34da 564 #endif
hudakz 4:d774541a34da 565 }
hudakz 0:5350a66d5279 566 }
hudakz 0:5350a66d5279 567 }
hudakz 0:5350a66d5279 568
hudakz 4:d774541a34da 569 finish:
hudakz 4:d774541a34da 570 uip_send(uip_appdata, send_len);
hudakz 4:d774541a34da 571 uip_len = send_len;
hudakz 0:5350a66d5279 572 }
hudakz 0:5350a66d5279 573
hudakz 0:5350a66d5279 574 /**
hudakz 0:5350a66d5279 575 * @brief
hudakz 0:5350a66d5279 576 * @note
hudakz 0:5350a66d5279 577 * @param
hudakz 0:5350a66d5279 578 * @retval
hudakz 0:5350a66d5279 579 */
hudakz 4:d774541a34da 580 uip_userdata_t* UIPClient::_allocateData(void) {
hudakz 4:d774541a34da 581 for(uint8_t sock = 0; sock < UIP_CONNS; sock++) {
hudakz 4:d774541a34da 582 uip_userdata_t* data = &UIPClient::all_data[sock];
hudakz 4:d774541a34da 583 if(!data->state) {
hudakz 4:d774541a34da 584 data->state = sock | UIP_CLIENT_CONNECTED;
hudakz 4:d774541a34da 585 memset(&data->packets_in[0], 0, sizeof(uip_userdata_t) - sizeof(data->state));
hudakz 4:d774541a34da 586 return data;
hudakz 4:d774541a34da 587 }
hudakz 4:d774541a34da 588 }
hudakz 4:d774541a34da 589
hudakz 4:d774541a34da 590 return NULL;
hudakz 4:d774541a34da 591 }
hudakz 4:d774541a34da 592
hudakz 4:d774541a34da 593 /**
hudakz 4:d774541a34da 594 * @brief
hudakz 4:d774541a34da 595 * @note
hudakz 4:d774541a34da 596 * @param
hudakz 4:d774541a34da 597 * @retval
hudakz 4:d774541a34da 598 */
hudakz 4:d774541a34da 599 uint8_t UIPClient::_currentBlock(memhandle* block) {
hudakz 4:d774541a34da 600 for(uint8_t i = 1; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 4:d774541a34da 601 if(block[i] == NOBLOCK)
hudakz 4:d774541a34da 602 return i - 1;
hudakz 4:d774541a34da 603 }
hudakz 4:d774541a34da 604
hudakz 4:d774541a34da 605 return UIP_SOCKET_NUMPACKETS - 1;
hudakz 0:5350a66d5279 606 }
hudakz 0:5350a66d5279 607
hudakz 0:5350a66d5279 608 /**
hudakz 0:5350a66d5279 609 * @brief
hudakz 0:5350a66d5279 610 * @note
hudakz 0:5350a66d5279 611 * @param
hudakz 0:5350a66d5279 612 * @retval
hudakz 0:5350a66d5279 613 */
hudakz 0:5350a66d5279 614 void UIPClient::_eatBlock(memhandle* block)
hudakz 0:5350a66d5279 615 {
hudakz 0:5350a66d5279 616 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 0:5350a66d5279 617 memhandle* start = block;
hudakz 4:d774541a34da 618 Serial.print(F("eatblock("));
hudakz 0:5350a66d5279 619 Serial.print(*block);
hudakz 4:d774541a34da 620 Serial.print(F("): "));
hudakz 0:5350a66d5279 621 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 0:5350a66d5279 622 Serial.print(start[i]);
hudakz 4:d774541a34da 623 Serial.print(F(" "));
hudakz 0:5350a66d5279 624 }
hudakz 0:5350a66d5279 625
hudakz 4:d774541a34da 626 Serial.print(F("-> "));
hudakz 0:5350a66d5279 627 #endif
hudakz 4:d774541a34da 628 UIPEthernet.network.freeBlock(block[0]);
hudakz 4:d774541a34da 629 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS - 1; i++) {
hudakz 4:d774541a34da 630 block[i] = block[i + 1];
hudakz 4:d774541a34da 631 }
hudakz 0:5350a66d5279 632
hudakz 4:d774541a34da 633 block[UIP_SOCKET_NUMPACKETS - 1] = NOBLOCK;
hudakz 0:5350a66d5279 634 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 0:5350a66d5279 635 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 0:5350a66d5279 636 Serial.print(start[i]);
hudakz 4:d774541a34da 637 Serial.print(F(" "));
hudakz 0:5350a66d5279 638 }
hudakz 0:5350a66d5279 639
hudakz 0:5350a66d5279 640 Serial.println();
hudakz 0:5350a66d5279 641 #endif
hudakz 0:5350a66d5279 642 }
hudakz 0:5350a66d5279 643
hudakz 0:5350a66d5279 644 /**
hudakz 0:5350a66d5279 645 * @brief
hudakz 0:5350a66d5279 646 * @note
hudakz 0:5350a66d5279 647 * @param
hudakz 0:5350a66d5279 648 * @retval
hudakz 0:5350a66d5279 649 */
hudakz 0:5350a66d5279 650 void UIPClient::_flushBlocks(memhandle* block) {
hudakz 4:d774541a34da 651 for(uint8_t i = 0; i < UIP_SOCKET_NUMPACKETS; i++) {
hudakz 4:d774541a34da 652 UIPEthernet.network.freeBlock(block[i]);
hudakz 4:d774541a34da 653 block[i] = NOBLOCK;
hudakz 0:5350a66d5279 654 }
hudakz 0:5350a66d5279 655 }
hudakz 2:049ce85163c5 656
hudakz 4:d774541a34da 657 #ifdef UIPETHERNET_DEBUG_CLIENT
hudakz 4:d774541a34da 658
hudakz 4:d774541a34da 659 /**
hudakz 4:d774541a34da 660 * @brief
hudakz 4:d774541a34da 661 * @note
hudakz 4:d774541a34da 662 * @param
hudakz 4:d774541a34da 663 * @retval
hudakz 4:d774541a34da 664 */
hudakz 4:d774541a34da 665 void UIPClient::_dumpAllData(void) {
hudakz 4:d774541a34da 666 for(uint8_t i = 0; i < UIP_CONNS; i++) {
hudakz 4:d774541a34da 667 Serial.print(F("UIPClient::all_data["));
hudakz 4:d774541a34da 668 Serial.print(i);
hudakz 4:d774541a34da 669 Serial.print(F("], state:"));
hudakz 4:d774541a34da 670 Serial.println(all_data[i].state, BIN);
hudakz 4:d774541a34da 671 Serial.print(F("packets_in: "));
hudakz 4:d774541a34da 672 for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) {
hudakz 4:d774541a34da 673 Serial.print(all_data[i].packets_in[j]);
hudakz 4:d774541a34da 674 Serial.print(F(" "));
hudakz 4:d774541a34da 675 }
hudakz 4:d774541a34da 676
hudakz 4:d774541a34da 677 Serial.println();
hudakz 4:d774541a34da 678 if(all_data[i].state & UIP_CLIENT_REMOTECLOSED) {
hudakz 4:d774541a34da 679 Serial.print(F("state remote closed, local port: "));
hudakz 4:d774541a34da 680 Serial.println(htons(((uip_userdata_closed_t *) (&all_data[i]))->lport));
hudakz 4:d774541a34da 681 }
hudakz 4:d774541a34da 682 else {
hudakz 4:d774541a34da 683 Serial.print(F("packets_out: "));
hudakz 4:d774541a34da 684 for(uint8_t j = 0; j < UIP_SOCKET_NUMPACKETS; j++) {
hudakz 4:d774541a34da 685 Serial.print(all_data[i].packets_out[j]);
hudakz 4:d774541a34da 686 Serial.print(F(" "));
hudakz 4:d774541a34da 687 }
hudakz 4:d774541a34da 688
hudakz 4:d774541a34da 689 Serial.println();
hudakz 4:d774541a34da 690 Serial.print(F("out_pos: "));
hudakz 4:d774541a34da 691 Serial.println(all_data[i].out_pos);
hudakz 4:d774541a34da 692 }
hudakz 4:d774541a34da 693 }
hudakz 4:d774541a34da 694 }
hudakz 4:d774541a34da 695 #endif