]>
Commit | Line | Data |
---|---|---|
92658f56 PR |
1 | #include <errno.h> |
2 | #include <stdio.h> | |
3 | #include <malloc.h> | |
4 | #include <string.h> | |
5 | ||
6 | /* | |
7 | * Read a single message from a (socket) filedescriptor. Messages are delimited | |
8 | * by blank lines. This call will block until all of a message is received. The | |
9 | * memory will be allocated from heap. Upon error, all memory is freed and the | |
10 | * buffer pointer is set to NULL. | |
11 | */ | |
12 | int read_buffer(int fd, char **buffer) { | |
13 | int bytes = 0; | |
14 | int buffersize = 32; | |
15 | *buffer = malloc(buffersize + 1); | |
16 | ||
17 | while (1) { | |
18 | int result = read(fd, (*buffer) + bytes, buffersize - bytes); | |
19 | if (result > 0) | |
20 | bytes += result; | |
21 | if (result == 0) | |
22 | goto fail; /* we should never encounter EOF here */ | |
23 | if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK) | |
24 | goto fail; | |
25 | ||
26 | if (bytes == buffersize) { | |
27 | buffersize += 1024; | |
28 | char *new = realloc(*buffer, buffersize + 1); | |
29 | if (new) | |
30 | *buffer = new; | |
31 | else | |
32 | goto fail; | |
33 | } else { | |
34 | (*buffer)[bytes] = 0; | |
35 | char *end; | |
36 | if ((end = strstr((*buffer) + bytes - 2, "\n\n"))) { | |
37 | *end = 0; | |
38 | break; /* success, we have the full message now */ | |
39 | } | |
40 | /* TODO call select here if we encountered EAGAIN/EWOULDBLOCK */ | |
41 | } | |
42 | } | |
43 | return 1; | |
44 | fail: | |
45 | free(*buffer); | |
46 | *buffer = NULL; | |
47 | return 0; | |
48 | } | |
49 | ||
50 | /* | |
51 | * Write a buffer to a filedescriptor. Keep trying. Blocks (even on | |
52 | * SOCK_NONBLOCK) until all of the write went through. | |
53 | * | |
54 | * TODO use select on EWOULDBLOCK/EAGAIN to avoid useless spinning | |
55 | */ | |
56 | int write_buffer(int fd, char *buffer, int length) { | |
57 | int written = 0; | |
58 | while (1) { | |
59 | int result = write(fd, buffer + written, length - written); | |
60 | if (result > 0) | |
61 | written += result; | |
62 | if (result < 0 && errno != EWOULDBLOCK && errno != EAGAIN) | |
63 | break; /* too bad */ | |
64 | if (written == length) | |
65 | return 1; /* done */ | |
66 | } | |
67 | return 0; | |
68 | } |