A Simple TCP & UDP Socket Library. An update from that of Hiroshi Yamaguchi.

Files at this revision

API Documentation at this revision

Comitter:
macgyveremir
Date:
Wed May 23 16:26:44 2012 +0000
Commit message:
Fixed dropping of null bytes (0x00) from incoming binary TCP frames

Changed in this revision

ClientSocket.cpp Show annotated file Show diff for this revision Revisions of this file
DatagramSocket.cpp Show annotated file Show diff for this revision Revisions of this file
Debug.h Show annotated file Show diff for this revision Revisions of this file
EventsErrors.cpp Show annotated file Show diff for this revision Revisions of this file
Resolver.cpp Show annotated file Show diff for this revision Revisions of this file
ServerSocket.cpp Show annotated file Show diff for this revision Revisions of this file
SimpleSocket.h Show annotated file Show diff for this revision Revisions of this file
--- /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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DatagramSocket.cpp	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,136 @@
+/*
+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 "EthernetNetIf.h"
+#include "SimpleSocket.h"
+#include <stdarg.h>
+
+DatagramSocket::DatagramSocket(int port, bool debug) : bufsize(512), debug(debug) {
+    host = Host(IpAddr(), port);
+    createDatagramSocket();
+}
+
+DatagramSocket::DatagramSocket(Host host, bool debug) : host(host), bufsize(512), debug(debug) {
+    createDatagramSocket();
+}
+
+DatagramSocket::DatagramSocket(IpAddr ip, int port, bool debug) : host(ip, port), bufsize(512), debug(debug) {
+    createDatagramSocket();
+}
+
+DatagramSocket::~DatagramSocket() {
+    delete[] buf;
+}
+
+void DatagramSocket::createDatagramSocket() {
+    udpSocket.setOnEvent(this, &DatagramSocket::onUDPSocketEvent);
+    UDPSocketErr err = udpSocket.bind(host);
+    DBG(DatagramError(err));
+    buf = new char[bufsize + 1];
+}
+
+int DatagramSocket::write(char *buf, int length) {
+    if (length > bufsize) length = bufsize;
+    this->length = length;
+    memcpy(this->buf, buf, length);
+    return length;
+}
+
+int DatagramSocket::printf(const char* format, ...) {
+    va_list argp;
+    va_start(argp, format);
+    int len = vsnprintf(buf, bufsize, format, argp);
+    va_end(argp);
+    if (len > 0)
+        length = len;
+    return len;
+}
+
+void DatagramSocket::send(Host& host) {
+    DBG("Host = %d.%d.%d.%d:%d\n", host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3], host.getPort());
+    Net::poll();
+    int err = udpSocket.sendto(buf, length, &host);
+    DBG(DatagramError((UDPSocketErr) (err < 0 ? err : 0)));
+}
+
+void DatagramSocket::send(IpAddr ip, int port) {
+    DBG("IP = %d.%d.%d.%d, Port = %d\n", ip[0], ip[1], ip[2], ip[3], port);
+    Host host(ip, port);
+    send(host);
+}
+
+void DatagramSocket::send(char *name, int port) {
+    DBG("Name = %s, Port = %d\n", name, port);
+    Resolver resolver;
+    IpAddr ip = resolver.resolve(name, debug);
+    send(ip, port);
+}
+
+int DatagramSocket::read(char *buf, int size) {
+    int len = length < size ? length : size;
+    if (len > 0)
+        memcpy(buf, this->buf, len);
+    return len;
+}
+
+int DatagramSocket::scanf(const char* format, ...) {
+    va_list argp;
+    va_start(argp, format);
+    buf[length] = '\0';
+    int ret = vsscanf(buf, format, argp);
+    va_end(argp);
+    return ret;
+}
+
+int DatagramSocket::receive(Host *host, float timeout) {
+    timer.reset();
+    timer.start();
+    readable = false;
+    length = 0;
+
+    do {
+        Net::poll();
+        if (readable) {
+            Host host2;
+            length = udpSocket.recvfrom(buf, bufsize, &host2);
+            if (length > 0 && host)
+                *host = host2;
+            break;
+        }
+    } while (timer.read() < timeout);
+
+    return length;
+}
+
+void DatagramSocket::setDebug(bool debug) {
+    this->debug = debug;
+}
+
+void DatagramSocket::onUDPSocketEvent(UDPSocketEvent e) {
+    DBG(DatagramEvent(e));
+
+    switch (e) {
+        case UDPSOCKET_READABLE: //The only event for now
+            readable = true;
+            break;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Debug.h	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,28 @@
+/*
+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.
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+#define DBG(...) if (debug) { ::printf("%s:%d: ", __FUNCTION__, __LINE__); ::printf(__VA_ARGS__); } else;
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EventsErrors.cpp	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,141 @@
+/*
+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"
+
+SocketEvent::SocketEvent(TCPSocketEvent event) : event(event) {}
+
+char *SocketEvent::toString() {
+    switch (event) {
+        case TCPSOCKET_CONNECTED:
+            return "TCPSOCKET_CONNECTED: Connected to host.\n";
+        case TCPSOCKET_ACCEPT:
+            return "TCPSOCKET_ACCEPT: Client is connected, must call accept() to get a new Socket.\n";
+        case TCPSOCKET_READABLE:
+            return "TCPSOCKET_READABLE: Data in buf.\n";
+        case TCPSOCKET_WRITEABLE:
+            return "TCPSOCKET_WRITEABLE: Can write data to buf.\n";
+        case TCPSOCKET_CONTIMEOUT:
+            return "TCPSOCKET_CONTIMEOUT: Connection timed out.\n";
+        case TCPSOCKET_CONRST:
+            return "TCPSOCKET_CONRST: Connection was reset by remote host.\n";
+        case TCPSOCKET_CONABRT:
+            return "TCPSOCKET_CONABRT: Connection was aborted.\n";
+        case TCPSOCKET_ERROR:
+            return "TCPSOCKET_ERROR: Unknown error.\n";
+        case TCPSOCKET_DISCONNECTED:
+            return "TCPSOCKET_DISCONNECTED: Disconnected.\n";
+        default:
+            static char buf[32];
+            sprintf(buf, "UNKNOWN EVENT (%d).\n", event);
+            return buf;
+    }
+}
+
+SocketEvent::operator char *() {
+    return toString();
+}
+
+SocketEvent::operator int() {
+    return event;
+}
+
+SocketError::SocketError(TCPSocketErr err) : err(err) {};
+
+char *SocketError::toString() {
+    switch (err) {
+        case TCPSOCKET_SETUP:
+            return "TCPSOCKET_SETUP: TCPSocket not properly configured.\n";
+        case TCPSOCKET_TIMEOUT:
+            return "TCPSOCKET_TIMEOUT: Connection timed out.\n";
+        case TCPSOCKET_IF:
+            return "TCPSOCKET_IF: Interface has problems, does not exist or is not initialized.\n";
+        case TCPSOCKET_MEM:
+            return "TCPSOCKET_MEM: Not enough memory.\n";
+        case TCPSOCKET_INUSE:
+            return "TCPSOCKET_INUSE: Interface/Port is in use.\n";
+        case TCPSOCKET_EMPTY:
+            return "TCPSOCKET_EMPTY: Connections queue is empty.\n";
+        case TCPSOCKET_RST:
+            return "TCPSOCKET_RST: Connection was reset by remote host.\n";
+        case TCPSOCKET_OK:
+            return "TCPSOCKET_OK: Success.\n";
+        default:
+            return "TCPSOCKET unknown error occurred.\n";
+    }
+}
+
+SocketError::operator char *() {
+    return toString();
+}
+
+SocketError::operator int() {
+    return err;
+}
+
+DatagramEvent::DatagramEvent(UDPSocketEvent event) : event(event) {}
+
+char *DatagramEvent::toString() {
+    switch (event) {
+        case UDPSOCKET_READABLE:
+            return "UDPSOCKET_READABLE: Data in buf.\n";
+        default:
+            static char buf[32];
+            sprintf(buf, "UNKNOWN EVENT (%d).\n", event);
+            return buf;
+    }
+}
+
+DatagramEvent::operator char *() {
+    return toString();
+}
+
+DatagramEvent::operator int() {
+    return event;
+}
+
+DatagramError::DatagramError(UDPSocketErr err) : err(err) {};
+
+char *DatagramError::toString() {
+    switch (err) {
+        case UDPSOCKET_SETUP:
+            return "UDPSOCKET_SETUP: UDPSocket not properly configured.\n";
+        case UDPSOCKET_IF:
+            return "UDPSOCKET_IF: Interface has problems, does not exist or is not initialized.\n";
+        case UDPSOCKET_MEM:
+            return "UDPSOCKET_MEM: Not enough memory.\n";
+        case UDPSOCKET_INUSE:
+            return "UDPSOCKET_INUSE: Interface/Port is in use.\n";
+        case UDPSOCKET_OK:
+            return "UDPSOCKET_OK: Success.\n";
+        default:
+            return "UDPSOCKET unknown error occurred.\n";
+    }
+}
+
+DatagramError::operator char *() {
+    return toString();
+}
+
+DatagramError::operator int() {
+    return err;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resolver.cpp	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,49 @@
+/*
+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"
+
+Resolver::Resolver() {}
+
+IpAddr Resolver::resolve(char *name, bool debug) {
+    IpAddr ip;
+    DNSRequest request;
+    
+    if (request.resolve(name) == DNS_OK) {
+        replied = false;
+        request.setOnReply(this, &Resolver::onReply);
+        while (!replied)
+            Net::poll();
+        if (reply == DNS_FOUND)
+            request.getResult(&ip);
+    }
+    
+    DBG("%s -> %d.%d.%d.%d\n", name, ip[0], ip[1], ip[2], ip[3]);
+    
+    return ip;
+}
+
+
+void Resolver::onReply(DNSReply reply) {
+    replied = true;
+    this->reply = reply;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ServerSocket.cpp	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,75 @@
+/*
+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"
+
+ServerSocket::ServerSocket(int port, bool debug)
+        : accepted(false), debug(debug) {
+    ssocket.setOnEvent(this, &ServerSocket::onTCPSocketEvent);
+
+    SocketError bindErr = ssocket.bind(Host(IpAddr(), port));
+    DBG("Init bind... %s\n", bindErr.toString());
+
+    SocketError listenErr = ssocket.listen();
+    DBG("Init listen... %s\n", listenErr.toString());
+}
+
+void ServerSocket::onTCPSocketEvent(TCPSocketEvent e) {
+    DBG(SocketEvent(e));
+
+    switch (e) {
+        case TCPSOCKET_ACCEPT:
+            accepted = true;
+            break;
+        case TCPSOCKET_DISCONNECTED:
+            ssocket.close();
+            break;
+    }
+}
+
+ClientSocket ServerSocket::accept(float timeout) {
+    TCPSocket* socket = 0;
+    Host host;
+    timer.reset();
+    timer.start();
+
+    do {
+        Net::poll();
+        if (accepted) {
+            accepted = false;
+            SocketError err = ssocket.accept(&host, &socket);
+            if (!err) {
+                IpAddr ip = host.getIp();
+                DBG("TCP connection from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
+                break;
+            } else {
+                DBG("accept error:%s\n", err.toString());
+            }
+        }
+    } while (timer.read() < timeout);
+
+    return ClientSocket(host.getIp(), socket, debug);
+}
+
+void ServerSocket::setDebug(bool debug) {
+    this->debug = debug;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleSocket.h	Wed May 23 16:26:44 2012 +0000
@@ -0,0 +1,490 @@
+/*
+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.
+*/
+
+#ifndef SIMPLE_SOCKET_H
+#define SIMPLE_SOCKET_H
+
+#include "mbed.h"
+#include "TCPSocket.h"
+#include "UDPSocket.h"
+#include "DNSRequest.h"
+#include "Debug.h"
+
+/**
+ * wrapper class of TCPSocketEvent
+ */
+class SocketEvent {
+public:
+    /**
+     * creates a SocketEvent wrapper object.
+     *
+     * @param event TCP socket event number
+     */
+    SocketEvent(TCPSocketEvent event);
+
+    /**
+     * @returns a string representation of the event
+     */
+    char *toString();
+
+    /**
+     * an operator overloading for toString()
+     */
+    operator char *();
+
+    /**
+     * an operator overloading for TCP socket event number
+     */
+    operator int();
+
+private:
+    TCPSocketEvent event;
+};
+
+/**
+ * wrapper class of TCPSocketErr
+ */
+class SocketError {
+public:
+    /**
+     * creates a SocketError wrapper object.
+     *
+     * @param err TCP socket error number
+     */
+    SocketError(TCPSocketErr err);
+
+    /**
+     * @returns a string representation of the error
+     */
+    char *toString();
+
+    /**
+     * an operator overloading for toString().
+     */
+    operator char *();
+
+    /**
+     * an operator overloading for TCP socket error number.
+     */
+    operator int();
+
+private:
+    TCPSocketErr err;
+};
+
+/**
+ * wrapper class of UDPSocketEvent
+ */
+class DatagramEvent {
+public:
+    /**
+     * creates a DatagramEvent wrapper object.
+     *
+     * @param event UDP socket event number
+     */
+    DatagramEvent(UDPSocketEvent event);
+
+    /**
+     * @returns a string representation of the event
+     */
+    char *toString();
+
+    /**
+     * an operator overloading for toString()
+     */
+    operator char *();
+
+    /**
+     * an operator overloading for UDP socket event number
+     */
+    operator int();
+
+private:
+    UDPSocketEvent event;
+};
+
+/**
+ * wrapper class of UDPSocketErr
+ */
+class DatagramError {
+public:
+    /**
+     * creates a DatagramError wrapper object.
+     *
+     * @param err UDP socket error number
+     */
+    DatagramError(UDPSocketErr err);
+
+    /**
+     * @returns a string representation of the error
+     */
+    char *toString();
+
+    /**
+     * an operator overloading for toString().
+     */
+    operator char *();
+
+    /**
+     * an operator overloading for UDP socket error number.
+     */
+    operator int();
+
+private:
+    UDPSocketErr err;
+};
+
+/**
+ * client socket class for communication endpoint
+ */
+class ClientSocket {
+    friend class ServerSocket;
+
+public:
+    /**
+     * creates a ClientSocket object.
+     *
+     * @param ip IP address of the socket
+     * @param port port number of the socket
+     * @param timeout max waiting time until connected
+     * @param debug set true to display debugging information
+     */
+    ClientSocket(IpAddr ip, int port, float timeout = 60, bool debug = false);
+
+    /**
+     * creates a ClientSocket object.
+     *
+     * @param hostname domain/host name of the socket
+     * @param port port number of the socket
+     * @param timeout max waiting time until connected
+     * @param debug set true to display debugging information
+     */
+    ClientSocket(char *hostname, int port, float timeout = 60, bool debug = false);
+
+
+    /**
+     * copy constructor
+     */
+    ClientSocket(const ClientSocket& that);
+     
+    /**
+     * gets the IP address.
+     *
+     * @returns IP address of the socket
+     */
+    IpAddr getIp();
+
+    /**
+     * gets the connection status.
+     *
+     * @returns true if connected, false otherwise
+     */
+    bool connected();
+
+    /**
+     * tests if input data available or not.
+     *
+     * @returns true if incomming data available, false otherwise
+     */
+    bool available();
+
+    /**
+     * reads a char.
+     *
+     * @returns a char from the socket input stream, or -1 if no data available
+     */
+    int read();
+
+    /**
+     * reads data into the specified buffer.
+     *
+     * @param buf input buffer
+     * @param size size of the buffer
+     *
+     * @returns the size of the data read
+     */
+    int read(char *buf, int size);
+
+    /**
+     * scans input stream according to the specified format string.
+     *
+     * @params format scanf format string, corresponding arguments follow
+     *
+     * @returns number of input items assigned
+     */
+    int scanf(const char *format, ...);
+
+    /**
+     * writes a char to the output stream.
+     *
+     * @param c a char to be written to the socket output stream
+     *
+     * @returns positive int if succeeded, or -1 if failed
+     */
+    int write(char c);
+
+    /**
+     * writes an array of chars to the output stream.
+     *
+     * @param buf an array of chars to be written to the socket output stream
+     * @param size number of chars in the array
+     *
+     * @returns number of chars written, or -1 if failed
+     */
+    int write(char *buf, int size);
+
+    /**
+     * prints the data to the socket output stream according to the specified format string.
+     *
+     * @param format printf format string, corresponding arguments follow
+     *
+     * @returns number of chars written, or -1 if failed
+     */
+    int printf(const char *format, ...);
+
+    /**
+     * closes the connection.
+     */
+    void close();
+
+    /**
+     * sets debug mode.
+     *
+     * @param debug true to display debugging information
+     */
+    void setDebug(bool debug);
+
+    /**
+     * an operator shorthand for connected()
+     */
+    operator bool();
+
+private:
+    enum ConnectionState {CONNECTING, CONNECTED, DISCONNECTED};
+    IpAddr ip;
+    TCPSocket *socket;
+    bool readable;
+    bool writable;
+    bool preread;
+    char preread_byte;
+    ConnectionState state;
+    bool disconnected;
+    bool debug;
+
+    ClientSocket(IpAddr ip, TCPSocket *socket, bool debug = false);
+    void createClientSocket(IpAddr ip, int port, float timeout);
+    void onTCPSocketEvent(TCPSocketEvent e);
+};
+
+/**
+ * server socket class for handling incoming communication requests
+ */
+class ServerSocket {
+public:
+    /**
+     * creates a ServerSocket object.
+     *
+     * @param port port for server socket
+     * @param debug set true to run in debug mode
+     */
+    ServerSocket(int port, bool debug = false);
+
+    /**
+     * waits for a client to connect.
+     *
+     * @param timeout max time (in msec) for waiting for clients to connect
+     *
+     * @returns a socket to talk with the connecting client or a disconnected socket if timed out
+     */
+    ClientSocket accept(float timeout = 5.0);
+
+    /**
+     * sets debug mode.
+     *
+     * @param debug true to run in debug mode, false to normal mode
+     */
+    void setDebug(bool debug);
+
+private:
+    TCPSocket ssocket;
+    bool accepted;
+    Timer timer;
+    bool debug;
+
+    void onTCPSocketEvent(TCPSocketEvent e);
+};
+
+/**
+ * datagram socket class for UDP
+ */
+class DatagramSocket {
+public:
+    /**
+     * creates a DatagramSocket object with the specified port number.
+     *
+     * @param port port for datagram socket
+     * @param debug set true to run in debug mode
+     */
+    DatagramSocket(int port = 0, bool debug = false);
+
+    /**
+     * creates a DatagramSocket object with the specified host.
+     *
+     * @param host host for datagram socket
+     * @param debug set true to run in debug mode
+     */
+    DatagramSocket(Host host, bool debug = false);
+
+    /**
+     * creates a DatagramSocket object with the specified ip address and port number.
+     *
+     * @param ip address for datagram socket
+     * @param port port for datagram socket
+     * @param debug set true to run in debug mode
+     */
+    DatagramSocket(IpAddr ip, int port, bool debug = false);
+
+    /**
+     * destructor for DatagramSocket.
+     */
+    ~DatagramSocket();
+
+    /**
+     * writes data to the socket
+     *
+     * @param buf buffer for data to be written
+     * @param length data length contained in the buffer
+     *
+     * @returns number of chars written
+     */
+    int write(char *buf, int length);
+
+    /**
+     * prints data to the socket according to the specified format string.
+     *
+     * @param format printf format string, corresponding arguments follow
+     *
+     * @returns number of chars written
+     */
+    int printf(const char* format, ...);
+
+    /**
+     * sends data packet to the specified host.
+     *
+     * @param host destination of this packet to be sent
+     */
+    void send(Host& host);
+
+    /**
+     * sends data packet to the specified IP address and port.
+     *
+     * @param ip destination IP address of the data packet
+     * @param port destination port number of the data packet
+     */
+    void send(IpAddr ip, int port);
+
+    /**
+     * sends data packet to the destination of specified name and port.
+     *
+     * @param name destination host name of the data packet
+     * @param port destination port number of the data packet
+     */
+    void send(char *name, int port);
+
+    /**
+     * reads data packet from the datagram socket.
+     *
+     * @param buf buffer to store data
+     * @param size size of the buf
+     *
+     * @returns number of bytes actually stored
+     */
+    int read(char *buf, int size);
+
+    /**
+     * scans data according to the specified format string.
+     *
+     * @param format scanf format string, corresponding arguments follow
+     *
+     * @returns number of input items assigned
+     */
+    int scanf(const char* format, ...);
+
+    /**
+     * receives data packet.
+     *
+     * @param host pointer to the Host object to store the host info, if specified
+     * @param timeout maximum waiting time before data packet comes in
+     *
+     * @returns number of bytes received
+     */
+    int receive(Host *host = 0, float timeout = 5.0);
+    
+    /**
+     * sets debug mode.
+     *
+     * @param debug true to run in debug mode, false to normal mode
+     */
+    void setDebug(bool debug);
+
+private:
+    Host host;
+    UDPSocket udpSocket;
+    Timer timer;
+    bool readable;
+    int length;
+    int bufsize;
+    char *buf;
+    bool debug;
+
+    void createDatagramSocket();
+    void onUDPSocketEvent(UDPSocketEvent e);
+};
+
+/**
+ * a simple DNS resolver
+ */
+class Resolver {
+public:
+    /**
+     * creates a Resolver object
+     */
+    Resolver();
+
+    /**
+     * resolves the specified domain/host name and returns its IP address.
+     *
+     * @param name domain/host name to be resolved or IP address in "nnn.nnn.nnn.nnn" format
+     * @param debug true to display debugging information
+     *
+     * @returns resolved IP address object
+     */
+    IpAddr resolve(char *name, bool debug = false);
+
+private:
+    bool replied;
+    DNSReply reply;
+
+    void onReply(DNSReply reply);
+};
+
+#endif
\ No newline at end of file