Skip to content

Commit ecbdc65

Browse files
committed
add UIPClientExt with nonblocking connect
1 parent 612d901 commit ecbdc65

File tree

4 files changed

+210
-0
lines changed

4 files changed

+210
-0
lines changed

UIPClient.h

+13
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,22 @@ class UIPClient : public Client {
9898

9999
friend class UIPEthernetClass;
100100
friend class UIPServer;
101+
friend class UIPClientExt;
101102

102103
friend void uipclient_appcall(void);
104+
};
105+
106+
class UIPClientExt : public UIPClient {
107+
108+
public:
109+
UIPClientExt();
110+
int connectNB(IPAddress ip, uint16_t port);
111+
void stop();
112+
uint8_t connected();
113+
operator bool();
103114

115+
private:
116+
struct uip_conn* conn;
104117
};
105118

106119
#endif

UIPClientExt.cpp

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
UIPClient.cpp - Arduino implementation of a uIP wrapper class.
3+
Copyright (c) 2013 Norbert Truchsess <[email protected]>
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 <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
extern "C"
21+
{
22+
#import "utility/uip-conf.h"
23+
#import "utility/uip.h"
24+
#import "utility/uip_arp.h"
25+
#import "string.h"
26+
}
27+
#include "UIPEthernet.h"
28+
#include "UIPClient.h"
29+
#include "Dns.h"
30+
31+
#ifdef UIPETHERNET_DEBUG_CLIENT
32+
#include "HardwareSerial.h"
33+
#endif
34+
35+
UIPClientExt::UIPClientExt() :
36+
conn(NULL)
37+
{
38+
UIPClient();
39+
}
40+
41+
int
42+
UIPClientExt::connectNB(IPAddress ip, uint16_t port)
43+
{
44+
stop();
45+
uip_ipaddr_t ipaddr;
46+
uip_ip_addr(ipaddr, ip);
47+
conn = uip_connect(&ipaddr, htons(port));
48+
return conn ? 1 : 0;
49+
}
50+
51+
void
52+
UIPClientExt::stop()
53+
{
54+
if (!data && conn)
55+
conn->tcpstateflags = UIP_CLOSED;
56+
else
57+
{
58+
conn = NULL;
59+
UIPClient::stop();
60+
}
61+
}
62+
63+
uint8_t
64+
UIPClientExt::connected()
65+
{
66+
return this ? UIPClient::connected() : 0;
67+
}
68+
69+
UIPClientExt::operator bool()
70+
{
71+
UIPEthernetClass::tick();
72+
if (conn && !data && (conn->tcpstateflags & UIP_TS_MASK) != UIP_CLOSED)
73+
{
74+
if ((conn->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED)
75+
{
76+
data = (uip_userdata_t*) conn->appstate;
77+
#ifdef UIPETHERNET_DEBUG_CLIENT
78+
Serial.print(F("connected, state: "));
79+
Serial.print(data->state);
80+
Serial.print(F(", first packet in: "));
81+
Serial.println(data->packets_in[0]);
82+
#endif
83+
}
84+
return true;
85+
}
86+
return data && (!(data->state & UIP_CLIENT_REMOTECLOSED) || data->packets_in[0] != NOBLOCK);
87+
}

UIPEthernet.h

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class UIPEthernetClass
102102
friend class UIPServer;
103103

104104
friend class UIPClient;
105+
friend class UIPClientExt;
105106

106107
friend class UIPUDP;
107108

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* UIPEthernet NonBlockingTcpClient 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 <[email protected]>
8+
*
9+
* -----------------
10+
*
11+
* This NonBlockingTcpClient example gets its local ip-address via dhcp and
12+
* attempts to connect via tcp socket-connection to 192.168.0.1 port 5000.
13+
* After initiating the connection it waits for up to 5 seconds for the
14+
* connection to be established.
15+
* If connected successfully it sends a message and waits for a response.
16+
* After receiving the response the client disconnects and tries to reconnect
17+
* after 5 seconds.
18+
* If the connection-attempt does not succeed within 5 seconds the connection
19+
* is cleaned up (calling stop()).
20+
*
21+
* Copyright (C) 2013 by Norbert Truchsess <[email protected]>
22+
*/
23+
24+
#include <UIPEthernet.h>
25+
26+
UIPClientExt client;
27+
signed long next;
28+
29+
void setup() {
30+
31+
Serial.begin(9600);
32+
33+
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
34+
Ethernet.begin(mac);
35+
36+
Serial.print(F("localIP: "));
37+
Serial.println(Ethernet.localIP());
38+
Serial.print(F("subnetMask: "));
39+
Serial.println(Ethernet.subnetMask());
40+
Serial.print(F("gatewayIP: "));
41+
Serial.println(Ethernet.gatewayIP());
42+
Serial.print(F("dnsServerIP: "));
43+
Serial.println(Ethernet.dnsServerIP());
44+
45+
next = 0;
46+
}
47+
48+
void loop() {
49+
50+
if (((signed long)(millis() - next)) > 0)
51+
{
52+
next = millis() + 5000;
53+
Serial.println(F("Client connect"));
54+
// connectNB returns without waiting for the connection to be established (non-blocking behaviour)
55+
if (client.connectNB(IPAddress(192,168,0,1),5000))
56+
{
57+
Serial.println(F("waiting for connection to be established"));
58+
// as long the connection is being established the boolean operator of client returns true,
59+
// but client.connected() return false (0).
60+
do
61+
{
62+
if (!client)
63+
{
64+
Serial.println(F("connection refused"));
65+
break;
66+
}
67+
if (client.connected())
68+
{
69+
Serial.println(F("Client connected"));
70+
break;
71+
}
72+
if ((signed long)(millis() - next) > 0)
73+
{
74+
Serial.println(F("timed out"));
75+
break;
76+
}
77+
}
78+
while (true);
79+
80+
if (client.connected())
81+
{
82+
client.println(F("DATA from Client"));
83+
while(client.available()==0)
84+
{
85+
if (next - millis() < 0)
86+
goto close;
87+
}
88+
int size;
89+
while((size = client.available()) > 0)
90+
{
91+
uint8_t* msg = (uint8_t*)malloc(size);
92+
size = client.read(msg,size);
93+
Serial.write(msg,size);
94+
free(msg);
95+
}
96+
close:
97+
//disconnect client
98+
Serial.println(F("Client disconnect"));
99+
client.stop();
100+
}
101+
else
102+
{
103+
Serial.println(F("Client connect failed"));
104+
}
105+
}
106+
else
107+
Serial.println(F("Client connect failed"));
108+
}
109+
}

0 commit comments

Comments
 (0)