summaryrefslogtreecommitdiff
path: root/src/libstrongswan/networking/streams/stream.h
blob: 810514da9642f8bb6e1f63bc56af2788e7e51a09 (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
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
/*
 * Copyright (C) 2013 Martin Willi
 * Copyright (C) 2013 revosec AG
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

/**
 * @defgroup stream stream
 * @{ @ingroup streams
 */

#ifndef STREAM_H_
#define STREAM_H_

typedef struct stream_t stream_t;

#include <library.h>

#include <sys/un.h>
#include <sys/socket.h>

/**
 * Constructor function prototype for stream_t.
 *
 * @param uri			URI to create a stream for
 * @return				stream instance, NULL on error
 */
typedef stream_t*(*stream_constructor_t)(char *uri);

/**
 * Callback function prototype, called when stream is ready.
 *
 * It is allowed to destroy the stream during the callback, but only if it has
 * no other active on_read()/on_write() callback and returns FALSE. It is not
 * allowed to to call on_read()/on_write/() during the callback.
 *
 * As select() may return even if a read()/write() would actually block, it is
 * recommended to use the non-blocking calls and handle return values
 * appropriately.
 *
 * @param data			data passed during callback registration
 * @param stream		associated stream
 * @return				FALSE unregisters the invoked callback, TRUE keeps it
 */
typedef bool (*stream_cb_t)(void *data, stream_t *stream);

/**
 * Abstraction of a Berkley socket using stream semantics.
 */
struct stream_t {

	/**
	 * Read data from the stream.
	 *
	 * If "block" is FALSE and no data is available, the function returns -1
	 * and sets errno to EWOULDBLOCK.
	 *
	 * @param buf		data buffer to read into
	 * @param len		number of bytes to read
	 * @param block		TRUE to use a blocking read
	 * @return			number of bytes read, -1 on error
	 */
	ssize_t (*read)(stream_t *this, void *buf, size_t len, bool block);

	/**
	 * Read data from the stream, avoiding short reads.
	 *
	 * This call is always blocking, and reads until len has been read
	 * completely. If the connection is closed before enough bytes could be
	 * returned, errno is set to ECONNRESET.
	 *
	 * @param buf		data buffer to read into
	 * @param len		number of bytes to read
	 * @return			TRUE if len bytes read, FALSE on error
	 */
	bool (*read_all)(stream_t *this, void *buf, size_t len);

	/**
	 * Register a callback to invoke when stream has data to read.
	 *
	 * @param cb		callback function, NULL to unregister
	 * @param data		data to pass to callback
	 */
	void (*on_read)(stream_t *this, stream_cb_t cb, void *data);

	/**
	 * Write data to the stream.
	 *
	 * If "block" is FALSE and the write would block, the function returns -1
	 * and sets errno to EWOULDBLOCK.
	 *
	 * @param buf		data buffer to write
	 * @param len		number of bytes to write
	 * @param block		TRUE to use a blocking write
	 * @return			number of bytes written, -1 on error
	 */
	ssize_t (*write)(stream_t *this, void *buf, size_t len, bool block);

	/**
	 * Write data to the stream, avoiding short writes.
	 *
	 * This call is always blocking, and writes until len bytes has been
	 * written.
	 *
	 * @param buf		data buffer to write
	 * @param len		number of bytes to write
	 * @return			TRUE if len bytes written, FALSE on error
	 */
	bool (*write_all)(stream_t *this, void *buf, size_t len);

	/**
	 * Register a callback to invoke when a write would not block.
	 *
	 * @param cb		callback function, NULL to unregister
	 * @param data		data to pass to callback
	 */
	void (*on_write)(stream_t *this, stream_cb_t cb, void *data);

	/**
	 * Get a FILE reference for this stream.
	 *
	 * @return			FILE*, must be fclose()d, NULL on error
	 */
	FILE* (*get_file)(stream_t *this);

	/**
	 * Destroy a stream_t.
	 */
	void (*destroy)(stream_t *this);
};

/**
 * Create a stream for UNIX sockets.
 *
 * UNIX URIs start with unix://, followed by the socket path. For absolute
 * paths, an URI looks something like:
 *
 *   unix:///path/to/socket
 *
 * @param uri		UNIX socket specific URI, must start with "unix://"
 * @return			stream instance, NULL on failure
 */
stream_t *stream_create_unix(char *uri);

/**
 * Helper function to parse a unix:// URI to a sockaddr
 *
 * @param uri		URI
 * @param addr		sockaddr
 * @return			length of sockaddr, -1 on error
 */
int stream_parse_uri_unix(char *uri, struct sockaddr_un *addr);

/**
 * Create a stream for TCP sockets.
 *
 * TCP URIs start with tcp://, followed by a hostname (FQDN or IP), followed
 * by a colon separated port. A full TCP uri looks something like:
 *
 *   tcp://srv.example.com:5555
 *   tcp://0.0.0.0:1234
 *   tcp://[fec2::1]:7654
 *
 * There is no default port, so a colon after tcp:// is mandatory.
 *
 * @param uri		TCP socket specific URI, must start with "tcp://"
 * @return			stream instance, NULL on failure
 */
stream_t *stream_create_tcp(char *uri);

/**
 * Helper function to parse a tcp:// URI to a sockaddr
 *
 * @param uri		URI
 * @param addr		sockaddr, large enough for URI
 * @return			length of sockaddr, -1 on error
 */
int stream_parse_uri_tcp(char *uri, struct sockaddr *addr);

/**
 * Create a stream from a file descriptor.
 *
 * The file descriptor MUST be a socket for non-blocking operation.
 *
 * @param fd		file descriptor to wrap into a stream_t
 * @return			stream instance
 */
stream_t *stream_create_from_fd(int fd);

#endif /** STREAM_H_ @}*/