D:/DRISSI/arduino-0022/arduino-0022/libraries/Ethernet/Client.cpp
00001 #include "w5100.h"
00002 #include "socket.h"
00003 
00004 extern "C" {
00005   #include "string.h"
00006 }
00007 
00008 #include "WProgram.h"
00009 
00010 #include "Ethernet.h"
00011 #include "Client.h"
00012 #include "Server.h"
00013 
00014 uint16_t Client::_srcport = 1024;
00015 
00016 Client::Client(uint8_t sock) : _sock(sock) {
00017 }
00018 
00019 Client::Client(uint8_t *ip, uint16_t port) : _ip(ip), _port(port), _sock(MAX_SOCK_NUM) {
00020 }
00021 
00022 uint8_t Client::connect() {
00023   if (_sock != MAX_SOCK_NUM)
00024     return 0;
00025 
00026   for (int i = 0; i < MAX_SOCK_NUM; i++) {
00027     uint8_t s = W5100.readSnSR(i);
00028     if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) {
00029       _sock = i;
00030       break;
00031     }
00032   }
00033 
00034   if (_sock == MAX_SOCK_NUM)
00035     return 0;
00036 
00037   _srcport++;
00038   if (_srcport == 0) _srcport = 1024;
00039   socket(_sock, SnMR::TCP, _srcport, 0);
00040 
00041   if (!::connect(_sock, _ip, _port)) {
00042     _sock = MAX_SOCK_NUM;
00043     return 0;
00044   }
00045 
00046   while (status() != SnSR::ESTABLISHED) {
00047     delay(1);
00048     if (status() == SnSR::CLOSED) {
00049       _sock = MAX_SOCK_NUM;
00050       return 0;
00051     }
00052   }
00053 
00054   return 1;
00055 }
00056 
00057 void Client::write(uint8_t b) {
00058   if (_sock != MAX_SOCK_NUM)
00059     send(_sock, &b, 1);
00060 }
00061 
00062 void Client::write(const char *str) {
00063   if (_sock != MAX_SOCK_NUM)
00064     send(_sock, (const uint8_t *)str, strlen(str));
00065 }
00066 
00067 void Client::write(const uint8_t *buf, size_t size) {
00068   if (_sock != MAX_SOCK_NUM)
00069     send(_sock, buf, size);
00070 }
00071 
00072 int Client::available() {
00073   if (_sock != MAX_SOCK_NUM)
00074     return W5100.getRXReceivedSize(_sock);
00075   return 0;
00076 }
00077 
00078 int Client::read() {
00079   uint8_t b;
00080   if (!available())
00081     return -1;
00082   recv(_sock, &b, 1);
00083   return b;
00084 }
00085 
00086 int Client::peek() {
00087   uint8_t b;
00088   if (!available())
00089     return -1;
00090   ::peek(_sock, &b);
00091   return b;
00092 }
00093 
00094 void Client::flush() {
00095   while (available())
00096     read();
00097 }
00098 
00099 void Client::stop() {
00100   if (_sock == MAX_SOCK_NUM)
00101     return;
00102 
00103   // attempt to close the connection gracefully (send a FIN to other side)
00104   disconnect(_sock);
00105   unsigned long start = millis();
00106 
00107   // wait a second for the connection to close
00108   while (status() != SnSR::CLOSED && millis() - start < 1000)
00109     delay(1);
00110 
00111   // if it hasn't closed, close it forcefully
00112   if (status() != SnSR::CLOSED)
00113     close(_sock);
00114 
00115   EthernetClass::_server_port[_sock] = 0;
00116   _sock = MAX_SOCK_NUM;
00117 }
00118 
00119 uint8_t Client::connected() {
00120   if (_sock == MAX_SOCK_NUM) return 0;
00121   
00122   uint8_t s = status();
00123   return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT ||
00124     (s == SnSR::CLOSE_WAIT && !available()));
00125 }
00126 
00127 uint8_t Client::status() {
00128   if (_sock == MAX_SOCK_NUM) return SnSR::CLOSED;
00129   return W5100.readSnSR(_sock);
00130 }
00131 
00132 // the next three functions are a hack so we can compare the client returned
00133 // by Server::available() to null, or use it as the condition in an
00134 // if-statement.  this lets us stay compatible with the Processing network
00135 // library.
00136 
00137 uint8_t Client::operator==(int p) {
00138   return _sock == MAX_SOCK_NUM;
00139 }
00140 
00141 uint8_t Client::operator!=(int p) {
00142   return _sock != MAX_SOCK_NUM;
00143 }
00144 
00145 Client::operator bool() {
00146   return _sock != MAX_SOCK_NUM;
00147 }