]>
Commit | Line | Data |
---|---|---|
9a1b46cc | 1 | /* |
ef57eb7b | 2 | * Copyright (C) 1996-2016 The Squid Software Foundation and contributors |
9a1b46cc AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
946b016d AR |
9 | /** |
10 | \defgroup Comm Comm Module | |
11 | \ingroup Components | |
12 | ||
13 | ||
14 | \section Basic Basic Comm API principles | |
15 | ||
16 | \par | |
17 | Comm API supports four major kinds of socket-related operations: | |
18 | accept, connect, read, and write. Sockets are identified by their | |
19 | descriptors. | |
20 | ||
21 | \par | |
22 | A Comm user requests its interest in operations by calling an | |
23 | appropriate API function (e.g., comm_read()) and optionally providing | |
24 | a notification "callback" (a.k.a., handler). For a given descriptor, | |
25 | there can be no more than one registered user per operation. | |
26 | ||
27 | \par | |
28 | In addition to the four operations listed above, a user can register | |
29 | to be notified when a given descriptor is closed. | |
30 | ||
31 | \par | |
32 | When a Comm operation completes, all users that registered the | |
33 | corresponding handler are notified. When a descriptor is closed, all | |
34 | users that registered any callback for the descriptor are notified | |
35 | (this will change though, see "Anticipated changes" below). | |
36 | ||
37 | \par | |
38 | All Comm notifications are asynchronous, performed using the | |
39 | AsyncCall API. | |
40 | ||
41 | \par | |
42 | Notifications for four operations listed above are scheduled in the | |
43 | order of the corresponding operations completion. User code can assume | |
44 | that the operation has completed (possibly with an error) only after | |
45 | receiving a notification. Until then, I/O resources such as buffers | |
46 | must remain available for the operation. | |
47 | ||
48 | \par | |
49 | Notifications related to closing of a descriptor are documented | |
50 | separately. | |
51 | ||
52 | ||
53 | \section IO-cancel I/O cancellation | |
54 | ||
55 | \par | |
56 | To cancel an interest in a read operation, call comm_read_cancel() | |
57 | with an AsyncCall object. This call guarantees that the passed Call | |
58 | will be canceled (see the AsyncCall API for call cancellation | |
59 | definitions and details). Naturally, the code has to store the | |
60 | original read callback Call pointer to use this interface. | |
61 | ||
62 | \par | |
63 | The comm_read_cancel() call does not guarantee that the read operation | |
64 | has not already happen. | |
65 | ||
66 | \par | |
67 | The comm_read_cancel() call guarantees that the read operation will not | |
68 | start for read operations that are performed by Comm (i.e., where read | |
69 | start is controlled by Comm). There is no such guarantee for | |
70 | asynchronous read operations scheduled by Comm but started by the | |
71 | operating system or other threads. | |
72 | ||
73 | \par | |
74 | The above applies to comm_read_cancel() interface with an AsyncCall | |
75 | object as a parameter. You cannot reliably cancel an interest in read | |
76 | operation using the old comm_read_cancel() call that uses a function | |
77 | pointer. The handler may get even called after old comm_read_cancel() | |
78 | was called. | |
79 | ||
80 | \par | |
81 | It is OK to call comm_read_cancel (both flavors) at any time as long | |
82 | as the descriptor has not been closed and there is either no read | |
83 | interest registered or the passed parameters match the registered | |
84 | ones. If the descriptor has been closed, the behavior is undefined. | |
85 | Otherwise, if parameters do not match, you get an assertion. | |
86 | ||
87 | \par | |
88 | To cancel Comm operations other than read, close the descriptor with | |
89 | comm_close(). | |
90 | ||
91 | ||
92 | \section comm-close Descriptor closing with comm_close | |
93 | ||
94 | \par | |
95 | The comm_close() function does not close the descriptor but initiates | |
96 | the following closing sequence: | |
97 | ||
98 | \par | |
99 | -# The descriptor is placed in a "closing" state. | |
100 | -# The registered read, write, and accept callbacks (if any) are | |
101 | scheduled (in an unspecified order). | |
102 | -# The close callbacks are scheduled (in an unspecified order). | |
103 | -# A call to the internal descriptor closing handler is | |
104 | scheduled. | |
105 | ||
106 | \par | |
107 | The "unspecified" order above means that the user should not rely on | |
108 | any specific or deterministic order because the currently hard-coded | |
109 | order may change. | |
110 | ||
111 | \par | |
112 | The read, write, and accept notifications (scheduled in step #2 | |
c8407295 AJ |
113 | above) carry the Comm::ERR_CLOSING error flag. When handling |
114 | Comm::ERR_CLOSING event, the user code should limit | |
946b016d AR |
115 | descriptor-related processing, especially Comm calls, because |
116 | supported Comm functionality is very limited when the descriptor is | |
117 | closing. New code should use the close handlers instead (scheduled | |
118 | in step #3). | |
119 | ||
120 | \par | |
121 | The internal closing handler (scheduled in step #4 above) closes the | |
122 | descriptor. When the descriptor is closed, all operations on the | |
123 | descriptor are prohibited and may cause bugs and asserts. Currently, | |
124 | the same descriptor will eventually be reused for another socket and | |
125 | Comm may not notice that a buggy code is still using a stale | |
126 | descriptor, but that may change. | |
127 | ||
128 | \par | |
129 | Since all notifications are asynchronous, it is possible for a read | |
130 | or write notification that was scheduled before comm_close() was | |
131 | called to arrive at its destination after comm_close() was called. | |
c8407295 | 132 | Such notification will arrive with Comm::ERR_CLOSING flag even though |
946b016d AR |
133 | that flag was not set at the time of the I/O (and the I/O may have |
134 | been successful). This behavior may change. | |
135 | ||
136 | ||
137 | \section Future Anticipated changes and preparation recommendations | |
138 | ||
139 | \par | |
140 | This section lists anticipated Comm API changes and provides | |
141 | recommendations for developers writing new (or rewriting old) Comm | |
142 | user code. The changes are listed in a rough order from more likely | |
143 | to less certain and from near-feature to long-term. | |
144 | ||
145 | \par | |
146 | The old comm_read_cancel() function that uses a function pointer will be | |
147 | removed as unreliable. Use the AsyncCall-based comm_read_cancel() | |
148 | instead. | |
149 | ||
150 | \par | |
c8407295 | 151 | Comm::ERR_CLOSING interface will be removed. The read, write, and |
946b016d AR |
152 | accept notifications will not be scheduled after comm_close() is |
153 | called. New user code should register close handlers instead. | |
154 | ||
155 | \par | |
c8407295 | 156 | When Comm::ERR_CLOSING interface is removed, pending notifications |
946b016d AR |
157 | (if any) will be canceled after comm_close() is called. However, the |
158 | cancellation may be removed later if Comm is modified to provide safe | |
159 | access to closing descriptors and their fragile state. New user code | |
160 | should continue to assume that it is safe to access Comm in a read, | |
161 | write, and accept handlers. | |
162 | ||
163 | \par | |
164 | The old comm_read_cancel() call that uses a function pointer will be | |
165 | removed as unreliable. New user code should use comm_read_cancel() with | |
166 | an AsyncCall parameter. | |
167 | ||
168 | \par | |
169 | Comm users may be required to become children of Comm-provided | |
170 | classes, to eliminate the need for a complicated (albeit hidden) | |
171 | hierarchy of Comm callback dialers (see CommCalls.h) and to provide | |
172 | default implementation for common I/O handling cases. New user code | |
173 | should use methods of AsyncJob-derived classes to handle Comm | |
174 | notifications instead of using stand-alone functions. Additionally, it | |
175 | should not call comm_close() for descriptors it does not "own". | |
176 | ||
177 | \par | |
178 | The comm_close() API will be used exclusively for "stop future I/O, | |
179 | schedule a close callback call, and cancel all other callbacks" | |
180 | purposes. New user code should not use comm_close() for the purpose of | |
181 | immediately ending a job. | |
182 | ||
183 | \par | |
184 | Raw socket descriptors will be replaced with unique IDs or small | |
185 | objects that help detect stale descriptor/socket usage bugs and | |
186 | encapsulate access to socket-specific information. New user code | |
187 | should treat descriptor integers as opaque objects. | |
188 | ||
189 | ||
190 | */ |