Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Ethernet / EthernetClient.cpp @ 58d82c77

History | View | Annotate | Download (3.26 KB)

1
#include "w5100.h"
2
#include "socket.h"
3

    
4
extern "C" {
5
  #include "string.h"
6
}
7

    
8
#include "Arduino.h"
9

    
10
#include "Ethernet.h"
11
#include "EthernetClient.h"
12
#include "EthernetServer.h"
13
#include "Dns.h"
14

    
15
uint16_t EthernetClient::_srcport = 1024;
16

    
17
EthernetClient::EthernetClient() : _sock(MAX_SOCK_NUM) {
18
}
19

    
20
EthernetClient::EthernetClient(uint8_t sock) : _sock(sock) {
21
}
22

    
23
int EthernetClient::connect(const char* host, uint16_t port) {
24
  // Look up the host first
25
  int ret = 0;
26
  DNSClient dns;
27
  IPAddress remote_addr;
28

    
29
  dns.begin(Ethernet.dnsServerIP());
30
  ret = dns.getHostByName(host, remote_addr);
31
  if (ret == 1) {
32
    return connect(remote_addr, port);
33
  } else {
34
    return ret;
35
  }
36
}
37

    
38
int EthernetClient::connect(IPAddress ip, uint16_t port) {
39
  if (_sock != MAX_SOCK_NUM)
40
    return 0;
41

    
42
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
43
    uint8_t s = W5100.readSnSR(i);
44
    if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
45
      _sock = i;
46
      break;
47
    }
48
  }
49

    
50
  if (_sock == MAX_SOCK_NUM)
51
    return 0;
52

    
53
  _srcport++;
54
  if (_srcport == 0) _srcport = 1024;
55
  socket(_sock, SnMR::TCP, _srcport, 0);
56

    
57
  if (!::connect(_sock, rawIPAddress(ip), port)) {
58
    _sock = MAX_SOCK_NUM;
59
    return 0;
60
  }
61

    
62
  while (status() != SnSR::ESTABLISHED) {
63
    delay(1);
64
    if (status() == SnSR::CLOSED) {
65
      _sock = MAX_SOCK_NUM;
66
      return 0;
67
    }
68
  }
69

    
70
  return 1;
71
}
72

    
73
size_t EthernetClient::write(uint8_t b) {
74
  return write(&b, 1);
75
}
76

    
77
size_t EthernetClient::write(const uint8_t *buf, size_t size) {
78
  if (_sock == MAX_SOCK_NUM) {
79
    setWriteError();
80
    return 0;
81
  }
82
  if (!send(_sock, buf, size)) {
83
    setWriteError();
84
    return 0;
85
  }
86
  return size;
87
}
88

    
89
int EthernetClient::available() {
90
  if (_sock != MAX_SOCK_NUM)
91
    return W5100.getRXReceivedSize(_sock);
92
  return 0;
93
}
94

    
95
int EthernetClient::read() {
96
  uint8_t b;
97
  if ( recv(_sock, &b, 1) > 0 )
98
  {
99
    // recv worked
100
    return b;
101
  }
102
  else
103
  {
104
    // No data available
105
    return -1;
106
  }
107
}
108

    
109
int EthernetClient::read(uint8_t *buf, size_t size) {
110
  return recv(_sock, buf, size);
111
}
112

    
113
int EthernetClient::peek() {
114
  uint8_t b;
115
  // Unlike recv, peek doesn't check to see if there's any data available, so we must
116
  if (!available())
117
    return -1;
118
  ::peek(_sock, &b);
119
  return b;
120
}
121

    
122
void EthernetClient::flush() {
123
  while (available())
124
    read();
125
}
126

    
127
void EthernetClient::stop() {
128
  if (_sock == MAX_SOCK_NUM)
129
    return;
130

    
131
  // attempt to close the connection gracefully (send a FIN to other side)
132
  disconnect(_sock);
133
  unsigned long start = millis();
134

    
135
  // wait a second for the connection to close
136
  while (status() != SnSR::CLOSED && millis() - start < 1000)
137
    delay(1);
138

    
139
  // if it hasn't closed, close it forcefully
140
  if (status() != SnSR::CLOSED)
141
    close(_sock);
142

    
143
  EthernetClass::_server_port[_sock] = 0;
144
  _sock = MAX_SOCK_NUM;
145
}
146

    
147
uint8_t EthernetClient::connected() {
148
  if (_sock == MAX_SOCK_NUM) return 0;
149
  
150
  uint8_t s = status();
151
  return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT ||
152
    (s == SnSR::CLOSE_WAIT && !available()));
153
}
154

    
155
uint8_t EthernetClient::status() {
156
  if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
157
  return W5100.readSnSR(_sock);
158
}
159

    
160
// the next function allows us to use the client returned by
161
// EthernetServer::available() as the condition in an if-statement.
162

    
163
EthernetClient::operator bool() {
164
  return _sock != MAX_SOCK_NUM;
165
}