summaryrefslogtreecommitdiffstats
path: root/fastos/src/vespa/fastos/serversocket.h
blob: 8452649015c4ed42f7c51dd569cb7e5b0028c9e9 (plain) (blame)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
//************************************************************************
/**
 * @file
 * Class definitons for FastOS_SocketFactory and FastOS_ServerSocket.
 *
 * @author  Div, Oivind H. Danielsen
 */

#pragma once


#include <vespa/fastos/socket.h>


/**
 * This base class is used to create Socket objects. You can supply
 * a subclassed @ref FastOS_SocketFactory to an instance of
 * @ref FastOS_ServerSocket, to have your own type of socket created
 * by @ref FastOS_ServerSocket::Accept().
 */
class FastOS_SocketFactory
{
public:
    /**
     * Destructor.  No cleanup needed for base class.
     */
    virtual ~FastOS_SocketFactory(void) { }

    /**
     * Create a socket object. Override this method to create
     * your own subclassed socket objects. It is not allowed
     * for the constructor to use the socket object, as it
     * is not set up yet at this point.
     */
    virtual FastOS_SocketInterface *CreateSocket()
    {
        return new FastOS_Socket();
    }
};


/**
 * This socket class provides a listening server socket that is
 * able to accept connections on a specified port number.
 *
 * The port number and connection backlog are specified in the
 * constructor  * (FastOS_ServerSocket(int portnum, int backLog)).
 *
 * Call @ref Listen() to create and configure the socket for
 * listening on the specified port number.
 *
 * To accept an incoming connection, call @ref Accept(). This will
 * return a newly created @ref FastOS_Socket object to handle
 * the new connection. If you want a different type of socket,
 * specify your own @ref FastOS_SocketFactory with @ref SetSocketFactory().
 */
class FastOS_ServerSocket : public FastOS_Socket
{
private:
    FastOS_ServerSocket(const FastOS_ServerSocket&);
    FastOS_ServerSocket& operator=(const FastOS_ServerSocket&);

protected:
    /**
     * The TCP port number to listen to.
     */
    int _portNumber;

    /**
     * Max number of connections in backlog.
     */
    int _backLog;

    /**
     * The socket factory to use for incoming connections.
     * If this is NULL, the default action is to create an
     * instance of the regular @ref FastOS_Socket.
     */
    FastOS_SocketFactory *_socketFactory;

    /**
     * Create socket for handling an incoming connection
     * @return    Returns pointer to newly created socket, or NULL on
     *            failure.
     */
    FastOS_SocketInterface *CreateHandlerSocket();

    bool _validAddress;

public:
    /**
     * Constructor. If strict binding is used, call @ref GetValidAddressFlag()
     * to check if setting the specified address was successful or not.
     * @param portnum        Listen on this port number.
     * @param backLog        Max number of connections in backlog.
     * @param socketFactory  See @ref SetSocketFactory().
     * @param strictBindHostName   IP address or hostname for strict binding
     */
    FastOS_ServerSocket (int portnum, int backLog=5,
                         FastOS_SocketFactory *socketFactory=NULL,
                         const char *strictBindHostName=NULL)
        : _portNumber(portnum),
          _backLog(backLog),
          _socketFactory(socketFactory),
          _validAddress(false)
    {
        setPreferIPv6(true);
        _validAddress = SetAddress(_portNumber, strictBindHostName);
    }

    bool GetValidAddressFlag () { return _validAddress; }

    /**
     * Use this constructor to supply a pre-created, configured,
     * bound and listening socket. When using this constructor,
     * don't call @ref Listen().
     * @param socketHandle   OS handle of supplied socket.
     * @param socketFactory  See @ref SetSocketFactory().
     */
    FastOS_ServerSocket(int socketHandle, FastOS_SocketFactory *socketFactory);

    /**
     * Create a listening socket. This involves creating an OS
     * socket, setting SO_REUSEADDR(true), binding the socket and
     * start to listen for incoming connections. You should
     * call @ref Listen() if you have supplied a pre-created listening
     * socket handle trough the constructor
     * @ref FastOS_ServerSocket(int listenSocketHandle, FastOS_SocketFactory *socketFactory=NULL).
     * @return    Boolean success/failure
     */
    bool Listen ();

    /**
     * Accept incoming connections. The socket factory (if present)
     * is used to create a socket instance for the new connection.
     * Make sure you have a listening socket (see @ref Listen()) before
     * calling @ref Accept().
     * @return   Returns pointer to newly created socket object for the
     *           connection that was accepted, or NULL on failure.
     */
    FastOS_SocketInterface *Accept ();

    /**
     * Accept incoming connections. This version does not use the
     * associated socket factory.
     * Make sure you have a listening socket (see @ref Listen()) before
     * calling @ref AcceptPlain().
     * @return   Returns pointer to newly created socket object for the
     *           connection that was accepted, or NULL on failure.
     */
    FastOS_Socket *AcceptPlain ();

    /**
     * Specify your own @ref FastOS_SocketFactory for this serversocket.
     * When new connections are accepted with @ref Accept, this socket
     * factory will be called to create a new socket object for the
     * connection.
     *
     * SetSocketFactory(NULL) will enable the default socket factory
     * mechanism which will create regular @ref FastOS_Socket instances
     * on accepted connections.
     */
    void SetSocketFactory(FastOS_SocketFactory *socketFactory);

    /**
     * Return the portnumber of the listing socket.
     * @return Port number.
     */
    int GetPortNumber ()
    {
        return _portNumber;
    }
};