|
@@ -1,4 +1,10 @@
|
|
|
+#ifndef DINIT_CONTROL_H
|
|
|
+#define DINIT_CONTROL_H
|
|
|
+
|
|
|
+#include <unistd.h>
|
|
|
#include <ev++.h>
|
|
|
+#include "dinit-log.h"
|
|
|
+#include "control-cmds.h"
|
|
|
|
|
|
// Control connection for dinit
|
|
|
|
|
@@ -6,10 +12,12 @@
|
|
|
// forward-declaration of callback:
|
|
|
static void control_conn_cb(struct ev_loop * loop, ev_io * w, int revents);
|
|
|
|
|
|
+class ControlConn;
|
|
|
+
|
|
|
+// Pointer to the control connection that is listening for rollback completion
|
|
|
+extern ControlConn * rollback_handler_conn;
|
|
|
|
|
|
-// Packet types:
|
|
|
-constexpr static int DINIT_CP_STARTSERVICE = 0;
|
|
|
-constexpr static int DINIT_CP_STOPSERVICE = 1;
|
|
|
+extern int active_control_conns;
|
|
|
|
|
|
// "packet" format:
|
|
|
// (1 byte) packet type
|
|
@@ -18,6 +26,8 @@ constexpr static int DINIT_CP_STOPSERVICE = 1;
|
|
|
// (2 bytes) service name length
|
|
|
// (M buyes) service name (without nul terminator)
|
|
|
|
|
|
+class ServiceSet;
|
|
|
+
|
|
|
|
|
|
class ControlConn
|
|
|
{
|
|
@@ -38,101 +48,15 @@ class ControlConn
|
|
|
ev_io_init(&iob, control_conn_cb, fd, EV_READ);
|
|
|
iob.data = this;
|
|
|
ev_io_start(loop, &iob);
|
|
|
- }
|
|
|
-
|
|
|
- void processPacket()
|
|
|
- {
|
|
|
- using std::string;
|
|
|
-
|
|
|
- int pktType = iobuf[0];
|
|
|
- if (pktType == DINIT_CP_STARTSERVICE || pktType == DINIT_CP_STOPSERVICE) {
|
|
|
- if (bufidx < 4) {
|
|
|
- chklen = 4;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- uint16_t svcSize;
|
|
|
- memcpy(&svcSize, iobuf + 1, 2);
|
|
|
- if (svcSize <= 0) {
|
|
|
- // TODO error response
|
|
|
- bufidx = 1024; // dataReady will delete - TODO clean up
|
|
|
- }
|
|
|
-
|
|
|
- chklen = svcSize + 3;
|
|
|
- if (chklen > 1024) {
|
|
|
- // We can't have a service name this long
|
|
|
- // TODO error response
|
|
|
- bufidx = 1024; // TODO cleanup.
|
|
|
- }
|
|
|
-
|
|
|
- if (bufidx < chklen) {
|
|
|
- // packet not complete yet; read more
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- string serviceName(iobuf + 3, (size_t) svcSize);
|
|
|
- if (pktType == DINIT_CP_STARTSERVICE) {
|
|
|
- service_set->startService(serviceName.c_str());
|
|
|
- // TODO catch exceptions, error response
|
|
|
- }
|
|
|
- else {
|
|
|
- // TODO verify the named service exists?
|
|
|
- service_set->stopService(serviceName.c_str());
|
|
|
- }
|
|
|
-
|
|
|
- // Clear the packet from the buffer
|
|
|
- memmove(iobuf, iobuf + chklen, 1024 - chklen);
|
|
|
- bufidx -= chklen;
|
|
|
- chklen = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- void dataReady()
|
|
|
- {
|
|
|
- int fd = iob.fd;
|
|
|
- int buffree = 1024 - bufidx;
|
|
|
-
|
|
|
- int r = read(fd, iobuf + bufidx, buffree);
|
|
|
-
|
|
|
- // Note file descriptor is non-blocking
|
|
|
- if (r == -1) {
|
|
|
- if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // TODO log error
|
|
|
- delete this;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (r == 0) {
|
|
|
- delete this;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- bufidx += r;
|
|
|
- buffree -= r;
|
|
|
|
|
|
- // complete packet?
|
|
|
- if (bufidx >= chklen) {
|
|
|
- processPacket();
|
|
|
- }
|
|
|
-
|
|
|
- if (bufidx == 1024) {
|
|
|
- // Too big packet
|
|
|
- // TODO log error?
|
|
|
- // TODO error response?
|
|
|
- delete this;
|
|
|
- }
|
|
|
+ active_control_conns++;
|
|
|
}
|
|
|
|
|
|
- ~ControlConn()
|
|
|
- {
|
|
|
- close(iob.fd);
|
|
|
- ev_io_stop(loop, &iob);
|
|
|
- delete [] iobuf;
|
|
|
- }
|
|
|
+ void processPacket();
|
|
|
+ void rollbackComplete();
|
|
|
+ void dataReady();
|
|
|
+
|
|
|
+ ~ControlConn();
|
|
|
};
|
|
|
|
|
|
|
|
@@ -141,3 +65,5 @@ static void control_conn_cb(struct ev_loop * loop, ev_io * w, int revents)
|
|
|
ControlConn *conn = (ControlConn *) w->data;
|
|
|
conn->dataReady();
|
|
|
}
|
|
|
+
|
|
|
+#endif
|