File: NetStream.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (197 lines) | stat: -rw-r--r-- 4,817 bytes parent folder | download
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
#pragma once
#include "Socket.h"
#include "Core/Io/HandleStream.h"

namespace storm {
	STORM_PKG(core.net);

	class NetIStream;
	class NetOStream;

	/**
	 * Keepalive times for NetStream (TCP sockets).
	 *
	 * Interestingly enough, it is not always possible to get the current timeouts from a socket. As
	 * such, this class has three possible states:
	 *
	 * - Keepalive off.
	 * - Keepalive on, using system defaults.
	 * - Keepalive on, using custom times.
	 *
	 * The two times are `idle` and `interval`. The first (`idle`) specifies how long to wait before
	 * sending a keepalive packet after the connection has been idle. The second (`interval`)
	 * decides how often keepalive packets should be sent if a reply from the first keepalive is not
	 * received. Number of retries is not always configurable.
	 */
	class Keepalive {
		STORM_VALUE;
	public:
		// Default constructor, means "off".
		STORM_CTOR Keepalive() : enabled(false) {}

		// Create "off" explicitly.
		static Keepalive STORM_FN off() {
			return Keepalive();
		}

		// Create "on", but using defaults.
		static Keepalive STORM_FN on() {
			return Keepalive(Duration(), Duration());
		}

		// Create "on", specifying timeouts.
		static Keepalive STORM_FN on(Duration idle) {
			return Keepalive(idle, time::s(2));
		}
		static Keepalive STORM_FN on(Duration idle, Duration interval) {
			return Keepalive(idle, interval);
		}

		// Enable keepalive?
		Bool enabled;

		// Durations for idle and interval. If <= 0 is used, then the default time is used. Note
		// that both must be set at the same time.
		Duration idle;
		Duration interval;

		// Are the times default?
		Bool STORM_FN defaultTimes() const {
			return idle.v > 0 && interval.v > 0;
		}

		// To string.
		void STORM_FN toS(StrBuf *to) const;

	private:
		// Internal constructor.
		Keepalive(Duration idle, Duration interval)
			: enabled(true), idle(idle), interval(interval) {}
	};


	/**
	 * A TCP socket.
	 *
	 * The socket contain two streams: one for reading data and another for writing data. These
	 * streams may be used simultaneously. As for regular streams, it is not a good idea to share
	 * these streams between different threads, even if it is possible.
	 *
	 * Sockets are created either by calling the 'connect' function, or by a Listener object.
	 */
	class NetStream : public Socket {
		STORM_CLASS;
	public:
		// Create. Assumes the socket in 'handle' is set up for asynchronious operation.
		NetStream(os::Handle handle, os::Thread attachedTo, Address *peer);

		// Deep copy.
		virtual void STORM_FN deepCopy(CloneEnv *env);

		// Get the input stream.
		NetIStream *STORM_FN input() const;

		// Get the output stream.
		NetOStream *STORM_FN output() const;

		// Close both ends of the socket.
		void STORM_FN close();

		// Get the value of the `nodelay` socket option.
		Bool STORM_FN nodelay() const;

		// Set the `nodelay` socket option.
		void STORM_ASSIGN nodelay(Bool v);

		// Get the current keepalive setting.
		Keepalive STORM_FN keepalive() const;

		// Set the current keepalive setting.
		void STORM_ASSIGN keepalive(Keepalive k);
		void STORM_ASSIGN keepalive(Duration d) {
			keepalive(Keepalive::on(d));
		}

		// Get the remote host we're connected to.
		Address *STORM_FN remote() const { return peer; }

		// To string.
		virtual void STORM_FN toS(StrBuf *to) const;

	protected:
		friend class NetIStream;
		friend class NetOStream;

		// Closed ends of the socket.
		Nat closed;

		enum {
			closeRead = 0x1,
			closeWrite = 0x2
		};

		// Close one end of the socket.
		void closeEnd(Nat which);

		// Input and output streams.
		NetIStream *i;
		NetOStream *o;

		// Connected peer (if any).
		Address *peer;

		// Current keepalive.
		Keepalive alive;
	};


	// Create a socket that is connected to a specific address.
	MAYBE(NetStream *) STORM_FN connect(Address *to);

	// Create a socket that is connected to a specific address, resolving the name first. If `host`
	// specifies a port, it overrides the port in `port`.
	MAYBE(NetStream *) STORM_FN connect(Str *host, Nat port);


	/**
	 * Input stream for the socket.
	 */
	class NetIStream : public HandleTimeoutIStream {
		STORM_CLASS;
	public:
		// Not exposed to Storm. Created by the Socket.
		NetIStream(NetStream *owner, const os::Thread &attachedTo);

		// Destroy.
		virtual ~NetIStream();

		// Close this stream.
		virtual void STORM_FN close();

	private:
		// Owner.
		NetStream *owner;
	};


	/**
	 * Output stream for the socket.
	 */
	class NetOStream : public HandleTimeoutOStream {
		STORM_CLASS;
	public:
		// Not exposed to Storm. Created by the socket.
		NetOStream(NetStream *owner, const os::Thread &attachedTo);

		// Destroy.
		virtual ~NetOStream();

		// Close.
		virtual void STORM_FN close();

	private:
		// Owner.
		NetStream *owner;
	};

}