4 * @author Sebastian Hack
6 * Protocol stuff for lpp server
8 * Copyright (C) 2005 Universitaet Karlsruhe
9 * Released under the GPL
18 #define WIN32_LEAN_AND_MEAN
22 #define vsnprintf _vsnprintf
26 #include <sys/types.h>
27 #include <sys/socket.h>
36 /* undef to disable buffering socket i/o */
37 #define ENABLE_BUFFERING
39 /* undef to disable debugging */
40 #undef ENABLE_DEBUGGING
52 static inline firm_dbg_module_t *get_dbg_module(void)
54 static firm_dbg_module_t *dbg = NULL;
56 dbg = firm_dbg_register("lpp.comm");
62 #define dbg get_dbg_module()
65 * Try to read some bytes but block until a certain amount is read.
66 * @param fd The file descriptor.
67 * @param buf The buffer to read into.
68 * @param try The amount of bytes to try to read.
69 * @param at_least block until this many bytes are read.
70 * @return The number of bytes read or -1 on error.
72 static ssize_t secure_recv(int fd, void *buf, size_t try, size_t at_least)
75 size_t bytes_read = 0;
79 res = recv(fd, &data[bytes_read], try - bytes_read, 0);
81 if(res == 0 || errno != EAGAIN)
88 } while(bytes_read < at_least);
93 static ssize_t secure_send(int fd, const void *buf, size_t n)
96 size_t bytes_written = 0;
97 const char *data = buf;
100 res = send(fd, &data[bytes_written], n - bytes_written, 0);
107 bytes_written += res;
109 } while(bytes_written < n);
114 #ifdef ENABLE_BUFFERING
115 ssize_t lpp_flush(lpp_comm_t *comm)
118 if(comm->w_pos - comm->w_buf > 0) {
119 DBG((dbg, LEVEL_1, "flushing %d bytes\n", comm->w_pos - comm->w_buf));
120 res = secure_send(comm->fd, comm->w_buf, comm->w_pos - comm->w_buf);
124 comm->w_pos = comm->w_buf;
129 static ssize_t lpp_write(lpp_comm_t *comm, const void *buf, size_t len)
131 assert(comm->w_pos - comm->w_buf >= 0);
133 DBG((dbg, LEVEL_1, "write of length %d\n", len));
135 size_t free = (comm->w_buf + comm->buf_size) - comm->w_pos;
136 size_t copy = MIN(free, len);
137 size_t rest = len - copy;
138 const char *pos = buf;
140 DBG((dbg, LEVEL_1, "\tfree = %d, copy = %d, rest = %d\n", free, copy, rest));
142 memcpy(comm->w_pos, pos, copy);
148 * Not everything in buf fits into the buffer,
149 * so flush the buffer and write the rest.
153 size_t n_direct = rest / comm->buf_size;
156 if(lpp_flush(comm) < 0)
159 for(i = 0; i < n_direct; ++i) {
160 if(secure_send(comm->fd, pos, comm->buf_size) < 0)
163 pos += comm->buf_size;
166 last_rest = ((const char *) buf + len) - pos;
169 assert(last_rest < comm->buf_size);
170 assert(comm->w_pos == comm->w_buf);
171 memcpy(comm->w_pos, pos, last_rest);
172 comm->w_pos += last_rest;
180 static ssize_t lpp_read(lpp_comm_t *comm, void *buf, size_t len)
182 DBG((dbg, LEVEL_1, "read of length %d\n", len));
184 size_t left = comm->r_max - comm->r_pos;
185 size_t copy = MIN(left, len);
186 size_t rest = len - copy;
189 DBG((dbg, LEVEL_1, "\tleft = %d, copy = %d, rest = %d\n", left, copy, rest));
191 memcpy(pos, comm->r_pos, copy);
196 /* We want to read more than the buffer can provide. */
198 size_t bs = comm->buf_size;
199 size_t n_direct = rest / comm->buf_size;
204 * The buffer is now completely read, so
205 * reset the pointers.
207 comm->r_pos = comm->r_buf;
208 comm->r_max = comm->r_buf;
210 for(i = 0; i < n_direct; ++i) {
211 if(secure_recv(comm->fd, pos, bs, bs) < 0)
214 pos += comm->buf_size;
217 last_rest = ((const char *) buf + len) - pos;
220 ssize_t bytes_read = 0;
222 assert(last_rest < comm->buf_size);
223 assert(comm->r_pos == comm->r_buf);
225 bytes_read = secure_recv(comm->fd, comm->r_buf, bs, last_rest);
229 memcpy(pos, comm->r_buf, last_rest);
230 comm->r_pos = comm->r_buf + last_rest;
231 comm->r_max = comm->r_buf + bytes_read;
239 #else /* ENABLE_BUFFERING */
240 ssize_t lpp_flush(lpp_comm_t *comm)
245 static ssize_t lpp_write(lpp_comm_t *comm, const void *buf, size_t len)
247 return secure_send(comm->fd, buf, len);
250 static ssize_t lpp_read(lpp_comm_t *comm, void *buf, size_t len)
252 return secure_recv(comm->fd, buf, len, len);
256 lpp_comm_t *lpp_comm_new(int fd, size_t buf_size)
258 lpp_comm_t *res = malloc(sizeof(res[0]));
261 res->w_buf = malloc(buf_size);
262 res->w_pos = res->w_buf;
263 res->r_buf = malloc(buf_size);
264 res->r_pos = res->r_buf;
265 res->r_max = res->r_buf;
266 res->buf_size = buf_size;
271 int lpp_comm_fileno(const lpp_comm_t *comm)
276 void lpp_comm_free(lpp_comm_t *comm)
283 void lpp_print_err(const char *fmt, ...)
288 vfprintf(stderr, fmt, args);
292 void lpp_writel(lpp_comm_t *comm, uint32_t x)
295 ERRNO_CHECK(lpp_write(comm, &x, sizeof(x)), !=, sizeof(x));
298 void lpp_writed(lpp_comm_t *comm, double dbl)
300 ERRNO_CHECK(lpp_write(comm, &dbl, sizeof(dbl)), !=, sizeof(dbl));
303 void lpp_writes(lpp_comm_t *comm, const char *str)
305 size_t n = strlen(str);
307 ERRNO_CHECK(lpp_write(comm, str, n), !=, (ssize_t) n);
310 uint32_t lpp_readl(lpp_comm_t *comm)
314 ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, sizeof(res));
318 int lpp_read_cmd(lpp_comm_t *comm)
324 retval = recv(comm->fd, (char *)&res, sizeof(res), 0);
334 return (int) ntohl(res);
337 double lpp_readd(lpp_comm_t *comm)
340 ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, sizeof(res));
344 char *lpp_reads(lpp_comm_t *comm)
346 size_t len = lpp_readl(comm);
347 char *res = malloc(sizeof(char) * (len + 1));
349 ERRNO_CHECK(lpp_read(comm, res, len), !=, (ssize_t) len);
354 char *lpp_readbuf(lpp_comm_t *comm, char *buf, size_t buflen)
358 size_t n = buflen - 1;
359 size_t len = lpp_readl(comm);
360 size_t max_read = n < len ? n : len;
361 size_t rest = len - max_read;
363 if(buflen > 0 && buf != NULL) {
364 ERRNO_CHECK(lpp_read(comm, buf, max_read), !=, (ssize_t) max_read);
365 buf[max_read] = '\0';
370 /* eat up data that didnt fit into the string */
371 for(i = 0, n = rest / sizeof(dummy); i < n; ++i)
372 ERRNO_CHECK(lpp_read(comm, dummy, sizeof(dummy)), !=, sizeof(dummy));
374 if(rest % sizeof(dummy) > 0)
375 ERRNO_CHECK(lpp_read(comm, dummy, rest % sizeof(dummy)), !=,
376 (ssize_t) (rest % sizeof(dummy)) );
381 int lpp_ack(lpp_comm_t *comm, char *buf, size_t buflen)
384 int cmd = lpp_readl(comm);
391 lpp_readbuf(comm, buf, buflen);
399 void lpp_send_res(lpp_comm_t *comm, int ok, const char *fmt, ...)
406 vsnprintf(buf, sizeof(buf), fmt, args);
409 lpp_writel(comm, LPP_CMD_BAD);
410 lpp_writes(comm, buf);
414 lpp_writel(comm, LPP_CMD_OK);
417 void lpp_send_ack(lpp_comm_t *comm)
419 lpp_send_res(comm, 1, "");
422 const char *lpp_get_cmd_name(int cmd)
425 #define LPP_CMD(x) case LPP_CMD_ ## x: return #x;
426 #include "lpp_cmd.def"