A Simple TCP & UDP Socket Library

Dependents:   SimpleSocketExamples 1.0

Revision:
0:3eb1ce25eac4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ClientSocket.cpp	Tue Jun 05 05:56:49 2012 +0000
@@ -0,0 +1,228 @@
+/*
+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(-1),
+        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(-1), debug(debug) {
+    createClientSocket(ip, port, timeout);
+}
+
+ClientSocket::ClientSocket(char *hostname, int port, float timeout, bool debug)
+        : readable(true), writable(true), preread(-1), 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 != -1)
+        return true;
+
+    if (!readable)
+        Net::poll();
+
+    if (readable) {
+        char c;
+        int ret = socket->recv(&c, 1);
+        if (ret > 0) {
+            preread = 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 != -1) {
+        c = preread & 255;
+        preread = -1;
+        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 != -1 && size > 0) {
+        *buf++ = preread & 255;
+        preread = -1;
+        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