2 * Copyright (C) 2005-2011 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Protocol stuff for lpp server
23 * @author Sebastian Hack
33 #define WIN32_LEAN_AND_MEAN
37 typedef SSIZE_T ssize_t;
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <arpa/inet.h>
62 static inline firm_dbg_module_t *get_dbg_module(void)
64 static firm_dbg_module_t *dbg = NULL;
66 dbg = firm_dbg_register("lpp.comm");
71 #define dbg get_dbg_module()
75 * Try to read some bytes but block until a certain amount is read.
76 * @param fd The file descriptor.
77 * @param buf The buffer to read into.
78 * @param try_amount The amount of bytes to try to read.
79 * @param at_least block until this many bytes are read.
80 * @return The number of bytes read or -1 on error.
82 static ssize_t secure_recv(int fd, void *buf, size_t try_amount, size_t at_least)
85 size_t bytes_read = 0;
86 char *data = (char*)buf;
89 res = recv(fd, &data[bytes_read], try_amount - bytes_read, 0);
91 if(res == 0 || errno != EAGAIN)
98 } while(bytes_read < at_least);
103 static ssize_t secure_send(int fd, const void *buf, size_t n)
106 size_t bytes_written = 0;
107 const char *data = (const char*)buf;
110 res = send(fd, &data[bytes_written], n - bytes_written, 0);
117 bytes_written += res;
119 } while(bytes_written < n);
124 static ssize_t lpp_flush_(lpp_comm_t *comm)
127 if(comm->w_pos - comm->w_buf > 0) {
128 DBG((dbg, LEVEL_1, "flushing %d bytes\n", comm->w_pos - comm->w_buf));
129 res = secure_send(comm->fd, comm->w_buf, comm->w_pos - comm->w_buf);
133 comm->w_pos = comm->w_buf;
138 void lpp_flush(lpp_comm_t *comm)
143 static ssize_t lpp_write(lpp_comm_t *comm, const void *buf, size_t len)
145 assert(comm->w_pos - comm->w_buf >= 0);
147 DBG((dbg, LEVEL_1, "write of length %d\n", len));
149 size_t free = (comm->w_buf + comm->buf_size) - comm->w_pos;
150 size_t copy = MIN(free, len);
151 size_t rest = len - copy;
152 const char *pos = (const char*)buf;
154 DBG((dbg, LEVEL_1, "\tfree = %d, copy = %d, rest = %d\n", free, copy, rest));
156 memcpy(comm->w_pos, pos, copy);
162 * Not everything in buf fits into the buffer,
163 * so flush the buffer and write the rest.
167 size_t n_direct = rest / comm->buf_size;
170 if(lpp_flush_(comm) < 0)
173 for(i = 0; i < n_direct; ++i) {
174 if(secure_send(comm->fd, pos, comm->buf_size) < 0)
177 pos += comm->buf_size;
180 last_rest = ((const char *) buf + len) - pos;
183 assert(last_rest < comm->buf_size);
184 assert(comm->w_pos == comm->w_buf);
185 memcpy(comm->w_pos, pos, last_rest);
186 comm->w_pos += last_rest;
194 static ssize_t lpp_read(lpp_comm_t *comm, void *buf, size_t len)
196 DBG((dbg, LEVEL_1, "read of length %d\n", len));
198 size_t left = comm->r_max - comm->r_pos;
199 size_t copy = MIN(left, len);
200 size_t rest = len - copy;
201 char *pos = (char*)buf;
203 DBG((dbg, LEVEL_1, "\tleft = %d, copy = %d, rest = %d\n", left, copy, rest));
205 memcpy(pos, comm->r_pos, copy);
210 /* We want to read more than the buffer can provide. */
212 size_t bs = comm->buf_size;
213 size_t n_direct = rest / comm->buf_size;
218 * The buffer is now completely read, so
219 * reset the pointers.
221 comm->r_pos = comm->r_buf;
222 comm->r_max = comm->r_buf;
224 for(i = 0; i < n_direct; ++i) {
225 if(secure_recv(comm->fd, pos, bs, bs) < 0)
228 pos += comm->buf_size;
231 last_rest = ((const char *) buf + len) - pos;
234 ssize_t bytes_read = 0;
236 assert(last_rest < comm->buf_size);
237 assert(comm->r_pos == comm->r_buf);
239 bytes_read = secure_recv(comm->fd, comm->r_buf, bs, last_rest);
243 memcpy(pos, comm->r_buf, last_rest);
244 comm->r_pos = comm->r_buf + last_rest;
245 comm->r_max = comm->r_buf + bytes_read;
253 lpp_comm_t *lpp_comm_new(int fd, size_t buf_size)
255 lpp_comm_t *res = XMALLOCZ(lpp_comm_t);
258 res->w_buf = XMALLOCN(char, buf_size);
259 res->w_pos = res->w_buf;
260 res->r_buf = XMALLOCN(char, buf_size);
261 res->r_pos = res->r_buf;
262 res->r_max = res->r_buf;
263 res->buf_size = buf_size;
268 int lpp_comm_fileno(const lpp_comm_t *comm)
273 void lpp_comm_free(lpp_comm_t *comm)
280 void lpp_print_err(const char *fmt, ...)
285 vfprintf(stderr, fmt, args);
289 void lpp_writel(lpp_comm_t *comm, uint32_t x)
292 ERRNO_CHECK(lpp_write(comm, &x, sizeof(x)), !=, (ssize_t)sizeof(x));
295 void lpp_writed(lpp_comm_t *comm, double dbl)
297 ERRNO_CHECK(lpp_write(comm, &dbl, sizeof(dbl)), !=, (ssize_t)sizeof(dbl));
300 void lpp_writes(lpp_comm_t *comm, const char *str)
302 size_t n = strlen(str);
304 ERRNO_CHECK(lpp_write(comm, str, n), !=, (ssize_t) n);
307 uint32_t lpp_readl(lpp_comm_t *comm)
311 ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, (ssize_t)sizeof(res));
315 int lpp_read_cmd(lpp_comm_t *comm)
321 retval = recv(comm->fd, (char *)&res, sizeof(res), 0);
331 return (int) ntohl(res);
334 double lpp_readd(lpp_comm_t *comm)
337 ERRNO_CHECK(lpp_read(comm, &res, sizeof(res)), !=, (ssize_t)sizeof(res));
341 char *lpp_reads(lpp_comm_t *comm)
343 size_t len = lpp_readl(comm);
344 char *res = XMALLOCN(char, len+1);
346 ERRNO_CHECK(lpp_read(comm, res, len), !=, (ssize_t) len);
351 char *lpp_readbuf(lpp_comm_t *comm, char *buf, size_t buflen)
355 size_t n = buflen - 1;
356 size_t len = lpp_readl(comm);
357 size_t max_read = n < len ? n : len;
358 size_t rest = len - max_read;
360 if(buflen > 0 && buf != NULL) {
361 ERRNO_CHECK(lpp_read(comm, buf, max_read), !=, (ssize_t) max_read);
362 buf[max_read] = '\0';
367 /* eat up data that didnt fit into the string */
368 for(i = 0, n = rest / sizeof(dummy); i < n; ++i)
369 ERRNO_CHECK(lpp_read(comm, dummy, sizeof(dummy)), !=, (ssize_t)sizeof(dummy));
371 if(rest % sizeof(dummy) > 0)
372 ERRNO_CHECK(lpp_read(comm, dummy, rest % sizeof(dummy)), !=,
373 (ssize_t) (rest % sizeof(dummy)) );
378 int lpp_ack(lpp_comm_t *comm, char *buf, size_t buflen)
381 int cmd = lpp_readl(comm);
388 lpp_readbuf(comm, buf, buflen);
396 void lpp_send_res(lpp_comm_t *comm, int ok, const char *fmt, ...)
403 vsnprintf(buf, sizeof(buf), fmt, args);
406 lpp_writel(comm, LPP_CMD_BAD);
407 lpp_writes(comm, buf);
409 lpp_writel(comm, LPP_CMD_OK);
413 void lpp_send_ack(lpp_comm_t *comm)
415 lpp_send_res(comm, 1, "");
418 const char *lpp_get_cmd_name(int cmd)
421 case LPP_CMD_BAD: return "BAD";
422 case LPP_CMD_OK: return "OK";
423 case LPP_CMD_PROBLEM: return "PROBLEM";
424 case LPP_CMD_SOLUTION: return "SOLUTION";
425 case LPP_CMD_SOLVER: return "SOLVER";
426 case LPP_CMD_BYE: return "BYE";
427 case LPP_CMD_SOLVERS: return "SOLVERS";
428 case LPP_CMD_SET_DEBUG: return "SET_DEBUG";
429 case LPP_CMD_INFO: return "INFO";