├── Dhcp.cpp ├── Dhcp.h ├── Dns.cpp ├── Dns.h ├── README ├── UIPClient.cpp ├── UIPClient.h ├── UIPEthernet.cpp ├── UIPEthernet.h ├── UIPServer.cpp ├── UIPServer.h ├── UIPUdp.cpp ├── UIPUdp.h ├── ethernet_comp.h ├── examples ├── AdvancedChatServer │ └── AdvancedChatServer.ino ├── EchoServer │ └── EchoServer.ino ├── HttpClient │ └── HttpClient.ino ├── HttpClientTest │ ├── HttpClientTest.ino │ └── WebServerFile │ │ ├── Readme.txt │ │ └── nums2.txt ├── InteractiveServer │ ├── HTML.h │ └── InteractiveServer.ino ├── TcpClient │ └── TcpClient.ino ├── TcpServer │ └── TcpServer.ino ├── UdpClient │ └── UdpClient.ino └── UdpServer │ └── UdpServer.ino ├── keywords.txt ├── library.properties ├── tests └── perl │ ├── tcpclient.pl │ ├── tcpserver.pl │ ├── udpclient.pl │ └── udpserver.pl └── utility ├── Enc28J60Network.cpp ├── Enc28J60Network.h ├── clock-arch.c ├── clock-arch.h ├── enc28j60.h ├── mempool.cpp ├── mempool.h ├── mempool_conf.h ├── uip-conf.h ├── uip.c ├── uip.h ├── uip_arch.h ├── uip_arp.c ├── uip_arp.h ├── uip_clock.h ├── uip_debug.cpp ├── uip_debug.h ├── uip_timer.c ├── uip_timer.h ├── uipethernet-conf.h ├── uipopt.h └── util.h /Dhcp.cpp: -------------------------------------------------------------------------------- 1 | // DHCP Library v0.3 - April 25, 2009 2 | // Author: Jordan Terrell - blog.jordanterrell.com 3 | 4 | #include 5 | #include 6 | #include "Dhcp.h" 7 | #include "Arduino.h" 8 | #include "utility/util.h" 9 | 10 | int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) 11 | { 12 | _dhcpLeaseTime=0; 13 | _dhcpT1=0; 14 | _dhcpT2=0; 15 | _lastCheck=0; 16 | _timeout = timeout; 17 | _responseTimeout = responseTimeout; 18 | 19 | // zero out _dhcpMacAddr 20 | memset(_dhcpMacAddr, 0, 6); 21 | reset_DHCP_lease(); 22 | 23 | memcpy((void*)_dhcpMacAddr, (void*)mac, 6); 24 | _dhcp_state = STATE_DHCP_START; 25 | return request_DHCP_lease(); 26 | } 27 | 28 | void DhcpClass::reset_DHCP_lease(){ 29 | // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp 30 | memset(_dhcpLocalIp, 0, 20); 31 | } 32 | 33 | //return:0 on error, 1 if request is sent and response is received 34 | int DhcpClass::request_DHCP_lease(){ 35 | 36 | uint8_t messageType = 0; 37 | 38 | 39 | 40 | // Pick an initial transaction ID 41 | _dhcpTransactionId = random(1UL, 2000UL); 42 | _dhcpInitialTransactionId = _dhcpTransactionId; 43 | 44 | _dhcpUdpSocket.stop(); 45 | if (_dhcpUdpSocket.begin(DHCP_CLIENT_PORT) == 0) 46 | { 47 | // Couldn't get a socket 48 | return 0; 49 | } 50 | 51 | presend_DHCP(); 52 | 53 | int result = 0; 54 | 55 | unsigned long startTime = millis(); 56 | 57 | while(_dhcp_state != STATE_DHCP_LEASED) 58 | { 59 | if(_dhcp_state == STATE_DHCP_START) 60 | { 61 | _dhcpTransactionId++; 62 | 63 | send_DHCP_MESSAGE(DHCP_DISCOVER, ((millis() - startTime) / 1000)); 64 | _dhcp_state = STATE_DHCP_DISCOVER; 65 | } 66 | else if(_dhcp_state == STATE_DHCP_REREQUEST){ 67 | _dhcpTransactionId++; 68 | send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000)); 69 | _dhcp_state = STATE_DHCP_REQUEST; 70 | } 71 | else if(_dhcp_state == STATE_DHCP_DISCOVER) 72 | { 73 | uint32_t respId; 74 | messageType = parseDHCPResponse(_responseTimeout, respId); 75 | if(messageType == DHCP_OFFER) 76 | { 77 | // We'll use the transaction ID that the offer came with, 78 | // rather than the one we were up to 79 | _dhcpTransactionId = respId; 80 | send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime) / 1000)); 81 | _dhcp_state = STATE_DHCP_REQUEST; 82 | } 83 | } 84 | else if(_dhcp_state == STATE_DHCP_REQUEST) 85 | { 86 | uint32_t respId; 87 | messageType = parseDHCPResponse(_responseTimeout, respId); 88 | if(messageType == DHCP_ACK) 89 | { 90 | _dhcp_state = STATE_DHCP_LEASED; 91 | result = 1; 92 | //use default lease time if we didn't get it 93 | if(_dhcpLeaseTime == 0){ 94 | _dhcpLeaseTime = DEFAULT_LEASE; 95 | } 96 | //calculate T1 & T2 if we didn't get it 97 | if(_dhcpT1 == 0){ 98 | //T1 should be 50% of _dhcpLeaseTime 99 | _dhcpT1 = _dhcpLeaseTime >> 1; 100 | } 101 | if(_dhcpT2 == 0){ 102 | //T2 should be 87.5% (7/8ths) of _dhcpLeaseTime 103 | _dhcpT2 = _dhcpT1 << 1; 104 | } 105 | _renewInSec = _dhcpT1; 106 | _rebindInSec = _dhcpT2; 107 | } 108 | else if(messageType == DHCP_NAK) 109 | _dhcp_state = STATE_DHCP_START; 110 | } 111 | 112 | if(messageType == 255) 113 | { 114 | messageType = 0; 115 | _dhcp_state = STATE_DHCP_START; 116 | } 117 | 118 | if(result != 1 && ((millis() - startTime) > _timeout)) 119 | break; 120 | } 121 | 122 | // We're done with the socket now 123 | _dhcpUdpSocket.stop(); 124 | _dhcpTransactionId++; 125 | 126 | return result; 127 | } 128 | 129 | void DhcpClass::presend_DHCP() 130 | { 131 | } 132 | 133 | void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) 134 | { 135 | uint8_t buffer[32]; 136 | memset(buffer, 0, 32); 137 | IPAddress dest_addr( 255, 255, 255, 255 ); // Broadcast address 138 | 139 | if (-1 == _dhcpUdpSocket.beginPacket(dest_addr, DHCP_SERVER_PORT)) 140 | { 141 | // FIXME Need to return errors 142 | return; 143 | } 144 | 145 | buffer[0] = DHCP_BOOTREQUEST; // op 146 | buffer[1] = DHCP_HTYPE10MB; // htype 147 | buffer[2] = DHCP_HLENETHERNET; // hlen 148 | buffer[3] = DHCP_HOPS; // hops 149 | 150 | // xid 151 | unsigned long xid = htonl(_dhcpTransactionId); 152 | memcpy(buffer + 4, &(xid), 4); 153 | 154 | // 8, 9 - seconds elapsed 155 | buffer[8] = ((secondsElapsed & 0xff00) >> 8); 156 | buffer[9] = (secondsElapsed & 0x00ff); 157 | 158 | // flags 159 | unsigned short flags = htons(DHCP_FLAGSBROADCAST); 160 | memcpy(buffer + 10, &(flags), 2); 161 | 162 | // ciaddr: already zeroed 163 | // yiaddr: already zeroed 164 | // siaddr: already zeroed 165 | // giaddr: already zeroed 166 | 167 | //put data in W5100 transmit buffer 168 | _dhcpUdpSocket.write(buffer, 28); 169 | 170 | memset(buffer, 0, 32); // clear local buffer 171 | 172 | memcpy(buffer, _dhcpMacAddr, 6); // chaddr 173 | 174 | //put data in W5100 transmit buffer 175 | _dhcpUdpSocket.write(buffer, 16); 176 | 177 | memset(buffer, 0, 32); // clear local buffer 178 | 179 | // leave zeroed out for sname && file 180 | // put in W5100 transmit buffer x 6 (192 bytes) 181 | 182 | for(int i = 0; i < 6; i++) { 183 | _dhcpUdpSocket.write(buffer, 32); 184 | } 185 | 186 | // OPT - Magic Cookie 187 | buffer[0] = (uint8_t)((MAGIC_COOKIE >> 24)& 0xFF); 188 | buffer[1] = (uint8_t)((MAGIC_COOKIE >> 16)& 0xFF); 189 | buffer[2] = (uint8_t)((MAGIC_COOKIE >> 8)& 0xFF); 190 | buffer[3] = (uint8_t)(MAGIC_COOKIE& 0xFF); 191 | 192 | // OPT - message type 193 | buffer[4] = dhcpMessageType; 194 | buffer[5] = 0x01; 195 | buffer[6] = messageType; //DHCP_REQUEST; 196 | 197 | // OPT - client identifier 198 | buffer[7] = dhcpClientIdentifier; 199 | buffer[8] = 0x07; 200 | buffer[9] = 0x01; 201 | memcpy(buffer + 10, _dhcpMacAddr, 6); 202 | 203 | // OPT - host name 204 | buffer[16] = hostName; 205 | buffer[17] = strlen(HOST_NAME) + 6; // length of hostname + last 3 bytes of mac address 206 | strcpy((char*)&(buffer[18]), HOST_NAME); 207 | 208 | printByte((char*)&(buffer[24]), _dhcpMacAddr[3]); 209 | printByte((char*)&(buffer[26]), _dhcpMacAddr[4]); 210 | printByte((char*)&(buffer[28]), _dhcpMacAddr[5]); 211 | 212 | //put data in W5100 transmit buffer 213 | _dhcpUdpSocket.write(buffer, 30); 214 | 215 | if(messageType == DHCP_REQUEST) 216 | { 217 | buffer[0] = dhcpRequestedIPaddr; 218 | buffer[1] = 0x04; 219 | buffer[2] = _dhcpLocalIp[0]; 220 | buffer[3] = _dhcpLocalIp[1]; 221 | buffer[4] = _dhcpLocalIp[2]; 222 | buffer[5] = _dhcpLocalIp[3]; 223 | 224 | buffer[6] = dhcpServerIdentifier; 225 | buffer[7] = 0x04; 226 | buffer[8] = _dhcpDhcpServerIp[0]; 227 | buffer[9] = _dhcpDhcpServerIp[1]; 228 | buffer[10] = _dhcpDhcpServerIp[2]; 229 | buffer[11] = _dhcpDhcpServerIp[3]; 230 | 231 | //put data in W5100 transmit buffer 232 | _dhcpUdpSocket.write(buffer, 12); 233 | } 234 | 235 | buffer[0] = dhcpParamRequest; 236 | buffer[1] = 0x06; 237 | buffer[2] = subnetMask; 238 | buffer[3] = routersOnSubnet; 239 | buffer[4] = dns; 240 | buffer[5] = domainName; 241 | buffer[6] = dhcpT1value; 242 | buffer[7] = dhcpT2value; 243 | buffer[8] = endOption; 244 | 245 | //put data in W5100 transmit buffer 246 | _dhcpUdpSocket.write(buffer, 9); 247 | 248 | _dhcpUdpSocket.endPacket(); 249 | } 250 | 251 | uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) 252 | { 253 | uint8_t type = 0; 254 | uint8_t opt_len = 0; 255 | 256 | unsigned long startTime = millis(); 257 | 258 | while(_dhcpUdpSocket.parsePacket() <= 0) 259 | { 260 | if((millis() - startTime) > responseTimeout) 261 | { 262 | return 255; 263 | } 264 | delay(50); 265 | } 266 | // start reading in the packet 267 | RIP_MSG_FIXED fixedMsg; 268 | _dhcpUdpSocket.read((uint8_t*)&fixedMsg, sizeof(RIP_MSG_FIXED)); 269 | 270 | if(fixedMsg.op == DHCP_BOOTREPLY && _dhcpUdpSocket.remotePort() == DHCP_SERVER_PORT) 271 | { 272 | transactionId = ntohl(fixedMsg.xid); 273 | if(memcmp(fixedMsg.chaddr, _dhcpMacAddr, 6) != 0 || (transactionId < _dhcpInitialTransactionId) || (transactionId > _dhcpTransactionId)) 274 | { 275 | // Need to read the rest of the packet here regardless 276 | _dhcpUdpSocket.flush(); 277 | return 0; 278 | } 279 | 280 | memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4); 281 | 282 | // Skip to the option part 283 | // Doing this a byte at a time so we don't have to put a big buffer 284 | // on the stack (as we don't have lots of memory lying around) 285 | for (int i =0; i < (240 - (int)sizeof(RIP_MSG_FIXED)); i++) 286 | { 287 | _dhcpUdpSocket.read(); // we don't care about the returned byte 288 | } 289 | 290 | while (_dhcpUdpSocket.available() > 0) 291 | { 292 | switch (_dhcpUdpSocket.read()) 293 | { 294 | case endOption : 295 | break; 296 | 297 | case padOption : 298 | break; 299 | 300 | case dhcpMessageType : 301 | opt_len = _dhcpUdpSocket.read(); 302 | type = _dhcpUdpSocket.read(); 303 | break; 304 | 305 | case subnetMask : 306 | opt_len = _dhcpUdpSocket.read(); 307 | _dhcpUdpSocket.read(_dhcpSubnetMask, 4); 308 | break; 309 | 310 | case routersOnSubnet : 311 | opt_len = _dhcpUdpSocket.read(); 312 | _dhcpUdpSocket.read(_dhcpGatewayIp, 4); 313 | for (int i = 0; i < opt_len-4; i++) 314 | { 315 | _dhcpUdpSocket.read(); 316 | } 317 | break; 318 | 319 | case dns : 320 | opt_len = _dhcpUdpSocket.read(); 321 | _dhcpUdpSocket.read(_dhcpDnsServerIp, 4); 322 | for (int i = 0; i < opt_len-4; i++) 323 | { 324 | _dhcpUdpSocket.read(); 325 | } 326 | break; 327 | 328 | case dhcpServerIdentifier : 329 | opt_len = _dhcpUdpSocket.read(); 330 | if( *((uint32_t*)_dhcpDhcpServerIp) == 0 || 331 | IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() ) 332 | { 333 | _dhcpUdpSocket.read(_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp)); 334 | } 335 | else 336 | { 337 | // Skip over the rest of this option 338 | while (opt_len--) 339 | { 340 | _dhcpUdpSocket.read(); 341 | } 342 | } 343 | break; 344 | 345 | case dhcpT1value : 346 | opt_len = _dhcpUdpSocket.read(); 347 | _dhcpUdpSocket.read((uint8_t*)&_dhcpT1, sizeof(_dhcpT1)); 348 | _dhcpT1 = ntohl(_dhcpT1); 349 | break; 350 | 351 | case dhcpT2value : 352 | opt_len = _dhcpUdpSocket.read(); 353 | _dhcpUdpSocket.read((uint8_t*)&_dhcpT2, sizeof(_dhcpT2)); 354 | _dhcpT2 = ntohl(_dhcpT2); 355 | break; 356 | 357 | case dhcpIPaddrLeaseTime : 358 | opt_len = _dhcpUdpSocket.read(); 359 | _dhcpUdpSocket.read((uint8_t*)&_dhcpLeaseTime, sizeof(_dhcpLeaseTime)); 360 | _dhcpLeaseTime = ntohl(_dhcpLeaseTime); 361 | _renewInSec = _dhcpLeaseTime; 362 | break; 363 | 364 | default : 365 | opt_len = _dhcpUdpSocket.read(); 366 | // Skip over the rest of this option 367 | while (opt_len--) 368 | { 369 | _dhcpUdpSocket.read(); 370 | } 371 | break; 372 | } 373 | } 374 | } 375 | 376 | // Need to skip to end of the packet regardless here 377 | _dhcpUdpSocket.flush(); 378 | 379 | return type; 380 | } 381 | 382 | 383 | /* 384 | returns: 385 | 0/DHCP_CHECK_NONE: nothing happened 386 | 1/DHCP_CHECK_RENEW_FAIL: renew failed 387 | 2/DHCP_CHECK_RENEW_OK: renew success 388 | 3/DHCP_CHECK_REBIND_FAIL: rebind fail 389 | 4/DHCP_CHECK_REBIND_OK: rebind success 390 | */ 391 | int DhcpClass::checkLease(){ 392 | //this uses a signed / unsigned trick to deal with millis overflow 393 | unsigned long now = millis(); 394 | signed long snow = (long)now; 395 | int rc=DHCP_CHECK_NONE; 396 | if (_lastCheck != 0){ 397 | signed long factor; 398 | //calc how many ms past the timeout we are 399 | factor = snow - (long)_secTimeout; 400 | //if on or passed the timeout, reduce the counters 401 | if ( factor >= 0 ){ 402 | //next timeout should be now plus 1000 ms minus parts of second in factor 403 | _secTimeout = snow + 1000 - factor % 1000; 404 | //how many seconds late are we, minimum 1 405 | factor = factor / 1000 +1; 406 | 407 | //reduce the counters by that mouch 408 | //if we can assume that the cycle time (factor) is fairly constant 409 | //and if the remainder is less than cycle time * 2 410 | //do it early instead of late 411 | if(_renewInSec < factor*2 ) 412 | _renewInSec = 0; 413 | else 414 | _renewInSec -= factor; 415 | 416 | if(_rebindInSec < factor*2 ) 417 | _rebindInSec = 0; 418 | else 419 | _rebindInSec -= factor; 420 | } 421 | 422 | //if we have a lease but should renew, do it 423 | if (_dhcp_state == STATE_DHCP_LEASED && _renewInSec <=0){ 424 | _dhcp_state = STATE_DHCP_REREQUEST; 425 | rc = 1 + request_DHCP_lease(); 426 | } 427 | 428 | //if we have a lease or is renewing but should bind, do it 429 | if( (_dhcp_state == STATE_DHCP_LEASED || _dhcp_state == STATE_DHCP_START) && _rebindInSec <=0){ 430 | //this should basically restart completely 431 | _dhcp_state = STATE_DHCP_START; 432 | reset_DHCP_lease(); 433 | rc = 3 + request_DHCP_lease(); 434 | } 435 | } 436 | else{ 437 | _secTimeout = snow + 1000; 438 | } 439 | 440 | _lastCheck = now; 441 | return rc; 442 | } 443 | 444 | IPAddress DhcpClass::getLocalIp() 445 | { 446 | return IPAddress(_dhcpLocalIp); 447 | } 448 | 449 | IPAddress DhcpClass::getSubnetMask() 450 | { 451 | return IPAddress(_dhcpSubnetMask); 452 | } 453 | 454 | IPAddress DhcpClass::getGatewayIp() 455 | { 456 | return IPAddress(_dhcpGatewayIp); 457 | } 458 | 459 | IPAddress DhcpClass::getDhcpServerIp() 460 | { 461 | return IPAddress(_dhcpDhcpServerIp); 462 | } 463 | 464 | IPAddress DhcpClass::getDnsServerIp() 465 | { 466 | return IPAddress(_dhcpDnsServerIp); 467 | } 468 | 469 | void DhcpClass::printByte(char * buf, uint8_t n ) { 470 | char *str = &buf[1]; 471 | buf[0]='0'; 472 | do { 473 | unsigned long m = n; 474 | n /= 16; 475 | char c = m - 16 * n; 476 | *str-- = c < 10 ? c + '0' : c + 'A' - 10; 477 | } while(n); 478 | } 479 | -------------------------------------------------------------------------------- /Dhcp.h: -------------------------------------------------------------------------------- 1 | // DHCP Library v0.3 - April 25, 2009 2 | // Author: Jordan Terrell - blog.jordanterrell.com 3 | 4 | #ifndef Dhcp_h 5 | #define Dhcp_h 6 | 7 | #include "UIPUdp.h" 8 | 9 | /* DHCP state machine. */ 10 | #define STATE_DHCP_START 0 11 | #define STATE_DHCP_DISCOVER 1 12 | #define STATE_DHCP_REQUEST 2 13 | #define STATE_DHCP_LEASED 3 14 | #define STATE_DHCP_REREQUEST 4 15 | #define STATE_DHCP_RELEASE 5 16 | 17 | #define DHCP_FLAGSBROADCAST 0x8000 18 | 19 | /* UDP port numbers for DHCP */ 20 | #define DHCP_SERVER_PORT 67 /* from server to client */ 21 | #define DHCP_CLIENT_PORT 68 /* from client to server */ 22 | 23 | /* DHCP message OP code */ 24 | #define DHCP_BOOTREQUEST 1 25 | #define DHCP_BOOTREPLY 2 26 | 27 | /* DHCP message type */ 28 | #define DHCP_DISCOVER 1 29 | #define DHCP_OFFER 2 30 | #define DHCP_REQUEST 3 31 | #define DHCP_DECLINE 4 32 | #define DHCP_ACK 5 33 | #define DHCP_NAK 6 34 | #define DHCP_RELEASE 7 35 | #define DHCP_INFORM 8 36 | 37 | #define DHCP_HTYPE10MB 1 38 | #define DHCP_HTYPE100MB 2 39 | 40 | #define DHCP_HLENETHERNET 6 41 | #define DHCP_HOPS 0 42 | #define DHCP_SECS 0 43 | 44 | #define MAGIC_COOKIE 0x63825363 45 | #define MAX_DHCP_OPT 16 46 | 47 | #define HOST_NAME "ENC28J" 48 | #define DEFAULT_LEASE (900) //default lease time in seconds 49 | 50 | #define DHCP_CHECK_NONE (0) 51 | #define DHCP_CHECK_RENEW_FAIL (1) 52 | #define DHCP_CHECK_RENEW_OK (2) 53 | #define DHCP_CHECK_REBIND_FAIL (3) 54 | #define DHCP_CHECK_REBIND_OK (4) 55 | 56 | enum 57 | { 58 | padOption = 0, 59 | subnetMask = 1, 60 | timerOffset = 2, 61 | routersOnSubnet = 3, 62 | /* timeServer = 4, 63 | nameServer = 5,*/ 64 | dns = 6, 65 | /*logServer = 7, 66 | cookieServer = 8, 67 | lprServer = 9, 68 | impressServer = 10, 69 | resourceLocationServer = 11,*/ 70 | hostName = 12, 71 | /*bootFileSize = 13, 72 | meritDumpFile = 14,*/ 73 | domainName = 15, 74 | /*swapServer = 16, 75 | rootPath = 17, 76 | extentionsPath = 18, 77 | IPforwarding = 19, 78 | nonLocalSourceRouting = 20, 79 | policyFilter = 21, 80 | maxDgramReasmSize = 22, 81 | defaultIPTTL = 23, 82 | pathMTUagingTimeout = 24, 83 | pathMTUplateauTable = 25, 84 | ifMTU = 26, 85 | allSubnetsLocal = 27, 86 | broadcastAddr = 28, 87 | performMaskDiscovery = 29, 88 | maskSupplier = 30, 89 | performRouterDiscovery = 31, 90 | routerSolicitationAddr = 32, 91 | staticRoute = 33, 92 | trailerEncapsulation = 34, 93 | arpCacheTimeout = 35, 94 | ethernetEncapsulation = 36, 95 | tcpDefaultTTL = 37, 96 | tcpKeepaliveInterval = 38, 97 | tcpKeepaliveGarbage = 39, 98 | nisDomainName = 40, 99 | nisServers = 41, 100 | ntpServers = 42, 101 | vendorSpecificInfo = 43, 102 | netBIOSnameServer = 44, 103 | netBIOSdgramDistServer = 45, 104 | netBIOSnodeType = 46, 105 | netBIOSscope = 47, 106 | xFontServer = 48, 107 | xDisplayManager = 49,*/ 108 | dhcpRequestedIPaddr = 50, 109 | dhcpIPaddrLeaseTime = 51, 110 | /*dhcpOptionOverload = 52,*/ 111 | dhcpMessageType = 53, 112 | dhcpServerIdentifier = 54, 113 | dhcpParamRequest = 55, 114 | /*dhcpMsg = 56, 115 | dhcpMaxMsgSize = 57,*/ 116 | dhcpT1value = 58, 117 | dhcpT2value = 59, 118 | /*dhcpClassIdentifier = 60,*/ 119 | dhcpClientIdentifier = 61, 120 | endOption = 255 121 | }; 122 | 123 | typedef struct _RIP_MSG_FIXED 124 | { 125 | uint8_t op; 126 | uint8_t htype; 127 | uint8_t hlen; 128 | uint8_t hops; 129 | uint32_t xid; 130 | uint16_t secs; 131 | uint16_t flags; 132 | uint8_t ciaddr[4]; 133 | uint8_t yiaddr[4]; 134 | uint8_t siaddr[4]; 135 | uint8_t giaddr[4]; 136 | uint8_t chaddr[6]; 137 | }RIP_MSG_FIXED; 138 | 139 | class DhcpClass { 140 | private: 141 | uint32_t _dhcpInitialTransactionId; 142 | uint32_t _dhcpTransactionId; 143 | uint8_t _dhcpMacAddr[6]; 144 | uint8_t _dhcpLocalIp[4]; 145 | uint8_t _dhcpSubnetMask[4]; 146 | uint8_t _dhcpGatewayIp[4]; 147 | uint8_t _dhcpDhcpServerIp[4]; 148 | uint8_t _dhcpDnsServerIp[4]; 149 | uint32_t _dhcpLeaseTime; 150 | uint32_t _dhcpT1, _dhcpT2; 151 | signed long _renewInSec; 152 | signed long _rebindInSec; 153 | signed long _lastCheck; 154 | unsigned long _timeout; 155 | unsigned long _responseTimeout; 156 | unsigned long _secTimeout; 157 | uint8_t _dhcp_state; 158 | UIPUDP _dhcpUdpSocket; 159 | 160 | int request_DHCP_lease(); 161 | void reset_DHCP_lease(); 162 | void presend_DHCP(); 163 | void send_DHCP_MESSAGE(uint8_t, uint16_t); 164 | void printByte(char *, uint8_t); 165 | 166 | uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); 167 | public: 168 | IPAddress getLocalIp(); 169 | IPAddress getSubnetMask(); 170 | IPAddress getGatewayIp(); 171 | IPAddress getDhcpServerIp(); 172 | IPAddress getDnsServerIp(); 173 | 174 | int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); 175 | int checkLease(); 176 | }; 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /Dns.cpp: -------------------------------------------------------------------------------- 1 | // Arduino DNS client for Enc28J60-based Ethernet shield 2 | // (c) Copyright 2009-2010 MCQN Ltd. 3 | // Released under Apache License, version 2.0 4 | 5 | #include "Udp.h" 6 | #include "utility/util.h" 7 | 8 | #include "Dns.h" 9 | #include 10 | //#include 11 | #include "Arduino.h" 12 | 13 | 14 | #define SOCKET_NONE 255 15 | // Various flags and header field values for a DNS message 16 | #define UDP_HEADER_SIZE 8 17 | #define DNS_HEADER_SIZE 12 18 | #define TTL_SIZE 4 19 | #define QUERY_FLAG (0) 20 | #define RESPONSE_FLAG (1<<15) 21 | #define QUERY_RESPONSE_MASK (1<<15) 22 | #define OPCODE_STANDARD_QUERY (0) 23 | #define OPCODE_INVERSE_QUERY (1<<11) 24 | #define OPCODE_STATUS_REQUEST (2<<11) 25 | #define OPCODE_MASK (15<<11) 26 | #define AUTHORITATIVE_FLAG (1<<10) 27 | #define TRUNCATION_FLAG (1<<9) 28 | #define RECURSION_DESIRED_FLAG (1<<8) 29 | #define RECURSION_AVAILABLE_FLAG (1<<7) 30 | #define RESP_NO_ERROR (0) 31 | #define RESP_FORMAT_ERROR (1) 32 | #define RESP_SERVER_FAILURE (2) 33 | #define RESP_NAME_ERROR (3) 34 | #define RESP_NOT_IMPLEMENTED (4) 35 | #define RESP_REFUSED (5) 36 | #define RESP_MASK (15) 37 | #define TYPE_A (0x0001) 38 | #define CLASS_IN (0x0001) 39 | #define LABEL_COMPRESSION_MASK (0xC0) 40 | // Port number that DNS servers listen on 41 | #define DNS_PORT 53 42 | 43 | // Possible return codes from ProcessResponse 44 | #define SUCCESS 1 45 | #define TIMED_OUT -1 46 | #define INVALID_SERVER -2 47 | #define TRUNCATED -3 48 | #define INVALID_RESPONSE -4 49 | 50 | void DNSClient::begin(const IPAddress& aDNSServer) 51 | { 52 | iDNSServer = aDNSServer; 53 | iRequestId = 0; 54 | } 55 | 56 | 57 | int DNSClient::inet_aton(const char* aIPAddrString, IPAddress& aResult) 58 | { 59 | // See if we've been given a valid IP address 60 | const char* p =aIPAddrString; 61 | while (*p && 62 | ( (*p == '.') || (*p >= '0') || (*p <= '9') )) 63 | { 64 | p++; 65 | } 66 | 67 | if (*p == '\0') 68 | { 69 | // It's looking promising, we haven't found any invalid characters 70 | p = aIPAddrString; 71 | int segment =0; 72 | int segmentValue =0; 73 | while (*p && (segment < 4)) 74 | { 75 | if (*p == '.') 76 | { 77 | // We've reached the end of a segment 78 | if (segmentValue > 255) 79 | { 80 | // You can't have IP address segments that don't fit in a byte 81 | return 0; 82 | } 83 | else 84 | { 85 | aResult[segment] = (byte)segmentValue; 86 | segment++; 87 | segmentValue = 0; 88 | } 89 | } 90 | else 91 | { 92 | // Next digit 93 | segmentValue = (segmentValue*10)+(*p - '0'); 94 | } 95 | p++; 96 | } 97 | // We've reached the end of address, but there'll still be the last 98 | // segment to deal with 99 | if ((segmentValue > 255) || (segment > 3)) 100 | { 101 | // You can't have IP address segments that don't fit in a byte, 102 | // or more than four segments 103 | return 0; 104 | } 105 | else 106 | { 107 | aResult[segment] = (byte)segmentValue; 108 | return 1; 109 | } 110 | } 111 | else 112 | { 113 | return 0; 114 | } 115 | } 116 | 117 | int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult) 118 | { 119 | int ret =0; 120 | 121 | // See if it's a numeric IP address 122 | if (inet_aton(aHostname, aResult)) 123 | { 124 | // It is, our work here is done 125 | return 1; 126 | } 127 | 128 | // Check we've got a valid DNS server to use 129 | if (iDNSServer == INADDR_NONE) 130 | { 131 | return INVALID_SERVER; 132 | } 133 | 134 | // Find a socket to use 135 | if (iUdp.begin(1024+(millis() & 0xF)) == 1) 136 | { 137 | // Try up to three times 138 | int retries = 0; 139 | // while ((retries < 3) && (ret <= 0)) 140 | { 141 | // Send DNS request 142 | ret = iUdp.beginPacket(iDNSServer, DNS_PORT); 143 | if (ret != 0) 144 | { 145 | // Now output the request data 146 | ret = BuildRequest(aHostname); 147 | if (ret != 0) 148 | { 149 | // And finally send the request 150 | ret = iUdp.endPacket(); 151 | if (ret != 0) 152 | { 153 | // Now wait for a response 154 | int wait_retries = 0; 155 | ret = TIMED_OUT; 156 | while ((wait_retries < 3) && (ret == TIMED_OUT)) 157 | { 158 | ret = ProcessResponse(5000, aResult); 159 | wait_retries++; 160 | } 161 | } 162 | } 163 | } 164 | retries++; 165 | } 166 | 167 | // We're done with the socket now 168 | iUdp.stop(); 169 | } 170 | 171 | return ret; 172 | } 173 | 174 | uint16_t DNSClient::BuildRequest(const char* aName) 175 | { 176 | // Build header 177 | // 1 1 1 1 1 1 178 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 179 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 180 | // | ID | 181 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 182 | // |QR| Opcode |AA|TC|RD|RA| Z | RCODE | 183 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 184 | // | QDCOUNT | 185 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 186 | // | ANCOUNT | 187 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 188 | // | NSCOUNT | 189 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 190 | // | ARCOUNT | 191 | // +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ 192 | // As we only support one request at a time at present, we can simplify 193 | // some of this header 194 | iRequestId = millis(); // generate a random ID 195 | uint16_t twoByteBuffer; 196 | 197 | // FIXME We should also check that there's enough space available to write to, rather 198 | // FIXME than assume there's enough space (as the code does at present) 199 | iUdp.write((uint8_t*)&iRequestId, sizeof(iRequestId)); 200 | 201 | twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG); 202 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 203 | 204 | twoByteBuffer = htons(1); // One question record 205 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 206 | 207 | twoByteBuffer = 0; // Zero answer records 208 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 209 | 210 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 211 | // and zero additional records 212 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 213 | 214 | // Build question 215 | const char* start =aName; 216 | const char* end =start; 217 | uint8_t len; 218 | // Run through the name being requested 219 | while (*end) 220 | { 221 | // Find out how long this section of the name is 222 | end = start; 223 | while (*end && (*end != '.') ) 224 | { 225 | end++; 226 | } 227 | 228 | if (end-start > 0) 229 | { 230 | // Write out the size of this section 231 | len = end-start; 232 | iUdp.write(&len, sizeof(len)); 233 | // And then write out the section 234 | iUdp.write((uint8_t*)start, end-start); 235 | } 236 | start = end+1; 237 | } 238 | 239 | // We've got to the end of the question name, so 240 | // terminate it with a zero-length section 241 | len = 0; 242 | iUdp.write(&len, sizeof(len)); 243 | // Finally the type and class of question 244 | twoByteBuffer = htons(TYPE_A); 245 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 246 | 247 | twoByteBuffer = htons(CLASS_IN); // Internet class of question 248 | iUdp.write((uint8_t*)&twoByteBuffer, sizeof(twoByteBuffer)); 249 | // Success! Everything buffered okay 250 | return 1; 251 | } 252 | 253 | 254 | uint16_t DNSClient::ProcessResponse(uint16_t aTimeout, IPAddress& aAddress) 255 | { 256 | uint32_t startTime = millis(); 257 | 258 | // Wait for a response packet 259 | while(iUdp.parsePacket() <= 0) 260 | { 261 | if((millis() - startTime) > aTimeout) 262 | return TIMED_OUT; 263 | delay(50); 264 | } 265 | 266 | // We've had a reply! 267 | // Read the UDP header 268 | uint8_t header[DNS_HEADER_SIZE]; // Enough space to reuse for the DNS header 269 | // Check that it's a response from the right server and the right port 270 | if ( (iDNSServer != iUdp.remoteIP()) || 271 | (iUdp.remotePort() != DNS_PORT) ) 272 | { 273 | // It's not from who we expected 274 | return INVALID_SERVER; 275 | } 276 | 277 | // Read through the rest of the response 278 | if (iUdp.available() < DNS_HEADER_SIZE) 279 | { 280 | return TRUNCATED; 281 | } 282 | iUdp.read(header, DNS_HEADER_SIZE); 283 | 284 | uint16_t header_flags = htons(*((uint16_t*)&header[2])); 285 | // Check that it's a response to this request 286 | if ( ( iRequestId != (*((uint16_t*)&header[0])) ) || 287 | ((header_flags & QUERY_RESPONSE_MASK) != (uint16_t)RESPONSE_FLAG) ) 288 | { 289 | // Mark the entire packet as read 290 | iUdp.flush(); 291 | return INVALID_RESPONSE; 292 | } 293 | // Check for any errors in the response (or in our request) 294 | // although we don't do anything to get round these 295 | if ( (header_flags & TRUNCATION_FLAG) || (header_flags & RESP_MASK) ) 296 | { 297 | // Mark the entire packet as read 298 | iUdp.flush(); 299 | return -5; //INVALID_RESPONSE; 300 | } 301 | 302 | // And make sure we've got (at least) one answer 303 | uint16_t answerCount = htons(*((uint16_t*)&header[6])); 304 | if (answerCount == 0 ) 305 | { 306 | // Mark the entire packet as read 307 | iUdp.flush(); 308 | return -6; //INVALID_RESPONSE; 309 | } 310 | 311 | // Skip over any questions 312 | for (uint16_t i =0; i < htons(*((uint16_t*)&header[4])); i++) 313 | { 314 | // Skip over the name 315 | uint8_t len; 316 | do 317 | { 318 | iUdp.read(&len, sizeof(len)); 319 | if (len > 0) 320 | { 321 | // Don't need to actually read the data out for the string, just 322 | // advance ptr to beyond it 323 | while(len--) 324 | { 325 | iUdp.read(); // we don't care about the returned byte 326 | } 327 | } 328 | } while (len != 0); 329 | 330 | // Now jump over the type and class 331 | for (int i =0; i < 4; i++) 332 | { 333 | iUdp.read(); // we don't care about the returned byte 334 | } 335 | } 336 | 337 | // Now we're up to the bit we're interested in, the answer 338 | // There might be more than one answer (although we'll just use the first 339 | // type A answer) and some authority and additional resource records but 340 | // we're going to ignore all of them. 341 | 342 | for (uint16_t i =0; i < answerCount; i++) 343 | { 344 | // Skip the name 345 | uint8_t len; 346 | do 347 | { 348 | iUdp.read(&len, sizeof(len)); 349 | if ((len & LABEL_COMPRESSION_MASK) == 0) 350 | { 351 | // It's just a normal label 352 | if (len > 0) 353 | { 354 | // And it's got a length 355 | // Don't need to actually read the data out for the string, 356 | // just advance ptr to beyond it 357 | while(len--) 358 | { 359 | iUdp.read(); // we don't care about the returned byte 360 | } 361 | } 362 | } 363 | else 364 | { 365 | // This is a pointer to a somewhere else in the message for the 366 | // rest of the name. We don't care about the name, and RFC1035 367 | // says that a name is either a sequence of labels ended with a 368 | // 0 length octet or a pointer or a sequence of labels ending in 369 | // a pointer. Either way, when we get here we're at the end of 370 | // the name 371 | // Skip over the pointer 372 | iUdp.read(); // we don't care about the returned byte 373 | // And set len so that we drop out of the name loop 374 | len = 0; 375 | } 376 | } while (len != 0); 377 | 378 | // Check the type and class 379 | uint16_t answerType; 380 | uint16_t answerClass; 381 | iUdp.read((uint8_t*)&answerType, sizeof(answerType)); 382 | iUdp.read((uint8_t*)&answerClass, sizeof(answerClass)); 383 | 384 | // Ignore the Time-To-Live as we don't do any caching 385 | for (int i =0; i < TTL_SIZE; i++) 386 | { 387 | iUdp.read(); // we don't care about the returned byte 388 | } 389 | 390 | // And read out the length of this answer 391 | // Don't need header_flags anymore, so we can reuse it here 392 | iUdp.read((uint8_t*)&header_flags, sizeof(header_flags)); 393 | 394 | if ( (htons(answerType) == TYPE_A) && (htons(answerClass) == CLASS_IN) ) 395 | { 396 | if (htons(header_flags) != 4) 397 | { 398 | // It's a weird size 399 | // Mark the entire packet as read 400 | iUdp.flush(); 401 | return -9;//INVALID_RESPONSE; 402 | } 403 | iUdp.read(aAddress.raw_address(), 4); 404 | return SUCCESS; 405 | } 406 | else 407 | { 408 | // This isn't an answer type we're after, move onto the next one 409 | for (uint16_t i =0; i < htons(header_flags); i++) 410 | { 411 | iUdp.read(); // we don't care about the returned byte 412 | } 413 | } 414 | } 415 | 416 | // Mark the entire packet as read 417 | iUdp.flush(); 418 | 419 | // If we get here then we haven't found an answer 420 | return -10;//INVALID_RESPONSE; 421 | } 422 | 423 | -------------------------------------------------------------------------------- /Dns.h: -------------------------------------------------------------------------------- 1 | // Arduino DNS client for Enc28J60-based Ethernet shield 2 | // (c) Copyright 2009-2010 MCQN Ltd. 3 | // Released under Apache License, version 2.0 4 | 5 | #ifndef DNSClient_h 6 | #define DNSClient_h 7 | 8 | #include 9 | 10 | class DNSClient 11 | { 12 | public: 13 | // ctor 14 | void begin(const IPAddress& aDNSServer); 15 | 16 | /** Convert a numeric IP address string into a four-byte IP address. 17 | @param aIPAddrString IP address to convert 18 | @param aResult IPAddress structure to store the returned IP address 19 | @result 1 if aIPAddrString was successfully converted to an IP address, 20 | else error code 21 | */ 22 | int inet_aton(const char *aIPAddrString, IPAddress& aResult); 23 | 24 | /** Resolve the given hostname to an IP address. 25 | @param aHostname Name to be resolved 26 | @param aResult IPAddress structure to store the returned IP address 27 | @result 1 if aIPAddrString was successfully converted to an IP address, 28 | else error code 29 | */ 30 | int getHostByName(const char* aHostname, IPAddress& aResult); 31 | 32 | protected: 33 | uint16_t BuildRequest(const char* aName); 34 | uint16_t ProcessResponse(uint16_t aTimeout, IPAddress& aAddress); 35 | 36 | IPAddress iDNSServer; 37 | uint16_t iRequestId; 38 | UIPUDP iUdp; 39 | }; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is UIPEthernet version 1.09 2 | 3 | An plugin-replacement of the stock Arduino Ethernet library for ENC28J60 shields and breakout boards. Full support for persistent (streaming) TCP-connections and UDP (Client and Server each), ARP, ICMP, DHCP and DNS. 4 | Just include 'UIPEthernet.h' instead of 'Ethernet.h' and use all your code written for the stock Arduino Ethernet lib! 5 | 6 | UIPEthernet is written as a wrapper around the mature uIP Stack by Adam Dunkels, which provides the low-level implementation for all supported protocols. To overcome the memory-constrains (a 'regular' uIP-application does all processing in RAM) the ENC28J60 internal memory is used for all stream buffers (in and out). Only 400-600 Bytes of Arduinos RAM are used (depending on the number of concurrently open connections). As of Flash-memory a ATmega368-based Arduino is the minimum requirenment. 7 | 8 | This library is written by Norbert Truchsess 9 | 10 | uIP was written by Adam Dunkels of the Networked Embedded Systems group at the Swedish Institute of Computer Science. 11 | 12 | This library was inspired by the SerialIP implementation by Adam Nielsen , actually I took this code as a starting point, but in the latest versions there are very few lines left. 13 | 14 | Installation 15 | ------------ 16 | 17 | To install the libraries, you need to place them into your "libraries" folder. You can find it within your Arduino IDE distribution within the "hardware" folder. 18 | 19 | C:\> cd [path to Arduino distribution]\libraries 20 | C:\> git clone https://github.com/ntruchsess/arduino_uip UIPEthernet 21 | 22 | Be sure to restart the IDE if it was running. 23 | 24 | On a Mac, you will want to create a folder named "libraries" in in the "Documents" -> "Arduino" folder within your home directory. Clone the project there (and restart the IDE, if it was running during this process). 25 | 26 | $ cd ~/Documents/Arduino/libraries 27 | $ git clone https://github.com/ntruchsess/arduino_uip UIPEthernet 28 | 29 | Or you download the zipped version of the library from https://github.com/ntruchsess/arduino_uip/releases, and copy the contained directory UIPEthernet to [path to Arduino distribution]\libraries\UIPEthernet. 30 | 31 | If you are running Arduino-IDE 1.5.x use release-version 1.59 or checkout branch 'Arduino_1.5.x' 32 | 33 | Additional information can be found on the Arduino website: http://www.arduino.cc/en/Hacking/Libraries 34 | 35 | Documentation 36 | ------------- 37 | 38 | For more information visit: 39 | 40 | - UIPEthernet Repository on github: 41 | https://github.com/ntruchsess/arduino_uip 42 | 43 | - Arduino Ethernet library description 44 | http://arduino.cc/en/Reference/Ethernet 45 | (Arduino_uip uses the same API as that, just include "UIPEthernet.h", "UIPClient.h", "UIPServer.h" and "UIPUDP.h" instead of the stock "Ethernet.h", "EthernetClient.h", "EthernetServer.h " and "EthernetUDP.h") 46 | 47 | - uIP API reference: 48 | http://www.sics.se/~adam/uip/uip-1.0-refman/ 49 | 50 | - Arduino forums 51 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl 52 | 53 | - uIP homepage: 54 | http://www.sics.se/~adam/uip/index.php/Main_Page 55 | 56 | Licenses 57 | ------------- 58 | 59 | UIPEthernet.h 60 | UIPEthernet.cpp 61 | UIPServer.h 62 | UIPServer.cpp 63 | UIPClient.h 64 | UIPClient.cpp 65 | UIPUdp.h 66 | UIPUdp.cpp 67 | utility/mempool.h 68 | utility/mempool.cpp 69 | 70 | Copyright (c) 2013 Norbert Truchsess 71 | All rights reserved. 72 | 73 | This program is free software: you can redistribute it and/or modify 74 | it under the terms of the GNU General Public License as published by 75 | the Free Software Foundation, either version 3 of the License, or 76 | (at your option) any later version. 77 | 78 | This program is distributed in the hope that it will be useful, 79 | but WITHOUT ANY WARRANTY; without even the implied warranty of 80 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 81 | GNU General Public License for more details. 82 | 83 | You should have received a copy of the GNU General Public License 84 | along with this program. If not, see . 85 | 86 | -------------- 87 | 88 | utility/enc28j60.h 89 | 90 | Author : Pascal Stang (c)2005 91 | Modified by Norbert Truchsess 92 | Copyright: GPL V2 93 | 94 | -------------- 95 | 96 | utility/Enc28J60Network.h 97 | utility/Enc28J60Network.cpp 98 | 99 | Copyright (c) 2013 Norbert Truchsess 100 | All rights reserved. 101 | 102 | inspired and based on enc28j60.c file from the AVRlib library by Pascal Stang. 103 | 104 | This program is free software: you can redistribute it and/or modify 105 | it under the terms of the GNU General Public License as published by 106 | the Free Software Foundation, either version 3 of the License, or 107 | (at your option) any later version. 108 | 109 | This program is distributed in the hope that it will be useful, 110 | but WITHOUT ANY WARRANTY; without even the implied warranty of 111 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 112 | GNU General Public License for more details. 113 | 114 | You should have received a copy of the GNU General Public License 115 | along with this program. If not, see . 116 | 117 | -------------- 118 | 119 | utility/uip.c 120 | utility/uip_arp.h 121 | utility/uip_arp.c 122 | utility/uip_arch.h 123 | utility/uip.h 124 | utility/uipopt.h 125 | 126 | Copyright (c) 2001-2003, Adam Dunkels , . 127 | All rights reserved. 128 | 129 | Redistribution and use in source and binary forms, with or without 130 | modification, are permitted provided that the following conditions 131 | are met: 132 | 1. Redistributions of source code must retain the above copyright 133 | notice, this list of conditions and the following disclaimer. 134 | 2. Redistributions in binary form must reproduce the above copyright 135 | notice, this list of conditions and the following disclaimer in the 136 | documentation and/or other materials provided with the distribution. 137 | 3. Neither the name of the Institute nor the names of its contributors 138 | may be used to endorse or promote products derived from this software 139 | without specific prior written permission. 140 | 141 | THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 142 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 143 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 144 | ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 145 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 146 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 147 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 148 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 149 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 150 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 151 | SUCH DAMAGE. 152 | 153 | -------------- 154 | 155 | uip-conf.h 156 | utility/uip-neighbor.h 157 | utility/uip-neighbor.c 158 | utility/uip_timer.h 159 | utility/uip_timer.c 160 | utility/uip_clock.h 161 | 162 | Author Adam Dunkels Adam Dunkels , 163 | Copyright (c) 2004,2006, Swedish Institute of Computer Science. 164 | All rights reserved. 165 | 166 | Redistribution and use in source and binary forms, with or without 167 | modification, are permitted provided that the following conditions 168 | are met: 169 | 1. Redistributions of source code must retain the above copyright 170 | notice, this list of conditions and the following disclaimer. 171 | 2. Redistributions in binary form must reproduce the above copyright 172 | notice, this list of conditions and the following disclaimer in the 173 | documentation and/or other materials provided with the distribution. 174 | 3. Neither the name of the Institute nor the names of its contributors 175 | may be used to endorse or promote products derived from this software 176 | without specific prior written permission. 177 | 178 | THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 179 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 181 | ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 182 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 183 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 184 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 185 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 186 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 187 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 188 | SUCH DAMAGE. 189 | 190 | -------------- 191 | 192 | Dhcp.h 193 | Dhcp.cpp 194 | 195 | DHCP Library v0.3 - April 25, 2009 196 | Author: Jordan Terrell - blog.jordanterrell.com 197 | - as included in Arduinos stock Ethernet-library, no special licence mentioned here 198 | 199 | -------------- 200 | 201 | Dns.h 202 | Dns.cpp 203 | 204 | (c) Copyright 2009-2010 MCQN Ltd. 205 | Released under Apache License, version 2.0 206 | 207 | -------------- 208 | 209 | clock-arch.h 210 | clock-arch.c 211 | 212 | Copyright (c) 2010 Adam Nielsen 213 | All rights reserved. 214 | 215 | This library is free software; you can redistribute it and/or 216 | modify it under the terms of the GNU Lesser General Public 217 | License as published by the Free Software Foundation; either 218 | version 2.1 of the License, or (at your option) any later version. 219 | 220 | This library is distributed in the hope that it will be useful, 221 | but WITHOUT ANY WARRANTY; without even the implied warranty of 222 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 223 | Lesser General Public License for more details. 224 | 225 | You should have received a copy of the GNU Lesser General Public 226 | License along with this library; if not, write to the Free Software 227 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 228 | -------------------------------------------------------------------------------- /UIPClient.h: -------------------------------------------------------------------------------- 1 | /* 2 | UIPClient.h - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #ifndef UIPCLIENT_H 21 | #define UIPCLIENT_H 22 | 23 | #include "ethernet_comp.h" 24 | #include "Print.h" 25 | #import "Client.h" 26 | #import "utility/mempool.h" 27 | 28 | extern "C" { 29 | #import "utility/uip.h" 30 | } 31 | 32 | #define UIP_SOCKET_DATALEN UIP_TCP_MSS 33 | //#define UIP_SOCKET_NUMPACKETS UIP_RECEIVE_WINDOW/UIP_TCP_MSS+1 34 | #ifndef UIP_SOCKET_NUMPACKETS 35 | #define UIP_SOCKET_NUMPACKETS 5 36 | #endif 37 | 38 | #define UIP_CLIENT_CONNECTED 0x10 39 | #define UIP_CLIENT_CLOSE 0x20 40 | #define UIP_CLIENT_REMOTECLOSED 0x40 41 | #define UIP_CLIENT_RESTART 0x80 42 | #define UIP_CLIENT_STATEFLAGS (UIP_CLIENT_CONNECTED | UIP_CLIENT_CLOSE | UIP_CLIENT_REMOTECLOSED | UIP_CLIENT_RESTART) 43 | #define UIP_CLIENT_SOCKETS ~UIP_CLIENT_STATEFLAGS 44 | 45 | typedef uint8_t uip_socket_ptr; 46 | 47 | typedef struct { 48 | uint8_t state; 49 | memhandle packets_in[UIP_SOCKET_NUMPACKETS]; 50 | uint16_t lport; /**< The local TCP port, in network byte order. */ 51 | } uip_userdata_closed_t; 52 | 53 | typedef struct { 54 | uint8_t state; 55 | memhandle packets_in[UIP_SOCKET_NUMPACKETS]; 56 | memhandle packets_out[UIP_SOCKET_NUMPACKETS+1]; 57 | memaddress out_pos; 58 | #if UIP_CLIENT_TIMER >= 0 59 | unsigned long timer; 60 | #endif 61 | bool windowOpened; 62 | uint32_t restartTime; 63 | uint32_t restartInterval; 64 | uint16_t dataCnt; 65 | } uip_userdata_t; 66 | 67 | class UIPClient : public Client { 68 | 69 | public: 70 | UIPClient(); 71 | int connect(IPAddress ip, uint16_t port); 72 | int connect(const char *host, uint16_t port); 73 | int read(uint8_t *buf, size_t size); 74 | void stop(); 75 | uint8_t connected(); 76 | operator bool(); 77 | virtual bool operator==(const EthernetClient&); 78 | virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); }; 79 | 80 | size_t write(uint8_t); 81 | size_t write(const uint8_t *buf, size_t size); 82 | int available(); 83 | int waitAvailable(uint32_t timeout=500); 84 | int read(); 85 | int peek(); 86 | void flush(); 87 | 88 | using Print::write; 89 | 90 | private: 91 | UIPClient(struct uip_conn *_conn); 92 | UIPClient(uip_userdata_t* conn_data); 93 | 94 | uip_userdata_t* data; 95 | 96 | static uip_userdata_t all_data[UIP_CONNS]; 97 | static uip_userdata_t* _allocateData(); 98 | 99 | static size_t _write(uip_userdata_t *,const uint8_t *buf, size_t size); 100 | static int _available(uip_userdata_t *); 101 | 102 | static uint8_t _currentBlock(memhandle* blocks); 103 | static void _eatBlock(memhandle* blocks); 104 | static void _flushBlocks(memhandle* blocks); 105 | 106 | #ifdef UIPETHERNET_DEBUG_CLIENT 107 | static void _dumpAllData(); 108 | #endif 109 | 110 | friend class UIPEthernetClass; 111 | friend class UIPServer; 112 | 113 | friend void uipclient_appcall(void); 114 | 115 | }; 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /UIPEthernet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include "UIPEthernet.h" 22 | #include "utility/Enc28J60Network.h" 23 | 24 | #if(defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM) 25 | #include "HardwareSerial.h" 26 | #endif 27 | 28 | #include "UIPUdp.h" 29 | 30 | extern "C" 31 | { 32 | #include "utility/uip-conf.h" 33 | #include "utility/uip.h" 34 | #include "utility/uip_arp.h" 35 | #include "utility/uip_timer.h" 36 | } 37 | 38 | #define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) 39 | 40 | memhandle UIPEthernetClass::in_packet(NOBLOCK); 41 | memhandle UIPEthernetClass::uip_packet(NOBLOCK); 42 | uint8_t UIPEthernetClass::uip_hdrlen(0); 43 | uint8_t UIPEthernetClass::packetstate(0); 44 | 45 | IPAddress UIPEthernetClass::_dnsServerAddress; 46 | DhcpClass* UIPEthernetClass::_dhcp(NULL); 47 | 48 | unsigned long UIPEthernetClass::periodic_timer; 49 | 50 | // Because uIP isn't encapsulated within a class we have to use global 51 | // variables, so we can only have one TCP/IP stack per program. 52 | 53 | UIPEthernetClass::UIPEthernetClass() 54 | { 55 | } 56 | 57 | void 58 | UIPEthernetClass::update() 59 | { 60 | Ethernet.tick(); 61 | } 62 | 63 | #if UIP_UDP 64 | int 65 | UIPEthernetClass::begin(const uint8_t* mac) 66 | { 67 | static DhcpClass s_dhcp; 68 | _dhcp = &s_dhcp; 69 | 70 | // Initialise the basic info 71 | init(mac); 72 | 73 | // Now try to get our config info from a DHCP server 74 | int ret = _dhcp->beginWithDHCP((uint8_t*)mac); 75 | if(ret == 1) 76 | { 77 | // We've successfully found a DHCP server and got our configuration info, so set things 78 | // accordingly 79 | configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); 80 | } 81 | return ret; 82 | } 83 | #endif 84 | 85 | void 86 | UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) 87 | { 88 | IPAddress dns = ip; 89 | dns[3] = 1; 90 | begin(mac, ip, dns); 91 | } 92 | 93 | void 94 | UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) 95 | { 96 | IPAddress gateway = ip; 97 | gateway[3] = 1; 98 | begin(mac, ip, dns, gateway); 99 | } 100 | 101 | void 102 | UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) 103 | { 104 | IPAddress subnet(255, 255, 255, 0); 105 | begin(mac, ip, dns, gateway, subnet); 106 | } 107 | 108 | void 109 | UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) 110 | { 111 | init(mac); 112 | configure(ip,dns,gateway,subnet); 113 | } 114 | 115 | int UIPEthernetClass::maintain(){ 116 | tick(); 117 | int rc = DHCP_CHECK_NONE; 118 | #if UIP_UDP 119 | if(_dhcp != NULL){ 120 | //we have a pointer to dhcp, use it 121 | rc = _dhcp->checkLease(); 122 | switch ( rc ){ 123 | case DHCP_CHECK_NONE: 124 | //nothing done 125 | break; 126 | case DHCP_CHECK_RENEW_OK: 127 | case DHCP_CHECK_REBIND_OK: 128 | //we might have got a new IP. 129 | configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); 130 | break; 131 | default: 132 | //this is actually a error, it will retry though 133 | break; 134 | } 135 | } 136 | return rc; 137 | #endif 138 | } 139 | 140 | IPAddress UIPEthernetClass::localIP() 141 | { 142 | IPAddress ret; 143 | uip_ipaddr_t a; 144 | uip_gethostaddr(a); 145 | return ip_addr_uip(a); 146 | } 147 | 148 | IPAddress UIPEthernetClass::subnetMask() 149 | { 150 | IPAddress ret; 151 | uip_ipaddr_t a; 152 | uip_getnetmask(a); 153 | return ip_addr_uip(a); 154 | } 155 | 156 | IPAddress UIPEthernetClass::gatewayIP() 157 | { 158 | IPAddress ret; 159 | uip_ipaddr_t a; 160 | uip_getdraddr(a); 161 | return ip_addr_uip(a); 162 | } 163 | 164 | IPAddress UIPEthernetClass::dnsServerIP() 165 | { 166 | return _dnsServerAddress; 167 | } 168 | 169 | void 170 | UIPEthernetClass::tick() 171 | { 172 | if (in_packet == NOBLOCK) 173 | { 174 | in_packet = Enc28J60Network::receivePacket(); 175 | #ifdef UIPETHERNET_DEBUG 176 | if (in_packet != NOBLOCK) 177 | { 178 | Serial.print(F("--------------\nreceivePacket: ")); 179 | Serial.println(in_packet); 180 | } 181 | #endif 182 | } 183 | if (in_packet != NOBLOCK) 184 | { 185 | packetstate = UIPETHERNET_FREEPACKET; 186 | uip_len = Enc28J60Network::blockSize(in_packet); 187 | if (uip_len > 0) 188 | { 189 | Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); 190 | if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) 191 | { 192 | uip_packet = in_packet; //required for upper_layer_checksum of in_packet! 193 | #ifdef UIPETHERNET_DEBUG 194 | Serial.print(F("readPacket type IP, uip_len: ")); 195 | Serial.println(uip_len); 196 | #endif 197 | uip_arp_ipin(); 198 | uip_input(); 199 | if (uip_len > 0) 200 | { 201 | uip_arp_out(); 202 | network_send(); 203 | } 204 | } 205 | else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) 206 | { 207 | #ifdef UIPETHERNET_DEBUG 208 | Serial.print(F("readPacket type ARP, uip_len: ")); 209 | Serial.println(uip_len); 210 | #endif 211 | uip_arp_arpin(); 212 | if (uip_len > 0) 213 | { 214 | network_send(); 215 | } 216 | } 217 | } 218 | if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) 219 | { 220 | #ifdef UIPETHERNET_DEBUG 221 | Serial.print(F("freeing packet: ")); 222 | Serial.println(in_packet); 223 | #endif 224 | Enc28J60Network::freePacket(); 225 | in_packet = NOBLOCK; 226 | } 227 | } 228 | 229 | unsigned long now = millis(); 230 | 231 | #if UIP_CLIENT_TIMER >= 0 232 | boolean periodic = (long)( now - periodic_timer ) >= 0; 233 | for (int i = 0; i < UIP_CONNS; i++) 234 | { 235 | #else 236 | if ((long)( now - periodic_timer ) >= 0) 237 | { 238 | periodic_timer = now + UIP_PERIODIC_TIMER; 239 | 240 | for (int i = 0; i < UIP_CONNS; i++) 241 | { 242 | #endif 243 | uip_conn = &uip_conns[i]; 244 | #if UIP_CLIENT_TIMER >= 0 245 | if (periodic) 246 | { 247 | #endif 248 | uip_process(UIP_TIMER); 249 | #if UIP_CLIENT_TIMER >= 0 250 | } 251 | else 252 | { 253 | if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) 254 | uip_process(UIP_POLL_REQUEST); 255 | else 256 | continue; 257 | } 258 | #endif 259 | // If the above function invocation resulted in data that 260 | // should be sent out on the Enc28J60Network, the global variable 261 | // uip_len is set to a value > 0. 262 | if (uip_len > 0) 263 | { 264 | uip_arp_out(); 265 | network_send(); 266 | } 267 | } 268 | #if UIP_CLIENT_TIMER >= 0 269 | if (periodic) 270 | { 271 | periodic_timer = now + UIP_PERIODIC_TIMER; 272 | #endif 273 | #if UIP_UDP 274 | for (int i = 0; i < UIP_UDP_CONNS; i++) 275 | { 276 | uip_udp_periodic(i); 277 | // If the above function invocation resulted in data that 278 | // should be sent out on the Enc28J60Network, the global variable 279 | // uip_len is set to a value > 0. */ 280 | if (uip_len > 0) 281 | { 282 | UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); 283 | } 284 | } 285 | #endif /* UIP_UDP */ 286 | } 287 | } 288 | 289 | boolean UIPEthernetClass::network_send() 290 | { 291 | if (packetstate & UIPETHERNET_SENDPACKET) 292 | { 293 | #ifdef UIPETHERNET_DEBUG 294 | Serial.print(F("Enc28J60Network_send uip_packet: ")); 295 | Serial.print(uip_packet); 296 | Serial.print(F(", hdrlen: ")); 297 | Serial.println(uip_hdrlen); 298 | #endif 299 | Enc28J60Network::writePacket(uip_packet,UIP_SENDBUFFER_OFFSET,uip_buf,uip_hdrlen); 300 | packetstate &= ~ UIPETHERNET_SENDPACKET; 301 | if (Enc28J60Network::sendPacket(uip_packet)) 302 | { 303 | Enc28J60Network::freeBlock(uip_packet); 304 | uip_packet = NOBLOCK; 305 | return true; 306 | } 307 | return false; 308 | } 309 | uip_packet = Enc28J60Network::allocBlock(uip_len + UIP_SENDBUFFER_OFFSET + UIP_SENDBUFFER_PADDING); 310 | if (uip_packet != NOBLOCK) 311 | { 312 | #ifdef UIPETHERNET_DEBUG 313 | Serial.print(F("Enc28J60Network_send uip_buf (uip_len): ")); 314 | Serial.print(uip_len); 315 | Serial.print(F(", packet: ")); 316 | Serial.println(uip_packet); 317 | #endif 318 | Enc28J60Network::writePacket(uip_packet,UIP_SENDBUFFER_OFFSET,uip_buf,uip_len); 319 | bool register success = Enc28J60Network::sendPacket(uip_packet); 320 | Enc28J60Network::freeBlock(uip_packet); 321 | uip_packet = NOBLOCK; 322 | return success; 323 | } 324 | return false; 325 | } 326 | 327 | void UIPEthernetClass::init(const uint8_t* mac) { 328 | periodic_timer = millis() + UIP_PERIODIC_TIMER; 329 | 330 | Enc28J60Network::init((uint8_t*)mac); 331 | uip_seteth_addr(mac); 332 | 333 | uip_init(); 334 | uip_arp_init(); 335 | } 336 | 337 | void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { 338 | uip_ipaddr_t ipaddr; 339 | 340 | uip_ip_addr(ipaddr, ip); 341 | uip_sethostaddr(ipaddr); 342 | 343 | uip_ip_addr(ipaddr, gateway); 344 | uip_setdraddr(ipaddr); 345 | 346 | uip_ip_addr(ipaddr, subnet); 347 | uip_setnetmask(ipaddr); 348 | 349 | _dnsServerAddress = dns; 350 | } 351 | 352 | UIPEthernetClass UIPEthernet; 353 | 354 | /*---------------------------------------------------------------------------*/ 355 | uint16_t 356 | UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) 357 | { 358 | uint16_t t; 359 | const uint8_t *dataptr; 360 | const uint8_t *last_byte; 361 | 362 | dataptr = data; 363 | last_byte = data + len - 1; 364 | 365 | while(dataptr < last_byte) { /* At least two more bytes */ 366 | t = (dataptr[0] << 8) + dataptr[1]; 367 | sum += t; 368 | if(sum < t) { 369 | sum++; /* carry */ 370 | } 371 | dataptr += 2; 372 | } 373 | 374 | if(dataptr == last_byte) { 375 | t = (dataptr[0] << 8) + 0; 376 | sum += t; 377 | if(sum < t) { 378 | sum++; /* carry */ 379 | } 380 | } 381 | 382 | /* Return sum in host byte order. */ 383 | return sum; 384 | } 385 | 386 | /*---------------------------------------------------------------------------*/ 387 | 388 | uint16_t 389 | UIPEthernetClass::ipchksum(void) 390 | { 391 | uint16_t sum; 392 | 393 | sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); 394 | return (sum == 0) ? 0xffff : htons(sum); 395 | } 396 | 397 | /*---------------------------------------------------------------------------*/ 398 | uint16_t 399 | #if UIP_UDP 400 | UIPEthernetClass::upper_layer_chksum(uint8_t proto) 401 | #else 402 | uip_tcpchksum(void) 403 | #endif 404 | { 405 | uint16_t upper_layer_len; 406 | uint16_t sum; 407 | 408 | #if UIP_CONF_IPV6 409 | upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); 410 | #else /* UIP_CONF_IPV6 */ 411 | upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; 412 | #endif /* UIP_CONF_IPV6 */ 413 | 414 | /* First sum pseudoheader. */ 415 | 416 | /* IP protocol and length fields. This addition cannot carry. */ 417 | #if UIP_UDP 418 | sum = upper_layer_len + proto; 419 | #else 420 | sum = upper_layer_len + UIP_PROTO_TCP; 421 | #endif 422 | /* Sum IP source and destination addresses. */ 423 | sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); 424 | 425 | uint8_t upper_layer_memlen; 426 | #if UIP_UDP 427 | switch(proto) 428 | { 429 | // case UIP_PROTO_ICMP: 430 | // case UIP_PROTO_ICMP6: 431 | // upper_layer_memlen = upper_layer_len; 432 | // break; 433 | case UIP_PROTO_UDP: 434 | upper_layer_memlen = UIP_UDPH_LEN; 435 | break; 436 | default: 437 | // case UIP_PROTO_TCP: 438 | #endif 439 | upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; 440 | #if UIP_UDP 441 | break; 442 | } 443 | #endif 444 | sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); 445 | #ifdef UIPETHERNET_DEBUG_CHKSUM 446 | Serial.print(F("chksum uip_buf[")); 447 | Serial.print(UIP_IPH_LEN + UIP_LLH_LEN); 448 | Serial.print(F("-")); 449 | Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); 450 | Serial.print(F("]: ")); 451 | Serial.println(htons(sum),HEX); 452 | #endif 453 | if (upper_layer_memlen < upper_layer_len) 454 | { 455 | sum = Enc28J60Network::chksum( 456 | sum, 457 | UIPEthernetClass::uip_packet, 458 | (UIPEthernetClass::packetstate & UIPETHERNET_SENDPACKET ? UIP_IPH_LEN + UIP_LLH_LEN + UIP_SENDBUFFER_OFFSET : UIP_IPH_LEN + UIP_LLH_LEN) + upper_layer_memlen, 459 | upper_layer_len - upper_layer_memlen 460 | ); 461 | #ifdef UIPETHERNET_DEBUG_CHKSUM 462 | Serial.print(F("chksum uip_packet(")); 463 | Serial.print(uip_packet); 464 | Serial.print(F(")[")); 465 | Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); 466 | Serial.print(F("-")); 467 | Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); 468 | Serial.print(F("]: ")); 469 | Serial.println(htons(sum),HEX); 470 | #endif 471 | } 472 | return (sum == 0) ? 0xffff : htons(sum); 473 | } 474 | 475 | uint16_t 476 | uip_ipchksum(void) 477 | { 478 | return UIPEthernet.ipchksum(); 479 | } 480 | 481 | #if UIP_UDP 482 | uint16_t 483 | uip_tcpchksum(void) 484 | { 485 | uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); 486 | return sum; 487 | } 488 | 489 | uint16_t 490 | uip_udpchksum(void) 491 | { 492 | uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); 493 | return sum; 494 | } 495 | #endif 496 | -------------------------------------------------------------------------------- /UIPEthernet.h: -------------------------------------------------------------------------------- 1 | /* 2 | UIPEthernet.h - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #ifndef UIPETHERNET_H 21 | #define UIPETHERNET_H 22 | 23 | //#define UIPETHERNET_DEBUG 24 | //#define UIPETHERNET_DEBUG_CHKSUM 25 | //#define UIPETHERNET_DEBUG_UDP 26 | //#define UIPETHERNET_DEBUG_CLIENT 27 | 28 | #include "ethernet_comp.h" 29 | #include 30 | #include "Dhcp.h" 31 | #include "IPAddress.h" 32 | #include "utility/Enc28J60Network.h" 33 | #include "UIPClient.h" 34 | #include "UIPServer.h" 35 | #include "UIPUdp.h" 36 | 37 | extern "C" 38 | { 39 | #include "utility/uip_timer.h" 40 | #include "utility/uip.h" 41 | } 42 | 43 | #define UIPETHERNET_FREEPACKET 1 44 | #define UIPETHERNET_SENDPACKET 2 45 | 46 | #define uip_ip_addr(addr, ip) do { \ 47 | ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ 48 | ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ 49 | } while(0) 50 | 51 | #define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable 52 | 53 | #define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ 54 | uip_ethaddr.addr[1] = eaddr[1];\ 55 | uip_ethaddr.addr[2] = eaddr[2];\ 56 | uip_ethaddr.addr[3] = eaddr[3];\ 57 | uip_ethaddr.addr[4] = eaddr[4];\ 58 | uip_ethaddr.addr[5] = eaddr[5];} while(0) 59 | 60 | #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) 61 | 62 | class UIPEthernetClass 63 | { 64 | public: 65 | UIPEthernetClass(); 66 | 67 | int begin(const uint8_t* mac); 68 | void begin(const uint8_t* mac, IPAddress ip); 69 | void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); 70 | void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); 71 | void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); 72 | 73 | // maintain() must be called at regular intervals to process the incoming serial 74 | // data and issue IP events to the sketch. It does not return until all IP 75 | // events have been processed. Renews dhcp-lease if required. 76 | int maintain(); 77 | 78 | IPAddress localIP(); 79 | IPAddress subnetMask(); 80 | IPAddress gatewayIP(); 81 | IPAddress dnsServerIP(); 82 | 83 | void update(); 84 | 85 | private: 86 | static memhandle in_packet; 87 | static memhandle uip_packet; 88 | static uint8_t uip_hdrlen; 89 | static uint8_t packetstate; 90 | 91 | static IPAddress _dnsServerAddress; 92 | static DhcpClass* _dhcp; 93 | 94 | static unsigned long periodic_timer; 95 | 96 | static void init(const uint8_t* mac); 97 | static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); 98 | 99 | static void tick(); 100 | 101 | static boolean network_send(); 102 | 103 | friend class UIPServer; 104 | 105 | friend class UIPClient; 106 | 107 | friend class UIPUDP; 108 | 109 | static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); 110 | static uint16_t ipchksum(void); 111 | #if UIP_UDP 112 | static uint16_t upper_layer_chksum(uint8_t proto); 113 | #endif 114 | friend uint16_t uip_ipchksum(void); 115 | friend uint16_t uip_tcpchksum(void); 116 | friend uint16_t uip_udpchksum(void); 117 | 118 | friend void uipclient_appcall(void); 119 | friend void uipudp_appcall(void); 120 | 121 | #if UIP_CONF_IPV6 122 | uint16_t uip_icmp6chksum(void); 123 | #endif /* UIP_CONF_IPV6 */ 124 | }; 125 | 126 | extern UIPEthernetClass UIPEthernet; 127 | 128 | #endif 129 | -------------------------------------------------------------------------------- /UIPServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | UIPServer.cpp - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | #include "UIPEthernet.h" 20 | #include "UIPServer.h" 21 | extern "C" { 22 | #include "utility/uip-conf.h" 23 | } 24 | 25 | UIPServer::UIPServer(uint16_t port) : _port(htons(port)) 26 | { 27 | } 28 | 29 | UIPClient UIPServer::available() 30 | { 31 | UIPEthernetClass::tick(); 32 | for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) 33 | { 34 | if (data->packets_in[0] != NOBLOCK 35 | && (((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) 36 | || ((data->state & UIP_CLIENT_REMOTECLOSED) && ((uip_userdata_closed_t *)data)->lport == _port))) 37 | return UIPClient(data); 38 | } 39 | return UIPClient(); 40 | } 41 | 42 | void UIPServer::begin() 43 | { 44 | uip_listen(_port); 45 | UIPEthernetClass::tick(); 46 | } 47 | 48 | size_t UIPServer::write(uint8_t c) 49 | { 50 | return write(&c,1); 51 | } 52 | 53 | size_t UIPServer::write(const uint8_t *buf, size_t size) 54 | { 55 | size_t ret = 0; 56 | for ( uip_userdata_t* data = &UIPClient::all_data[0]; data < &UIPClient::all_data[UIP_CONNS]; data++ ) 57 | { 58 | if ((data->state & UIP_CLIENT_CONNECTED) && uip_conns[data->state & UIP_CLIENT_SOCKETS].lport ==_port) 59 | ret += UIPClient::_write(data,buf,size); 60 | } 61 | return ret; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /UIPServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | UIPServer.h - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | #ifndef UIPSERVER_H 20 | #define UIPSERVER_H 21 | 22 | #include "ethernet_comp.h" 23 | #import "Server.h" 24 | #import "UIPClient.h" 25 | 26 | class UIPServer : public Server { 27 | 28 | public: 29 | UIPServer(uint16_t); 30 | UIPClient available(); 31 | void begin(); 32 | size_t write(uint8_t); 33 | size_t write(const uint8_t *buf, size_t size); 34 | using Print::write; 35 | 36 | private: 37 | uint16_t _port; 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /UIPUdp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | UIPUdp.cpp - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "UIPEthernet.h" 21 | #include "UIPUdp.h" 22 | #include "Dns.h" 23 | 24 | #ifdef UIPETHERNET_DEBUG_UDP 25 | #include "HardwareSerial.h" 26 | #endif 27 | 28 | extern "C" { 29 | #include "utility/uip-conf.h" 30 | #include "utility/uip.h" 31 | #include "utility/uip_arp.h" 32 | } 33 | 34 | #if UIP_UDP 35 | #define UIP_ARPHDRSIZE 42 36 | #define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) 37 | 38 | // Constructor 39 | UIPUDP::UIPUDP() : 40 | _uip_udp_conn(NULL) 41 | { 42 | memset(&appdata,0,sizeof(appdata)); 43 | } 44 | 45 | // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 46 | uint8_t 47 | UIPUDP::begin(uint16_t port) 48 | { 49 | if (!_uip_udp_conn) 50 | { 51 | _uip_udp_conn = uip_udp_new(NULL, 0); 52 | } 53 | if (_uip_udp_conn) 54 | { 55 | uip_udp_bind(_uip_udp_conn,htons(port)); 56 | _uip_udp_conn->appstate = &appdata; 57 | return 1; 58 | } 59 | return 0; 60 | } 61 | 62 | // Finish with the UDP socket 63 | void 64 | UIPUDP::stop() 65 | { 66 | if (_uip_udp_conn) 67 | { 68 | uip_udp_remove(_uip_udp_conn); 69 | _uip_udp_conn->appstate = NULL; 70 | _uip_udp_conn=NULL; 71 | Enc28J60Network::freeBlock(appdata.packet_in); 72 | Enc28J60Network::freeBlock(appdata.packet_next); 73 | Enc28J60Network::freeBlock(appdata.packet_out); 74 | memset(&appdata,0,sizeof(appdata)); 75 | } 76 | } 77 | 78 | // Sending UDP packets 79 | 80 | // Start building up a packet to send to the remote host specific in ip and port 81 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 82 | int 83 | UIPUDP::beginPacket(IPAddress ip, uint16_t port) 84 | { 85 | UIPEthernetClass::tick(); 86 | if (ip && port) 87 | { 88 | uip_ipaddr_t ripaddr; 89 | uip_ip_addr(&ripaddr, ip); 90 | #ifdef UIPETHERNET_DEBUG_UDP 91 | Serial.print(F("udp beginPacket, ")); 92 | #endif 93 | if (_uip_udp_conn) 94 | { 95 | _uip_udp_conn->rport = htons(port); 96 | uip_ipaddr_copy(_uip_udp_conn->ripaddr, &ripaddr); 97 | } 98 | else 99 | { 100 | _uip_udp_conn = uip_udp_new(&ripaddr,htons(port)); 101 | if (_uip_udp_conn) 102 | { 103 | #ifdef UIPETHERNET_DEBUG_UDP 104 | Serial.print(F("new connection, ")); 105 | #endif 106 | _uip_udp_conn->appstate = &appdata; 107 | } 108 | else 109 | { 110 | #ifdef UIPETHERNET_DEBUG_UDP 111 | Serial.println(F("failed to allocate new connection")); 112 | #endif 113 | return 0; 114 | } 115 | } 116 | #ifdef UIPETHERNET_DEBUG_UDP 117 | Serial.print(F("rip: ")); 118 | Serial.print(ip); 119 | Serial.print(F(", port: ")); 120 | Serial.println(port); 121 | #endif 122 | } 123 | if (_uip_udp_conn) 124 | { 125 | if (appdata.packet_out == NOBLOCK) 126 | { 127 | appdata.packet_out = Enc28J60Network::allocBlock(UIP_UDP_MAXPACKETSIZE + UIP_SENDBUFFER_OFFSET + UIP_SENDBUFFER_PADDING); 128 | appdata.out_pos = UIP_UDP_PHYH_LEN + UIP_SENDBUFFER_OFFSET; 129 | if (appdata.packet_out != NOBLOCK) 130 | return 1; 131 | #ifdef UIPETHERNET_DEBUG_UDP 132 | else 133 | Serial.println(F("failed to allocate memory for packet")); 134 | #endif 135 | } 136 | #ifdef UIPETHERNET_DEBUG_UDP 137 | else 138 | Serial.println(F("previous packet on that connection not sent yet")); 139 | #endif 140 | } 141 | return 0; 142 | } 143 | 144 | // Start building up a packet to send to the remote host specific in host and port 145 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 146 | int 147 | UIPUDP::beginPacket(const char *host, uint16_t port) 148 | { 149 | // Look up the host first 150 | int ret = 0; 151 | DNSClient dns; 152 | IPAddress remote_addr; 153 | 154 | dns.begin(UIPEthernet.dnsServerIP()); 155 | ret = dns.getHostByName(host, remote_addr); 156 | if (ret == 1) { 157 | return beginPacket(remote_addr, port); 158 | } else { 159 | return ret; 160 | } 161 | } 162 | 163 | // Finish off this packet and send it 164 | // Returns 1 if the packet was sent successfully, 0 if there was an error 165 | int 166 | UIPUDP::endPacket() 167 | { 168 | if (_uip_udp_conn && appdata.packet_out != NOBLOCK) 169 | { 170 | appdata.send = true; 171 | Enc28J60Network::resizeBlock(appdata.packet_out,0,appdata.out_pos + UIP_SENDBUFFER_PADDING); 172 | uip_udp_periodic_conn(_uip_udp_conn); 173 | if (uip_len > 0) 174 | { 175 | _send(&appdata); 176 | return 1; 177 | } 178 | } 179 | return 0; 180 | } 181 | 182 | // Write a single byte into the packet 183 | size_t 184 | UIPUDP::write(uint8_t c) 185 | { 186 | return write(&c,1); 187 | } 188 | 189 | // Write size bytes from buffer into the packet 190 | size_t 191 | UIPUDP::write(const uint8_t *buffer, size_t size) 192 | { 193 | if (appdata.packet_out != NOBLOCK) 194 | { 195 | size_t ret = Enc28J60Network::writePacket(appdata.packet_out,appdata.out_pos,(uint8_t*)buffer,size); 196 | appdata.out_pos += ret; 197 | return ret; 198 | } 199 | return 0; 200 | } 201 | 202 | // Start processing the next available incoming packet 203 | // Returns the size of the packet in bytes, or 0 if no packets are available 204 | int 205 | UIPUDP::parsePacket() 206 | { 207 | UIPEthernetClass::tick(); 208 | #ifdef UIPETHERNET_DEBUG_UDP 209 | if (appdata.packet_in != NOBLOCK) 210 | { 211 | Serial.print(F("udp parsePacket freeing previous packet: ")); 212 | Serial.println(appdata.packet_in); 213 | } 214 | #endif 215 | Enc28J60Network::freeBlock(appdata.packet_in); 216 | 217 | appdata.packet_in = appdata.packet_next; 218 | appdata.packet_next = NOBLOCK; 219 | 220 | #ifdef UIPETHERNET_DEBUG_UDP 221 | if (appdata.packet_in != NOBLOCK) 222 | { 223 | Serial.print(F("udp parsePacket received packet: ")); 224 | Serial.print(appdata.packet_in); 225 | } 226 | #endif 227 | int size = Enc28J60Network::blockSize(appdata.packet_in); 228 | #ifdef UIPETHERNET_DEBUG_UDP 229 | if (appdata.packet_in != NOBLOCK) 230 | { 231 | Serial.print(F(", size: ")); 232 | Serial.println(size); 233 | } 234 | #endif 235 | return size; 236 | } 237 | 238 | // Number of bytes remaining in the current packet 239 | int 240 | UIPUDP::available() 241 | { 242 | UIPEthernetClass::tick(); 243 | return Enc28J60Network::blockSize(appdata.packet_in); 244 | } 245 | 246 | // Read a single byte from the current packet 247 | int 248 | UIPUDP::read() 249 | { 250 | unsigned char c; 251 | if (read(&c,1) > 0) 252 | { 253 | return c; 254 | } 255 | return -1; 256 | } 257 | 258 | // Read up to len bytes from the current packet and place them into buffer 259 | // Returns the number of bytes read, or 0 if none are available 260 | int 261 | UIPUDP::read(unsigned char* buffer, size_t len) 262 | { 263 | UIPEthernetClass::tick(); 264 | if (appdata.packet_in != NOBLOCK) 265 | { 266 | memaddress read = Enc28J60Network::readPacket(appdata.packet_in,0,buffer,len); 267 | if (read == Enc28J60Network::blockSize(appdata.packet_in)) 268 | { 269 | Enc28J60Network::freeBlock(appdata.packet_in); 270 | appdata.packet_in = NOBLOCK; 271 | } 272 | else 273 | Enc28J60Network::resizeBlock(appdata.packet_in,read); 274 | return read; 275 | } 276 | return 0; 277 | } 278 | 279 | // Return the next byte from the current packet without moving on to the next byte 280 | int 281 | UIPUDP::peek() 282 | { 283 | UIPEthernetClass::tick(); 284 | if (appdata.packet_in != NOBLOCK) 285 | { 286 | unsigned char c; 287 | if (Enc28J60Network::readPacket(appdata.packet_in,0,&c,1) == 1) 288 | return c; 289 | } 290 | return -1; 291 | } 292 | 293 | // Finish reading the current packet 294 | void 295 | UIPUDP::flush() 296 | { 297 | UIPEthernetClass::tick(); 298 | Enc28J60Network::freeBlock(appdata.packet_in); 299 | appdata.packet_in = NOBLOCK; 300 | } 301 | 302 | // Return the IP address of the host who sent the current incoming packet 303 | IPAddress 304 | UIPUDP::remoteIP() 305 | { 306 | return _uip_udp_conn ? ip_addr_uip(_uip_udp_conn->ripaddr) : IPAddress(); 307 | } 308 | 309 | // Return the port of the host who sent the current incoming packet 310 | uint16_t 311 | UIPUDP::remotePort() 312 | { 313 | return _uip_udp_conn ? ntohs(_uip_udp_conn->rport) : 0; 314 | } 315 | 316 | // uIP callback function 317 | 318 | void 319 | uipudp_appcall(void) { 320 | if (uip_udp_userdata_t *data = (uip_udp_userdata_t *)(uip_udp_conn->appstate)) 321 | { 322 | if (uip_newdata()) 323 | { 324 | if (data->packet_next == NOBLOCK) 325 | { 326 | uip_udp_conn->rport = UDPBUF->srcport; 327 | uip_ipaddr_copy(uip_udp_conn->ripaddr,UDPBUF->srcipaddr); 328 | data->packet_next = Enc28J60Network::allocBlock(ntohs(UDPBUF->udplen)-UIP_UDPH_LEN); 329 | //if we are unable to allocate memory the packet is dropped. udp doesn't guarantee packet delivery 330 | if (data->packet_next != NOBLOCK) 331 | { 332 | //discard Linklevel and IP and udp-header and any trailing bytes: 333 | Enc28J60Network::copyPacket(data->packet_next,0,UIPEthernetClass::in_packet,UIP_UDP_PHYH_LEN,Enc28J60Network::blockSize(data->packet_next)); 334 | #ifdef UIPETHERNET_DEBUG_UDP 335 | Serial.print(F("udp, uip_newdata received packet: ")); 336 | Serial.print(data->packet_next); 337 | Serial.print(F(", size: ")); 338 | Serial.println(Enc28J60Network::blockSize(data->packet_next)); 339 | #endif 340 | } 341 | } 342 | } 343 | if (uip_poll() && data->send) 344 | { 345 | //set uip_slen (uip private) by calling uip_udp_send 346 | #ifdef UIPETHERNET_DEBUG_UDP 347 | Serial.print(F("udp, uip_poll preparing packet to send: ")); 348 | Serial.print(data->packet_out); 349 | Serial.print(F(", size: ")); 350 | Serial.println(Enc28J60Network::blockSize(data->packet_out)); 351 | #endif 352 | UIPEthernetClass::uip_packet = data->packet_out; 353 | UIPEthernetClass::packetstate |= UIPETHERNET_SENDPACKET; 354 | UIPEthernetClass::uip_hdrlen = UIP_UDP_PHYH_LEN; 355 | uip_udp_send(data->out_pos - (UIP_UDP_PHYH_LEN + UIP_SENDBUFFER_OFFSET)); 356 | } 357 | } 358 | } 359 | 360 | void 361 | UIPUDP::_send(uip_udp_userdata_t *data) { 362 | uip_arp_out(); //add arp 363 | if (uip_len == UIP_ARPHDRSIZE) 364 | { 365 | UIPEthernetClass::uip_packet = NOBLOCK; 366 | UIPEthernetClass::packetstate &= ~UIPETHERNET_SENDPACKET; 367 | #ifdef UIPETHERNET_DEBUG_UDP 368 | Serial.println(F("udp, uip_poll results in ARP-packet")); 369 | #endif 370 | UIPEthernetClass::network_send(); 371 | } 372 | else 373 | //arp found ethaddr for ip (otherwise packet is replaced by arp-request) 374 | { 375 | #ifdef UIPETHERNET_DEBUG_UDP 376 | Serial.print(F("udp, uip_packet to send: ")); 377 | Serial.println(UIPEthernetClass::uip_packet); 378 | #endif 379 | if (UIPEthernetClass::network_send()) 380 | { 381 | data->send = false; 382 | data->packet_out = NOBLOCK; 383 | } 384 | } 385 | } 386 | #endif 387 | -------------------------------------------------------------------------------- /UIPUdp.h: -------------------------------------------------------------------------------- 1 | /* 2 | UIPUdp.h - Arduino implementation of a uIP wrapper class. 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #ifndef UIPUDP_H 21 | #define UIPUDP_H 22 | 23 | #include "ethernet_comp.h" 24 | #include "Arduino.h" 25 | #include 26 | #include "utility/mempool.h" 27 | extern "C" { 28 | #include "utility/uip.h" 29 | } 30 | 31 | #define UIP_UDP_MAXDATALEN 1500 32 | #define UIP_UDP_PHYH_LEN UIP_LLH_LEN+UIP_IPUDPH_LEN 33 | #define UIP_UDP_MAXPACKETSIZE UIP_UDP_MAXDATALEN+UIP_UDP_PHYH_LEN 34 | 35 | typedef struct { 36 | memaddress out_pos; 37 | memhandle packet_next; 38 | memhandle packet_in; 39 | memhandle packet_out; 40 | boolean send; 41 | } uip_udp_userdata_t; 42 | 43 | class UIPUDP : public UDP 44 | { 45 | 46 | private: 47 | struct uip_udp_conn *_uip_udp_conn; 48 | 49 | uip_udp_userdata_t appdata; 50 | 51 | public: 52 | UIPUDP(); // Constructor 53 | uint8_t 54 | begin(uint16_t);// initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use 55 | void 56 | stop(); // Finish with the UDP socket 57 | 58 | // Sending UDP packets 59 | 60 | // Start building up a packet to send to the remote host specific in ip and port 61 | // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port 62 | int 63 | beginPacket(IPAddress ip, uint16_t port); 64 | // Start building up a packet to send to the remote host specific in host and port 65 | // Returns 1 if successful, 0 if there was a problem resolving the hostname or port 66 | int 67 | beginPacket(const char *host, uint16_t port); 68 | // Finish off this packet and send it 69 | // Returns 1 if the packet was sent successfully, 0 if there was an error 70 | int 71 | endPacket(); 72 | // Write a single byte into the packet 73 | size_t 74 | write(uint8_t); 75 | // Write size bytes from buffer into the packet 76 | size_t 77 | write(const uint8_t *buffer, size_t size); 78 | 79 | using Print::write; 80 | 81 | // Start processing the next available incoming packet 82 | // Returns the size of the packet in bytes, or 0 if no packets are available 83 | int 84 | parsePacket(); 85 | // Number of bytes remaining in the current packet 86 | int 87 | available(); 88 | // Read a single byte from the current packet 89 | int 90 | read(); 91 | // Read up to len bytes from the current packet and place them into buffer 92 | // Returns the number of bytes read, or 0 if none are available 93 | int 94 | read(unsigned char* buffer, size_t len); 95 | // Read up to len characters from the current packet and place them into buffer 96 | // Returns the number of characters read, or 0 if none are available 97 | int 98 | read(char* buffer, size_t len) 99 | { 100 | return read((unsigned char*) buffer, len); 101 | } 102 | ; 103 | // Return the next byte from the current packet without moving on to the next byte 104 | int 105 | peek(); 106 | void 107 | flush(); // Finish reading the current packet 108 | 109 | // Return the IP address of the host who sent the current incoming packet 110 | IPAddress 111 | remoteIP(); 112 | 113 | // Return the port of the host who sent the current incoming packet 114 | uint16_t 115 | remotePort(); 116 | 117 | private: 118 | 119 | friend void uipudp_appcall(void); 120 | 121 | friend class UIPEthernetClass; 122 | static void _send(uip_udp_userdata_t *data); 123 | 124 | }; 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /ethernet_comp.h: -------------------------------------------------------------------------------- 1 | #ifndef ETHERNET_COMP_H 2 | #define ETHERNET_COMP_H 3 | 4 | #define Ethernet UIPEthernet 5 | #define EthernetClient UIPClient 6 | #define EthernetServer UIPServer 7 | #define EthernetUDP UIPUDP 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /examples/AdvancedChatServer/AdvancedChatServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Advanced Chat Server 3 | 4 | A simple server that distributes any incoming messages to all 5 | connected clients but the client the message comes from. 6 | To use telnet to your device's IP address and type. 7 | You can see the client's input in the serial monitor as well. 8 | Using an Arduino Wiznet Ethernet shield. 9 | 10 | Circuit: 11 | * Ethernet shield attached to pins 10, 11, 12, 13 12 | * Analog inputs attached to pins A0 through A5 (optional) 13 | 14 | created 18 Dec 2009 15 | by David A. Mellis 16 | modified 9 Apr 2012 17 | by Tom Igoe 18 | redesigned to make use of operator== 25 Nov 2013 19 | by Norbert Truchsess 20 | 21 | */ 22 | 23 | #include 24 | 25 | // Enter a MAC address and IP address for your controller below. 26 | // The IP address will be dependent on your local network. 27 | 28 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 29 | IPAddress ip(192,168,0,6); 30 | 31 | // telnet defaults to port 23 32 | EthernetServer server(23); 33 | 34 | EthernetClient clients[4]; 35 | 36 | void setup() { 37 | // initialize the ethernet device 38 | Ethernet.begin(mac, ip); 39 | // start listening for clients 40 | server.begin(); 41 | // Open serial communications and wait for port to open: 42 | Serial.begin(9600); 43 | while (!Serial) { 44 | ; // wait for serial port to connect. Needed for Leonardo only 45 | } 46 | 47 | 48 | Serial.print("Chat server address:"); 49 | Serial.println(Ethernet.localIP()); 50 | } 51 | 52 | void loop() { 53 | // wait for a new client: 54 | EthernetClient client = server.available(); 55 | 56 | if (client) { 57 | 58 | boolean newClient = true; 59 | for (byte i=0;i<4;i++) { 60 | //check whether this client refers to the same socket as one of the existing instances: 61 | if (clients[i]==client) { 62 | newClient = false; 63 | break; 64 | } 65 | } 66 | 67 | if (newClient) { 68 | //check which of the existing clients can be overridden: 69 | for (byte i=0;i<4;i++) { 70 | if (!clients[i] && clients[i]!=client) { 71 | clients[i] = client; 72 | // clead out the input buffer: 73 | client.flush(); 74 | // clead out the input buffer: 75 | client.flush(); 76 | Serial.println("We have a new client"); 77 | client.println("Hello, client!"); 78 | client.print("my IP: "); 79 | client.println(Ethernet.localIP()); 80 | break; 81 | } 82 | } 83 | } 84 | 85 | if (client.available() > 0) { 86 | // read the bytes incoming from the client: 87 | char thisChar = client.read(); 88 | // echo the bytes back to all other connected clients: 89 | for (byte i=0;i<4;i++) { 90 | if (clients[i] && clients[i]!=client) { 91 | clients[i].write(thisChar); 92 | } 93 | } 94 | // echo the bytes to the server as well: 95 | Serial.write(thisChar); 96 | } 97 | } 98 | for (byte i=0;i<4;i++) { 99 | if (!(clients[i].connected())) { 100 | // client.stop() invalidates the internal socket-descriptor, so next use of == will allways return false; 101 | clients[i].stop(); 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /examples/EchoServer/EchoServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet EchoServer example. 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This Hello World example sets up a server at 192.168.1.6 on port 1000. 12 | * Telnet here to access the service. The uIP stack will also respond to 13 | * pings to test if you have successfully established a TCP connection to 14 | * the Arduino. 15 | * 16 | * This example was based upon uIP hello-world by Adam Dunkels 17 | * Ported to the Arduino IDE by Adam Nielsen 18 | * Adaption to Enc28J60 by Norbert Truchsess 19 | */ 20 | 21 | #include 22 | // The connection_data struct needs to be defined in an external file. 23 | #include 24 | #include 25 | 26 | EthernetServer server = EthernetServer(1000); 27 | 28 | void setup() 29 | { 30 | Serial.begin(9600); 31 | 32 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 33 | IPAddress myIP(192,168,0,6); 34 | 35 | Ethernet.begin(mac,myIP); 36 | 37 | server.begin(); 38 | } 39 | 40 | void loop() 41 | { 42 | size_t size; 43 | 44 | if (EthernetClient client = server.available()) 45 | { 46 | if (client) 47 | { 48 | while((size = client.available()) > 0) 49 | { 50 | uint8_t* msg = (uint8_t*)malloc(size); 51 | size = client.read(msg,size); 52 | Serial.write(msg,size); 53 | client.write(msg,size); 54 | free(msg); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/HttpClient/HttpClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet HttpClient example by TMRh20 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This HttpClient example gets its local ip-address via dhcp and sets 12 | * up a tcp socket-connection to google.com port 80 every 5 Seconds. 13 | * After sending a message it waits for a response. After receiving the 14 | * response the client disconnects and tries to reconnect after 5 seconds. 15 | * 16 | * Copyright (C) 2013 by Norbert Truchsess 17 | */ 18 | 19 | #include 20 | 21 | EthernetClient client; 22 | signed long next; 23 | 24 | void setup() { 25 | 26 | Serial.begin(9600); 27 | 28 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 29 | Ethernet.begin(mac); 30 | 31 | Serial.print("localIP: "); 32 | Serial.println(Ethernet.localIP()); 33 | Serial.print("subnetMask: "); 34 | Serial.println(Ethernet.subnetMask()); 35 | Serial.print("gatewayIP: "); 36 | Serial.println(Ethernet.gatewayIP()); 37 | Serial.print("dnsServerIP: "); 38 | Serial.println(Ethernet.dnsServerIP()); 39 | 40 | next = 0; 41 | } 42 | uint32_t counter = 0; 43 | 44 | void loop() { 45 | 46 | Ethernet.update(); 47 | 48 | if (((signed long)(millis() - next)) > 0) 49 | { 50 | next = millis() + 5000; 51 | Serial.println("Client connect"); 52 | // replace hostname with name of machine running tcpserver.pl 53 | // if (client.connect("server.local",5000)) 54 | if (client.connect("www.google.com", 80)) 55 | // if (client.connect("www.fiikus.net", 80)) 56 | { 57 | Serial.println("Client connected"); 58 | client.write("GET / HTTP/1.1\n"); 59 | // client.write("GET /asciiart/pizza.txt HTTP/1.1\n"); 60 | client.write("Host: www.google.ca\n"); 61 | // client.write("Host: fiikus.net\n"); 62 | client.write("Connection: close\n"); 63 | client.println(); 64 | 65 | while((client.waitAvailable(2000)) > 0) 66 | { 67 | Serial.write(client.read()); 68 | if(counter > 100){ Serial.println(" "); counter=0;} 69 | counter++; 70 | } 71 | close: 72 | //disconnect client 73 | Serial.println("Client disconnect"); 74 | client.stop(); 75 | } 76 | else 77 | Serial.println("Client connect failed"); 78 | } 79 | } -------------------------------------------------------------------------------- /examples/HttpClientTest/HttpClientTest.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet HttpClientTest example by TMRh20 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This example will test for hardware failures or errors in data transmissions. This example should be 12 | * accompanied by a text file named nums2.txt, which contains about 100,000 characters (bytes) of data. The nums2.txt 13 | * file is to be placed onto a webserver, accessible by this device. 14 | * 15 | * With the IP addresses configured appropriately, the following sketch will continuously download the file, 16 | * pausing for 5 seconds to display the number of cycles and any errors detected. 17 | */ 18 | 19 | #include 20 | 21 | EthernetClient client; 22 | signed long next; 23 | 24 | void setup() { 25 | 26 | Serial.begin(115200); 27 | 28 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 29 | Ethernet.begin(mac); 30 | 31 | Serial.print(F("localIP: ")); 32 | Serial.println(Ethernet.localIP()); 33 | Serial.print(F("subnetMask: ")); 34 | Serial.println(Ethernet.subnetMask()); 35 | Serial.print(F("gatewayIP: ")); 36 | Serial.println(Ethernet.gatewayIP()); 37 | Serial.print(F("dnsServerIP: ")); 38 | Serial.println(Ethernet.dnsServerIP()); 39 | 40 | next = 0; 41 | } 42 | uint32_t charCounter = 0; 43 | uint8_t countAlong = 0; 44 | uint32_t failCount = 0; 45 | 46 | uint32_t totalRcvd = 0; 47 | uint32_t errorCount = 0; 48 | uint32_t cycleCount = 0; 49 | uint32_t failedCycles = 0; 50 | 51 | 52 | void loop() { 53 | 54 | Ethernet.update(); 55 | 56 | if (((signed long)(millis() - next)) > 0) { 57 | Serial.println(F("Client connect")); 58 | 59 | //Use the IP or hostname of the web server hosting the nums2.txt file 60 | IPAddress loc(10,10,1,59); 61 | if (client.connect("Pie-is-Round", 80)) { 62 | Serial.println(F("Client connected")); 63 | client.write("GET /nums2.txt HTTP/1.1\n"); 64 | client.write("Host: www.some-host\n"); 65 | client.write("Connection: close\n"); 66 | client.println(); 67 | 68 | if(client.waitAvailable(2000)>0){ 69 | client.findUntil("0909",""); 70 | countAlong=1; 71 | } 72 | 73 | while((client.waitAvailable(3500)) > 0) { 74 | char c = client.read(); 75 | if(c != (countAlong + 48) && totalRcvd < 100000){ 76 | Serial.println(); Serial.println(F("********F WARN ****")); 77 | Serial.print(F("C ")); Serial.println(c); 78 | Serial.print(F("CA ")); Serial.println(countAlong); 79 | ++errorCount; 80 | }else{ 81 | Serial.print(c); 82 | } 83 | ++countAlong; 84 | if(countAlong > 9){countAlong = 0;} 85 | if(charCounter >= 100){ Serial.println(); charCounter=0;} 86 | ++charCounter; 87 | ++totalRcvd; 88 | } 89 | if(totalRcvd != 100001){ failedCycles++; }else{cycleCount++;} 90 | Serial.println(); 91 | Serial.println(F("****** Total RCV ********")); 92 | Serial.println(totalRcvd); 93 | Serial.print(F(" Errors ")); Serial.println(errorCount); 94 | Serial.print(F(" Cycles OK ")); Serial.println(cycleCount); 95 | Serial.print(F(" Cycles Failed ")); Serial.println(failedCycles); 96 | 97 | close: 98 | //disconnect client 99 | Serial.println(F("Client disconnect")); 100 | client.stop(); 101 | 102 | }else{ // !client.connect() 103 | Serial.println(F("Client connect failed")); 104 | 105 | } 106 | totalRcvd=0; 107 | charCounter=0; 108 | next = millis() + 5000; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /examples/HttpClientTest/WebServerFile/Readme.txt: -------------------------------------------------------------------------------- 1 | Place this file in the root directory of a web server for testing -------------------------------------------------------------------------------- /examples/InteractiveServer/HTML.h: -------------------------------------------------------------------------------- 1 | 2 | bool led_state = 0; 3 | 4 | /** 5 | * This page stores the actual HTML code that will be presented. 6 | * The data is stored in program memory as a single long string, and is presented 7 | * below in a manageable format 8 | */ 9 | 10 | /***************************************************************/ 11 | 12 | // The basic beginning of an HTML connection, plus 13 | // a style (CSS) section and header to be used on every page 14 | static const char begin_html[] PROGMEM = 15 | "HTTP/1.1 200 OK\n" 16 | "Content-Type: text/html\n" //40b 17 | "Connection: close\n\n" //59 18 | "\n" //75 19 | ""//87 20 | "" 24 | ""; 25 | 26 | /***************************************************************/ 27 | 28 | // The main HTML page, broken into 2 parts 29 | // It is broken up so some variables can be printed manually in the middle 30 | static const char main_html_p1[] PROGMEM = 31 | 32 | "" 33 | "" 35 | "
Hello From Arduino!
\n" 36 | "

