A Simple TCP & UDP Socket Library. An update from that of Hiroshi Yamaguchi.
Diff: ClientSocket.cpp
- Revision:
- 0:1e4a74c2c16f
diff -r 000000000000 -r 1e4a74c2c16f ClientSocket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ClientSocket.cpp Wed May 23 16:26:44 2012 +0000 @@ -0,0 +1,237 @@ +/* +Copyright (c) 2011, Senio Networks, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "SimpleSocket.h" +#include <stdarg.h> + +ClientSocket::ClientSocket(IpAddr ip, TCPSocket *socket, bool debug) + : ip(ip), socket(socket), readable(true), writable(true), preread(false), + state(CONNECTED), debug(debug) { + if (socket) + socket->setOnEvent(this, &ClientSocket::onTCPSocketEvent); +} + +ClientSocket::ClientSocket(IpAddr ip, int port, float timeout, bool debug) + : readable(true), writable(true), preread(false), debug(debug) { + createClientSocket(ip, port, timeout); +} + +ClientSocket::ClientSocket(char *hostname, int port, float timeout, bool debug) + : readable(true), writable(true), preread(false), debug(debug) { + Resolver resolver; + createClientSocket(resolver.resolve(hostname, debug), port, timeout); +} + +ClientSocket::ClientSocket(const ClientSocket& that) { + *this = that; + ::printf("cc called\n"); +} + +void ClientSocket::createClientSocket(IpAddr ip, int port, float timeout) { + this->ip = ip; + socket = new TCPSocket(); + socket->setOnEvent(this, &ClientSocket::onTCPSocketEvent); + SocketError err = socket->connect(Host(ip, port)); + if (!err) { + Timer timer; + timer.start(); + state = CONNECTING; + while (state == CONNECTING && timer.read() < timeout) { + Net::poll(); + if (state == CONNECTED) + return; + wait_us(100); + } + } else + DBG(SocketError(err)); + + writable = false; + state = DISCONNECTED; + socket->resetOnEvent(); + socket->close(); + delete socket; + socket = 0; +} + +IpAddr ClientSocket::getIp() { + return ip; +} + +bool ClientSocket::connected() { + if (socket) + Net::poll(); + + if (!readable && state == DISCONNECTED) + close(); + + return socket != 0; +} + +bool ClientSocket::available() { + if (preread) + return true; + + if (!readable) + Net::poll(); + + if (readable) { + char c; + int ret = socket->recv(&c, 1); + if (ret > 0) + { + preread = true; + preread_byte = c; + return true; + } + else + readable = false; + } + + if (!readable && state == DISCONNECTED) + close(); + + return false; +} + +void ClientSocket::onTCPSocketEvent(TCPSocketEvent e) { + DBG(SocketEvent(e)); + + switch (e) { + case TCPSOCKET_CONNECTED: + state = CONNECTED; + break; + case TCPSOCKET_READABLE: + readable = true; + break; + case TCPSOCKET_WRITEABLE: + writable = true; + break; + case TCPSOCKET_DISCONNECTED: + state = DISCONNECTED; + break; + } +} + +int ClientSocket::read() { + char c; + + if (preread) + { + preread = false; + c = preread_byte; + return c; + } + + int ret = socket->recv(&c, 1); + if (ret > 0) { + return (int) c & 255; + } else { + readable = false; + return -1; + } +} + +int ClientSocket::read(char *buf, int size) { + int req = size; + + if (preread && size > 0) + { + preread = false; + *buf++ = preread_byte; + req--; + } + + while (req > 0) + { + int got = socket->recv(buf, req); + if (got > 0) + { + buf += got; + req -= got; + } + else + { + readable = false; + break; + } + } + + return size - req; +} + +int ClientSocket::scanf(const char* format, ...) { + va_list argp; + va_start(argp, format); + char buf[256]; + + int len = read(buf, sizeof(buf) - 1); + if (len <= 0) + return 0; + buf[len] = '\0'; + + int ret = vsscanf(buf, format, argp); + va_end(argp); + return ret; +} + +int ClientSocket::write(char c) { + return write(&c, 1); +} + +int ClientSocket::write(char *buf, int size) { + int ret = socket->send(buf, size); + if (ret > 0) { + return ret; + } else { + writable = false; + return -1; + } +} + +int ClientSocket::printf(const char* format, ...) { + va_list argp; + va_start(argp, format); + char buf[256]; + + int len = vsnprintf(buf, sizeof(buf), format, argp); + va_end(argp); + return write(buf, len); +} + +void ClientSocket::close() { + if (socket) { + readable = false; + writable = false; + socket->resetOnEvent(); + socket->close(); + delete socket; + socket = 0; + } +} + +ClientSocket::operator bool() { + return connected(); +} + +void ClientSocket::setDebug(bool debug) { + this->debug = debug; +} \ No newline at end of file