2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 typedef struct private_stream_t private_stream_t
;
23 * Private data of an stream_t object.
25 struct private_stream_t
{
28 * Public stream_t interface.
38 * FILE* for convenience functions, or NULL
43 * Callback if data is ready to read
48 * Data for read-ready callback
53 * Callback if write is non-blocking
58 * Data for write-ready callback
65 METHOD(stream_t
, read_
, ssize_t
,
66 private_stream_t
*this, void *buf
, size_t len
, bool block
)
74 ret
= read(this->fd
, buf
, len
);
78 ret
= recv(this->fd
, buf
, len
, MSG_DONTWAIT
);
79 if (ret
== -1 && errno
== EAGAIN
)
81 /* unify EGAIN and EWOULDBLOCK */
85 if (ret
== -1 && errno
== EINTR
)
86 { /* interrupted, try again */
93 METHOD(stream_t
, write_
, ssize_t
,
94 private_stream_t
*this, void *buf
, size_t len
, bool block
)
102 ret
= write(this->fd
, buf
, len
);
106 ret
= send(this->fd
, buf
, len
, MSG_DONTWAIT
);
107 if (ret
== -1 && errno
== EAGAIN
)
109 /* unify EGAIN and EWOULDBLOCK */
113 if (ret
== -1 && errno
== EINTR
)
114 { /* interrupted, try again */
122 * Remove a registered watcher
124 static void remove_watcher(private_stream_t
*this)
126 if (this->read_cb
|| this->write_cb
)
128 lib
->watcher
->remove(lib
->watcher
, this->fd
);
135 static bool watch(private_stream_t
*this, int fd
, watcher_event_t event
)
142 keep
= this->read_cb(this->read_data
, &this->public);
145 this->read_cb
= NULL
;
149 keep
= this->write_cb(this->write_data
, &this->public);
152 this->write_cb
= NULL
;
162 * Register watcher for stream callbacks
164 static void add_watcher(private_stream_t
*this)
166 watcher_event_t events
= 0;
170 events
|= WATCHER_READ
;
174 events
|= WATCHER_WRITE
;
178 lib
->watcher
->add(lib
->watcher
, this->fd
, events
,
179 (watcher_cb_t
)watch
, this);
183 METHOD(stream_t
, on_read
, void,
184 private_stream_t
*this, stream_cb_t cb
, void *data
)
186 remove_watcher(this);
189 this->read_data
= data
;
194 METHOD(stream_t
, on_write
, void,
195 private_stream_t
*this, stream_cb_t cb
, void *data
)
197 remove_watcher(this);
200 this->write_data
= data
;
205 METHOD(stream_t
, vprint
, int,
206 private_stream_t
*this, char *format
, va_list ap
)
210 this->file
= fdopen(this->fd
, "w+");
216 return vfprintf(this->file
, format
, ap
);
219 METHOD(stream_t
, print
, int,
220 private_stream_t
*this, char *format
, ...)
225 va_start(ap
, format
);
226 ret
= vprint(this, format
, ap
);
232 METHOD(stream_t
, destroy
, void,
233 private_stream_t
*this)
235 remove_watcher(this);
250 stream_t
*stream_create_from_fd(int fd
)
252 private_stream_t
*this;
259 .on_write
= _on_write
,
267 return &this->public;