LED/Digital Pin Control:" 37 | "

\n"; 38 | 39 | /***************************************************************/ 40 | 41 | static const char main_html_p2[] PROGMEM = 42 | 43 | "
Turn LED On" 44 | 45 | "
Turn LED Off" 46 | 47 | "

" 48 | 49 | "Stats Credits" 50 | 51 | ""; 52 | 53 | /***************************************************************/ 54 | 55 | // The HTML for the credits page 56 | static const char credits_html[] PROGMEM = 57 | "" 58 | "" 60 | "
Credits:
" 61 | "" 62 | "" 63 | "" 64 | "" 65 | "" 66 | "" 67 | "" 68 | "" 69 | "
UIPEthernet by Norbert Truchsess
uIP by Adam Dunkels
Web Server Example by: TMRh20
" 70 | "
Thanks to everybody that contributes to Open Source Projects" 71 | "

Home" 72 | "" 73 | ""; 74 | 75 | /***************************************************************/ 76 | 77 | /** 78 | * This function reads from a specified program memory buffer, and sends the data to the client 79 | * in chunks equal to the max output buffer size 80 | * This allows the HTML code to be modified as desired, with no need to change any other code 81 | */ 82 | void sendPage(EthernetClient& _client, const char* _pointer, size_t size ){ 83 | 84 | size_t bufSize = UIP_BUFSIZE; 85 | 86 | char buffer[bufSize+1]; // 91 bytes by default 87 | 88 | // Create a pointer for iterating through the array 89 | const char *i; 90 | 91 | // Increment the iterator (i) in increments of 45-3 (OUTPUT_BUFFER_SIZE-3) and send the data to the client 92 | for(i=_pointer; i<_pointer+(size-(bufSize));i+=bufSize){ 93 | snprintf_P(buffer,bufSize+1,i); 94 | _client.write( buffer, bufSize ); 95 | } 96 | // For the last bit, send only the data that remains 97 | snprintf_P(buffer,((_pointer+size)-i)+1,i); 98 | _client.write( buffer,((_pointer+size)-i) ); 99 | } 100 | 101 | /***************************************************************/ 102 | 103 | // Function to send the main page 104 | void main_page(EthernetClient& _client) { 105 | 106 | // Send the connection info and header 107 | const char* html_pointer = begin_html; 108 | sendPage(_client,html_pointer,sizeof(begin_html)); 109 | 110 | //Send the first part of the page 111 | html_pointer = main_html_p1; 112 | sendPage(_client,html_pointer,sizeof(main_html_p1)); 113 | 114 | // Include some variables, print them into the page manually 115 | const char *lState = led_state ? "ON" : "OFF"; 116 | const char *lColor = led_state ? "darkseagreen 1" : "lightpink"; 117 | 118 | char bf[UIP_CONF_BUFFER_SIZE]; 119 | 120 | if(!led_state){ 121 | sprintf_P(bf,PSTR("\n"),lColor); 122 | _client.write(bf); 123 | sprintf_P(bf,PSTR("LED is %s\n"), lState); 124 | }else{ 125 | sprintf_P(bf,PSTR(" \n"),lColor); 126 | _client.write(bf); 127 | sprintf_P(bf,PSTR("LED is %s\n"), lState); 128 | } 129 | _client.write(bf); 130 | 131 | // Send the 2nd half of the page 132 | static const char* html_pointer2 = main_html_p2; 133 | sendPage(_client,html_pointer2,sizeof(main_html_p2)); 134 | 135 | } 136 | 137 | /***************************************************************/ 138 | 139 | void credits_page(EthernetClient& _client) { 140 | //Set the pointer to the HTML connection data + header 141 | const char* html_pointer = begin_html; 142 | sendPage(_client,html_pointer,sizeof(begin_html)); 143 | 144 | //Set the pointer to the HTML page data and send it 145 | html_pointer = credits_html; 146 | sendPage(_client,html_pointer,sizeof(credits_html)); 147 | } 148 | 149 | /***************************************************************/ 150 | 151 | // The stats page is sent differently, just to demonstrate a different method of handling pages 152 | void stats_page(EthernetClient& _client) { 153 | 154 | uint32_t seconds = millis() / 1000UL; 155 | uint32_t minutes = seconds / 60UL; 156 | uint32_t hours = minutes / 60UL; 157 | uint8_t days = hours / 24UL; 158 | seconds %= 60; 159 | minutes %= 60; 160 | hours %= 24; 161 | 162 | char buffer[UIP_CONF_BUFFER_SIZE]; 163 | 164 | 165 | sprintf_P(buffer, PSTR("HTTP/1.1 200 OK\nContent-Type: text/html\n")); 166 | _client.write(buffer); 167 | sprintf_P(buffer, PSTR("Connection: close\n\n\n\n")); 168 | _client.write(buffer); 169 | sprintf_P(buffer, PSTR("\n")); 172 | _client.write(buffer); 173 | sprintf_P(buffer, PSTR("
Uptime\n")); 174 | _client.write(buffer); 175 | sprintf_P(buffer, PSTR("%u days, %lu hours %lu minutes %lu"),days,hours,minutes,seconds); 176 | _client.write(buffer); 177 | sprintf_P(buffer, PSTR("seconds
UIP Buffer Size")); 178 | _client.write(buffer); 179 | sprintf_P(buffer, PSTR("%d bytes
User "),UIP_BUFSIZE); 180 | _client.write(buffer); 181 | sprintf_P(buffer, PSTR("Output
Buffer Size
%d bytes"),UIP_CONF_BUFFER_SIZE); 182 | _client.write(buffer); 183 | sprintf_P(buffer, PSTR("


