Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
ccan
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mirror
ccan
Commits
cece0985
Commit
cece0985
authored
Oct 14, 2013
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ccan/io: add examples.
Signed-off-by:
Rusty Russell
<
rusty@rustcorp.com.au
>
parent
b85c47bb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
239 additions
and
0 deletions
+239
-0
ccan/io/io.h
ccan/io/io.h
+207
-0
ccan/io/io_plan.h
ccan/io/io_plan.h
+32
-0
No files found.
ccan/io/io.h
View file @
cece0985
...
...
@@ -16,6 +16,16 @@
* next io_loop().
*
* Returns NULL on error (and sets errno).
*
* Example:
* int fd[2];
* struct io_conn *conn;
*
* pipe(fd);
* // Plan is to close the fd immediately.
* conn = io_new_conn(fd[0], io_close());
* if (!conn)
* exit(1);
*/
#define io_new_conn(fd, plan) \
(io_plan_no_debug(), io_new_conn_((fd), (plan)))
...
...
@@ -30,6 +40,15 @@ struct io_conn *io_new_conn_(int fd, struct io_plan plan);
* @finish will be called when an I/O operation fails, or you call
* io_close() on the connection. errno will be set to the value
* after the failed I/O, or at the call to io_close().
*
* Example:
* static void finish(struct io_conn *conn, void *unused)
* {
* // errno is not 0 after success, so this is a bit useless.
* printf("Conn %p closed with errno %i\n", conn, errno);
* }
* ...
* io_set_finish(conn, finish, NULL);
*/
#define io_set_finish(conn, finish, arg) \
io_set_finish_((conn), \
...
...
@@ -50,6 +69,50 @@ void io_set_finish_(struct io_conn *conn,
* When @fd becomes readable, we accept() and pass that fd to init().
*
* Returns NULL on error (and sets errno).
*
* Example:
* #include <sys/types.h>
* #include <sys/socket.h>
* #include <netdb.h>
*
* static void start_conn(int fd, char *msg)
* {
* printf("%s fd %i\n", msg, fd);
* close(fd);
* }
*
* // Set up a listening socket, return it.
* static struct io_listener *do_listen(const char *port)
* {
* struct addrinfo *addrinfo, hints;
* int fd, on = 1;
*
* memset(&hints, 0, sizeof(hints));
* hints.ai_family = AF_UNSPEC;
* hints.ai_socktype = SOCK_STREAM;
* hints.ai_flags = AI_PASSIVE;
* hints.ai_protocol = 0;
*
* if (getaddrinfo(NULL, port, &hints, &addrinfo) != 0)
* return NULL;
*
* fd = socket(addrinfo->ai_family, addrinfo->ai_socktype,
* addrinfo->ai_protocol);
* if (fd < 0)
* return NULL;
*
* freeaddrinfo(addrinfo);
* setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
* if (bind(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) != 0) {
* close(fd);
* return NULL;
* }
* if (listen(fd, 1) != 0) {
* close(fd);
* return NULL;
* }
* return io_new_listener(fd, start_conn, (char *)"Got one!");
* }
*/
#define io_new_listener(fd, init, arg) \
io_new_listener_((fd), \
...
...
@@ -66,6 +129,14 @@ struct io_listener *io_new_listener_(int fd,
* @listener: the listener returned from io_new_listener.
*
* This closes the fd and frees @listener.
*
* Example:
* ...
* struct io_listener *l = do_listen("8111");
* if (l) {
* io_loop();
* io_close_listener(l);
* }
*/
void
io_close_listener
(
struct
io_listener
*
listener
);
...
...
@@ -81,6 +152,13 @@ void io_close_listener(struct io_listener *listener);
* function is called instead.
*
* Note that the I/O may actually be done immediately.
*
* Example:
* static void start_conn_with_write(int fd, const char *msg)
* {
* // Write message, then close.
* io_new_conn(fd, io_write(msg, strlen(msg), io_close_cb, NULL));
* }
*/
#define io_write(data, len, cb, arg) \
io_debug(io_write_((data), (len), \
...
...
@@ -103,6 +181,13 @@ struct io_plan io_write_(const void *data, size_t len,
* function is called instead.
*
* Note that the I/O may actually be done immediately.
*
* Example:
* static void start_conn_with_read(int fd, char msg[12])
* {
* // Read message, then close.
* io_new_conn(fd, io_read(msg, 12, io_close_cb, NULL));
* }
*/
#define io_read(data, len, cb, arg) \
io_debug(io_read_((data), (len), \
...
...
@@ -126,6 +211,28 @@ struct io_plan io_read_(void *data, size_t len,
* error, the finish function is called instead.
*
* Note that the I/O may actually be done immediately.
*
* Example:
* struct buf {
* size_t len;
* char buf[12];
* };
*
* static struct io_plan dump_and_close(struct io_conn *conn, struct buf *b)
* {
* printf("Partial read: '%*s'\n", (int)b->len, b->buf);
* free(b);
* return io_close();
* }
*
* static void start_conn_with_part_read(int fd, void *unused)
* {
* struct buf *b = malloc(sizeof(*b));
*
* // Read message, then dump and close.
* b->len = sizeof(b->buf);
* io_new_conn(fd, io_read_partial(b->buf, &b->len, dump_and_close, b));
* }
*/
#define io_read_partial(data, len, cb, arg) \
io_debug(io_read_partial_((data), (len), \
...
...
@@ -149,6 +256,29 @@ struct io_plan io_read_partial_(void *data, size_t *len,
* error, the finish function is called instead.
*
* Note that the I/O may actually be done immediately.
*
* Example:
* struct buf {
* size_t len;
* char buf[12];
* };
*
* static struct io_plan show_remainder(struct io_conn *conn, struct buf *b)
* {
* printf("Only wrote: '%*s'\n", (int)b->len, b->buf);
* free(b);
* return io_close();
* }
*
* static void start_conn_with_part_read(int fd, void *unused)
* {
* struct buf *b = malloc(sizeof(*b));
*
* // Write message, then dump and close.
* b->len = sizeof(b->buf);
* strcpy(b->buf, "Hello world");
* io_new_conn(fd, io_write_partial(b->buf, &b->len, show_remainder, b));
* }
*/
#define io_write_partial(data, len, cb, arg) \
io_debug(io_write_partial_((data), (len), \
...
...
@@ -173,6 +303,26 @@ struct io_plan io_write_partial_(const void *data, size_t *len,
* function is called instead.
*
* Note that the connect may actually be done immediately.
*
* Example:
* #include <sys/types.h>
* #include <sys/socket.h>
* #include <netdb.h>
*
* // Write, then close socket.
* static struct io_plan start_write(struct io_conn *conn, void *unused)
* {
* return io_write("hello", 5, io_close_cb, NULL);
* }
*
* ...
*
* int fd;
* struct addrinfo *addrinfo;
*
* fd = socket(AF_INET, SOCK_STREAM, 0);
* getaddrinfo("localhost", "8111", NULL, &addrinfo);
* io_new_conn(fd, io_connect(fd, addrinfo, start_write, NULL));
*/
struct
addrinfo
;
#define io_connect(fd, addr, cb, arg) \
...
...
@@ -190,6 +340,12 @@ struct io_plan io_connect_(int fd, const struct addrinfo *addr,
*
* This indicates the connection is idle: io_wake() will be called later do
* give the connection a new plan.
*
* Example:
* struct io_conn *sleeper;
* sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
* if (!sleeper)
* exit(1);
*/
#define io_idle() io_debug(io_idle_())
struct
io_plan
io_idle_
(
void
);
...
...
@@ -207,6 +363,17 @@ struct io_plan io_idle_(void);
*
* Returns false on allocation failure. A connection can only have one
* timeout.
*
* Example:
* static struct io_plan close_on_timeout(struct io_conn *conn, char *msg)
* {
* printf("%s\n", msg);
* return io_close();
* }
*
* ...
* io_timeout(sleeper, time_from_msec(100),
* close_on_timeout, (char *)"Bye!");
*/
#define io_timeout(conn, ts, fn, arg) \
io_timeout_((conn), (ts), \
...
...
@@ -228,6 +395,21 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts,
* operations and one for write.
*
* You must io_close() both of them to close the fd.
*
* Example:
* static void setup_read_write(int fd,
* char greet_in[5], const char greet_out[5])
* {
* struct io_conn *writer, *reader;
*
* // Read their greeting and send ours at the same time.
* writer = io_new_conn(fd,
* io_write(greet_out, 5, io_close_cb, NULL));
* reader = io_duplex(writer,
* io_read(greet_in, 5, io_close_cb, NULL));
* if (!reader || !writer)
* exit(1);
* }
*/
#define io_duplex(conn, plan) \
(io_plan_no_debug(), io_duplex_((conn), (plan)))
...
...
@@ -239,6 +421,12 @@ struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan);
* @plan: the next I/O plan for @conn.
*
* This makes @conn ready to do I/O the next time around the io_loop().
*
* Example:
* struct io_conn *sleeper;
* sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
*
* io_wake(sleeper, io_write("junk", 4, io_close_cb, NULL));
*/
#define io_wake(conn, plan) (io_plan_no_debug(), io_wake_((conn), (plan)))
void
io_wake_
(
struct
io_conn
*
conn
,
struct
io_plan
plan
);
...
...
@@ -253,6 +441,12 @@ void io_wake_(struct io_conn *conn, struct io_plan plan);
* finish callbacks called, then io_loop() with return with @ret.
*
* If io_loop() is called again, then @plan will be carried out.
*
* Example:
* static struct io_plan fail_on_timeout(struct io_conn *conn, char *msg)
* {
* return io_break(msg, io_close());
* }
*/
#define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan)))
struct
io_plan
io_break_
(
void
*
ret
,
struct
io_plan
plan
);
...
...
@@ -263,6 +457,13 @@ struct io_plan io_break_(void *ret, struct io_plan plan);
* io_close - plan to close a connection.
*
* On return to io_loop, the connection will be closed.
*
* Example:
* static struct io_plan close_on_timeout(struct io_conn *conn, const char *msg)
* {
* printf("closing: %s\n", msg);
* return io_close();
* }
*/
#define io_close() io_debug(io_close_())
struct
io_plan
io_close_
(
void
);
...
...
@@ -273,6 +474,9 @@ struct io_plan io_close_(void);
*
* This schedules a connection to be closed; designed to be used as
* a callback function.
*
* Example:
* #define close_on_timeout io_close_cb
*/
struct
io_plan
io_close_cb
(
struct
io_conn
*
,
void
*
unused
);
...
...
@@ -281,6 +485,9 @@ struct io_plan io_close_cb(struct io_conn *, void *unused);
*
* This is the core loop; it exits with the io_break() arg, or NULL if
* all connections and listeners are closed.
*
* Example:
* io_loop();
*/
void
*
io_loop
(
void
);
#endif
/* CCAN_IO_H */
ccan/io/io_plan.h
View file @
cece0985
...
...
@@ -68,6 +68,17 @@ struct io_plan {
* If this is set, the routine should return true if the connection is a
* debugging candidate. If so, the callchain for I/O operations on this
* connection will be linear, for easier use of a debugger.
*
* You will also see calls to any callbacks which wake the connection
* which is being debugged.
*
* Example:
* static bool debug_all(struct io_conn *conn)
* {
* return true();
* }
* ...
* io_debug_conn = debug_all;
*/
extern
bool
(
*
io_debug_conn
)(
struct
io_conn
*
conn
);
...
...
@@ -77,6 +88,10 @@ extern bool (*io_debug_conn)(struct io_conn *conn);
* This determines if we are debugging the current connection: if so,
* it immediately applies the plan and calls back into io_loop() to
* create a linear call chain.
*
* Example:
* #define io_idle() io_debug(io_idle_())
* struct io_plan io_idle_(void);
*/
struct
io_plan
io_debug
(
struct
io_plan
plan
);
...
...
@@ -86,6 +101,19 @@ struct io_plan io_debug(struct io_plan plan);
* This determines if we are debugging the current connection: if so,
* it immediately sets the next function and calls into io_loop() to
* create a linear call chain.
*
* Example:
*
* static int do_write(int fd, struct io_plan *plan)
* {
* ssize_t ret = write(fd, plan->u.write.buf, plan->u.write.len);
* if (ret < 0)
* return io_debug_io(-1);
*
* plan->u.write.buf += ret;
* plan->u.write.len -= ret;
* return io_debug_io(plan->u.write.len == 0);
* }
*/
int
io_debug_io
(
int
ret
);
...
...
@@ -99,6 +127,10 @@ int io_debug_io(int ret);
* Some routines, like io_break(), io_duplex() and io_wake() take an
* io_plan, but they must not be applied immediately to the current
* connection, so we call this first.
*
* Example:
* #define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan)))
* struct io_plan io_break_(void *ret, struct io_plan plan);
*/
#define io_plan_no_debug() ((io_plan_nodebug = true))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment