summaryrefslogtreecommitdiff
path: root/legacy/evas/src/bin/evas_cserve2_messages.c
diff options
context:
space:
mode:
authorIván Briano <sachieru@gmail.com>2012-05-03 21:01:31 +0000
committerIván Briano <sachieru@gmail.com>2012-05-03 21:01:31 +0000
commit15328efb85bcf413025d787d1d58d812a407f25a (patch)
tree37c09205c159d8b9758ffdada5dff2248e632613 /legacy/evas/src/bin/evas_cserve2_messages.c
parentb8ade6a7cfa99ca19c054bd6b0bf488e63accbf4 (diff)
evas/cserve2: fix typo that kept cserve2 disabled
now seriously... Introducing Cache Serve 2. This cache server will initially load images for clients connected to it. It starts slave processes to load these images, and share the loaded images through shm with the clients. All the connection done between clients and the server goes through sockets. The cserve2 build option is turned on by default, while the old cserve was disabled, but in order to make clients use it, the environment variable EVAS_CSERVE2 must be set, and a server must be running. Clients will try to find the socket on a specified location using the environment variable EVAS_CSERVE2_SOCKET. If it's not defined, then the XDG_RUNTIME_DIR path should be used, and finally HOME, TMPDIR and /tmp. SVN revision: 70699
Diffstat (limited to 'legacy/evas/src/bin/evas_cserve2_messages.c')
-rw-r--r--legacy/evas/src/bin/evas_cserve2_messages.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/legacy/evas/src/bin/evas_cserve2_messages.c b/legacy/evas/src/bin/evas_cserve2_messages.c
new file mode 100644
index 0000000000..51868969dd
--- /dev/null
+++ b/legacy/evas/src/bin/evas_cserve2_messages.c
@@ -0,0 +1,189 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <errno.h>
6#include <string.h>
7
8#include "evas_cserve2.h"
9
10// #define DEBUG_MSG 1
11
12static void
13debug_msg(const char *typestr, const void *buf, int size)
14{
15#ifdef DEBUG_MSG
16 const char *str = buf;
17 int i;
18
19 printf("message %s: ", typestr);
20 for (i = 0; i < size; i++)
21 printf("%x ", str[i]);
22
23 printf("\n");
24#endif
25}
26
27static void
28_client_msg_allocate_buf(Client *client, int msgsize)
29{
30 client->msg.reading = EINA_TRUE;
31 client->msg.buf = malloc(msgsize + 1);
32 client->msg.size = msgsize;
33 client->msg.done = 0;
34}
35
36static void
37_client_msg_free(Client *client)
38{
39 client->msg.reading = EINA_FALSE;
40 free(client->msg.buf);
41}
42
43static void
44_client_msg_parse(Client *client)
45{
46 Msg_Base *msg = (Msg_Base *)client->msg.buf;
47 DBG("Message received. Size: %d; type = %d",
48 client->msg.size, msg->type);
49
50 cserve2_command_run(client, msg->type);
51}
52
53static void
54_client_msg_read(Client *client, int done)
55{
56 client->msg.done += done;
57 if (client->msg.done == client->msg.size)
58 {
59 debug_msg("received", client->msg.buf, client->msg.size);
60 _client_msg_parse(client);
61 _client_msg_free(client);
62 }
63}
64
65void
66cserve2_message_handler(int fd __UNUSED__, Fd_Flags flags, void *data)
67{
68 Client *client = data;
69 int len;
70 int msgsize;
71
72 if (flags & FD_ERROR)
73 {
74 ERR("Error on socket for client: %d", client->id);
75 goto client_close;
76 }
77
78 if (flags & FD_WRITE)
79 cserve2_client_deliver(client);
80
81 if (!(flags & FD_READ))
82 return;
83
84 if (!client->msg.reading)
85 len = cserve2_client_read(client, &msgsize, sizeof(msgsize));
86 else
87 len = cserve2_client_read(client, &client->msg.buf[client->msg.done],
88 client->msg.size - client->msg.done);
89
90 if (!len)
91 {
92 INF("Client %d connection closed.", client->id);
93 goto client_close;
94 }
95
96 if (len < 0)
97 {
98 if (errno == EAGAIN || errno == EWOULDBLOCK)
99 {
100 WRN("No data to read but the message handler was called.");
101 return;
102 }
103 WRN("Error when reading message from client: \"%s\"",
104 strerror(errno));
105 // FIXME: Should we close the connection, or just send an ERROR
106 // message?
107 goto client_close;
108 }
109
110 if (!client->msg.reading)
111 _client_msg_allocate_buf(client, msgsize);
112 else
113 _client_msg_read(client, len);
114
115 return;
116
117client_close:
118 if (client->msg.reading)
119 _client_msg_free(client);
120 cserve2_client_del(client);
121}
122
123void
124cserve2_client_deliver(Client *client)
125{
126 size_t sent, size;
127 const char *str;
128
129 if (!client->msg.pending)
130 {
131 Fd_Flags cur_flags;
132 cserve2_fd_watch_flags_get(client->socket, &cur_flags);
133 cur_flags ^= FD_WRITE;
134 cserve2_fd_watch_flags_set(client->socket, cur_flags);
135 return;
136 }
137
138 size = eina_binbuf_length_get(client->msg.pending);
139 str = (const char *)eina_binbuf_string_get(client->msg.pending);
140 sent = cserve2_client_write(client, str, size);
141 if (sent == size)
142 {
143 eina_binbuf_free(client->msg.pending);
144 client->msg.pending = NULL;
145 return;
146 }
147
148 eina_binbuf_remove(client->msg.pending, 0, sent);
149}
150
151ssize_t
152cserve2_client_send(Client *client, const void *data, size_t size)
153{
154 ssize_t sent;
155
156 debug_msg("sent", data, size);
157 if (client->msg.pending)
158 {
159 eina_binbuf_append_length
160 (client->msg.pending, (unsigned char *)data, size);
161 return size;
162 }
163
164 sent = cserve2_client_write(client, data, size);
165 if ((sent < 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
166 {
167 // FIXME: Big error when writing on the socket to the client,
168 // so we must close the connection to the client and remove
169 // its references inside our cache.
170 WRN("Error on socket with client %d: %s", client->id, strerror(errno));
171 if (client->msg.reading)
172 _client_msg_free(client);
173 cserve2_client_del(client);
174 return sent;
175 }
176 if (sent < 0)
177 sent = 0;
178 if (sent < (int)size)
179 {
180 Fd_Flags cur_flags;
181 client->msg.pending = eina_binbuf_new();
182 eina_binbuf_append_length
183 (client->msg.pending, (unsigned char *)data + sent, size - sent);
184 cserve2_fd_watch_flags_get(client->socket, &cur_flags);
185 cur_flags |= FD_WRITE;
186 cserve2_fd_watch_flags_set(client->socket, cur_flags);
187 }
188 return size;
189}