")); 184 | _client.write(buffer); 185 | sprintf_P(buffer, PSTR("Home\n\n")); 186 | _client.write(buffer); 187 | 188 | } 189 | 190 | /***************************************************************/ 191 | 192 | /** 193 | * An example of a very basic HTML page 194 | */ 195 | static const char html_page[] PROGMEM = 196 | "HTTP/1.1 200 OK\n" 197 | "Content-Type: text/html\n" 198 | "Connection: close\n\n" 199 | "" 200 | "" 201 | "" 202 | "Hello From Arduino!" 203 | "" 204 | ""; 205 | 206 | -------------------------------------------------------------------------------- /examples/InteractiveServer/InteractiveServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet InteractiveServer example by TMRh20 3 | * - Webserver controlling an LED example 4 | * - Based on similar example for RF24Ethernet TCP/IP Radio Networking library 5 | * 6 | * UIPEthernet uses the uIP stack by Adam Dunkels 7 | * 8 | * This example demonstrates how to configure a sensor node to act as a webserver and 9 | * allows a user to control a connected LED by clicking links on the webpage 10 | * The requested URL is used as input, to determine whether to turn the LED off or on 11 | * 12 | */ 13 | 14 | 15 | #include 16 | #include "HTML.h" 17 | 18 | // Configure the server to listen on port 80 19 | EthernetServer server = EthernetServer(80); 20 | 21 | /**********************************************************/ 22 | #define LED_PIN A3 //Analog pin A3 23 | 24 | void setup() { 25 | 26 | pinMode(LED_PIN, OUTPUT); 27 | 28 | Serial.begin(115200); 29 | Serial.println("start"); 30 | 31 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 32 | Ethernet.begin(mac); 33 | 34 | server.begin(); 35 | } 36 | 37 | 38 | /********************************************************/ 39 | 40 | void loop() { 41 | 42 | size_t size; 43 | 44 | if (EthernetClient client = server.available()) 45 | { 46 | uint8_t pageReq = 0; 47 | generate_tcp_stats(); 48 | while ((size = client.waitAvailable()) > 0) 49 | { 50 | // If a request is received with enough characters, search for the / character 51 | if (size >= 7) { 52 | client.findUntil("/", "/"); 53 | char buf[3] = {" "}; 54 | buf[0] = client.read(); // Read in the first two characters from the request 55 | buf[1] = client.read(); 56 | 57 | if (strcmp(buf, "ON") == 0) { // If the user requested http://ip-of-node:1000/ON 58 | led_state = 1; 59 | pageReq = 1; 60 | digitalWrite(LED_PIN, led_state); 61 | 62 | }else if (strcmp(buf, "OF") == 0) { // If the user requested http://ip-of-node:1000/OF 63 | led_state = 0; 64 | pageReq = 1; 65 | digitalWrite(LED_PIN, led_state); 66 | 67 | }else if (strcmp(buf, "ST") == 0) { // If the user requested http://ip-of-node:1000/OF 68 | pageReq = 2; 69 | 70 | }else if (strcmp(buf, "CR") == 0) { // If the user requested http://ip-of-node:1000/OF 71 | pageReq = 3; 72 | 73 | }else if(buf[0] == ' '){ 74 | pageReq = 4; 75 | } 76 | } 77 | // Empty the rest of the data from the client 78 | while (client.waitAvailable(100)) { 79 | Serial.print((char)client.read()); 80 | } 81 | } 82 | 83 | /** 84 | * Based on the incoming URL request, send the correct page to the client 85 | * see HTML.h 86 | */ 87 | switch(pageReq){ 88 | case 2: stats_page(client); break; 89 | case 3: credits_page(client); break; 90 | case 4: main_page(client); break; 91 | case 1: main_page(client); break; 92 | default: break; 93 | } 94 | 95 | client.stop(); 96 | Serial.println(F("********")); 97 | 98 | } 99 | 100 | // We can do other things in the loop, but be aware that the loop will 101 | // briefly pause while IP data is being processed. 102 | } 103 | 104 | /** 105 | * This section displays some basic connection stats via Serial and demonstrates 106 | * how to interact directly with the uIP TCP/IP stack 107 | * See the uIP documentation for more info 108 | */ 109 | static unsigned short generate_tcp_stats() 110 | { 111 | struct uip_conn *conn; 112 | 113 | // If multiple connections are enabled, get info for each active connection 114 | for (uint8_t i = 0; i < UIP_CONF_MAX_CONNECTIONS; i++) { 115 | conn = &uip_conns[i]; 116 | 117 | // If there is an open connection to one of the listening ports, print the info 118 | // This logic seems to be backwards? 119 | if (uip_stopped(conn)) { 120 | Serial.print(F("Connection no ")); 121 | Serial.println(i); 122 | Serial.print(F("Local Port ")); 123 | Serial.println(htons(conn->lport)); 124 | Serial.print(F("Remote IP/Port ")); 125 | Serial.print(htons(conn->ripaddr[0]) >> 8); 126 | Serial.print(F(".")); 127 | Serial.print(htons(conn->ripaddr[0]) & 0xff); 128 | Serial.print(F(".")); 129 | Serial.print(htons(conn->ripaddr[1]) >> 8); 130 | Serial.print(F(".")); 131 | Serial.print(htons(conn->ripaddr[1]) & 0xff); 132 | Serial.print(F(":")); 133 | Serial.println(htons(conn->rport)); 134 | Serial.print(F("Outstanding ")); 135 | Serial.println((uip_outstanding(conn)) ? '*' : ' '); 136 | 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /examples/TcpClient/TcpClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet TcpClient example. 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This TcpClient example gets its local ip-address via dhcp and sets 12 | * up a tcp socket-connection to 192.168.0.1 port 5000 every 5 Seconds. 13 | * After sending a message it waits for a response. After receiving the 14 | * response the client disconnects and tries to reconnect after 5 seconds. 15 | * 16 | * Copyright (C) 2013 by Norbert Truchsess 17 | */ 18 | 19 | #include 20 | 21 | EthernetClient client; 22 | signed long next; 23 | 24 | void setup() { 25 | 26 | Serial.begin(9600); 27 | 28 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 29 | Ethernet.begin(mac); 30 | 31 | Serial.print("localIP: "); 32 | Serial.println(Ethernet.localIP()); 33 | Serial.print("subnetMask: "); 34 | Serial.println(Ethernet.subnetMask()); 35 | Serial.print("gatewayIP: "); 36 | Serial.println(Ethernet.gatewayIP()); 37 | Serial.print("dnsServerIP: "); 38 | Serial.println(Ethernet.dnsServerIP()); 39 | 40 | next = 0; 41 | } 42 | 43 | void loop() { 44 | 45 | if (((signed long)(millis() - next)) > 0) 46 | { 47 | next = millis() + 5000; 48 | Serial.println("Client connect"); 49 | // replace hostname with name of machine running tcpserver.pl 50 | // if (client.connect("server.local",5000)) 51 | if (client.connect(IPAddress(192,168,0,1),5000)) 52 | { 53 | Serial.println("Client connected"); 54 | client.println("DATA from Client"); 55 | while(client.available()==0) 56 | { 57 | if (next - millis() < 0) 58 | goto close; 59 | } 60 | int size; 61 | while((size = client.available()) > 0) 62 | { 63 | uint8_t* msg = (uint8_t*)malloc(size); 64 | size = client.read(msg,size); 65 | Serial.write(msg,size); 66 | free(msg); 67 | } 68 | close: 69 | //disconnect client 70 | Serial.println("Client disconnect"); 71 | client.stop(); 72 | } 73 | else 74 | Serial.println("Client connect failed"); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /examples/TcpServer/TcpServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet EchoServer example. 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This Hello World example sets up a server at 192.168.1.6 on port 1000. 12 | * Telnet here to access the service. The uIP stack will also respond to 13 | * pings to test if you have successfully established a TCP connection to 14 | * the Arduino. 15 | * 16 | * This example was based upon uIP hello-world by Adam Dunkels 17 | * Ported to the Arduino IDE by Adam Nielsen 18 | * Adaption to Enc28J60 by Norbert Truchsess 19 | */ 20 | 21 | #include 22 | 23 | EthernetServer server = EthernetServer(1000); 24 | 25 | void setup() 26 | { 27 | Serial.begin(9600); 28 | 29 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 30 | IPAddress myIP(192,168,0,6); 31 | 32 | Ethernet.begin(mac,myIP); 33 | 34 | server.begin(); 35 | } 36 | 37 | void loop() 38 | { 39 | size_t size; 40 | 41 | if (EthernetClient client = server.available()) 42 | { 43 | while((size = client.available()) > 0) 44 | { 45 | uint8_t* msg = (uint8_t*)malloc(size); 46 | size = client.read(msg,size); 47 | Serial.write(msg,size); 48 | free(msg); 49 | } 50 | client.println("DATA from Server!"); 51 | client.stop(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /examples/UdpClient/UdpClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet UdpClient example. 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This UdpClient example tries to send a packet via udp to 192.168.0.1 12 | * on port 5000 every 5 seconds. After successfully sending the packet it 13 | * waits for up to 5 seconds for a response on the local port that has been 14 | * implicitly opened when sending the packet. 15 | * 16 | * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) 17 | */ 18 | 19 | #include 20 | 21 | EthernetUDP udp; 22 | unsigned long next; 23 | 24 | void setup() { 25 | 26 | Serial.begin(9600); 27 | 28 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 29 | 30 | Ethernet.begin(mac,IPAddress(192,168,0,6)); 31 | 32 | next = millis()+5000; 33 | } 34 | 35 | void loop() { 36 | 37 | int success; 38 | int len = 0; 39 | 40 | if (((signed long)(millis()-next))>0) 41 | { 42 | do 43 | { 44 | success = udp.beginPacket(IPAddress(192,168,0,1),5000); 45 | Serial.print("beginPacket: "); 46 | Serial.println(success ? "success" : "failed"); 47 | //beginPacket fails if remote ethaddr is unknown. In this case an 48 | //arp-request is send out first and beginPacket succeeds as soon 49 | //the arp-response is received. 50 | } 51 | while (!success && ((signed long)(millis()-next))<0); 52 | if (!success ) 53 | goto stop; 54 | 55 | success = udp.write("hello world from arduino"); 56 | 57 | Serial.print("bytes written: "); 58 | Serial.println(success); 59 | 60 | success = udp.endPacket(); 61 | 62 | Serial.print("endPacket: "); 63 | Serial.println(success ? "success" : "failed"); 64 | 65 | do 66 | { 67 | //check for new udp-packet: 68 | success = udp.parsePacket(); 69 | } 70 | while (!success && ((signed long)(millis()-next))<0); 71 | if (!success ) 72 | goto stop; 73 | 74 | Serial.print("received: '"); 75 | do 76 | { 77 | int c = udp.read(); 78 | Serial.write(c); 79 | len++; 80 | } 81 | while ((success = udp.available())>0); 82 | Serial.print("', "); 83 | Serial.print(len); 84 | Serial.println(" bytes"); 85 | 86 | //finish reading this packet: 87 | udp.flush(); 88 | 89 | stop: 90 | udp.stop(); 91 | next = millis()+5000; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /examples/UdpServer/UdpServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UIPEthernet UdpServer example. 3 | * 4 | * UIPEthernet is a TCP/IP stack that can be used with a enc28j60 based 5 | * Ethernet-shield. 6 | * 7 | * UIPEthernet uses the fine uIP stack by Adam Dunkels 8 | * 9 | * ----------------- 10 | * 11 | * This UdpServer example sets up a udp-server at 192.168.0.6 on port 5000. 12 | * send packet via upd to test 13 | * 14 | * Copyright (C) 2013 by Norbert Truchsess (norbert.truchsess@t-online.de) 15 | */ 16 | 17 | #include 18 | 19 | EthernetUDP udp; 20 | 21 | void setup() { 22 | 23 | Serial.begin(9600); 24 | 25 | uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; 26 | 27 | Ethernet.begin(mac,IPAddress(192,168,0,6)); 28 | 29 | int success = udp.begin(5000); 30 | 31 | Serial.print("initialize: "); 32 | Serial.println(success ? "success" : "failed"); 33 | 34 | } 35 | 36 | void loop() { 37 | 38 | //check for new udp-packet: 39 | int size = udp.parsePacket(); 40 | if (size > 0) { 41 | do 42 | { 43 | char* msg = (char*)malloc(size+1); 44 | int len = udp.read(msg,size+1); 45 | msg[len]=0; 46 | Serial.print("received: '"); 47 | Serial.print(msg); 48 | free(msg); 49 | } 50 | while ((size = udp.available())>0); 51 | //finish reading this packet: 52 | udp.flush(); 53 | Serial.println("'"); 54 | int success; 55 | do 56 | { 57 | Serial.print("remote ip: "); 58 | Serial.println(udp.remoteIP()); 59 | Serial.print("remote port: "); 60 | Serial.println(udp.remotePort()); 61 | //send new packet back to ip/port of client. This also 62 | //configures the current connection to ignore packets from 63 | //other clients! 64 | success = udp.beginPacket(udp.remoteIP(),udp.remotePort()); 65 | Serial.print("beginPacket: "); 66 | Serial.println(success ? "success" : "failed"); 67 | //beginPacket fails if remote ethaddr is unknown. In this case an 68 | //arp-request is send out first and beginPacket succeeds as soon 69 | //the arp-response is received. 70 | } 71 | while (!success); 72 | 73 | success = udp.println("hello world from arduino"); 74 | 75 | Serial.print("bytes written: "); 76 | Serial.println(success); 77 | 78 | success = udp.endPacket(); 79 | 80 | Serial.print("endPacket: "); 81 | Serial.println(success ? "success" : "failed"); 82 | 83 | udp.stop(); 84 | //restart with new connection to receive packets from other clients 85 | Serial.print("restart connection: "); 86 | Serial.println (udp.begin(5000) ? "success" : "failed"); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for SerialIP 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | UIPEthernet KEYWORD1 10 | UIPServer KEYWORD1 11 | UIPClient KEYWORD1 12 | 13 | ####################################### 14 | # Methods and Functions (KEYWORD2) 15 | ####################################### 16 | PSOCK_BEGIN KEYWORD2 17 | PSOCK_CLOSE KEYWORD2 18 | PSOCK_END KEYWORD2 19 | PSOCK_EXIT KEYWORD2 20 | PSOCK_INIT KEYWORD2 21 | PSOCK_READBUF KEYWORD2 22 | PSOCK_READTO KEYWORD2 23 | PSOCK_SEND KEYWORD2 24 | PSOCK_SEND_STR KEYWORD2 25 | 26 | uip_listen KEYWORD2 27 | uip_unlisten KEYWORD2 28 | uip_connect KEYWORD2 29 | uip_outstanding KEYWORD2 30 | uip_send KEYWORD2 31 | uip_datalen KEYWORD2 32 | uip_close KEYWORD2 33 | uip_abort KEYWORD2 34 | uip_stop KEYWORD2 35 | uip_stopped KEYWORD2 36 | uip_restart KEYWORD2 37 | uip_acked KEYWORD2 38 | uip_connected KEYWORD2 39 | uip_closed KEYWORD2 40 | uip_aborted KEYWORD2 41 | uip_timedout KEYWORD2 42 | uip_rexmit KEYWORD2 43 | uip_poll KEYWORD2 44 | uip_initialmss KEYWORD2 45 | uip_mss KEYWORD2 46 | uip_ipaddr KEYWORD2 47 | uip_ipaddr_maskcmp KEYWORD2 48 | uip_ipaddr_mask KEYWORD2 49 | HTONS KEYWORD2 50 | htons KEYWORD2 51 | 52 | use_device KEYWORD2 53 | set_uip_callback KEYWORD2 54 | set_gateway KEYWORD2 55 | 56 | ####################################### 57 | # Constants (LITERAL1) 58 | ####################################### 59 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=UIPEthernet 2 | author=ntruchsess 3 | email=Norbert Truchsess 4 | sentence=Ethernet library for ENC28J60 5 | paragraph=implements the same API as stock Ethernet-lib. Just replace the include of Ethernet.h with UIPEthernet.h 6 | url=https://github.com/ntruchsess/arduino_uip 7 | architectures=avr 8 | version=1.04 9 | dependencies= 10 | core-dependencies=arduino (>=1.5.0) 11 | -------------------------------------------------------------------------------- /tests/perl/tcpclient.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #tcpclient.pl 3 | 4 | use IO::Socket::INET; 5 | 6 | # flush after every write 7 | $| = 1; 8 | 9 | my ($socket,$client_socket); 10 | 11 | # creating object interface of IO::Socket::INET modules which internally creates 12 | # socket, binds and connects to the TCP server running on the specific port. 13 | $socket = new IO::Socket::INET ( 14 | PeerHost => '192.168.0.6', 15 | PeerPort => '1000', 16 | Proto => 'tcp', 17 | ) or die "ERROR in Socket Creation : $!\n"; 18 | 19 | print "TCP Connection Success.\n"; 20 | 21 | # write on the socket to server. 22 | $data = "DATA from Client"; 23 | print $socket "$data\n"; 24 | # we can also send the data through IO::Socket::INET module, 25 | # $socket->send($data); 26 | 27 | # read the socket data sent by server. 28 | $data = <$socket>; 29 | # we can also read from socket through recv() in IO::Socket::INET 30 | # $socket->recv($data,1024); 31 | print "Received from Server : $data\n"; 32 | 33 | sleep (10); 34 | $socket->close(); -------------------------------------------------------------------------------- /tests/perl/tcpserver.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #tcpserver.pl 3 | 4 | use IO::Socket::INET; 5 | 6 | # flush after every write 7 | $| = 1; 8 | 9 | my ($socket,$client_socket); 10 | my ($peeraddress,$peerport); 11 | 12 | # creating object interface of IO::Socket::INET modules which internally does 13 | # socket creation, binding and listening at the specified port address. 14 | $socket = new IO::Socket::INET ( 15 | LocalHost => '192.168.0.1', 16 | LocalPort => '5000', 17 | Proto => 'tcp', 18 | Listen => 5, 19 | Reuse => 1 20 | ) or die "ERROR in Socket Creation : $!\n"; 21 | 22 | print "SERVER Waiting for client connection on port 5000\n"; 23 | 24 | while(1) 25 | { 26 | # waiting for new client connection. 27 | $client_socket = $socket->accept(); 28 | 29 | # get the host and port number of newly connected client. 30 | $peer_address = $client_socket->peerhost(); 31 | $peer_port = $client_socket->peerport(); 32 | 33 | print "Accepted New Client Connection From : $peer_address, $peer_port\n "; 34 | 35 | # read operation on the newly accepted client 36 | $data = <$client_socket>; 37 | # we can also read from socket through recv() in IO::Socket::INET 38 | # $client_socket->recv($data,1024); 39 | print "Received from Client : $data\n"; 40 | 41 | # write operation on the newly accepted client. 42 | $data = "DATA from Server"; 43 | print $client_socket "$data\n"; 44 | # we can also send the data through IO::Socket::INET module, 45 | # $client_socket->send($data); 46 | 47 | sleep(1); 48 | 49 | $client_socket->close(); 50 | } 51 | 52 | $socket->close(); 53 | 54 | -------------------------------------------------------------------------------- /tests/perl/udpclient.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #udpclient.pl 3 | 4 | use IO::Socket::INET; 5 | 6 | # flush after every write 7 | $| = 1; 8 | 9 | my ($socket,$data); 10 | 11 | # We call IO::Socket::INET->new() to create the UDP Socket 12 | # and bind with the PeerAddr. 13 | $socket = new IO::Socket::INET ( 14 | PeerAddr => '192.168.0.6:5000', 15 | Proto => 'udp' 16 | ) or die "ERROR in Socket Creation : $!\n"; 17 | #send operation 18 | $data = "data from client"; 19 | $socket->send($data); 20 | 21 | #read operation 22 | $data = <$socket>; 23 | print "Data received from socket : $data\n "; 24 | 25 | sleep(10); 26 | $socket->close(); 27 | -------------------------------------------------------------------------------- /tests/perl/udpserver.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | #udpserver.pl 3 | 4 | use IO::Socket::INET; 5 | 6 | # flush after every write 7 | $| = 1; 8 | 9 | my ($socket,$received_data); 10 | my ($peeraddress,$peerport); 11 | 12 | # we call IO::Socket::INET->new() to create the UDP Socket and bound 13 | # to specific port number mentioned in LocalPort and there is no need to provide 14 | # LocalAddr explicitly as in TCPServer. 15 | $socket = new IO::Socket::INET ( 16 | LocalPort => '5000', 17 | Proto => 'udp', 18 | ) or die "ERROR in Socket Creation : $!\n"; 19 | 20 | while(1) 21 | { 22 | # read operation on the socket 23 | $socket->recv($recieved_data,1024); 24 | 25 | #get the peerhost and peerport at which the recent data received. 26 | $peer_address = $socket->peerhost(); 27 | $peer_port = $socket->peerport(); 28 | print "($peer_address , $peer_port) said : $recieved_data\n"; 29 | 30 | #send the data to the client at which the read/write operations done recently. 31 | $data = "data from server\n"; 32 | 33 | $socket->send($data); 34 | 35 | print $socket "$data"; 36 | 37 | } 38 | 39 | $socket->close(); 40 | 41 | -------------------------------------------------------------------------------- /utility/Enc28J60Network.h: -------------------------------------------------------------------------------- 1 | /* 2 | Enc28J60NetworkClass.h 3 | UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. 4 | 5 | Copyright (c) 2013 Norbert Truchsess 6 | All rights reserved. 7 | 8 | inspired by enc28j60.c file from the AVRlib library by Pascal Stang. 9 | For AVRlib See http://www.procyonengineering.com/ 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see . 23 | */ 24 | 25 | #ifndef Enc28J60Network_H_ 26 | #define Enc28J60Network_H_ 27 | 28 | #include "mempool.h" 29 | 30 | #define ENC28J60_CONTROL_CS SS 31 | #define SPI_MOSI MOSI 32 | #define SPI_MISO MISO 33 | #define SPI_SCK SCK 34 | #define SPI_SS SS 35 | 36 | #define UIP_RECEIVEBUFFERHANDLE 0xff 37 | 38 | #define UIP_SENDBUFFER_PADDING 7 39 | #define UIP_SENDBUFFER_OFFSET 1 40 | 41 | //#define ENC28J60DEBUG 42 | 43 | /* 44 | * Empfangen von ip-header, arp etc... 45 | * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection 46 | */ 47 | 48 | class Enc28J60Network : public MemoryPool 49 | { 50 | 51 | private: 52 | static uint16_t nextPacketPtr; 53 | static uint8_t bank; 54 | 55 | static struct memblock receivePkt; 56 | 57 | static uint8_t readOp(uint8_t op, uint8_t address); 58 | static void writeOp(uint8_t op, uint8_t address, uint8_t data); 59 | static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); 60 | static void setERXRDPT(); 61 | static void readBuffer(uint16_t len, uint8_t* data); 62 | static void writeBuffer(uint16_t len, uint8_t* data); 63 | static uint8_t readByte(uint16_t addr); 64 | static void writeByte(uint16_t addr, uint8_t data); 65 | static void setBank(uint8_t address); 66 | static uint8_t readReg(uint8_t address); 67 | static void writeReg(uint8_t address, uint8_t data); 68 | static void writeRegPair(uint8_t address, uint16_t data); 69 | static void phyWrite(uint8_t address, uint16_t data); 70 | static uint16_t phyRead(uint8_t address); 71 | static void clkout(uint8_t clk); 72 | 73 | friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); 74 | 75 | public: 76 | 77 | uint8_t getrev(void); 78 | void powerOn(); 79 | void powerOff(); 80 | bool linkStatus(); 81 | 82 | static void init(uint8_t* macaddr); 83 | static memhandle receivePacket(); 84 | static void freePacket(); 85 | static memaddress blockSize(memhandle handle); 86 | static bool sendPacket(memhandle handle); 87 | static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); 88 | static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); 89 | static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); 90 | static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); 91 | }; 92 | 93 | extern Enc28J60Network Enc28J60; 94 | #endif /* Enc28J60NetworkClass_H_ */ 95 | -------------------------------------------------------------------------------- /utility/clock-arch.c: -------------------------------------------------------------------------------- 1 | /* 2 | clock-arch.c - Arduino implementation of uIP clock device. 3 | Copyright (c) 2010 Adam Nielsen 4 | All rights reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include 22 | #include "clock-arch.h" 23 | 24 | clock_time_t 25 | clock_time(void) 26 | { 27 | return (clock_time_t) millis(); 28 | } 29 | -------------------------------------------------------------------------------- /utility/clock-arch.h: -------------------------------------------------------------------------------- 1 | /* 2 | clock-arch.h - Arduino implementation of uIP clock device. 3 | Copyright (c) 2010 Adam Nielsen 4 | All rights reserved. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef clock_h_ 22 | #define clock_h_ 23 | 24 | typedef unsigned long clock_time_t; 25 | #define CLOCK_CONF_SECOND 1000 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /utility/enc28j60.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * 3 | * Title : Microchip ENC28J60 Ethernet Interface Driver 4 | * Author : Pascal Stang (c)2005 5 | * Modified by Norbert Truchsess 6 | * Copyright: GPL V2 7 | * 8 | *This driver provides initialization and transmit/receive 9 | *functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY. 10 | *This chip is novel in that it is a full MAC+PHY interface all in a 28-pin 11 | *chip, using an SPI interface to the host processor. 12 | * 13 | * 14 | *****************************************************************************/ 15 | 16 | #ifndef ENC28J60_H 17 | #define ENC28J60_H 18 | #include 19 | 20 | // ENC28J60 Control Registers 21 | // Control register definitions are a combination of address, 22 | // bank number, and Ethernet/MAC/PHY indicator bits. 23 | // - Register address (bits 0-4) 24 | // - Bank number (bits 5-6) 25 | // - MAC/PHY indicator (bit 7) 26 | #define ADDR_MASK 0x1F 27 | #define BANK_MASK 0x60 28 | #define SPRD_MASK 0x80 29 | // All-bank registers 30 | #define EIE 0x1B 31 | #define EIR 0x1C 32 | #define ESTAT 0x1D 33 | #define ECON2 0x1E 34 | #define ECON1 0x1F 35 | // Bank 0 registers 36 | #define ERDPTL (0x00|0x00) 37 | #define ERDPTH (0x01|0x00) 38 | #define EWRPTL (0x02|0x00) 39 | #define EWRPTH (0x03|0x00) 40 | #define ETXSTL (0x04|0x00) 41 | #define ETXSTH (0x05|0x00) 42 | #define ETXNDL (0x06|0x00) 43 | #define ETXNDH (0x07|0x00) 44 | #define ERXSTL (0x08|0x00) 45 | #define ERXSTH (0x09|0x00) 46 | #define ERXNDL (0x0A|0x00) 47 | #define ERXNDH (0x0B|0x00) 48 | #define ERXRDPTL (0x0C|0x00) 49 | #define ERXRDPTH (0x0D|0x00) 50 | #define ERXWRPTL (0x0E|0x00) 51 | #define ERXWRPTH (0x0F|0x00) 52 | #define EDMASTL (0x10|0x00) 53 | #define EDMASTH (0x11|0x00) 54 | #define EDMANDL (0x12|0x00) 55 | #define EDMANDH (0x13|0x00) 56 | #define EDMADSTL (0x14|0x00) 57 | #define EDMADSTH (0x15|0x00) 58 | #define EDMACSL (0x16|0x00) 59 | #define EDMACSH (0x17|0x00) 60 | // Bank 1 registers 61 | #define EHT0 (0x00|0x20) 62 | #define EHT1 (0x01|0x20) 63 | #define EHT2 (0x02|0x20) 64 | #define EHT3 (0x03|0x20) 65 | #define EHT4 (0x04|0x20) 66 | #define EHT5 (0x05|0x20) 67 | #define EHT6 (0x06|0x20) 68 | #define EHT7 (0x07|0x20) 69 | #define EPMM0 (0x08|0x20) 70 | #define EPMM1 (0x09|0x20) 71 | #define EPMM2 (0x0A|0x20) 72 | #define EPMM3 (0x0B|0x20) 73 | #define EPMM4 (0x0C|0x20) 74 | #define EPMM5 (0x0D|0x20) 75 | #define EPMM6 (0x0E|0x20) 76 | #define EPMM7 (0x0F|0x20) 77 | #define EPMCSL (0x10|0x20) 78 | #define EPMCSH (0x11|0x20) 79 | #define EPMOL (0x14|0x20) 80 | #define EPMOH (0x15|0x20) 81 | #define EWOLIE (0x16|0x20) 82 | #define EWOLIR (0x17|0x20) 83 | #define ERXFCON (0x18|0x20) 84 | #define EPKTCNT (0x19|0x20) 85 | // Bank 2 registers 86 | #define MACON1 (0x00|0x40|0x80) 87 | #define MACON2 (0x01|0x40|0x80) 88 | #define MACON3 (0x02|0x40|0x80) 89 | #define MACON4 (0x03|0x40|0x80) 90 | #define MABBIPG (0x04|0x40|0x80) 91 | #define MAIPGL (0x06|0x40|0x80) 92 | #define MAIPGH (0x07|0x40|0x80) 93 | #define MACLCON1 (0x08|0x40|0x80) 94 | #define MACLCON2 (0x09|0x40|0x80) 95 | #define MAMXFLL (0x0A|0x40|0x80) 96 | #define MAMXFLH (0x0B|0x40|0x80) 97 | #define MAPHSUP (0x0D|0x40|0x80) 98 | #define MICON (0x11|0x40|0x80) 99 | #define MICMD (0x12|0x40|0x80) 100 | #define MIREGADR (0x14|0x40|0x80) 101 | #define MIWRL (0x16|0x40|0x80) 102 | #define MIWRH (0x17|0x40|0x80) 103 | #define MIRDL (0x18|0x40|0x80) 104 | #define MIRDH (0x19|0x40|0x80) 105 | // Bank 3 registers 106 | #define MAADR1 (0x00|0x60|0x80) 107 | #define MAADR0 (0x01|0x60|0x80) 108 | #define MAADR3 (0x02|0x60|0x80) 109 | #define MAADR2 (0x03|0x60|0x80) 110 | #define MAADR5 (0x04|0x60|0x80) 111 | #define MAADR4 (0x05|0x60|0x80) 112 | #define EBSTSD (0x06|0x60) 113 | #define EBSTCON (0x07|0x60) 114 | #define EBSTCSL (0x08|0x60) 115 | #define EBSTCSH (0x09|0x60) 116 | #define MISTAT (0x0A|0x60|0x80) 117 | #define EREVID (0x12|0x60) 118 | #define ECOCON (0x15|0x60) 119 | #define EFLOCON (0x17|0x60) 120 | #define EPAUSL (0x18|0x60) 121 | #define EPAUSH (0x19|0x60) 122 | // PHY registers 123 | #define PHCON1 0x00 124 | #define PHSTAT1 0x01 125 | #define PHHID1 0x02 126 | #define PHHID2 0x03 127 | #define PHCON2 0x10 128 | #define PHSTAT2 0x11 129 | #define PHIE 0x12 130 | #define PHIR 0x13 131 | #define PHLCON 0x14 132 | 133 | // ENC28J60 ERXFCON Register Bit Definitions 134 | #define ERXFCON_UCEN 0x80 135 | #define ERXFCON_ANDOR 0x40 136 | #define ERXFCON_CRCEN 0x20 137 | #define ERXFCON_PMEN 0x10 138 | #define ERXFCON_MPEN 0x08 139 | #define ERXFCON_HTEN 0x04 140 | #define ERXFCON_MCEN 0x02 141 | #define ERXFCON_BCEN 0x01 142 | // ENC28J60 EIE Register Bit Definitions 143 | #define EIE_INTIE 0x80 144 | #define EIE_PKTIE 0x40 145 | #define EIE_DMAIE 0x20 146 | #define EIE_LINKIE 0x10 147 | #define EIE_TXIE 0x08 148 | #define EIE_WOLIE 0x04 149 | #define EIE_TXERIE 0x02 150 | #define EIE_RXERIE 0x01 151 | // ENC28J60 EIR Register Bit Definitions 152 | #define EIR_PKTIF 0x40 153 | #define EIR_DMAIF 0x20 154 | #define EIR_LINKIF 0x10 155 | #define EIR_TXIF 0x08 156 | #define EIR_WOLIF 0x04 157 | #define EIR_TXERIF 0x02 158 | #define EIR_RXERIF 0x01 159 | // ENC28J60 ESTAT Register Bit Definitions 160 | #define ESTAT_INT 0x80 161 | #define ESTAT_LATECOL 0x10 162 | #define ESTAT_RXBUSY 0x04 163 | #define ESTAT_TXABRT 0x02 164 | #define ESTAT_CLKRDY 0x01 165 | // ENC28J60 ECON2 Register Bit Definitions 166 | #define ECON2_AUTOINC 0x80 167 | #define ECON2_PKTDEC 0x40 168 | #define ECON2_PWRSV 0x20 169 | #define ECON2_VRPS 0x08 170 | // ENC28J60 ECON1 Register Bit Definitions 171 | #define ECON1_TXRST 0x80 172 | #define ECON1_RXRST 0x40 173 | #define ECON1_DMAST 0x20 174 | #define ECON1_CSUMEN 0x10 175 | #define ECON1_TXRTS 0x08 176 | #define ECON1_RXEN 0x04 177 | #define ECON1_BSEL1 0x02 178 | #define ECON1_BSEL0 0x01 179 | // ENC28J60 MACON1 Register Bit Definitions 180 | #define MACON1_LOOPBK 0x10 181 | #define MACON1_TXPAUS 0x08 182 | #define MACON1_RXPAUS 0x04 183 | #define MACON1_PASSALL 0x02 184 | #define MACON1_MARXEN 0x01 185 | // ENC28J60 MACON2 Register Bit Definitions 186 | #define MACON2_MARST 0x80 187 | #define MACON2_RNDRST 0x40 188 | #define MACON2_MARXRST 0x08 189 | #define MACON2_RFUNRST 0x04 190 | #define MACON2_MATXRST 0x02 191 | #define MACON2_TFUNRST 0x01 192 | // ENC28J60 MACON3 Register Bit Definitions 193 | #define MACON3_PADCFG2 0x80 194 | #define MACON3_PADCFG1 0x40 195 | #define MACON3_PADCFG0 0x20 196 | #define MACON3_TXCRCEN 0x10 197 | #define MACON3_PHDRLEN 0x08 198 | #define MACON3_HFRMLEN 0x04 199 | #define MACON3_FRMLNEN 0x02 200 | #define MACON3_FULDPX 0x01 201 | // ENC28J60 MICMD Register Bit Definitions 202 | #define MICMD_MIISCAN 0x02 203 | #define MICMD_MIIRD 0x01 204 | // ENC28J60 MISTAT Register Bit Definitions 205 | #define MISTAT_NVALID 0x04 206 | #define MISTAT_SCAN 0x02 207 | #define MISTAT_BUSY 0x01 208 | // ENC28J60 PHY PHCON1 Register Bit Definitions 209 | #define PHCON1_PRST 0x8000 210 | #define PHCON1_PLOOPBK 0x4000 211 | #define PHCON1_PPWRSV 0x0800 212 | #define PHCON1_PDPXMD 0x0100 213 | // ENC28J60 PHY PHSTAT1 Register Bit Definitions 214 | #define PHSTAT1_PFDPX 0x1000 215 | #define PHSTAT1_PHDPX 0x0800 216 | #define PHSTAT1_LLSTAT 0x0004 217 | #define PHSTAT1_JBSTAT 0x0002 218 | // ENC28J60 PHY PHCON2 Register Bit Definitions 219 | #define PHCON2_FRCLINK 0x4000 220 | #define PHCON2_TXDIS 0x2000 221 | #define PHCON2_JABBER 0x0400 222 | #define PHCON2_HDLDIS 0x0100 223 | 224 | // ENC28J60 Packet Control Byte Bit Definitions 225 | #define PKTCTRL_PHUGEEN 0x08 226 | #define PKTCTRL_PPADEN 0x04 227 | #define PKTCTRL_PCRCEN 0x02 228 | #define PKTCTRL_POVERRIDE 0x01 229 | 230 | // SPI operation codes 231 | #define ENC28J60_READ_CTRL_REG 0x00 232 | #define ENC28J60_READ_BUF_MEM 0x3A 233 | #define ENC28J60_WRITE_CTRL_REG 0x40 234 | #define ENC28J60_WRITE_BUF_MEM 0x7A 235 | #define ENC28J60_BIT_FIELD_SET 0x80 236 | #define ENC28J60_BIT_FIELD_CLR 0xA0 237 | #define ENC28J60_SOFT_RESET 0xFF 238 | 239 | 240 | // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata 241 | // buffer boundaries applied to internal 8K ram 242 | // the entire available packet buffer space is allocated 243 | // 244 | // start with recbuf at 0/ 245 | #define RXSTART_INIT 0x0 246 | // receive buffer end. make sure this is an odd value ( See Rev. B1,B4,B5,B7 Silicon Errata 'Memory (Ethernet Buffer)') 247 | #define RXSTOP_INIT (0x1FFF-0x1800) 248 | // start TX buffer RXSTOP_INIT+1 249 | #define TXSTART_INIT (RXSTOP_INIT+1) 250 | // stp TX buffer at end of mem 251 | #define TXSTOP_INIT 0x1FFF 252 | // 253 | // max frame length which the conroller will accept: 254 | #define MAX_FRAMELEN UIP_CONF_TCP_MSS + UIP_LLH_LEN + UIP_TCPIP_HLEN + 4//1500 // (note: maximum ethernet frame length would be 1518) 255 | //#define MAX_FRAMELEN 600 256 | 257 | #endif 258 | -------------------------------------------------------------------------------- /utility/mempool.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | mempool.cpp - sleek implementation of a memory pool 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #include "mempool.h" 21 | #include 22 | 23 | #define POOLOFFSET 1 24 | 25 | struct memblock MemoryPool::blocks[MEMPOOL_NUM_MEMBLOCKS+1]; 26 | 27 | void 28 | MemoryPool::init() 29 | { 30 | memset(&blocks[0], 0, sizeof(blocks)); 31 | blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS; 32 | blocks[POOLSTART].size = 0; 33 | blocks[POOLSTART].nextblock = NOBLOCK; 34 | } 35 | 36 | memhandle 37 | MemoryPool::allocBlock(memaddress size) 38 | { 39 | memblock* best = NULL; 40 | memhandle cur = POOLSTART; 41 | memblock* block = &blocks[POOLSTART]; 42 | memaddress bestsize = MEMPOOL_SIZE + 1; 43 | 44 | do 45 | { 46 | memhandle next = block->nextblock; 47 | memaddress freesize = ( next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - block->begin - block->size; 48 | if (freesize == size) 49 | { 50 | best = &blocks[cur]; 51 | goto found; 52 | } 53 | if (freesize > size && freesize < bestsize) 54 | { 55 | bestsize = freesize; 56 | best = &blocks[cur]; 57 | } 58 | if (next == NOBLOCK) 59 | { 60 | if (best) 61 | goto found; 62 | else 63 | goto collect; 64 | } 65 | block = &blocks[next]; 66 | cur = next; 67 | } 68 | while (true); 69 | 70 | collect: 71 | { 72 | cur = POOLSTART; 73 | block = &blocks[POOLSTART]; 74 | memhandle next; 75 | while ((next = block->nextblock) != NOBLOCK) 76 | { 77 | memaddress dest = block->begin + block->size; 78 | memblock* nextblock = &blocks[next]; 79 | memaddress* src = &nextblock->begin; 80 | if (dest != *src) 81 | { 82 | #ifdef MEMPOOL_MEMBLOCK_MV 83 | MEMPOOL_MEMBLOCK_MV(dest,*src,nextblock->size); 84 | #endif 85 | *src = dest; 86 | } 87 | block = nextblock; 88 | } 89 | if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size) 90 | best = block; 91 | else 92 | goto notfound; 93 | } 94 | 95 | found: 96 | { 97 | block = &blocks[POOLOFFSET]; 98 | for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) 99 | { 100 | if (block->size) 101 | { 102 | block++; 103 | continue; 104 | } 105 | memaddress address = best->begin + best->size; 106 | #ifdef MEMBLOCK_ALLOC 107 | MEMBLOCK_ALLOC(address,size); 108 | #endif 109 | block->begin = address; 110 | block->size = size; 111 | block->nextblock = best->nextblock; 112 | best->nextblock = cur; 113 | return cur; 114 | } 115 | } 116 | 117 | notfound: return NOBLOCK; 118 | } 119 | 120 | void 121 | MemoryPool::freeBlock(memhandle handle) 122 | { 123 | if (handle == NOBLOCK) 124 | return; 125 | memblock *b = &blocks[POOLSTART]; 126 | 127 | do 128 | { 129 | memhandle next = b->nextblock; 130 | if (next == handle) 131 | { 132 | memblock *f = &blocks[next]; 133 | #ifdef MEMBLOCK_FREE 134 | MEMBLOCK_FREE(f->begin,f->size); 135 | #endif 136 | b->nextblock = f->nextblock; 137 | f->size = 0; 138 | f->nextblock = NOBLOCK; 139 | return; 140 | } 141 | if (next == NOBLOCK) 142 | return; 143 | b = &blocks[next]; 144 | } 145 | while (true); 146 | } 147 | 148 | void 149 | MemoryPool::resizeBlock(memhandle handle, memaddress position) 150 | { 151 | memblock * block = &blocks[handle]; 152 | block->begin += position; 153 | block->size -= position; 154 | } 155 | 156 | void 157 | MemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size) 158 | { 159 | memblock * block = &blocks[handle]; 160 | block->begin += position; 161 | block->size = size; 162 | } 163 | 164 | memaddress 165 | MemoryPool::blockSize(memhandle handle) 166 | { 167 | return blocks[handle].size; 168 | } 169 | -------------------------------------------------------------------------------- /utility/mempool.h: -------------------------------------------------------------------------------- 1 | /* 2 | mempool.h - sleek implementation of a memory pool 3 | Copyright (c) 2013 Norbert Truchsess 4 | All rights reserved. 5 | 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program. If not, see . 18 | */ 19 | 20 | #ifndef MEMPOOL_H 21 | #define MEMPOOL_H 22 | 23 | #include 24 | 25 | #define POOLSTART 0 26 | #define NOBLOCK 0 27 | 28 | #include "mempool_conf.h" 29 | 30 | struct memblock 31 | { 32 | memaddress begin; 33 | memaddress size; 34 | memhandle nextblock; 35 | }; 36 | 37 | class MemoryPool 38 | { 39 | #ifdef MEMPOOLTEST_H 40 | friend class MemoryPoolTest; 41 | #endif 42 | 43 | protected: 44 | static struct memblock blocks[MEMPOOL_NUM_MEMBLOCKS+1]; 45 | 46 | public: 47 | static void init(); 48 | static memhandle allocBlock(memaddress); 49 | static void freeBlock(memhandle); 50 | static void resizeBlock(memhandle handle, memaddress position); 51 | static void resizeBlock(memhandle handle, memaddress position, memaddress size); 52 | static memaddress blockSize(memhandle); 53 | }; 54 | #endif 55 | -------------------------------------------------------------------------------- /utility/mempool_conf.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMPOOLCONF_H 2 | #define MEMPOOLCONF_H 3 | #include "uipethernet-conf.h" 4 | extern "C" { 5 | #include "uipopt.h" 6 | #include "enc28j60.h" 7 | } 8 | #include 9 | 10 | typedef uint16_t memaddress; 11 | typedef uint8_t memhandle; 12 | 13 | #if UIP_SOCKET_NUMPACKETS and UIP_CONNS 14 | #define NUM_TCP_MEMBLOCKS (UIP_SOCKET_NUMPACKETS*2)*UIP_CONNS 15 | #else 16 | #define NUM_TCP_MEMBLOCKS 0 17 | #endif 18 | 19 | #if UIP_UDP and UIP_UDP_CONNS 20 | #define NUM_UDP_MEMBLOCKS 3*UIP_UDP_CONNS 21 | #else 22 | #define NUM_UDP_MEMBLOCKS 0 23 | #endif 24 | 25 | #define MEMPOOL_NUM_MEMBLOCKS (NUM_TCP_MEMBLOCKS+NUM_UDP_MEMBLOCKS) 26 | 27 | #define MEMPOOL_STARTADDRESS TXSTART_INIT+1 28 | #define MEMPOOL_SIZE TXSTOP_INIT-TXSTART_INIT 29 | 30 | void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); 31 | 32 | #define MEMPOOL_MEMBLOCK_MV(dest,src,size) enc28J60_mempool_block_move_callback(dest,src,size) 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /utility/uip-conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | * UIPEthernet Project-specific configuration options 3 | * Copyright (c) 2013 Norbert Truchsess 4 | * @{ 5 | * 6 | * uIP has a number of configuration options that can be overridden 7 | * for each project. These are kept in a project-specific uip-conf.h 8 | * file and all configuration names have the prefix UIP_CONF. 9 | */ 10 | 11 | /* 12 | * Copyright (c) 2006, Swedish Institute of Computer Science. 13 | * All rights reserved. 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions 17 | * are met: 18 | * 1. Redistributions of source code must retain the above copyright 19 | * notice, this list of conditions and the following disclaimer. 20 | * 2. Redistributions in binary form must reproduce the above copyright 21 | * notice, this list of conditions and the following disclaimer in the 22 | * documentation and/or other materials provided with the distribution. 23 | * 3. Neither the name of the Institute nor the names of its contributors 24 | * may be used to endorse or promote products derived from this software 25 | * without specific prior written permission. 26 | * 27 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 | * SUCH DAMAGE. 38 | * 39 | * This file is part of the uIP TCP/IP stack 40 | * 41 | */ 42 | 43 | #ifndef __UIP_CONF_H__ 44 | #define __UIP_CONF_H__ 45 | 46 | #include 47 | #include "uipethernet-conf.h" 48 | 49 | /** 50 | * 8 bit datatype 51 | * 52 | * This typedef defines the 8-bit type used throughout uIP. 53 | * 54 | * \hideinitializer 55 | */ 56 | typedef uint8_t u8_t; 57 | 58 | /** 59 | * 16 bit datatype 60 | * 61 | * This typedef defines the 16-bit type used throughout uIP. 62 | * 63 | * \hideinitializer 64 | */ 65 | typedef uint16_t u16_t; 66 | 67 | /** 68 | * Statistics datatype 69 | * 70 | * This typedef defines the dataype used for keeping statistics in 71 | * uIP. 72 | * 73 | * \hideinitializer 74 | */ 75 | typedef unsigned short uip_stats_t; 76 | 77 | /** 78 | * Maximum number of TCP connections. 79 | * (see uipethernet-conf.h) 80 | * \hideinitializer 81 | * 82 | * #define UIP_CONF_MAX_CONNECTIONS 4 83 | */ 84 | 85 | /** 86 | * Maximum number of listening TCP ports. 87 | * 88 | * \hideinitializer 89 | */ 90 | #define UIP_CONF_MAX_LISTENPORTS 4 91 | 92 | /** 93 | * uIP buffer size. 94 | * 95 | * \hideinitializer 96 | */ 97 | #define UIP_CONF_BUFFER_SIZE 98 98 | //#define UIP_CONF_BUFFER_SIZE 118 99 | 100 | /** 101 | * The TCP maximum segment size. 102 | * 103 | * This is should not be to set to more than 104 | * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. 105 | */ 106 | 107 | #define UIP_CONF_TCP_MSS 511 108 | 109 | /** 110 | * The size of the advertised receiver's window. 111 | * 112 | * Should be set low (i.e., to the size of the uip_buf buffer) is the 113 | * application is slow to process incoming data, or high (32768 bytes) 114 | * if the application processes data quickly. 115 | * 116 | * \hideinitializer 117 | */ 118 | #define UIP_CONF_RECEIVE_WINDOW 511 119 | 120 | /** 121 | * CPU byte order. 122 | * 123 | * \hideinitializer 124 | */ 125 | #define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN 126 | 127 | /** 128 | * Logging on or off 129 | * 130 | * \hideinitializer 131 | */ 132 | #define UIP_CONF_LOGGING 0 133 | 134 | /** 135 | * UDP support on or off 136 | * (see uipethernet-conf.h) 137 | * \hideinitializer 138 | * 139 | * #define UIP_CONF_UDP 1 140 | * 141 | * #define UIP_CONF_UDP_CONNS 4 142 | */ 143 | 144 | /** 145 | * UDP checksums on or off 146 | * 147 | * \hideinitializer 148 | */ 149 | #define UIP_CONF_UDP_CHECKSUMS 1 150 | 151 | /** 152 | * UDP Broadcast (receive) on or off 153 | * (see uipethernet-conf.h) 154 | * \hideinitializer 155 | * #define UIP_CONF_BROADCAST 1 156 | */ 157 | 158 | 159 | /** 160 | * uIP statistics on or off 161 | * 162 | * \hideinitializer 163 | */ 164 | #define UIP_CONF_STATISTICS 0 165 | 166 | // SLIP 167 | //#define UIP_CONF_LLH_LEN 0 168 | 169 | typedef void* uip_tcp_appstate_t; 170 | 171 | void uipclient_appcall(void); 172 | 173 | #define UIP_APPCALL uipclient_appcall 174 | 175 | typedef void* uip_udp_appstate_t; 176 | 177 | void uipudp_appcall(void); 178 | 179 | #define UIP_UDP_APPCALL uipudp_appcall 180 | 181 | #define CC_REGISTER_ARG register 182 | 183 | #define UIP_ARCH_CHKSUM 1 184 | 185 | #endif /* __UIP_CONF_H__ */ 186 | -------------------------------------------------------------------------------- /utility/uip_arch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * {@ 4 | */ 5 | 6 | /** 7 | * \defgroup uiparch Architecture specific uIP functions 8 | * @{ 9 | * 10 | * The functions in the architecture specific module implement the IP 11 | * check sum and 32-bit additions. 12 | * 13 | * The IP checksum calculation is the most computationally expensive 14 | * operation in the TCP/IP stack and it therefore pays off to 15 | * implement this in efficient assembler. The purpose of the uip-arch 16 | * module is to let the checksum functions to be implemented in 17 | * architecture specific assembler. 18 | * 19 | */ 20 | 21 | /** 22 | * \file 23 | * Declarations of architecture specific functions. 24 | * \author Adam Dunkels 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2001, Adam Dunkels. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. The name of the author may not be used to endorse or promote 40 | * products derived from this software without specific prior 41 | * written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 44 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 45 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 47 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 49 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack. 56 | * 57 | * $Id: uip_arch.h,v 1.2 2006/06/07 09:15:19 adam Exp $ 58 | * 59 | */ 60 | 61 | #ifndef __UIP_ARCH_H__ 62 | #define __UIP_ARCH_H__ 63 | 64 | #include "uip.h" 65 | 66 | /** 67 | * Carry out a 32-bit addition. 68 | * 69 | * Because not all architectures for which uIP is intended has native 70 | * 32-bit arithmetic, uIP uses an external C function for doing the 71 | * required 32-bit additions in the TCP protocol processing. This 72 | * function should add the two arguments and place the result in the 73 | * global variable uip_acc32. 74 | * 75 | * \note The 32-bit integer pointed to by the op32 parameter and the 76 | * result in the uip_acc32 variable are in network byte order (big 77 | * endian). 78 | * 79 | * \param op32 A pointer to a 4-byte array representing a 32-bit 80 | * integer in network byte order (big endian). 81 | * 82 | * \param op16 A 16-bit integer in host byte order. 83 | */ 84 | void uip_add32(u8_t *op32, u16_t op16); 85 | 86 | /** 87 | * Calculate the Internet checksum over a buffer. 88 | * 89 | * The Internet checksum is the one's complement of the one's 90 | * complement sum of all 16-bit words in the buffer. 91 | * 92 | * See RFC1071. 93 | * 94 | * \note This function is not called in the current version of uIP, 95 | * but future versions might make use of it. 96 | * 97 | * \param buf A pointer to the buffer over which the checksum is to be 98 | * computed. 99 | * 100 | * \param len The length of the buffer over which the checksum is to 101 | * be computed. 102 | * 103 | * \return The Internet checksum of the buffer. 104 | */ 105 | u16_t uip_chksum(u16_t *buf, u16_t len); 106 | 107 | /** 108 | * Calculate the IP header checksum of the packet header in uip_buf. 109 | * 110 | * The IP header checksum is the Internet checksum of the 20 bytes of 111 | * the IP header. 112 | * 113 | * \return The IP header checksum of the IP header in the uip_buf 114 | * buffer. 115 | */ 116 | u16_t uip_ipchksum(void); 117 | 118 | /** 119 | * Calculate the TCP checksum of the packet in uip_buf and uip_appdata. 120 | * 121 | * The TCP checksum is the Internet checksum of data contents of the 122 | * TCP segment, and a pseudo-header as defined in RFC793. 123 | * 124 | * \note The uip_appdata pointer that points to the packet data may 125 | * point anywhere in memory, so it is not possible to simply calculate 126 | * the Internet checksum of the contents of the uip_buf buffer. 127 | * 128 | * \return The TCP checksum of the TCP segment in uip_buf and pointed 129 | * to by uip_appdata. 130 | */ 131 | u16_t uip_tcpchksum(void); 132 | 133 | u16_t uip_udpchksum(void); 134 | 135 | /** @} */ 136 | /** @} */ 137 | 138 | #endif /* __UIP_ARCH_H__ */ 139 | -------------------------------------------------------------------------------- /utility/uip_arp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \defgroup uiparp uIP Address Resolution Protocol 8 | * @{ 9 | * 10 | * The Address Resolution Protocol ARP is used for mapping between IP 11 | * addresses and link level addresses such as the Ethernet MAC 12 | * addresses. ARP uses broadcast queries to ask for the link level 13 | * address of a known IP address and the host which is configured with 14 | * the IP address for which the query was meant, will respond with its 15 | * link level address. 16 | * 17 | * \note This ARP implementation only supports Ethernet. 18 | */ 19 | 20 | /** 21 | * \file 22 | * Implementation of the ARP Address Resolution Protocol. 23 | * \author Adam Dunkels 24 | * 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2001-2003, Adam Dunkels. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. The name of the author may not be used to endorse or promote 40 | * products derived from this software without specific prior 41 | * written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 44 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 45 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 47 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 49 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 50 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 52 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack. 56 | * 57 | * $Id: uip_arp.c,v 1.8 2006/06/02 23:36:21 adam Exp $ 58 | * 59 | */ 60 | 61 | 62 | #include "uip_arp.h" 63 | 64 | #include 65 | 66 | struct arp_hdr { 67 | struct uip_eth_hdr ethhdr; 68 | u16_t hwtype; 69 | u16_t protocol; 70 | u8_t hwlen; 71 | u8_t protolen; 72 | u16_t opcode; 73 | struct uip_eth_addr shwaddr; 74 | u16_t sipaddr[2]; 75 | struct uip_eth_addr dhwaddr; 76 | u16_t dipaddr[2]; 77 | }; 78 | 79 | struct ethip_hdr { 80 | struct uip_eth_hdr ethhdr; 81 | /* IP header. */ 82 | u8_t vhl, 83 | tos, 84 | len[2], 85 | ipid[2], 86 | ipoffset[2], 87 | ttl, 88 | proto; 89 | u16_t ipchksum; 90 | u16_t srcipaddr[2], 91 | destipaddr[2]; 92 | }; 93 | 94 | #define ARP_REQUEST 1 95 | #define ARP_REPLY 2 96 | 97 | #define ARP_HWTYPE_ETH 1 98 | 99 | struct arp_entry { 100 | u16_t ipaddr[2]; 101 | struct uip_eth_addr ethaddr; 102 | u8_t time; 103 | }; 104 | 105 | static const struct uip_eth_addr broadcast_ethaddr = 106 | {{0xff,0xff,0xff,0xff,0xff,0xff}}; 107 | static const u16_t broadcast_ipaddr[2] = {0xffff,0xffff}; 108 | 109 | static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; 110 | static u16_t ipaddr[2]; 111 | static u8_t i, c; 112 | 113 | static u8_t arptime; 114 | static u8_t tmpage; 115 | 116 | #define BUF ((struct arp_hdr *)&uip_buf[0]) 117 | #define IPBUF ((struct ethip_hdr *)&uip_buf[0]) 118 | /*-----------------------------------------------------------------------------------*/ 119 | /** 120 | * Initialize the ARP module. 121 | * 122 | */ 123 | /*-----------------------------------------------------------------------------------*/ 124 | void 125 | uip_arp_init(void) 126 | { 127 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 128 | memset(arp_table[i].ipaddr, 0, 4); 129 | } 130 | } 131 | /*-----------------------------------------------------------------------------------*/ 132 | /** 133 | * Periodic ARP processing function. 134 | * 135 | * This function performs periodic timer processing in the ARP module 136 | * and should be called at regular intervals. The recommended interval 137 | * is 10 seconds between the calls. 138 | * 139 | */ 140 | /*-----------------------------------------------------------------------------------*/ 141 | void 142 | uip_arp_timer(void) 143 | { 144 | struct arp_entry *tabptr; 145 | 146 | ++arptime; 147 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 148 | tabptr = &arp_table[i]; 149 | if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && 150 | arptime - tabptr->time >= UIP_ARP_MAXAGE) { 151 | memset(tabptr->ipaddr, 0, 4); 152 | } 153 | } 154 | 155 | } 156 | /*-----------------------------------------------------------------------------------*/ 157 | static void 158 | uip_arp_update(u16_t *ipaddr, struct uip_eth_addr *ethaddr) 159 | { 160 | register struct arp_entry *tabptr; 161 | /* Walk through the ARP mapping table and try to find an entry to 162 | update. If none is found, the IP -> MAC address mapping is 163 | inserted in the ARP table. */ 164 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 165 | 166 | tabptr = &arp_table[i]; 167 | /* Only check those entries that are actually in use. */ 168 | if(tabptr->ipaddr[0] != 0 && 169 | tabptr->ipaddr[1] != 0) { 170 | 171 | /* Check if the source IP address of the incoming packet matches 172 | the IP address in this ARP table entry. */ 173 | if(ipaddr[0] == tabptr->ipaddr[0] && 174 | ipaddr[1] == tabptr->ipaddr[1]) { 175 | 176 | /* An old entry found, update this and return. */ 177 | memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 178 | tabptr->time = arptime; 179 | 180 | return; 181 | } 182 | } 183 | } 184 | 185 | /* If we get here, no existing ARP table entry was found, so we 186 | create one. */ 187 | 188 | /* First, we try to find an unused entry in the ARP table. */ 189 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 190 | tabptr = &arp_table[i]; 191 | if(tabptr->ipaddr[0] == 0 && 192 | tabptr->ipaddr[1] == 0) { 193 | break; 194 | } 195 | } 196 | 197 | /* If no unused entry is found, we try to find the oldest entry and 198 | throw it away. */ 199 | if(i == UIP_ARPTAB_SIZE) { 200 | tmpage = 0; 201 | c = 0; 202 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 203 | tabptr = &arp_table[i]; 204 | if(arptime - tabptr->time > tmpage) { 205 | tmpage = arptime - tabptr->time; 206 | c = i; 207 | } 208 | } 209 | i = c; 210 | tabptr = &arp_table[i]; 211 | } 212 | 213 | /* Now, i is the ARP table entry which we will fill with the new 214 | information. */ 215 | memcpy(tabptr->ipaddr, ipaddr, 4); 216 | memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); 217 | tabptr->time = arptime; 218 | } 219 | /*-----------------------------------------------------------------------------------*/ 220 | /** 221 | * ARP processing for incoming IP packets 222 | * 223 | * This function should be called by the device driver when an IP 224 | * packet has been received. The function will check if the address is 225 | * in the ARP cache, and if so the ARP cache entry will be 226 | * refreshed. If no ARP cache entry was found, a new one is created. 227 | * 228 | * This function expects an IP packet with a prepended Ethernet header 229 | * in the uip_buf[] buffer, and the length of the packet in the global 230 | * variable uip_len. 231 | */ 232 | /*-----------------------------------------------------------------------------------*/ 233 | //#if 0 234 | void 235 | uip_arp_ipin(void) 236 | { 237 | uip_len -= sizeof(struct uip_eth_hdr); 238 | 239 | /* Only insert/update an entry if the source IP address of the 240 | incoming IP packet comes from a host on the local network. */ 241 | if((IPBUF->srcipaddr[0] & uip_netmask[0]) != 242 | (uip_hostaddr[0] & uip_netmask[0])) { 243 | return; 244 | } 245 | if((IPBUF->srcipaddr[1] & uip_netmask[1]) != 246 | (uip_hostaddr[1] & uip_netmask[1])) { 247 | return; 248 | } 249 | uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); 250 | 251 | return; 252 | } 253 | //#endif /* 0 */ 254 | /*-----------------------------------------------------------------------------------*/ 255 | /** 256 | * ARP processing for incoming ARP packets. 257 | * 258 | * This function should be called by the device driver when an ARP 259 | * packet has been received. The function will act differently 260 | * depending on the ARP packet type: if it is a reply for a request 261 | * that we previously sent out, the ARP cache will be filled in with 262 | * the values from the ARP reply. If the incoming ARP packet is an ARP 263 | * request for our IP address, an ARP reply packet is created and put 264 | * into the uip_buf[] buffer. 265 | * 266 | * When the function returns, the value of the global variable uip_len 267 | * indicates whether the device driver should send out a packet or 268 | * not. If uip_len is zero, no packet should be sent. If uip_len is 269 | * non-zero, it contains the length of the outbound packet that is 270 | * present in the uip_buf[] buffer. 271 | * 272 | * This function expects an ARP packet with a prepended Ethernet 273 | * header in the uip_buf[] buffer, and the length of the packet in the 274 | * global variable uip_len. 275 | */ 276 | /*-----------------------------------------------------------------------------------*/ 277 | void 278 | uip_arp_arpin(void) 279 | { 280 | 281 | if(uip_len < sizeof(struct arp_hdr)) { 282 | uip_len = 0; 283 | return; 284 | } 285 | uip_len = 0; 286 | 287 | switch(BUF->opcode) { 288 | case HTONS(ARP_REQUEST): 289 | /* ARP request. If it asked for our address, we send out a 290 | reply. */ 291 | if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 292 | /* First, we register the one who made the request in our ARP 293 | table, since it is likely that we will do more communication 294 | with this host in the future. */ 295 | uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 296 | 297 | /* The reply opcode is 2. */ 298 | BUF->opcode = HTONS(2); 299 | 300 | memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); 301 | memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 302 | memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 303 | memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); 304 | 305 | BUF->dipaddr[0] = BUF->sipaddr[0]; 306 | BUF->dipaddr[1] = BUF->sipaddr[1]; 307 | BUF->sipaddr[0] = uip_hostaddr[0]; 308 | BUF->sipaddr[1] = uip_hostaddr[1]; 309 | 310 | BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 311 | uip_len = sizeof(struct arp_hdr); 312 | } 313 | break; 314 | case HTONS(ARP_REPLY): 315 | /* ARP reply. We insert or update the ARP table if it was meant 316 | for us. */ 317 | if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { 318 | uip_arp_update(BUF->sipaddr, &BUF->shwaddr); 319 | } 320 | break; 321 | } 322 | 323 | return; 324 | } 325 | /*-----------------------------------------------------------------------------------*/ 326 | /** 327 | * Prepend Ethernet header to an outbound IP packet and see if we need 328 | * to send out an ARP request. 329 | * 330 | * This function should be called before sending out an IP packet. The 331 | * function checks the destination IP address of the IP packet to see 332 | * what Ethernet MAC address that should be used as a destination MAC 333 | * address on the Ethernet. 334 | * 335 | * If the destination IP address is in the local network (determined 336 | * by logical ANDing of netmask and our IP address), the function 337 | * checks the ARP cache to see if an entry for the destination IP 338 | * address is found. If so, an Ethernet header is prepended and the 339 | * function returns. If no ARP cache entry is found for the 340 | * destination IP address, the packet in the uip_buf[] is replaced by 341 | * an ARP request packet for the IP address. The IP packet is dropped 342 | * and it is assumed that they higher level protocols (e.g., TCP) 343 | * eventually will retransmit the dropped packet. 344 | * 345 | * If the destination IP address is not on the local network, the IP 346 | * address of the default router is used instead. 347 | * 348 | * When the function returns, a packet is present in the uip_buf[] 349 | * buffer, and the length of the packet is in the global variable 350 | * uip_len. 351 | */ 352 | /*-----------------------------------------------------------------------------------*/ 353 | void 354 | uip_arp_out(void) 355 | { 356 | struct arp_entry *tabptr; 357 | 358 | /* Find the destination IP address in the ARP table and construct 359 | the Ethernet header. If the destination IP addres isn't on the 360 | local network, we use the default router's IP address instead. 361 | 362 | If not ARP table entry is found, we overwrite the original IP 363 | packet with an ARP request for the IP address. */ 364 | 365 | /* First check if destination is a local broadcast. */ 366 | if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { 367 | memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); 368 | } else { 369 | /* Check if the destination address is on the local network. */ 370 | if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { 371 | /* Destination address was not on the local network, so we need to 372 | use the default router's IP address instead of the destination 373 | address when determining the MAC address. */ 374 | uip_ipaddr_copy(ipaddr, uip_draddr); 375 | } else { 376 | /* Else, we use the destination IP address. */ 377 | uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); 378 | } 379 | 380 | for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { 381 | tabptr = &arp_table[i]; 382 | if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { 383 | break; 384 | } 385 | } 386 | 387 | if(i == UIP_ARPTAB_SIZE) { 388 | /* The destination address was not in our ARP table, so we 389 | overwrite the IP packet with an ARP request. */ 390 | 391 | memset(BUF->ethhdr.dest.addr, 0xff, 6); 392 | memset(BUF->dhwaddr.addr, 0x00, 6); 393 | memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 394 | memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); 395 | 396 | uip_ipaddr_copy(BUF->dipaddr, ipaddr); 397 | uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); 398 | BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ 399 | BUF->hwtype = HTONS(ARP_HWTYPE_ETH); 400 | BUF->protocol = HTONS(UIP_ETHTYPE_IP); 401 | BUF->hwlen = 6; 402 | BUF->protolen = 4; 403 | BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); 404 | 405 | uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; 406 | 407 | uip_len = sizeof(struct arp_hdr); 408 | return; 409 | } 410 | 411 | /* Build an ethernet header. */ 412 | memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); 413 | } 414 | memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); 415 | 416 | IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); 417 | 418 | uip_len += sizeof(struct uip_eth_hdr); 419 | } 420 | /*-----------------------------------------------------------------------------------*/ 421 | 422 | /** @} */ 423 | /** @} */ 424 | -------------------------------------------------------------------------------- /utility/uip_arp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \addtogroup uip 3 | * @{ 4 | */ 5 | 6 | /** 7 | * \addtogroup uiparp 8 | * @{ 9 | */ 10 | 11 | /** 12 | * \file 13 | * Macros and definitions for the ARP module. 14 | * \author Adam Dunkels 15 | */ 16 | 17 | 18 | /* 19 | * Copyright (c) 2001-2003, Adam Dunkels. 20 | * All rights reserved. 21 | * 22 | * Redistribution and use in source and binary forms, with or without 23 | * modification, are permitted provided that the following conditions 24 | * are met: 25 | * 1. Redistributions of source code must retain the above copyright 26 | * notice, this list of conditions and the following disclaimer. 27 | * 2. Redistributions in binary form must reproduce the above copyright 28 | * notice, this list of conditions and the following disclaimer in the 29 | * documentation and/or other materials provided with the distribution. 30 | * 3. The name of the author may not be used to endorse or promote 31 | * products derived from this software without specific prior 32 | * written permission. 33 | * 34 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 35 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 36 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 38 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 40 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 42 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 43 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 44 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 45 | * 46 | * This file is part of the uIP TCP/IP stack. 47 | * 48 | * $Id: uip_arp.h,v 1.5 2006/06/11 21:46:39 adam Exp $ 49 | * 50 | */ 51 | 52 | #ifndef __UIP_ARP_H__ 53 | #define __UIP_ARP_H__ 54 | 55 | #include "uip.h" 56 | 57 | 58 | extern struct uip_eth_addr uip_ethaddr; 59 | 60 | /** 61 | * The Ethernet header. 62 | */ 63 | struct uip_eth_hdr { 64 | struct uip_eth_addr dest; 65 | struct uip_eth_addr src; 66 | u16_t type; 67 | }; 68 | 69 | #define UIP_ETHTYPE_ARP 0x0806 70 | #define UIP_ETHTYPE_IP 0x0800 71 | #define UIP_ETHTYPE_IP6 0x86dd 72 | 73 | 74 | /* The uip_arp_init() function must be called before any of the other 75 | ARP functions. */ 76 | void uip_arp_init(void); 77 | 78 | /* The uip_arp_ipin() function should be called whenever an IP packet 79 | arrives from the Ethernet. This function refreshes the ARP table or 80 | inserts a new mapping if none exists. The function assumes that an 81 | IP packet with an Ethernet header is present in the uip_buf buffer 82 | and that the length of the packet is in the uip_len variable. */ 83 | void uip_arp_ipin(void); 84 | //#define uip_arp_ipin() 85 | 86 | /* The uip_arp_arpin() should be called when an ARP packet is received 87 | by the Ethernet driver. This function also assumes that the 88 | Ethernet frame is present in the uip_buf buffer. When the 89 | uip_arp_arpin() function returns, the contents of the uip_buf 90 | buffer should be sent out on the Ethernet if the uip_len variable 91 | is > 0. */ 92 | void uip_arp_arpin(void); 93 | 94 | /* The uip_arp_out() function should be called when an IP packet 95 | should be sent out on the Ethernet. This function creates an 96 | Ethernet header before the IP header in the uip_buf buffer. The 97 | Ethernet header will have the correct Ethernet MAC destination 98 | address filled in if an ARP table entry for the destination IP 99 | address (or the IP address of the default router) is present. If no 100 | such table entry is found, the IP packet is overwritten with an ARP 101 | request and we rely on TCP to retransmit the packet that was 102 | overwritten. In any case, the uip_len variable holds the length of 103 | the Ethernet frame that should be transmitted. */ 104 | void uip_arp_out(void); 105 | 106 | /* The uip_arp_timer() function should be called every ten seconds. It 107 | is responsible for flushing old entries in the ARP table. */ 108 | void uip_arp_timer(void); 109 | 110 | /** @} */ 111 | 112 | /** 113 | * \addtogroup uipconffunc 114 | * @{ 115 | */ 116 | 117 | 118 | /** 119 | * Specifiy the Ethernet MAC address. 120 | * 121 | * The ARP code needs to know the MAC address of the Ethernet card in 122 | * order to be able to respond to ARP queries and to generate working 123 | * Ethernet headers. 124 | * 125 | * \note This macro only specifies the Ethernet MAC address to the ARP 126 | * code. It cannot be used to change the MAC address of the Ethernet 127 | * card. 128 | * 129 | * \param eaddr A pointer to a struct uip_eth_addr containing the 130 | * Ethernet MAC address of the Ethernet card. 131 | * 132 | * \hideinitializer 133 | */ 134 | #define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ 135 | uip_ethaddr.addr[1] = eaddr.addr[1];\ 136 | uip_ethaddr.addr[2] = eaddr.addr[2];\ 137 | uip_ethaddr.addr[3] = eaddr.addr[3];\ 138 | uip_ethaddr.addr[4] = eaddr.addr[4];\ 139 | uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) 140 | 141 | /** @} */ 142 | /** @} */ 143 | 144 | #endif /* __UIP_ARP_H__ */ 145 | -------------------------------------------------------------------------------- /utility/uip_clock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \defgroup clock Clock interface 3 | * 4 | * The clock interface is the interface between the \ref timer "timer library" 5 | * and the platform specific clock functionality. The clock 6 | * interface must be implemented for each platform that uses the \ref 7 | * timer "timer library". 8 | * 9 | * The clock interface does only one this: it measures time. The clock 10 | * interface provides a macro, CLOCK_SECOND, which corresponds to one 11 | * second of system time. 12 | * 13 | * \sa \ref timer "Timer library" 14 | * 15 | * @{ 16 | */ 17 | 18 | /* 19 | * Copyright (c) 2004, Swedish Institute of Computer Science. 20 | * All rights reserved. 21 | * 22 | * Redistribution and use in source and binary forms, with or without 23 | * modification, are permitted provided that the following conditions 24 | * are met: 25 | * 1. Redistributions of source code must retain the above copyright 26 | * notice, this list of conditions and the following disclaimer. 27 | * 2. Redistributions in binary form must reproduce the above copyright 28 | * notice, this list of conditions and the following disclaimer in the 29 | * documentation and/or other materials provided with the distribution. 30 | * 3. Neither the name of the Institute nor the names of its contributors 31 | * may be used to endorse or promote products derived from this software 32 | * without specific prior written permission. 33 | * 34 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 35 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 38 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44 | * SUCH DAMAGE. 45 | * 46 | * This file is part of the uIP TCP/IP stack 47 | * 48 | * Author: Adam Dunkels 49 | * 50 | * $Id: clock.h,v 1.3 2006/06/11 21:46:39 adam Exp $ 51 | */ 52 | #ifndef __UIP_CLOCK_H__ 53 | #define __UIP_CLOCK_H__ 54 | 55 | #include "clock-arch.h" 56 | 57 | /** 58 | * Initialize the clock library. 59 | * 60 | * This function initializes the clock library and should be called 61 | * from the main() function of the system. 62 | * 63 | */ 64 | void uip_clock_init(void); 65 | 66 | /** 67 | * Get the current clock time. 68 | * 69 | * This function returns the current system clock time. 70 | * 71 | * \return The current clock time, measured in system ticks. 72 | */ 73 | clock_time_t clock_time(void); 74 | 75 | /** 76 | * A second, measured in system clock time. 77 | * 78 | * \hideinitializer 79 | */ 80 | #ifdef CLOCK_CONF_SECOND 81 | #define CLOCK_SECOND CLOCK_CONF_SECOND 82 | #else 83 | #define CLOCK_SECOND (clock_time_t)32 84 | #endif 85 | 86 | #endif /* __CLOCK_H__ */ 87 | 88 | /** @} */ 89 | -------------------------------------------------------------------------------- /utility/uip_debug.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | extern "C" { 6 | #import "utility/uip.h" 7 | } 8 | 9 | struct uip_conn con[UIP_CONNS]; 10 | 11 | void 12 | UIPDebug::uip_debug_printconns() 13 | { 14 | for(uint8_t i=0;iripaddr,rhs->ripaddr)) 30 | { 31 | Serial.print(" ripaddr: "); 32 | uip_debug_printbytes((const uint8_t *)lhs->ripaddr,4); 33 | Serial.print(" -> "); 34 | uip_debug_printbytes((const uint8_t *)rhs->ripaddr,4); 35 | Serial.println(); 36 | uip_ipaddr_copy(lhs->ripaddr,rhs->ripaddr); 37 | changed = true; 38 | } 39 | if (lhs->lport != rhs->lport) 40 | { 41 | Serial.print(" lport: "); 42 | Serial.print(htons(lhs->lport)); 43 | Serial.print(" -> "); 44 | Serial.println(htons(rhs->lport)); 45 | lhs->lport = rhs->lport; 46 | changed = true; 47 | } 48 | if (lhs->rport != rhs->rport) 49 | { 50 | Serial.print(" rport: "); 51 | Serial.print(htons(lhs->rport)); 52 | Serial.print(" -> "); 53 | Serial.println(htons(rhs->rport)); 54 | lhs->rport = rhs->rport; 55 | changed = true; 56 | } 57 | if ((uint32_t)lhs->rcv_nxt[0] != (uint32_t)rhs->rcv_nxt[0]) 58 | { 59 | Serial.print(" rcv_nxt: "); 60 | uip_debug_printbytes(lhs->rcv_nxt,4); 61 | Serial.print(" -> "); 62 | uip_debug_printbytes(rhs->rcv_nxt,4); 63 | *((uint32_t *)&lhs->rcv_nxt[0]) = (uint32_t)rhs->rcv_nxt[0]; 64 | Serial.println(); 65 | changed = true; 66 | } 67 | if ((uint32_t)lhs->snd_nxt[0] != (uint32_t)rhs->snd_nxt[0]) 68 | { 69 | Serial.print(" snd_nxt: "); 70 | uip_debug_printbytes(lhs->snd_nxt,4); 71 | Serial.print(" -> "); 72 | uip_debug_printbytes(rhs->snd_nxt,4); 73 | *((uint32_t *)&lhs->snd_nxt[0]) = (uint32_t)rhs->snd_nxt[0]; 74 | Serial.println(); 75 | changed = true; 76 | } 77 | if (lhs->len != rhs->len) 78 | { 79 | Serial.print(" len: "); 80 | Serial.print(lhs->len); 81 | Serial.print(" -> "); 82 | Serial.println(rhs->len); 83 | lhs->len = rhs->len; 84 | changed = true; 85 | } 86 | if (lhs->mss != rhs->mss) 87 | { 88 | Serial.print(" mss: "); 89 | Serial.print(lhs->mss); 90 | Serial.print(" -> "); 91 | Serial.println(rhs->mss); 92 | lhs->mss = rhs->mss; 93 | changed = true; 94 | } 95 | if (lhs->initialmss != rhs->initialmss) 96 | { 97 | Serial.print(" initialmss: "); 98 | Serial.print(lhs->initialmss); 99 | Serial.print(" -> "); 100 | Serial.println(rhs->initialmss); 101 | lhs->initialmss = rhs->initialmss; 102 | changed = true; 103 | } 104 | if (lhs->sa != rhs->sa) 105 | { 106 | Serial.print(" sa: "); 107 | Serial.print(lhs->sa); 108 | Serial.print(" -> "); 109 | Serial.println(rhs->sa); 110 | lhs->sa = rhs->sa; 111 | changed = true; 112 | } 113 | if (lhs->sv != rhs->sv) 114 | { 115 | Serial.print(" sv: "); 116 | Serial.print(lhs->sv); 117 | Serial.print(" -> "); 118 | Serial.println(rhs->sv); 119 | lhs->sv = rhs->sv; 120 | changed = true; 121 | } 122 | if (lhs->rto != rhs->rto) 123 | { 124 | Serial.print(" rto: "); 125 | Serial.print(lhs->rto); 126 | Serial.print(" -> "); 127 | Serial.println(rhs->rto); 128 | lhs->rto = rhs->rto; 129 | changed = true; 130 | } 131 | if (lhs->tcpstateflags != rhs->tcpstateflags) 132 | { 133 | Serial.print(" tcpstateflags: "); 134 | Serial.print(lhs->tcpstateflags); 135 | Serial.print(" -> "); 136 | Serial.println(rhs->tcpstateflags); 137 | lhs->tcpstateflags = rhs->tcpstateflags; 138 | changed = true; 139 | } 140 | if (lhs->timer != rhs->timer) 141 | { 142 | Serial.print(" timer: "); 143 | Serial.print(lhs->timer); 144 | Serial.print(" -> "); 145 | Serial.println(rhs->timer); 146 | lhs->timer = rhs->timer; 147 | changed = true; 148 | } 149 | if (lhs->nrtx != rhs->nrtx) 150 | { 151 | Serial.print(" nrtx: "); 152 | Serial.print(lhs->nrtx); 153 | Serial.print(" -> "); 154 | Serial.println(rhs->nrtx); 155 | lhs->nrtx = rhs->nrtx; 156 | changed = true; 157 | } 158 | return changed; 159 | } 160 | 161 | void 162 | UIPDebug::uip_debug_printbytes(const uint8_t *data, uint8_t len) 163 | { 164 | for(uint8_t i=0;i 11 | */ 12 | 13 | /* 14 | * Copyright (c) 2004, Swedish Institute of Computer Science. 15 | * All rights reserved. 16 | * 17 | * Redistribution and use in source and binary forms, with or without 18 | * modification, are permitted provided that the following conditions 19 | * are met: 20 | * 1. Redistributions of source code must retain the above copyright 21 | * notice, this list of conditions and the following disclaimer. 22 | * 2. Redistributions in binary form must reproduce the above copyright 23 | * notice, this list of conditions and the following disclaimer in the 24 | * documentation and/or other materials provided with the distribution. 25 | * 3. Neither the name of the Institute nor the names of its contributors 26 | * may be used to endorse or promote products derived from this software 27 | * without specific prior written permission. 28 | * 29 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 30 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 33 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | * SUCH DAMAGE. 40 | * 41 | * This file is part of the uIP TCP/IP stack 42 | * 43 | * Author: Adam Dunkels 44 | * 45 | * $Id: timer.c,v 1.2 2006/06/12 08:00:30 adam Exp $ 46 | */ 47 | 48 | #include "uip_clock.h" 49 | #include "uip_timer.h" 50 | 51 | /*---------------------------------------------------------------------------*/ 52 | /** 53 | * Set a timer. 54 | * 55 | * This function is used to set a timer for a time sometime in the 56 | * future. The function timer_expired() will evaluate to true after 57 | * the timer has expired. 58 | * 59 | * \param t A pointer to the timer 60 | * \param interval The interval before the timer expires. 61 | * 62 | */ 63 | void 64 | uip_timer_set(struct uip_timer *t, clock_time_t interval) 65 | { 66 | t->interval = interval; 67 | t->start = clock_time(); 68 | } 69 | /*---------------------------------------------------------------------------*/ 70 | /** 71 | * Reset the timer with the same interval. 72 | * 73 | * This function resets the timer with the same interval that was 74 | * given to the timer_set() function. The start point of the interval 75 | * is the exact time that the timer last expired. Therefore, this 76 | * function will cause the timer to be stable over time, unlike the 77 | * timer_rester() function. 78 | * 79 | * \param t A pointer to the timer. 80 | * 81 | * \sa timer_restart() 82 | */ 83 | void 84 | uip_timer_reset(struct uip_timer *t) 85 | { 86 | t->start += t->interval; 87 | } 88 | /*---------------------------------------------------------------------------*/ 89 | /** 90 | * Restart the timer from the current point in time 91 | * 92 | * This function restarts a timer with the same interval that was 93 | * given to the timer_set() function. The timer will start at the 94 | * current time. 95 | * 96 | * \note A periodic timer will drift if this function is used to reset 97 | * it. For preioric timers, use the timer_reset() function instead. 98 | * 99 | * \param t A pointer to the timer. 100 | * 101 | * \sa timer_reset() 102 | */ 103 | void 104 | uip_timer_restart(struct uip_timer *t) 105 | { 106 | t->start = clock_time(); 107 | } 108 | /*---------------------------------------------------------------------------*/ 109 | /** 110 | * Check if a timer has expired. 111 | * 112 | * This function tests if a timer has expired and returns true or 113 | * false depending on its status. 114 | * 115 | * \param t A pointer to the timer 116 | * 117 | * \return Non-zero if the timer has expired, zero otherwise. 118 | * 119 | */ 120 | int 121 | uip_timer_expired(struct uip_timer *t) 122 | { 123 | return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval; 124 | } 125 | /*---------------------------------------------------------------------------*/ 126 | 127 | /** @} */ 128 | -------------------------------------------------------------------------------- /utility/uip_timer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \defgroup timer Timer library 3 | * 4 | * The timer library provides functions for setting, resetting and 5 | * restarting timers, and for checking if a timer has expired. An 6 | * application must "manually" check if its timers have expired; this 7 | * is not done automatically. 8 | * 9 | * A timer is declared as a \c struct \c timer and all access to the 10 | * timer is made by a pointer to the declared timer. 11 | * 12 | * \note The timer library uses the \ref clock "Clock library" to 13 | * measure time. Intervals should be specified in the format used by 14 | * the clock library. 15 | * 16 | * @{ 17 | */ 18 | 19 | 20 | /** 21 | * \file 22 | * Timer library header file. 23 | * \author 24 | * Adam Dunkels 25 | */ 26 | 27 | /* 28 | * Copyright (c) 2004, Swedish Institute of Computer Science. 29 | * All rights reserved. 30 | * 31 | * Redistribution and use in source and binary forms, with or without 32 | * modification, are permitted provided that the following conditions 33 | * are met: 34 | * 1. Redistributions of source code must retain the above copyright 35 | * notice, this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright 37 | * notice, this list of conditions and the following disclaimer in the 38 | * documentation and/or other materials provided with the distribution. 39 | * 3. Neither the name of the Institute nor the names of its contributors 40 | * may be used to endorse or promote products derived from this software 41 | * without specific prior written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 | * SUCH DAMAGE. 54 | * 55 | * This file is part of the uIP TCP/IP stack 56 | * 57 | * Author: Adam Dunkels 58 | * 59 | * $Id: timer.h,v 1.3 2006/06/11 21:46:39 adam Exp $ 60 | */ 61 | #ifndef __UIP_TIMER_H__ 62 | #define __UIP_TIMER_H__ 63 | 64 | #include "uip_clock.h" 65 | 66 | /** 67 | * A timer. 68 | * 69 | * This structure is used for declaring a timer. The timer must be set 70 | * with timer_set() before it can be used. 71 | * 72 | * \hideinitializer 73 | */ 74 | struct uip_timer { 75 | clock_time_t start; 76 | clock_time_t interval; 77 | }; 78 | 79 | void uip_timer_set(struct uip_timer *t, clock_time_t interval); 80 | void uip_timer_reset(struct uip_timer *t); 81 | void uip_timer_restart(struct uip_timer *t); 82 | int uip_timer_expired(struct uip_timer *t); 83 | 84 | #endif /* __UIP_TIMER_H__ */ 85 | 86 | /** @} */ 87 | -------------------------------------------------------------------------------- /utility/uipethernet-conf.h: -------------------------------------------------------------------------------- 1 | #ifndef UIPETHERNET_CONF_H 2 | #define UIPETHERNET_CONF_H 3 | 4 | /* for TCP */ 5 | #define UIP_SOCKET_NUMPACKETS 4 6 | #define UIP_CONF_MAX_CONNECTIONS 4 7 | 8 | /* for UDP 9 | * set UIP_CONF_UDP to 0 to disable UDP (saves aprox. 5kb flash) */ 10 | #define UIP_CONF_UDP 1 11 | #define UIP_CONF_BROADCAST 1 12 | #define UIP_CONF_UDP_CONNS 4 13 | 14 | /* number of attempts on write before returning number of bytes sent so far 15 | * set to -1 to block until connection is closed by timeout */ 16 | #define UIP_ATTEMPTS_ON_WRITE -1 17 | 18 | /* timeout after which UIPClient::connect gives up. The timeout is specified in seconds. 19 | * if set to a number <= 0 connect will timeout when uIP does (which might be longer than you expect...) */ 20 | #define UIP_CONNECT_TIMEOUT -1 21 | 22 | /* periodic timer for uip (in ms) */ 23 | #define UIP_PERIODIC_TIMER 100 24 | 25 | /* timer to poll client for data after last write (in ms) 26 | * set to -1 to disable fast polling and rely on periodic only (saves 100 bytes flash) */ 27 | #define UIP_CLIENT_TIMER 10 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /utility/uipopt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \defgroup uipopt Configuration options for uIP 3 | * @{ 4 | * 5 | * uIP is configured using the per-project configuration file 6 | * uipopt.h. This file contains all compile-time options for uIP and 7 | * should be tweaked to match each specific project. The uIP 8 | * distribution contains a documented example "uipopt.h" that can be 9 | * copied and modified for each project. 10 | * 11 | * \note Most of the configuration options in the uipopt.h should not 12 | * be changed, but rather the per-project uip-conf.h file. 13 | */ 14 | 15 | /** 16 | * \file 17 | * Configuration options for uIP. 18 | * \author Adam Dunkels 19 | * 20 | * This file is used for tweaking various configuration options for 21 | * uIP. You should make a copy of this file into one of your project's 22 | * directories instead of editing this example "uipopt.h" file that 23 | * comes with the uIP distribution. 24 | */ 25 | 26 | /* 27 | * Copyright (c) 2001-2003, Adam Dunkels. 28 | * All rights reserved. 29 | * 30 | * Redistribution and use in source and binary forms, with or without 31 | * modification, are permitted provided that the following conditions 32 | * are met: 33 | * 1. Redistributions of source code must retain the above copyright 34 | * notice, this list of conditions and the following disclaimer. 35 | * 2. Redistributions in binary form must reproduce the above copyright 36 | * notice, this list of conditions and the following disclaimer in the 37 | * documentation and/or other materials provided with the distribution. 38 | * 3. The name of the author may not be used to endorse or promote 39 | * products derived from this software without specific prior 40 | * written permission. 41 | * 42 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 43 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 44 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 46 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 48 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 49 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 50 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 51 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 52 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 | * 54 | * This file is part of the uIP TCP/IP stack. 55 | * 56 | * $Id: uipopt.h,v 1.4 2006/06/12 08:00:31 adam Exp $ 57 | * 58 | */ 59 | 60 | #ifndef __UIPOPT_H__ 61 | #define __UIPOPT_H__ 62 | 63 | #ifndef UIP_LITTLE_ENDIAN 64 | #define UIP_LITTLE_ENDIAN 3412 65 | #endif /* UIP_LITTLE_ENDIAN */ 66 | #ifndef UIP_BIG_ENDIAN 67 | #define UIP_BIG_ENDIAN 1234 68 | #endif /* UIP_BIG_ENDIAN */ 69 | 70 | #include "uip-conf.h" 71 | 72 | /*------------------------------------------------------------------------------*/ 73 | 74 | /** 75 | * \name Static configuration options 76 | * @{ 77 | * 78 | * These configuration options can be used for setting the IP address 79 | * settings statically, but only if UIP_FIXEDADDR is set to 1. The 80 | * configuration options for a specific node includes IP address, 81 | * netmask and default router as well as the Ethernet address. The 82 | * netmask, default router and Ethernet address are appliciable only 83 | * if uIP should be run over Ethernet. 84 | * 85 | * All of these should be changed to suit your project. 86 | */ 87 | 88 | /** 89 | * Determines if uIP should use a fixed IP address or not. 90 | * 91 | * If uIP should use a fixed IP address, the settings are set in the 92 | * uipopt.h file. If not, the macros uip_sethostaddr(), 93 | * uip_setdraddr() and uip_setnetmask() should be used instead. 94 | * 95 | * \hideinitializer 96 | */ 97 | #define UIP_FIXEDADDR 0 98 | 99 | /** 100 | * Ping IP address asignment. 101 | * 102 | * uIP uses a "ping" packets for setting its own IP address if this 103 | * option is set. If so, uIP will start with an empty IP address and 104 | * the destination IP address of the first incoming "ping" (ICMP echo) 105 | * packet will be used for setting the hosts IP address. 106 | * 107 | * \note This works only if UIP_FIXEDADDR is 0. 108 | * 109 | * \hideinitializer 110 | */ 111 | #ifdef UIP_CONF_PINGADDRCONF 112 | #define UIP_PINGADDRCONF UIP_CONF_PINGADDRCONF 113 | #else /* UIP_CONF_PINGADDRCONF */ 114 | #define UIP_PINGADDRCONF 0 115 | #endif /* UIP_CONF_PINGADDRCONF */ 116 | 117 | 118 | /** 119 | * Specifies if the uIP ARP module should be compiled with a fixed 120 | * Ethernet MAC address or not. 121 | * 122 | * If this configuration option is 0, the macro uip_setethaddr() can 123 | * be used to specify the Ethernet address at run-time. 124 | * 125 | * \hideinitializer 126 | */ 127 | #define UIP_FIXEDETHADDR 0 128 | 129 | /** @} */ 130 | /*------------------------------------------------------------------------------*/ 131 | /** 132 | * \name IP configuration options 133 | * @{ 134 | * 135 | */ 136 | /** 137 | * The IP TTL (time to live) of IP packets sent by uIP. 138 | * 139 | * This should normally not be changed. 140 | */ 141 | #define UIP_TTL 64 142 | 143 | /** 144 | * Turn on support for IP packet reassembly. 145 | * 146 | * uIP supports reassembly of fragmented IP packets. This features 147 | * requires an additonal amount of RAM to hold the reassembly buffer 148 | * and the reassembly code size is approximately 700 bytes. The 149 | * reassembly buffer is of the same size as the uip_buf buffer 150 | * (configured by UIP_BUFSIZE). 151 | * 152 | * \note IP packet reassembly is not heavily tested. 153 | * 154 | * \hideinitializer 155 | */ 156 | #define UIP_REASSEMBLY 0 157 | 158 | /** 159 | * The maximum time an IP fragment should wait in the reassembly 160 | * buffer before it is dropped. 161 | * 162 | */ 163 | #define UIP_REASS_MAXAGE 40 164 | 165 | /** @} */ 166 | 167 | /*------------------------------------------------------------------------------*/ 168 | /** 169 | * \name UDP configuration options 170 | * @{ 171 | */ 172 | 173 | /** 174 | * Toggles wether UDP support should be compiled in or not. 175 | * 176 | * \hideinitializer 177 | */ 178 | #ifdef UIP_CONF_UDP 179 | #define UIP_UDP UIP_CONF_UDP 180 | #else /* UIP_CONF_UDP */ 181 | #define UIP_UDP 0 182 | #endif /* UIP_CONF_UDP */ 183 | 184 | /** 185 | * Toggles if UDP checksums should be used or not. 186 | * 187 | * \note Support for UDP checksums is currently not included in uIP, 188 | * so this option has no function. 189 | * 190 | * \hideinitializer 191 | */ 192 | #ifdef UIP_CONF_UDP_CHECKSUMS 193 | #define UIP_UDP_CHECKSUMS UIP_CONF_UDP_CHECKSUMS 194 | #else 195 | #define UIP_UDP_CHECKSUMS 0 196 | #endif 197 | 198 | /** 199 | * The maximum amount of concurrent UDP connections. 200 | * 201 | * \hideinitializer 202 | */ 203 | #ifdef UIP_CONF_UDP_CONNS 204 | #define UIP_UDP_CONNS UIP_CONF_UDP_CONNS 205 | #else /* UIP_CONF_UDP_CONNS */ 206 | #define UIP_UDP_CONNS 10 207 | #endif /* UIP_CONF_UDP_CONNS */ 208 | 209 | /** 210 | * The name of the function that should be called when UDP datagrams arrive. 211 | * 212 | * \hideinitializer 213 | */ 214 | 215 | 216 | /** @} */ 217 | /*------------------------------------------------------------------------------*/ 218 | /** 219 | * \name TCP configuration options 220 | * @{ 221 | */ 222 | 223 | /** 224 | * Determines if support for opening connections from uIP should be 225 | * compiled in. 226 | * 227 | * If the applications that are running on top of uIP for this project 228 | * do not need to open outgoing TCP connections, this configration 229 | * option can be turned off to reduce the code size of uIP. 230 | * 231 | * \hideinitializer 232 | */ 233 | #define UIP_ACTIVE_OPEN 1 234 | 235 | /** 236 | * The maximum number of simultaneously open TCP connections. 237 | * 238 | * Since the TCP connections are statically allocated, turning this 239 | * configuration knob down results in less RAM used. Each TCP 240 | * connection requires approximatly 30 bytes of memory. 241 | * 242 | * \hideinitializer 243 | */ 244 | #ifndef UIP_CONF_MAX_CONNECTIONS 245 | #define UIP_CONNS 10 246 | #else /* UIP_CONF_MAX_CONNECTIONS */ 247 | #define UIP_CONNS UIP_CONF_MAX_CONNECTIONS 248 | #endif /* UIP_CONF_MAX_CONNECTIONS */ 249 | 250 | 251 | /** 252 | * The maximum number of simultaneously listening TCP ports. 253 | * 254 | * Each listening TCP port requires 2 bytes of memory. 255 | * 256 | * \hideinitializer 257 | */ 258 | #ifndef UIP_CONF_MAX_LISTENPORTS 259 | #define UIP_LISTENPORTS 20 260 | #else /* UIP_CONF_MAX_LISTENPORTS */ 261 | #define UIP_LISTENPORTS UIP_CONF_MAX_LISTENPORTS 262 | #endif /* UIP_CONF_MAX_LISTENPORTS */ 263 | 264 | /** 265 | * Determines if support for TCP urgent data notification should be 266 | * compiled in. 267 | * 268 | * Urgent data (out-of-band data) is a rarely used TCP feature that 269 | * very seldom would be required. 270 | * 271 | * \hideinitializer 272 | */ 273 | #define UIP_URGDATA 0 274 | 275 | /** 276 | * The initial retransmission timeout counted in timer pulses. 277 | * 278 | * This should not be changed. 279 | */ 280 | #define UIP_RTO 3 281 | 282 | /** 283 | * The maximum number of times a segment should be retransmitted 284 | * before the connection should be aborted. 285 | * 286 | * This should not be changed. 287 | */ 288 | #define UIP_MAXRTX 8 289 | 290 | /** 291 | * The maximum number of times a SYN segment should be retransmitted 292 | * before a connection request should be deemed to have been 293 | * unsuccessful. 294 | * 295 | * This should not need to be changed. 296 | */ 297 | #define UIP_MAXSYNRTX 5 298 | 299 | /** 300 | * The TCP maximum segment size. 301 | * 302 | * This is should not be to set to more than 303 | * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. 304 | */ 305 | #ifndef UIP_CONF_TCP_MSS 306 | #define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) 307 | #else 308 | #define UIP_TCP_MSS UIP_CONF_TCP_MSS 309 | #endif 310 | 311 | /** 312 | * The size of the advertised receiver's window. 313 | * 314 | * Should be set low (i.e., to the size of the uip_buf buffer) is the 315 | * application is slow to process incoming data, or high (32768 bytes) 316 | * if the application processes data quickly. 317 | * 318 | * \hideinitializer 319 | */ 320 | #ifndef UIP_CONF_RECEIVE_WINDOW 321 | #define UIP_RECEIVE_WINDOW UIP_TCP_MSS 322 | #else 323 | #define UIP_RECEIVE_WINDOW UIP_CONF_RECEIVE_WINDOW 324 | #endif 325 | 326 | /** 327 | * How long a connection should stay in the TIME_WAIT state. 328 | * 329 | * This configiration option has no real implication, and it should be 330 | * left untouched. 331 | */ 332 | #define UIP_TIME_WAIT_TIMEOUT 120 333 | 334 | 335 | /** @} */ 336 | /*------------------------------------------------------------------------------*/ 337 | /** 338 | * \name ARP configuration options 339 | * @{ 340 | */ 341 | 342 | /** 343 | * The size of the ARP table. 344 | * 345 | * This option should be set to a larger value if this uIP node will 346 | * have many connections from the local network. 347 | * 348 | * \hideinitializer 349 | */ 350 | #ifdef UIP_CONF_ARPTAB_SIZE 351 | #define UIP_ARPTAB_SIZE UIP_CONF_ARPTAB_SIZE 352 | #else 353 | #define UIP_ARPTAB_SIZE 8 354 | #endif 355 | 356 | /** 357 | * The maxium age of ARP table entries measured in 10ths of seconds. 358 | * 359 | * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD 360 | * default). 361 | */ 362 | #define UIP_ARP_MAXAGE 120 363 | 364 | /** @} */ 365 | 366 | /*------------------------------------------------------------------------------*/ 367 | 368 | /** 369 | * \name General configuration options 370 | * @{ 371 | */ 372 | 373 | /** 374 | * The size of the uIP packet buffer. 375 | * 376 | * The uIP packet buffer should not be smaller than 60 bytes, and does 377 | * not need to be larger than 1500 bytes. Lower size results in lower 378 | * TCP throughput, larger size results in higher TCP throughput. 379 | * 380 | * \hideinitializer 381 | */ 382 | #ifndef UIP_CONF_BUFFER_SIZE 383 | #define UIP_BUFSIZE 400 384 | #else /* UIP_CONF_BUFFER_SIZE */ 385 | #define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE 386 | #endif /* UIP_CONF_BUFFER_SIZE */ 387 | 388 | 389 | /** 390 | * Determines if statistics support should be compiled in. 391 | * 392 | * The statistics is useful for debugging and to show the user. 393 | * 394 | * \hideinitializer 395 | */ 396 | #ifndef UIP_CONF_STATISTICS 397 | #define UIP_STATISTICS 0 398 | #else /* UIP_CONF_STATISTICS */ 399 | #define UIP_STATISTICS UIP_CONF_STATISTICS 400 | #endif /* UIP_CONF_STATISTICS */ 401 | 402 | /** 403 | * Determines if logging of certain events should be compiled in. 404 | * 405 | * This is useful mostly for debugging. The function uip_log() 406 | * must be implemented to suit the architecture of the project, if 407 | * logging is turned on. 408 | * 409 | * \hideinitializer 410 | */ 411 | #ifndef UIP_CONF_LOGGING 412 | #define UIP_LOGGING 0 413 | #else /* UIP_CONF_LOGGING */ 414 | #define UIP_LOGGING UIP_CONF_LOGGING 415 | #endif /* UIP_CONF_LOGGING */ 416 | 417 | /** 418 | * Broadcast support. 419 | * 420 | * This flag configures IP broadcast support. This is useful only 421 | * together with UDP. 422 | * 423 | * \hideinitializer 424 | * 425 | */ 426 | #if UIP_UDP && UIP_CONF_BROADCAST 427 | #define UIP_BROADCAST UIP_CONF_BROADCAST 428 | #else /* UIP_CONF_BROADCAST */ 429 | #define UIP_BROADCAST 0 430 | #endif /* UIP_CONF_BROADCAST */ 431 | 432 | /** 433 | * Print out a uIP log message. 434 | * 435 | * This function must be implemented by the module that uses uIP, and 436 | * is called by uIP whenever a log message is generated. 437 | */ 438 | void uip_log(char *msg); 439 | 440 | /** 441 | * The link level header length. 442 | * 443 | * This is the offset into the uip_buf where the IP header can be 444 | * found. For Ethernet, this should be set to 14. For SLIP, this 445 | * should be set to 0. 446 | * 447 | * \hideinitializer 448 | */ 449 | #ifdef UIP_CONF_LLH_LEN 450 | #define UIP_LLH_LEN UIP_CONF_LLH_LEN 451 | #else /* UIP_CONF_LLH_LEN */ 452 | #define UIP_LLH_LEN 14 453 | #endif /* UIP_CONF_LLH_LEN */ 454 | 455 | /** @} */ 456 | /*------------------------------------------------------------------------------*/ 457 | /** 458 | * \name CPU architecture configuration 459 | * @{ 460 | * 461 | * The CPU architecture configuration is where the endianess of the 462 | * CPU on which uIP is to be run is specified. Most CPUs today are 463 | * little endian, and the most notable exception are the Motorolas 464 | * which are big endian. The BYTE_ORDER macro should be changed to 465 | * reflect the CPU architecture on which uIP is to be run. 466 | */ 467 | 468 | /** 469 | * The byte order of the CPU architecture on which uIP is to be run. 470 | * 471 | * This option can be either BIG_ENDIAN (Motorola byte order) or 472 | * LITTLE_ENDIAN (Intel byte order). 473 | * 474 | * \hideinitializer 475 | */ 476 | #ifdef UIP_CONF_BYTE_ORDER 477 | #define UIP_BYTE_ORDER UIP_CONF_BYTE_ORDER 478 | #else /* UIP_CONF_BYTE_ORDER */ 479 | #define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN 480 | #endif /* UIP_CONF_BYTE_ORDER */ 481 | 482 | /** @} */ 483 | /*------------------------------------------------------------------------------*/ 484 | 485 | /** 486 | * \name Appication specific configurations 487 | * @{ 488 | * 489 | * An uIP application is implemented using a single application 490 | * function that is called by uIP whenever a TCP/IP event occurs. The 491 | * name of this function must be registered with uIP at compile time 492 | * using the UIP_APPCALL definition. 493 | * 494 | * uIP applications can store the application state within the 495 | * uip_conn structure by specifying the type of the application 496 | * structure by typedef:ing the type uip_tcp_appstate_t and uip_udp_appstate_t. 497 | * 498 | * The file containing the definitions must be included in the 499 | * uipopt.h file. 500 | * 501 | * The following example illustrates how this can look. 502 | \code 503 | 504 | void httpd_appcall(void); 505 | #define UIP_APPCALL httpd_appcall 506 | 507 | struct httpd_state { 508 | u8_t state; 509 | u16_t count; 510 | char *dataptr; 511 | char *script; 512 | }; 513 | typedef struct httpd_state uip_tcp_appstate_t 514 | \endcode 515 | */ 516 | 517 | /** 518 | * \var #define UIP_APPCALL 519 | * 520 | * The name of the application function that uIP should call in 521 | * response to TCP/IP events. 522 | * 523 | */ 524 | 525 | /** 526 | * \var typedef uip_tcp_appstate_t 527 | * 528 | * The type of the application state that is to be stored in the 529 | * uip_conn structure. This usually is typedef:ed to a struct holding 530 | * application state information. 531 | */ 532 | 533 | /** 534 | * \var typedef uip_udp_appstate_t 535 | * 536 | * The type of the application state that is to be stored in the 537 | * uip_conn structure. This usually is typedef:ed to a struct holding 538 | * application state information. 539 | */ 540 | /** @} */ 541 | /** @} */ 542 | 543 | #endif /* __UIPOPT_H__ */ 544 | -------------------------------------------------------------------------------- /utility/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | #define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) ) 5 | #define ntohs(x) htons(x) 6 | 7 | #define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \ 8 | ((x)<< 8 & 0x00FF0000UL) | \ 9 | ((x)>> 8 & 0x0000FF00UL) | \ 10 | ((x)>>24 & 0x000000FFUL) ) 11 | #define ntohl(x) htonl(x) 12 | 13 | #endif 14 | --------------------------------------------------------------------------------