mbed OS5

Fork of UIPEthernet by Zoltan Hudak

Committer:
hudakz
Date:
Mon Sep 15 11:12:30 2014 +0000
Revision:
0:5350a66d5279
Child:
2:049ce85163c5
rev. 00

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