A Simple TCP & UDP Socket Library

Dependents:   SimpleSocketExamples 1.0

SimpleSocket.h

Committer:
yamaguch
Date:
2012-06-05
Revision:
0:3eb1ce25eac4

File content as of revision 0:3eb1ce25eac4:

/*
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;
    int preread;
    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