Hiroshi Yamaguchi / SimpleSocket 1.0

Dependents:   SimpleSocketExamples 1.0

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ClientSocket.cpp Source File

ClientSocket.cpp

00001 /*
00002 Copyright (c) 2011, Senio Networks, Inc.
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 #include "SimpleSocket.h"
00024 #include <stdarg.h>
00025 
00026 ClientSocket::ClientSocket(IpAddr ip, TCPSocket *socket, bool debug)
00027         : ip(ip), socket(socket), readable(true), writable(true), preread(-1),
00028         state(CONNECTED), debug(debug) {
00029     if (socket)
00030         socket->setOnEvent(this, &ClientSocket::onTCPSocketEvent);
00031 }
00032 
00033 ClientSocket::ClientSocket(IpAddr ip, int port, float timeout, bool debug)
00034         : readable(true), writable(true), preread(-1), debug(debug) {
00035     createClientSocket(ip, port, timeout);
00036 }
00037 
00038 ClientSocket::ClientSocket(char *hostname, int port, float timeout, bool debug)
00039         : readable(true), writable(true), preread(-1), debug(debug) {
00040     Resolver resolver;
00041     createClientSocket(resolver.resolve(hostname, debug), port, timeout);
00042 }
00043 
00044 ClientSocket::ClientSocket(const ClientSocket& that) {
00045     *this = that;
00046     ::printf("cc called\n");
00047 }
00048 
00049 void ClientSocket::createClientSocket(IpAddr ip, int port, float timeout) {
00050     this->ip = ip;
00051     socket = new TCPSocket();
00052     socket->setOnEvent(this, &ClientSocket::onTCPSocketEvent);
00053     SocketError err = socket->connect(Host(ip, port));
00054     if (!err) {
00055         Timer timer;
00056         timer.start();
00057         state = CONNECTING;
00058         while (state == CONNECTING && timer.read() < timeout) {
00059             Net::poll();
00060             if (state == CONNECTED)
00061                 return;
00062             wait_us(100);
00063         }
00064     } else
00065         DBG(SocketError(err));
00066 
00067     writable = false;
00068     state = DISCONNECTED;
00069     socket->resetOnEvent();
00070     socket->close();
00071     delete socket;
00072     socket = 0;
00073 }
00074 
00075 IpAddr ClientSocket::getIp() {
00076     return ip;
00077 }
00078 
00079 bool ClientSocket::connected() {
00080     if (socket)
00081         Net::poll();
00082 
00083     if (!readable && state == DISCONNECTED)
00084         close();
00085 
00086     return socket != 0;
00087 }
00088 
00089 bool ClientSocket::available() {
00090     if (preread != -1)
00091         return true;
00092 
00093     if (!readable)
00094         Net::poll();
00095 
00096     if (readable) {
00097         char c;
00098         int ret = socket->recv(&c, 1);
00099         if (ret > 0) {
00100             preread = c;
00101             return true;
00102         } else
00103             readable = false;
00104     }
00105 
00106     if (!readable && state == DISCONNECTED)
00107         close();
00108 
00109     return false;
00110 }
00111 
00112 void ClientSocket::onTCPSocketEvent(TCPSocketEvent e) {
00113     DBG(SocketEvent(e));
00114 
00115     switch (e) {
00116         case TCPSOCKET_CONNECTED:
00117             state = CONNECTED;
00118             break;
00119         case TCPSOCKET_READABLE:
00120             readable = true;
00121             break;
00122         case TCPSOCKET_WRITEABLE:
00123             writable = true;
00124             break;
00125         case TCPSOCKET_DISCONNECTED:
00126             state = DISCONNECTED;
00127             break;
00128     }
00129 }
00130 
00131 int ClientSocket::read() {
00132     char c;
00133 
00134     if (preread != -1) {
00135         c = preread & 255;
00136         preread = -1;
00137         return c;
00138     }
00139 
00140     int ret = socket->recv(&c, 1);
00141     if (ret > 0) {
00142         return (int) c & 255;
00143     } else {
00144         readable = false;
00145         return -1;
00146     }
00147 }
00148 
00149 int ClientSocket::read(char *buf, int size) {
00150     int req = size;
00151 
00152     if (preread != -1 && size > 0) {
00153         *buf++ = preread & 255;
00154         preread = -1;
00155         req--;
00156     }
00157 
00158     while (req > 0) {
00159         int got = socket->recv(buf, req);
00160         if (got > 0) {
00161             buf += got;
00162             req -= got;
00163         } else {
00164             readable = false;
00165             break;
00166         }
00167     }
00168 
00169     return size - req;
00170 }
00171 
00172 int ClientSocket::scanf(const char* format, ...) {
00173     va_list argp;
00174     va_start(argp, format);
00175     char buf[256];
00176 
00177     int len = read(buf, sizeof(buf) - 1);
00178     if (len <= 0)
00179         return 0;
00180     buf[len] = '\0';
00181 
00182     int ret = vsscanf(buf, format, argp);
00183     va_end(argp);
00184     return ret;
00185 }
00186 
00187 int ClientSocket::write(char c) {
00188     return write(&c, 1);
00189 }
00190 
00191 int ClientSocket::write(char *buf, int size) {
00192     int ret = socket->send(buf, size);
00193     if (ret > 0) {
00194         return ret;
00195     } else {
00196         writable = false;
00197         return -1;
00198     }
00199 }
00200 
00201 int ClientSocket::printf(const char* format, ...) {
00202     va_list argp;
00203     va_start(argp, format);
00204     char buf[256];
00205 
00206     int len = vsnprintf(buf, sizeof(buf), format, argp);
00207     va_end(argp);
00208     return write(buf, len);
00209 }
00210 
00211 void ClientSocket::close() {
00212     if (socket) {
00213         readable = false;
00214         writable = false;
00215         socket->resetOnEvent();
00216         socket->close();
00217         delete socket;
00218         socket = 0;
00219     }
00220 }
00221 
00222 ClientSocket::operator bool() {
00223     return connected();
00224 }
00225 
00226 void ClientSocket::setDebug(bool debug) {
00227     this->debug = debug;
00228 }