summaryrefslogtreecommitdiffstats
path: root/fastos/src/vespa/fastos/socket.h
blob: 572770879d9726e00a841bbe62e06a4db33e5a39 (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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include <vespa/fastos/types.h>

#include <string>
#include <vector>

class FastOS_SocketInterface;
class FastOS_ServerSocket;
class FastOS_SocketEvent;

#include <vespa/fastos/socketevent.h>

/**
 * This class implements TCP/IP network socket.
 */
class FastOS_SocketInterface
{
private:
    friend class FastOS_SocketEvent;

protected:
    bool                    _readEventEnabled;
    bool                    _writeEventEnabled;
    bool                    _readPossible;
    bool                    _writePossible;
    bool                    _epolled; // true -> part of epoll set
    FastOS_SocketEvent     *_socketEvent;
    void                   *_eventAttribute;
    int                     _socketEventArrayPos;
    struct sockaddr_storage _address;
    int                     _socketHandle;
    bool                    _preferIPv6;

    /**
     * Cancel all socket events and detach from the current socket
     * event, if any.
     */
    void CleanupEvents ();

    /**
     * Is a valid socket handle associated with this instance?
     * @return  True if the handle is valid, else false.
     */
    bool ValidHandle () const { return (_socketHandle != -1); }

    /**
     * If no OS socket is yet associated with this instance,
     * create one.
     * @return     Boolean success/failure
     */
    bool CreateIfNoSocketYet();

    void ConstructorWork();

public:
    FastOS_SocketInterface (const FastOS_SocketInterface&) = delete;
    FastOS_SocketInterface& operator=(const FastOS_SocketInterface&) = delete;
    // Static members

    /**
     * Convenience method. Does GetErrorString(GetLastError())
     * @return Error string
     */
    static std::string getLastErrorString(void);

    static const char *InitializeServices ();
    static void CleanupServices ();

    /**
     * Default constructor. Use @ref SetUp() or the various SetAddress..()
     * methods to complete the socket setup.
     */
    FastOS_SocketInterface();
    /**
     * This constructor does @ref SetUp() with the specified parameters.
     * @param  socketHandle    OS handle to already created socket
     * @param  hostAddress     IP address or host name of remote host
     */
    FastOS_SocketInterface(int socketHandle, struct sockaddr *hostAddress);

    /**
     * Destructor
     * The socket will be closed unless it was supplied by the caller.
     */
    virtual ~FastOS_SocketInterface();

    /**
     * Setup of socket parameters from explicit address and socket handle
     * If a socket is already associated with this instance it will be
     * closed (see @ref Close()).
     * The socket is closed when the socket instance is deleted.
     * @param  socketHandle    OS handle to already created socket
     * @param  hostAddress     Address of remote host
     */
    void SetUp(int socketHandle, struct sockaddr *hostAddress);

    /**
     * Set address of host to connect to.
     * @param  portNum         IP port number of remote host
     * @param  hostAddress     IP address or host name of remote host
     * @return                 Boolean success/failure
     */
    bool SetAddress(const int portNum, const char *hostAddress);

    /**
     * Set address of host to connect to
     * @param  portNum         IP port number of remote host
     * @param  hostName        Hostname of remote host
     * @return                 Boolean success/failure
     */
    bool SetAddressByHostName (const int portNum, const char *hostName);

    /**
     * Connects to the host using the IP Address and port number predefined.
     * @return      Boolean success/failure
     */
    bool Connect();

    /**
     * Connects to the host using the IP Address and port number specified.
     * @return      Boolean success/failure
     */
    bool Connect(const char *hostNameOrIPaddress, const int portNum) {
        return SetAddress(portNum, hostNameOrIPaddress) ? Connect() : false;
    }

    /**
     * Attempts to retrieve the local port number for the socket.
     * The socket must be connected when this method is called.
     * @return     Local port number or -1 on error.
     */
    int GetLocalPort ();

    /**
     * Read [buffersize] bytes to [readbuffer]. The socket must
     * have a connection (see @ref Connect()) before a read is
     * attempted.
     * @param  readBuffer    Pointer to target memory buffer
     * @param  bufferSize    Size of the buffer / bytes to read
     * @return               Returns number of bytes read.
     */
    virtual ssize_t Read (void *readBuffer, size_t bufferSize) = 0;

    /**
     * Write [buffersize] bytes from [readbuffer].  The socket must
     * have a connection (see @ref Connect()) before a write is
     * attempted.
     * @param  writeBuffer   Pointer to target memory buffer
     * @param  bufferSize    Size of the buffer / bytes to write
     * @return               Returns number of bytes written.
     */
    virtual ssize_t Write (const void *writeBuffer, size_t bufferSize) = 0;

    /**
     * Close the socket.
     * Only socket handles created within this class are closed. This
     * means user-supplied socket handles (through constructor or
     * @ref SetUp) will not be closed.
     * If the socket is already closed, the method call will return
     * success.
     * @return     Boolean success/failure
     */
    virtual bool Close () = 0;

    /**
     * Shut down a connection.
     * If the socket is already closed, the method call will return
     * success. Socket write events are disabled.
     * @return     Boolean success/failure
     */
    virtual bool Shutdown() = 0;

    /**
     * Get socket error
     * If getting the socket error fails, the error code of GetLastError()
     * is returned instad. If getting the socket error succeds with a wrong
     * parameter EINVAL is returned.
     * @return          Socket error
     */
    int GetSoError();

    /**
     * Set SO_KEEPALIVE flag on socket
     * @param  keep            SO_KEEPALIVE on (true) / off (false)
     * @return                 Boolean success/failure
     */
    bool SetSoKeepAlive (bool keep) {
        return SetSoIntOpt(SO_KEEPALIVE, keep ? 1 : 0);
    }

    /**
     * Set SO_REUSEADDR flag on socket
     * @param  reuse           SO_REUSEADDR on (true) / off (false)
     * @return                 Boolean success/failure
     */
    bool SetSoReuseAddr (bool reuse) {
        return SetSoIntOpt(SO_REUSEADDR, reuse ? 1 : 0);
    }

    /**
     * Set SO_LINGER flag on socket
     * @param  doLinger        SO_LINGER on (true) / off (false)
     * @param  seconds         Seconds to linger after close
     * @return                 Boolean success/failure
     */
    bool SetSoLinger (bool doLinger, int seconds);

    /**
     * Set TCP Nodelay option on socket
     * @param  noDelay         Don't delay data (true) / delay data (false)
     * @return                 Boolean success/failure
     */
    bool SetNoDelay(bool noDelay);
    /**
     * Set socket option
     * @param  option          Number of option to set
     * @param  value           Value of option to set
     * @return                 Boolean success/failure
     */
    bool SetSoIntOpt (int option, int value);

    /**
     * Get socket option
     * @param  option          Number of option to get
     * @param  value           Ref to variable for holding the value of option
     * @return                 Boolean success/failure
     */
    bool GetSoIntOpt (int option, int &value);

    /**
     * Set blocking flag on socket
     * @param blockingEnabled  SO_BLOCKING on (true) / off (false)
     * @return Boolean success/failure
     */
    virtual bool SetSoBlocking (bool blockingEnabled)=0;

    /**
     * Associate a socket event object with this socket.
     * Any events registered with an already associated event
     * object is cancelled.
     * @param  event       Socket event object
     * @param  attribute   Event attribute pointer
     * @return Boolean success/failure.
     */
    bool SetSocketEvent (FastOS_SocketEvent *event, void *attribute=NULL);

    /**
     * Get socket event object
     * @return             Associated socket event object or NULL
     */
    FastOS_SocketEvent *GetSocketEvent () { return _socketEvent; }

    /**
     * Enable or disable read events for the socket.
     * The behaviour caused by invoking this method while waiting for
     * socket events is undefined.
     * A @ref FastOS_SocketEvent must be associated with the socket prior
     * to calling @ref EnableReadEvent and @ref EnableWriteEvent.
     */
    void EnableReadEvent (bool enabled);

    /**
     * Enable or disable write events for the socket.
     * The behaviour caused by invoking this method while waiting for
     * socket events is undefined.
     * A @ref FastOS_SocketEvent must be associated with the socket prior
     * to calling @ref EnableReadEvent and @ref EnableWriteEvent.
     */
    void EnableWriteEvent (bool enabled);

    /**
     * Is the socket open?
     * @return True if opened, false if cloed.
     */
    bool IsOpened () const {
        return ValidHandle();
    }

    /**
     * Return socket port.
     */
    unsigned short GetPort () const
    {
        switch (_address.ss_family) {
        case AF_INET:
            return reinterpret_cast<const sockaddr_in &>(_address).sin_port;
        case AF_INET6:
            return reinterpret_cast<const sockaddr_in6 &>(_address).sin6_port;
        default:
            return 0;
        }
    }

    /**
     * Tune the socket for transport use.
     * This includes:
     *  SO_KEEPALIVE = 1
     *  SO_LINGER = 0
     *
     * @return Boolean success/failure
     */
    bool TuneTransport ();
    bool getPreferIPv6(void) const { return _preferIPv6; }
    void setPreferIPv6(bool preferIPv6) { _preferIPv6 = preferIPv6; }
};

#include <vespa/fastos/unix_socket.h>
typedef FastOS_UNIX_Socket FASTOS_PREFIX(Socket);