diff options
| author | Pixel <pixel@nobis-crew.org> | 2011-10-17 21:19:58 -0700 | 
|---|---|---|
| committer | Pixel <pixel@nobis-crew.org> | 2011-10-17 21:19:58 -0700 | 
| commit | 58f4ba6c8a4f9662dad9f5ddb3106c2e2c34daa6 (patch) | |
| tree | d44d7b9de90739e88dd371ac1afc432b18e6e899 /includes/Socket.h | |
| parent | be3a4cbad2cdeef8a306180e7c867824f7f2f2af (diff) | |
Adding the Socket class, and a few tools that comes with it.
Diffstat (limited to 'includes/Socket.h')
| -rw-r--r-- | includes/Socket.h | 90 | 
1 files changed, 90 insertions, 0 deletions
| diff --git a/includes/Socket.h b/includes/Socket.h new file mode 100644 index 0000000..1f20fbb --- /dev/null +++ b/includes/Socket.h @@ -0,0 +1,90 @@ +#pragma once + +#include <netdb.h> +#include <Handle.h> +#include <Task.h> +#include <Printer.h> + +namespace Balau { + +class Socket : public Handle { +  public: + +      Socket() throw (GeneralException); +    virtual void close() throw (GeneralException); +    virtual ssize_t read(void * buf, size_t count) throw (GeneralException); +    virtual ssize_t write(const void * buf, size_t count) throw (GeneralException); +    virtual bool isClosed(); +    virtual bool isEOF(); +    virtual bool canRead(); +    virtual bool canWrite(); +    virtual const char * getName(); + +    bool setLocal(const char * hostname = NULL, int port = 0); +    bool connect(const char * hostname, int port); +    IO<Socket> accept() throw (GeneralException); +    bool listen(); +  private: +      Socket(int fd); +    class SocketEvent : public Events::BaseEvent { +      public: +          SocketEvent(int fd, int evt = EV_READ | EV_WRITE) : m_task(NULL) { Printer::elog(E_SOCKET, "Got a new SocketEvent at %p", this); m_evt.set<SocketEvent, &SocketEvent::evt_cb>(this); m_evt.set(fd, evt); } +          virtual ~SocketEvent() { m_evt.stop(); } +          void stop() { reset(); m_evt.stop(); } +      private: +        void evt_cb(ev::io & w, int revents) { Printer::elog(E_SOCKET, "Got a libev callback on a SocketEvent at %p", this); doSignal(); } +        virtual void gotOwner(Task * task); + +        ev::io m_evt; +        Task * m_task; +    }; + +    int m_fd; +    String m_name; +    bool m_connected; +    bool m_connecting; +    bool m_listening; +    sockaddr_in6 m_localAddr, m_remoteAddr; +    SocketEvent * m_evtR, * m_evtW; +}; + +template<class Worker> +class Listener : public Task { +  public: +      Listener(int port, const char * local = NULL) : m_stop(false) { +          m_listener.setLocal(local, port); +          m_listener.listen(); +          m_name = String(ClassName(this).c_str()) + " - " + m_listener.getName(); +          Printer::elog(E_SOCKET, "Created a listener task at %p", this); +      } +    virtual void Do() { +        waitFor(&m_evt); +        setOkayToEAgain(true); +        while (!m_stop) { +            IO<Socket> io; +            try { +                io = m_listener.accept(); +            } +            catch (EAgain) { +                Printer::elog(E_SOCKET, "Listener task at %p (%s) got an EAgain - stop = %s", this, ClassName(this).c_str(), m_stop ? "true" : "false"); +                if (!m_stop) +                    yield(); +                continue; +            } +            new Worker(io); +        } +    } +    void stop() { +        Printer::elog(E_SOCKET, "Listener task at %p (%s) is asked to stop.", this, ClassName(this).c_str()); +        m_stop = true; +        m_evt.trigger(); +    } +    virtual const char * getName() { return m_name.to_charp(); } +  private: +    Socket m_listener; +    Events::Async m_evt; +    volatile bool m_stop; +    String m_name; +}; + +}; | 
