Code

frontend/connection: Try to handle as much as possible in read().
[sysdb.git] / src / frontend / connection.c
1 /*
2  * SysDB - src/frontend/connection.c
3  * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
28 #include "sysdb.h"
29 #include "frontend/connection.h"
30 #include "utils/strbuf.h"
32 #include <assert.h>
33 #include <errno.h>
35 #include <arpa/inet.h>
37 #include <string.h>
39 /*
40  * connection handler functions
41  */
43 static uint32_t
44 connection_get_int32(sdb_conn_t *conn, size_t offset)
45 {
46         const char *data;
47         uint32_t n;
49         assert(conn && (sdb_strbuf_len(conn->buf) >= offset + sizeof(uint32_t)));
51         data = sdb_strbuf_string(conn->buf);
52         memcpy(&n, data + offset, sizeof(n));
53         n = ntohl(n);
54         return n;
55 } /* connection_get_int32 */
57 static int
58 command_handle(sdb_conn_t *conn)
59 {
60         assert(conn && conn->cmd && conn->cmd_len);
61         /* XXX */
62         sdb_strbuf_skip(conn->buf, conn->cmd_len);
63         return 0;
64 } /* command_handle */
66 /* initialize the connection state information */
67 static int
68 command_init(sdb_conn_t *conn)
69 {
70         assert(conn && (! conn->cmd) && (! conn->cmd_len));
72         conn->cmd = connection_get_int32(conn, 0);
73         conn->cmd_len = connection_get_int32(conn, sizeof(uint32_t));
74         sdb_strbuf_skip(conn->buf, 2 * sizeof(uint32_t));
75         return 0;
76 } /* command_init */
78 /* returns negative value on error, 0 on EOF, number of octets else */
79 static ssize_t
80 connection_read(sdb_conn_t *conn)
81 {
82         ssize_t n = 0;
84         while (42) {
85                 ssize_t status;
87                 errno = 0;
88                 status = sdb_strbuf_read(conn->buf, conn->fd, 1024);
89                 if (status < 0) {
90                         if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
91                                 break;
92                         return (int)status;
93                 }
94                 else if (! status) /* EOF */
95                         break;
97                 n += status;
98         }
100         return n;
101 } /* connection_read */
103 /*
104  * public API
105  */
107 ssize_t
108 sdb_connection_read(sdb_conn_t *conn)
110         ssize_t n = 0;
112         while (42) {
113                 ssize_t status = connection_read(conn);
115                 if ((! conn->cmd) && (! conn->cmd_len)
116                                 && (sdb_strbuf_len(conn->buf) >= 2 * sizeof(int32_t)))
117                         command_init(conn);
118                 if (conn->cmd_len && (sdb_strbuf_len(conn->buf) >= conn->cmd_len))
119                         command_handle(conn);
121                 if (status <= 0)
122                         break;
124                 n += status;
125         }
126         return n;
127 } /* sdb_connection_read */
129 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */