Line data Source code
1 : // Copyright (c) 2012-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Event dispatch class.
22 : *
23 : * Class used to handle events.
24 : */
25 :
26 :
27 : // self
28 : //
29 : #include "eventdispatcher/local_dgram_client.h"
30 :
31 :
32 : // last include
33 : //
34 : #include <snapdev/poison.h>
35 :
36 :
37 :
38 : namespace ed
39 : {
40 :
41 :
42 :
43 : /** \brief Initialize a local datagram client object.
44 : *
45 : * This function initializes the local datagram client object using the
46 : * address and the sequential flag as specified.
47 : *
48 : * The \p address parameter is a Unix address. It may be a file, abstract
49 : * or unnamed.
50 : *
51 : * \note
52 : * The sequential flag means we use a SOCK_SEQPACKET type instead of
53 : * SOCK_DGRAM. Both essentially work the same way except that the
54 : * SOCK_SEQPACKET has a promess to keep the packets in sequential
55 : * order (the order in which they were sent).
56 : *
57 : * \note
58 : * The socket is open in this process. If you fork() or exec() then the
59 : * socket will be closed by the operating system if the close_on_exec
60 : * was set to true.
61 : *
62 : * \param[in] address The address to send data to.
63 : * \param[in] sequential Whether to force sequential sends.
64 : * \param[in] close_on_exec Whether the socket has to be closed on exec.
65 : */
66 3 : local_dgram_client::local_dgram_client(
67 : addr::unix const & address
68 : , bool sequential
69 3 : , bool close_on_exec)
70 3 : : local_dgram_base(address, sequential, close_on_exec)
71 : {
72 3 : }
73 :
74 :
75 : /** \brief Send a message through this UDP client.
76 : *
77 : * This function sends \p msg through the UDP client socket. The function
78 : * cannot be used to change the destination as it was defined when creating
79 : * the local_dgram_client object.
80 : *
81 : * The size must be small enough for the message to fit. In most cases, we
82 : * use these in Snap! to send very small signals (i.e. 4 bytes commands.)
83 : * Any data we would want to share remains in the Cassandra database so
84 : * that way we can avoid losing it because of a UDP message.
85 : *
86 : * \note
87 : * The send may fail with EAGAIN, EWOULDBLOCK, or ENOBUFS which all mean
88 : * that the attempt can be tried again. The ENOBUFS means that a new buffer
89 : * could not be allocated, not that the UDP queue is full or that packets
90 : * are being lost because too many are being sent in a row. Also, you want
91 : * to control the size of your buffer with get_mss_size(). UDP buffers that
92 : * are larger will be broken up in multiple packets and that increases the
93 : * chance that the packet never arrives. Also over a certain size (probably
94 : * around 64K in IPv4) the ENOBUFS automatically happens. Note that IPv6
95 : * allows for much buffer packets. This is not automatically a good idea
96 : * unless the number of packets is quite small because when it fails, you
97 : * have to resend a very large packet...
98 : *
99 : * \note
100 : * To avoid loss of datagram messages, you need to time your calls to the send()
101 : * function taking in account the amount of data being sent and the network
102 : * speed. With a Unix socket, the throughput is very high and packets can be
103 : * really large (often 128Kb or even 256Kb). You can check the size with the
104 : * get_mss_size() function and (TBD how?) check the speed. You certainly
105 : * can use up to about 95% of the speed without much problems assuming that
106 : * the pipe is only used by these datagram packets. Too much and the
107 : * dropping is going to increase steadily. In also depends on how fast
108 : * the receiver retrieves the packets.
109 : *
110 : * \param[in] msg The message to send.
111 : * \param[in] size The number of bytes representing this message.
112 : *
113 : * \return -1 if an error occurs, otherwise the number of bytes sent. errno
114 : * is set accordingly on error.
115 : */
116 3 : int local_dgram_client::send(char const * msg, size_t size)
117 : {
118 3 : struct sockaddr_un un;
119 3 : f_address.get_un(un);
120 3 : return static_cast<int>(sendto(
121 6 : f_socket.get()
122 : , msg
123 : , size
124 : , 0
125 : , reinterpret_cast<sockaddr const *>(&un)
126 9 : , sizeof(un)));
127 : }
128 :
129 :
130 :
131 6 : } // namespace ed
132 : // vim: ts=4 sw=4 et
|