summaryrefslogtreecommitdiff
path: root/includes/Socket.h
blob: 22bf972e56deecfab00ac3b2b0cde335e9bdaa46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#pragma once

#ifdef _WIN32
#ifndef _MSC_VER
#include <windows.h>
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#endif
#include <Handle.h>
#include <Selectable.h>
#include <TaskMan.h>
#include <Task.h>
#include <StacklessTask.h>
#include <Printer.h>

namespace Balau {

struct DNSRequest;

class Socket : public Selectable {
  public:
      Socket() 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 void close() throw (GeneralException);
    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();
    bool resolved();
  private:
      Socket(int fd);

    virtual ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    virtual ssize_t send(int sockfd, const void *buf, size_t len, int flags);

    String m_name;
    bool m_connected = false;
    bool m_connecting = false;
    bool m_listening = false;
    sockaddr_in6 m_localAddr, m_remoteAddr;
    DNSRequest * m_req = NULL;
};

class ListenerBase : public StacklessTask {
  public:
    virtual void Do();
    void stop();
    virtual const char * getName() const;
  protected:
      ListenerBase(int port, const char * local, void * opaque);
    virtual void factory(IO<Socket> & io, void * opaque) = 0;
    virtual void setName() = 0;
    String m_name;
    IO<Socket> m_listener;
  private:
    Events::Async m_evt;
    volatile bool m_stop;
    String m_local;
    int m_port = 0;
    void * m_opaque = NULL;
};

template<class Worker>
class Listener : public ListenerBase {
  public:
      Listener(int port, const char * local = "", void * opaque = NULL) : ListenerBase(port, local, opaque) { }
  protected:
    virtual void factory(IO<Socket> & io, void * opaque) { TaskMan::registerTask(new Worker(io, opaque)); }
    virtual void setName() { m_name = String(ClassName(this).c_str()) + " - " + m_listener->getName(); }
};

};