Branch data Line data Source code
1 : : // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
2 : : //
3 : : // Permission to use, copy, modify, and/or distribute this software for any
4 : : // purpose with or without fee is hereby granted, provided that the above
5 : : // copyright notice and this permission notice appear in all copies.
6 : : //
7 : : // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
8 : : // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
9 : : // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
10 : : // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11 : : // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
12 : : // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13 : : // PERFORMANCE OF THIS SOFTWARE.
14 : :
15 : : #ifndef __SOCKET_REQUEST_H
16 : : #define __SOCKET_REQUEST_H 1
17 : :
18 : : #include <exceptions/exceptions.h>
19 : :
20 : : #include <boost/noncopyable.hpp>
21 : : #include <utility>
22 : : #include <string>
23 : : #include <stdint.h>
24 : :
25 : : namespace isc {
26 : :
27 : : namespace cc {
28 : : class AbstractSession;
29 : : };
30 : :
31 : : namespace server_common {
32 : :
33 : : /// \brief A singleton class for requesting sockets
34 : : ///
35 : : /// This class allows requesting sockets from the socket creator.
36 : : ///
37 : : /// It is considered to be a singleton - a class which is instantiated
38 : : /// at most once in the whole application. This is because it makes no
39 : : /// sense to have two of them.
40 : : ///
41 : : /// This is actually an abstract base class. There'll be one with
42 : : /// hidden implementation and we expect the tests to create its own
43 : : /// subclass when needed.
44 : : ///
45 : : /// \see socketRequestor function to access the object of this class.
46 : : class SocketRequestor : boost::noncopyable {
47 : : protected:
48 : : /// \brief Protected constructor
49 : : ///
50 : : /// The constructor is protected so this class is not created by accident
51 : : /// (which it can't anyway, as it has pure virtual methods, but just to
52 : : /// be sure).
53 : 125 : SocketRequestor() {}
54 : :
55 : : public:
56 : : /// \brief virtual destructor
57 : : ///
58 : : /// A virtual destructor, as we have virtual methods, to make sure it is
59 : : /// destroyed by the destructor of the subclass. This shouldn't matter, as
60 : : /// a singleton class wouldn't get destroyed, but just to be sure.
61 : 122 : virtual ~ SocketRequestor() {}
62 : :
63 : : /// \brief A representation of received socket
64 : : ///
65 : : /// The pair holds two parts. The OS-level file descriptor acting as the
66 : : /// socket (you might want to use it directly with functions like recv,
67 : : /// or fill it into an asio socket). The other part is the token
68 : : /// representing the socket, which allows it to be given up again.
69 : : typedef std::pair<int, std::string> SocketID;
70 : :
71 : : /// \brief The protocol of requested socket
72 : : ///
73 : : /// This describes which protocol the socket should have when created.
74 : : enum Protocol {
75 : : UDP,
76 : : TCP
77 : : };
78 : :
79 : : /// \brief The share mode of the requested socket
80 : : ///
81 : : /// The socket creator is able to "borrow" the same socket to multiple
82 : : /// applications at once. However, it isn't always what is required. This
83 : : /// describes the restrains we want to have on our socket regarding the
84 : : /// sharing. Union of restriction of all requests on the given socket
85 : : /// is taken (so you still don't have to get your socket even if you
86 : : /// say SHARE_ANY, because someone else might already asked for the socket
87 : : /// with DONT_SHARE).
88 : : enum ShareMode {
89 : : DONT_SHARE, //< Request an exclusive ownership of the socket.
90 : : SHARE_SAME, //< It is possible to share the socket with anybody who
91 : : //< provided the same share_name.
92 : : SHARE_ANY //< Any sharing is allowed.
93 : : };
94 : :
95 : : /// \brief Exception when we can't manipulate a socket
96 : : ///
97 : : /// This is thrown if the other side doesn't want to comply to our
98 : : /// requests, like when we ask for a socket already held by someone
99 : : /// else or ask for nonsense (releasing a socket we don't own).
100 : 19 : class SocketError : public Exception {
101 : : public:
102 : 25 : SocketError(const char* file, size_t line, const char* what) :
103 [ + - ][ # # ]: 33 : Exception(file, line, what)
[ + - ][ # # ]
104 : 25 : { }
105 : : };
106 : :
107 : : /// \brief Exception when we can't return a requested socket, but we're
108 : : /// sure we could return others
109 : : ///
110 : : /// This is thrown if the requested socket can't be granted, but it is only
111 : : /// that one socket, not that the system would be broken or anything. This
112 : : /// exception is a common base class for the concrete exceptions actually
113 : : /// thrown. You can safely keep using the SocketRequestor after this
114 : : /// exception (or anything derived from it) is thrown.
115 : : ///
116 : : /// \see ShareError
117 : : /// \see SocketAllocateError
118 : 10 : class NonFatalSocketError : public SocketError {
119 : : public:
120 : : NonFatalSocketError(const char* file, size_t line, const char* what) :
121 [ + - ][ + - ]: 22 : SocketError(file, line, what)
122 : : { }
123 : : };
124 : :
125 : : /// \brief Exception when the socket is allocated by other bind10 module
126 : : /// and it doesn't want to share it.
127 : : ///
128 : : /// This is thrown if a socket is requested and the socket is already
129 : : /// allocated by bind10, but other bind10 module(s) is using it and
130 : : /// the sharing parameters are incompatible (the socket can't be shared
131 : : /// between the module and our module).
132 : 2 : class ShareError : public NonFatalSocketError {
133 : : public:
134 : : ShareError(const char* file, size_t line, const char* what) :
135 : 8 : NonFatalSocketError(file, line, what)
136 : : { }
137 : : };
138 : :
139 : : /// \brief Exception when the operating system doesn't allow us to create
140 : : /// the requested socket.
141 : : ///
142 : : /// This happens when the socket() or bind() call fails in the socket
143 : : /// creator. This can happen when the address/port pair is already taken
144 : : /// by a different application, the socket creator doesn't have enough
145 : : /// privileges, or for some kind of similar reason.
146 : 8 : class SocketAllocateError : public NonFatalSocketError {
147 : : public:
148 : : SocketAllocateError(const char* file, size_t line, const char* what) :
149 : 20 : NonFatalSocketError(file, line, what)
150 : : { }
151 : : };
152 : :
153 : : /// \brief Ask for a socket
154 : : ///
155 : : /// Asks the socket creator to give us a socket. The socket will be bound
156 : : /// to the given address and port.
157 : : ///
158 : : /// \param protocol specifies the protocol of the socket. This must be
159 : : /// either UDP or TCP.
160 : : /// \param address to which the socket should be bound.
161 : : /// \param port the port to which the socket should be bound (native endian,
162 : : /// not network byte order).
163 : : /// \param share_mode how the socket can be shared with other requests.
164 : : /// This must be one of the defined values of ShareMode..
165 : : /// \param share_name the name of sharing group, relevant for SHARE_SAME
166 : : /// (specified by us or someone else). If left empty (the default),
167 : : /// the app_name parameter of initSocketRequestor is used. If that one
168 : : /// is empty as well, it is accepted, but not recommended, as such
169 : : /// a non-descriptive name has a high chance of collisions between
170 : : /// applications. Note that you should provide a name (by share_name
171 : : /// or app_name) even when you set it to DONT_SHARE (for logs and
172 : : /// debugging) and you need to provide one with SHARE_SAME (to know
173 : : /// what is same) and SHARE_ANY (someone else might want SHARE_SAME,
174 : : /// so it would check against this)
175 : : /// \return the socket, as a file descriptor and token representing it on
176 : : /// the socket creator side.
177 : : ///
178 : : /// To understand the modes better:
179 : : /// - If mode is DONT_SHARE, it succeeds if no one else has opened an FD
180 : : /// for requested protocol, address and port.
181 : : /// - If mode is SHARE_SAME, it succeeds if all applications who opened an
182 : : /// FD for the requested protocol, address and port provided the same
183 : : /// share_name as this one and none of them had mode DONT_SHARE.
184 : : /// - If mode is SHARE_ANY, it succeeds if no applications who requested
185 : : /// the same potocol, address and port provided DONT_SHARE and all the
186 : : /// applications who provided SHARE_SAME also provided the same
187 : : /// share_name as this process did.
188 : : ///
189 : : /// \throw InvalidParameter protocol or share_mode is invalid
190 : : /// \throw CCSessionError when we have a problem talking over the CC
191 : : /// session.
192 : : /// \throw SocketError in case we have some other problems receiving the
193 : : /// socket (eg. inconsistency in the protocol, the socket got stuck
194 : : /// in the transport, etc). If the exception is not of the following
195 : : /// derived ones, it usualy means something serious happened.
196 : : /// \throw SocketAllocateError if the other side can't create the socket.
197 : : /// \throw ShareError if the socket is used by other bind10 module and
198 : : /// that one doesn't want to share it with us.
199 : : virtual SocketID requestSocket(Protocol protocol,
200 : : const std::string& address,
201 : : uint16_t port, ShareMode share_mode,
202 : : const std::string& share_name = "") = 0;
203 : :
204 : : /// \brief Tell the socket creator we no longer need the socket
205 : : ///
206 : : /// Releases the identified socket. This must be called *after*
207 : : /// the file descriptor was closed on our side. This will allow
208 : : /// the remote side to either give it to some other application
209 : : /// or close it, depending on the situation.
210 : : ///
211 : : /// \param token the token representing the socket, as received
212 : : /// in the second part of the requestSocket result.
213 : : /// \throw CCSessionError when we have a problem talking over the CC
214 : : /// session.
215 : : /// \throw SocketError in case the other side doesn't like the
216 : : /// release (like we're trying to release a socket that doesn't
217 : : /// belong to us or exist at all).
218 : : virtual void releaseSocket(const std::string& token) = 0;
219 : : };
220 : :
221 : : /// \brief Access the requestor object.
222 : : ///
223 : : /// This returns the singleton object for the Requestor.
224 : : ///
225 : : /// \return the active socket requestor object.
226 : : /// \throw InvalidOperation if the object was not yet initialized.
227 : : /// \see SocketRequestor::init to initialize the object.
228 : : SocketRequestor& socketRequestor();
229 : :
230 : : /// \brief Initialize the singleton object
231 : : ///
232 : : /// This creates the object that will be used to request sockets.
233 : : /// It can be called only once per the life of application.
234 : : ///
235 : : /// \param session the CC session that'll be used to talk to the
236 : : /// socket creator.
237 : : /// \param app_name default share name if one is not provided with
238 : : /// requestSocket. You can leave this as empty string,
239 : : /// but then you should provide a reasonably descriptive
240 : : /// name to requestSocket. Empty names work like any others,
241 : : /// but have a high chance of collisions, so it is recommended
242 : : /// to avoid them and provide the name of the application
243 : : /// here.
244 : : /// \throw InvalidOperation when it is called more than once
245 : : void initSocketRequestor(cc::AbstractSession& session,
246 : : const std::string& app_name);
247 : :
248 : : /// \brief Initialization for tests
249 : : ///
250 : : /// This is to support different subclasses in tests. It replaces
251 : : /// the object used by socketRequestor() function by this one provided
252 : : /// as parameter. The ownership is not taken, eg. it's up to the caller
253 : : /// to delete it when necessary.
254 : : ///
255 : : /// This is not to be used in production applications. It is meant as
256 : : /// an replacement of init.
257 : : ///
258 : : /// This never throws.
259 : : ///
260 : : /// \param requestor the object to be used. It can be NULL to reset to
261 : : /// an "virgin" state (which acts as if initTest or init was never
262 : : /// called before).
263 : : void initTestSocketRequestor(SocketRequestor* requestor);
264 : :
265 : : /// \brief Destroy the singleton instance
266 : : ///
267 : : /// Calling this function is not strictly necessary; the socket
268 : : /// requestor is a singleton anyway. However, for some tests it
269 : : /// is useful to destroy and recreate it, as well as for programs
270 : : /// that want to be completely clean on exit.
271 : : /// After this function has been called, all operations except init
272 : : /// will fail.
273 : : void cleanupSocketRequestor();
274 : :
275 : : }
276 : : }
277 : :
278 : : #endif // __SOCKET_REQUEST_H
|