dinit-client.h 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #include <cstdint>
  2. // Client library for Dinit clients
  3. using handle_t = uint32_t;
  4. class read_cp_exception
  5. {
  6. public:
  7. int errcode;
  8. read_cp_exception(int err) : errcode(err) { }
  9. };
  10. // Fill a circular buffer from a file descriptor, until it contains at least _rlength_ bytes.
  11. // Throws read_cp_exception if the requested number of bytes cannot be read, with:
  12. // errcode = 0 if end of stream (remote end closed)
  13. // errcode = errno if another error occurred
  14. // Note that EINTR is ignored (i.e. the read will be re-tried).
  15. inline void fill_buffer_to(cpbuffer<1024> *buf, int fd, int rlength)
  16. {
  17. do {
  18. int r = buf->fill_to(fd, rlength);
  19. if (r == -1) {
  20. if (errno != EINTR) {
  21. throw read_cp_exception(errno);
  22. }
  23. }
  24. else if (r == 0) {
  25. throw read_cp_exception(0);
  26. }
  27. else {
  28. return;
  29. }
  30. }
  31. while (true);
  32. }
  33. // Wait for a reply packet, skipping over any information packets that are received in the meantime.
  34. inline void wait_for_reply(cpbuffer<1024> &rbuffer, int fd)
  35. {
  36. fill_buffer_to(&rbuffer, fd, 1);
  37. while (rbuffer[0] >= 100) {
  38. // Information packet; discard.
  39. fill_buffer_to(&rbuffer, fd, 2);
  40. int pktlen = (unsigned char) rbuffer[1];
  41. rbuffer.consume(1); // Consume one byte so we'll read one byte of the next packet
  42. fill_buffer_to(&rbuffer, fd, pktlen);
  43. rbuffer.consume(pktlen - 1);
  44. }
  45. }
  46. // Wait for an info packet. If any other reply packet comes, throw a read_cp_exception.
  47. inline void wait_for_info(cpbuffer<1024> &rbuffer, int fd)
  48. {
  49. fill_buffer_to(&rbuffer, fd, 2);
  50. if (rbuffer[0] < 100) {
  51. throw read_cp_exception(0);
  52. }
  53. int pktlen = (unsigned char) rbuffer[1];
  54. fill_buffer_to(&rbuffer, fd, pktlen);
  55. }
  56. // Write *all* the requested buffer and re-try if necessary until
  57. // the buffer is written or an unrecoverable error occurs.
  58. inline int write_all(int fd, const void *buf, size_t count)
  59. {
  60. const char *cbuf = static_cast<const char *>(buf);
  61. int w = 0;
  62. while (count > 0) {
  63. int r = write(fd, cbuf, count);
  64. if (r == -1) {
  65. if (errno == EINTR) continue;
  66. return r;
  67. }
  68. w += r;
  69. cbuf += r;
  70. count -= r;
  71. }
  72. return w;
  73. }