+static void try_send_reply(struct client *c)
+{
+ struct fastbuf fb;
+ fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
+
+ TRANS_TRY
+ {
+ json_write(c->json, &fb, c->reply);
+ }
+ TRANS_CATCH(x)
+ {
+ msg(L_ERROR, "Unable to construct reply, it is probably too long");
+ fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
+ bputs(&fb, "{ \"error\": \"Reply too long\" }\n");
+ }
+ TRANS_END;
+
+ int len = fbbuf_count_written(&fb);
+ msg(L_INFO, "Sending reply of %d bytes", len);
+ if (send(c->socket.fd, packet_buffer, len, 0) < 0)
+ {
+ if (errno == EAGAIN || errno == EINTR)
+ {
+ msg(L_INFO, "Postponed send");
+ c->socket.write_handler = socket_write_handler;
+ file_chg(&c->socket);
+ }
+ msg(L_ERROR, "Client write error: %m");
+ client_close(c);
+ }
+ else
+ {
+ msg(L_INFO, "Reply sent");
+ c->socket.read_handler = socket_read_handler;
+ c->socket.write_handler = NULL;
+ file_chg(&c->socket);
+ timer_add_rel(&c->timer, SOCKET_TIMEOUT);
+ }
+}
+
+static void send_reply(struct client *c)
+{
+ timer_add_rel(&c->timer, SOCKET_TIMEOUT);
+ try_send_reply(c);
+}
+
+static void received_packet(struct client *c, byte *pkt, int len)
+{
+ json_reset(c->json);
+
+ struct fastbuf fb;
+ fbbuf_init_read(&fb, pkt, len, 0);
+
+ c->reply = json_new_object(c->json);
+
+ TRANS_TRY
+ {
+ c->request = json_parse(c->json, &fb);
+ }
+ TRANS_CATCH(x)
+ {
+ cmd_error(c, "Parse error");
+ send_reply(c);
+ return;
+ }
+ TRANS_END;
+
+ cmd_error(c, "OK");
+ send_reply(c);
+}
+
+static int socket_write_handler(struct main_file *fi)
+{
+ struct client *c = fi->data;
+ try_send_reply(c);
+ return HOOK_IDLE;
+}
+