stream: create library instance of stream-manager
[strongswan.git] / src / libstrongswan / networking / streams / stream.c
1 /*
2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include <library.h>
17 #include <errno.h>
18 #include <unistd.h>
19
20 typedef struct private_stream_t private_stream_t;
21
22 /**
23 * Private data of an stream_t object.
24 */
25 struct private_stream_t {
26
27 /**
28 * Public stream_t interface.
29 */
30 stream_t public;
31
32 /**
33 * Underlying socket
34 */
35 int fd;
36 };
37
38 METHOD(stream_t, read_, ssize_t,
39 private_stream_t *this, void *buf, size_t len, bool block)
40 {
41 while (TRUE)
42 {
43 ssize_t ret;
44
45 if (block)
46 {
47 ret = read(this->fd, buf, len);
48 }
49 else
50 {
51 ret = recv(this->fd, buf, len, MSG_DONTWAIT);
52 if (ret == -1 && errno == EAGAIN)
53 {
54 /* unify EGAIN and EWOULDBLOCK */
55 errno = EWOULDBLOCK;
56 }
57 }
58 if (ret == -1 && errno == EINTR)
59 { /* interrupted, try again */
60 continue;
61 }
62 return ret;
63 }
64 }
65
66 METHOD(stream_t, write_, ssize_t,
67 private_stream_t *this, void *buf, size_t len, bool block)
68 {
69 ssize_t ret;
70
71 while (TRUE)
72 {
73 if (block)
74 {
75 ret = write(this->fd, buf, len);
76 }
77 else
78 {
79 ret = send(this->fd, buf, len, MSG_DONTWAIT);
80 if (ret == -1 && errno == EAGAIN)
81 {
82 /* unify EGAIN and EWOULDBLOCK */
83 errno = EWOULDBLOCK;
84 }
85 }
86 if (ret == -1 && errno == EINTR)
87 { /* interrupted, try again */
88 continue;
89 }
90 return ret;
91 }
92 }
93
94 METHOD(stream_t, destroy, void,
95 private_stream_t *this)
96 {
97 close(this->fd);
98 free(this);
99 }
100
101 /**
102 * See header
103 */
104 stream_t *stream_create_from_fd(int fd)
105 {
106 private_stream_t *this;
107
108 INIT(this,
109 .public = {
110 .read = _read_,
111 .write = _write_,
112 .destroy = _destroy,
113 },
114 .fd = fd,
115 );
116
117 return &this->public;
118 }