libubox
C utility functions for OpenWrt.
ustream-fd.c
Go to the documentation of this file.
1 /*
2  * ustream - library for stream buffer management
3  *
4  * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <unistd.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include "ustream.h"
23 
24 static void ustream_fd_set_uloop(struct ustream *s, bool write)
25 {
26  struct ustream_fd *sf = container_of(s, struct ustream_fd, stream);
27  struct ustream_buf *buf;
28  unsigned int flags = ULOOP_EDGE_TRIGGER | ULOOP_ERROR_CB;
29 
30  if (!s->read_blocked && !s->eof)
31  flags |= ULOOP_READ;
32 
33  buf = s->w.head;
34  if (write || (buf && s->w.data_bytes && !s->write_error))
35  flags |= ULOOP_WRITE;
36 
37  uloop_fd_add(&sf->fd, flags);
38 }
39 
40 static void ustream_fd_set_read_blocked(struct ustream *s)
41 {
42  ustream_fd_set_uloop(s, false);
43 }
44 
45 static void ustream_fd_read_pending(struct ustream_fd *sf, bool *more)
46 {
47  struct ustream *s = &sf->stream;
48  int buflen = 0;
49  ssize_t len;
50  char *buf;
51 
52  do {
53  if (s->read_blocked)
54  break;
55 
56  buf = ustream_reserve(s, 1, &buflen);
57  if (!buf)
58  break;
59 
60  len = read(sf->fd.fd, buf, buflen);
61  if (len < 0) {
62  if (errno == EINTR)
63  continue;
64 
65  if (errno == EAGAIN || errno == ENOTCONN)
66  return;
67 
68  len = 0;
69  }
70 
71  if (!len) {
72  if (!s->eof)
74  s->eof = true;
75  ustream_fd_set_uloop(s, false);
76  return;
77  }
78 
79  ustream_fill_read(s, len);
80  *more = true;
81  } while (1);
82 }
83 
84 static int ustream_fd_write(struct ustream *s, const char *buf, int buflen, bool more)
85 {
86  struct ustream_fd *sf = container_of(s, struct ustream_fd, stream);
87  ssize_t ret = 0, len;
88 
89  if (!buflen)
90  return 0;
91 
92  while (buflen) {
93  len = write(sf->fd.fd, buf, buflen);
94 
95  if (len < 0) {
96  if (errno == EINTR)
97  continue;
98 
99  if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ENOTCONN)
100  break;
101 
102  return -1;
103  }
104 
105  ret += len;
106  buf += len;
107  buflen -= len;
108  }
109 
110  if (buflen)
111  ustream_fd_set_uloop(s, true);
112 
113  return ret;
114 }
115 
116 static bool __ustream_fd_poll(struct ustream_fd *sf, unsigned int events)
117 {
118  struct ustream *s = &sf->stream;
119  bool more = false;
120 
121  if (events & ULOOP_READ)
122  ustream_fd_read_pending(sf, &more);
123 
124  if (events & ULOOP_WRITE) {
125  bool no_more = ustream_write_pending(s);
126  if (no_more)
127  ustream_fd_set_uloop(s, false);
128  }
129 
130  if (sf->fd.error && !s->write_error) {
132  s->write_error = true;
133  ustream_fd_set_uloop(s, false);
134  }
135 
136  return more;
137 }
138 
139 static bool ustream_fd_poll(struct ustream *s)
140 {
141  struct ustream_fd *sf = container_of(s, struct ustream_fd, stream);
142 
144 }
145 
146 static void ustream_uloop_cb(struct uloop_fd *fd, unsigned int events)
147 {
148  struct ustream_fd *sf = container_of(fd, struct ustream_fd, fd);
149 
151 }
152 
153 static void ustream_fd_free(struct ustream *s)
154 {
155  struct ustream_fd *sf = container_of(s, struct ustream_fd, stream);
156 
157  uloop_fd_delete(&sf->fd);
158 }
159 
160 void ustream_fd_init(struct ustream_fd *sf, int fd)
161 {
162  struct ustream *s = &sf->stream;
163 
165 
166  sf->fd.fd = fd;
167  sf->fd.cb = ustream_uloop_cb;
169  s->write = ustream_fd_write;
170  s->free = ustream_fd_free;
171  s->poll = ustream_fd_poll;
172  ustream_fd_set_uloop(s, false);
173 }
#define container_of(ptr, type, member)
Definition: list.h:38
Definition: uloop.h:63
int fd
Definition: uloop.h:65
uloop_fd_handler cb
Definition: uloop.h:64
bool error
Definition: uloop.h:67
struct ustream_buf * head
Definition: ustream.h:34
struct uloop_fd fd
Definition: ustream.h:124
struct ustream stream
Definition: ustream.h:123
struct ustream_buf_list r w
Definition: ustream.h:50
bool eof
Definition: ustream.h:117
int(* write)(struct ustream *s, const char *buf, int len, bool more)
Definition: ustream.h:88
void(* set_read_blocked)(struct ustream *s)
Definition: ustream.h:101
void(* free)(struct ustream *s)
Definition: ustream.h:94
bool(* poll)(struct ustream *s)
Definition: ustream.h:109
bool write_error
Definition: ustream.h:116
enum read_blocked_reason read_blocked
Definition: ustream.h:119
int fd
Definition: udebug-priv.h:27
static struct epoll_event events[ULOOP_MAX_EVENTS]
Definition: uloop-epoll.c:60
int uloop_fd_add(struct uloop_fd *sock, unsigned int flags)
Definition: uloop.c:235
int uloop_fd_delete(struct uloop_fd *fd)
Definition: uloop.c:265
#define ULOOP_ERROR_CB
Definition: uloop.h:60
#define ULOOP_WRITE
Definition: uloop.h:48
#define ULOOP_READ
Definition: uloop.h:47
#define ULOOP_EDGE_TRIGGER
Definition: uloop.h:49
static void ustream_fd_set_uloop(struct ustream *s, bool write)
Definition: ustream-fd.c:24
static int ustream_fd_write(struct ustream *s, const char *buf, int buflen, bool more)
Definition: ustream-fd.c:84
static bool ustream_fd_poll(struct ustream *s)
Definition: ustream-fd.c:139
static void ustream_fd_free(struct ustream *s)
Definition: ustream-fd.c:153
static void ustream_fd_set_read_blocked(struct ustream *s)
Definition: ustream-fd.c:40
static void ustream_fd_read_pending(struct ustream_fd *sf, bool *more)
Definition: ustream-fd.c:45
static void ustream_uloop_cb(struct uloop_fd *fd, unsigned int events)
Definition: ustream-fd.c:146
void ustream_fd_init(struct ustream_fd *sf, int fd)
Definition: ustream-fd.c:160
static bool __ustream_fd_poll(struct ustream_fd *sf, unsigned int events)
Definition: ustream-fd.c:116
void ustream_init_defaults(struct ustream *s)
Definition: ustream.c:112
bool ustream_write_pending(struct ustream *s)
Definition: ustream.c:372
void ustream_fill_read(struct ustream *s, int len)
Definition: ustream.c:301
char * ustream_reserve(struct ustream *s, int len, int *maxlen)
Definition: ustream.c:286
static void ustream_state_change(struct ustream *s)
Definition: ustream.h:208