socketsession_inc.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. namespace {
  2. const char* const socketsession_doc = "\
  3. This module defines a set of classes that support forwarding a\n\
  4. \"socket session\" from one process to another. A socket session is a\n\
  5. conceptual tuple of the following elements:\n\
  6. \n\
  7. - A network socket\n\
  8. - The local and remote endpoints of a (IP) communication taking place\n\
  9. on the socket. In practice an endpoint is a pair of an IP address\n\
  10. and TCP or UDP port number.\n\
  11. - Some amount of data sent from the remote endpoint and received on\n\
  12. the socket. We call it (socket) session data in this documentation.\n\
  13. \n\
  14. Note that this is a conceptual definition. Depending on the underlying\n\
  15. implementation and/or the network protocol, some of the elements could\n\
  16. be part of others; for example, if it's an established TCP connection,\n\
  17. the local and remote endpoints would be able to be retrieved from the\n\
  18. socket using the standard getsockname() and getpeername() system\n\
  19. calls. But in this definition we separate these to be more generic.\n\
  20. Also, as a matter of fact our intended usage includes non-connected\n\
  21. UDP communications, in which case at least the remote endpoint should\n\
  22. be provided separately from the socket.\n\
  23. \n\
  24. In the actual implementation we represent a socket as a Python socket\n\
  25. object, which contains the information of the address family\n\
  26. (e.g. AF_INET6), socket type (e.g. SOCK_STREAM), and protocol\n\
  27. (e.g. IPPROTO_TCP).\n\
  28. \n\
  29. We use the Python socket address tuple to represent endpoints.\n\
  30. \n\
  31. Socket session data is an opaque blob in the form of a Python byte\n\
  32. object.\n\
  33. \n\
  34. To forward a socket session between processes, we use connected UNIX\n\
  35. domain sockets established between the processes. The file descriptor\n\
  36. will be forwarded through the sockets as an ancillary data item of\n\
  37. type SCM_RIGHTS. Other elements of the session will be transferred as\n\
  38. normal data over the connection.\n\
  39. \n\
  40. We provide two classes to help applications forward socket sessions:\n\
  41. SocketSessionForwarder is the sender of the UNIX domain connection,\n\
  42. while SocketSessionReceiver is the receiver (this interface assumes\n\
  43. one direction of forwarding).\n\
  44. \n\
  45. Note: this paragraph and following discussions on the internal\n\
  46. protocol are for reference purposes only; it's not necessary to\n\
  47. understand how to use the API.\n\
  48. SocketSessionForwarder and SocketSessionReceiver objects (internally)\n\
  49. use a straightforward protocol to pass elements of socket sessions.\n\
  50. Once the connection is established, the forwarder object first forwards\n\
  51. the file descriptor with 1-byte dummy data. It then forwards a\n\
  52. \"(socket) session header\", which contains all other elements of\n\
  53. the session except the file descriptor (already forwarded) and session\n\
  54. data. The wire format of the header is as follows:\n\
  55. \n\
  56. - The length of the header (16-bit unsigned integer)\n\
  57. - Address family\n\
  58. - Socket type\n\
  59. - Protocol\n\
  60. - Size of the local endpoint in bytes\n\
  61. - Local endpoint (a copy of the memory image of the corresponding\n\
  62. sockaddr)\n\
  63. - Size of the remote endpoint in bytes\n\
  64. - Remote endpoint (same as local endpoint)\n\
  65. - Size of session data in bytes\n\
  66. \n\
  67. The type of the fields is 32-bit unsigned integer unless explicitly\n\
  68. noted, and all fields are formatted in the network byte order.\n\
  69. \n\
  70. The socket session data immediately follows the session header.\n\
  71. \n\
  72. Note that the fields do not necessarily be in the network byte order\n\
  73. because they are expected to be exchanged on the same machine.\n\
  74. Likewise, integer elements such as address family do not necessarily\n\
  75. be represented as an fixed-size value (i.e., 32-bit). But fixed size\n\
  76. fields are used in order to ensure maximum portability in such a\n\
  77. (rare) case where the forwarder and the receiver are built with\n\
  78. different compilers that have different definitions of int. Also,\n\
  79. since sockaddr fields are generally formatted in the network byte\n\
  80. order, other fields are defined so to be consistent.\n\
  81. \n\
  82. One basic assumption in the API of this module is socket sessions\n\
  83. should be forwarded without blocking, thus eliminating the need for\n\
  84. incremental read/write or blocking other important services such as\n\
  85. responding to requests from the application's clients. This assumption\n\
  86. should be held as long as both the forwarder and receiver have\n\
  87. sufficient resources to handle the forwarding process since the\n\
  88. communication is local. But a forward attempt could still block if the\n\
  89. receiver is busy (or even hang up) and cannot keep up with the volume\n\
  90. of incoming sessions.\n\
  91. \n\
  92. So, in this implementation, the forwarder uses non blocking writes to\n\
  93. forward sessions. If a write attempt could block, it immediately gives\n\
  94. up the operation with an exception. The corresponding application is\n\
  95. expected to catch it, close the connection, and perform any necessary\n\
  96. recovery for that application (that would normally be re-establish the\n\
  97. connection with a new receiver, possibly after confirming the\n\
  98. receiving side is still alive). On the other hand, the receiver\n\
  99. implementation assumes it's possible that it only receive incomplete\n\
  100. elements of a session (such as in the case where the forwarder writes\n\
  101. part of the entire session and gives up the connection). The receiver\n\
  102. implementation throws an exception when it encounters an incomplete\n\
  103. session. Like the case of the forwarder application, the receiver\n\
  104. application is expected to catch it, close the connection, and perform\n\
  105. any necessary recovery steps.\n\
  106. \n\
  107. Note that the receiver implementation uses blocking read. So it's\n\
  108. application's responsibility to ensure that there's at least some data\n\
  109. in the connection when the receiver object is requested to receive a\n\
  110. session (unless this operation can be blocking, e.g., by the use of a\n\
  111. separate thread). Also, if the forwarder implementation or application\n\
  112. is malicious or extremely buggy and intentionally sends partial\n\
  113. session and keeps the connection, the receiver could block in\n\
  114. receiving a session. In general, we assume the forwarder doesn't do\n\
  115. intentional blocking as it's a local node and is generally a module of\n\
  116. the same (BIND 10) system. The minimum requirement for the forwarder\n\
  117. implementation (and application) is to make sure the connection is\n\
  118. closed once it detects an error on it. Even a naive implementation\n\
  119. that simply dies due to the exception will meet this requirement.\n\
  120. \n\
  121. ";
  122. } // unnamed namespace