1 /* Copyright (C) 2014 The giomm Development Team
2  *
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <giomm/socketsource.h>
18 #include <giomm/socket.h>
19 #include <glibmm/exceptionhandler.h>
20 #include <glibmm/wrap.h>
21 #include <gio/gio.h>
22 
23 namespace
24 {
25 
26 gboolean
giomm_generic_socket_callback(sigc::slot_base * slot,GIOCondition condition)27 giomm_generic_socket_callback(sigc::slot_base* slot, GIOCondition condition)
28 {
29   g_return_val_if_fail(slot != nullptr, FALSE);
30 
31   try
32   {
33     // Recreate the specific slot from the generic slot node.
34     return (*static_cast<sigc::slot<bool, Glib::IOCondition>*>(slot))((Glib::IOCondition)condition);
35   }
36   catch (...)
37   {
38     Glib::exception_handlers_invoke();
39   }
40   return 0;
41 }
42 
43 gboolean
giomm_signalsocket_callback(GSocket *,GIOCondition condition,void * user_data)44 giomm_signalsocket_callback(GSocket*, GIOCondition condition, void* user_data)
45 {
46   sigc::slot_base* const slot = Glib::Source::get_slot_from_connection_node(user_data);
47   return giomm_generic_socket_callback(slot, condition);
48 }
49 
50 gboolean
giomm_socketsource_callback(GSocket *,GIOCondition condition,void * user_data)51 giomm_socketsource_callback(GSocket*, GIOCondition condition, void* user_data)
52 {
53   sigc::slot_base* const slot = Glib::Source::get_slot_from_callback_data(user_data);
54   return giomm_generic_socket_callback(slot, condition);
55 }
56 
57 } // anonymous namespace
58 
59 namespace Gio
60 {
61 
62 /**** Glib::SignalSocket *******************************************************/
63 
SignalSocket(GMainContext * context)64 inline SignalSocket::SignalSocket(GMainContext* context) : context_(context)
65 {
66 }
67 
68 sigc::connection
connect(const sigc::slot<bool,Glib::IOCondition> & slot,const Glib::RefPtr<Socket> & socket,Glib::IOCondition condition,const Glib::RefPtr<Cancellable> & cancellable,int priority)69 SignalSocket::connect(const sigc::slot<bool, Glib::IOCondition>& slot,
70   const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
71   const Glib::RefPtr<Cancellable>& cancellable, int priority)
72 {
73   GSource* const source =
74     g_socket_create_source(socket->gobj(), (GIOCondition)condition, Glib::unwrap(cancellable));
75   return Glib::Source::attach_signal_source(
76     slot, priority, source, context_,
77     Glib::function_pointer_cast<GSourceFunc>(&giomm_signalsocket_callback));
78 }
79 
80 SignalSocket
signal_socket(const Glib::RefPtr<Glib::MainContext> & context)81 signal_socket(const Glib::RefPtr<Glib::MainContext>& context)
82 {
83   return SignalSocket(Glib::unwrap(context)); // 0 means default context
84 }
85 
86 /**** Glib::SocketSource *******************************************************/
87 
88 // static
89 Glib::RefPtr<SocketSource>
create(const Glib::RefPtr<Socket> & socket,Glib::IOCondition condition,const Glib::RefPtr<Cancellable> & cancellable)90 SocketSource::create(const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
91   const Glib::RefPtr<Cancellable>& cancellable)
92 {
93   return Glib::RefPtr<SocketSource>(new SocketSource(socket, condition, cancellable));
94 }
95 
SocketSource(const Glib::RefPtr<Socket> & socket,Glib::IOCondition condition,const Glib::RefPtr<Cancellable> & cancellable)96 SocketSource::SocketSource(const Glib::RefPtr<Socket>& socket, Glib::IOCondition condition,
97   const Glib::RefPtr<Cancellable>& cancellable)
98 : IOSource(
99     g_socket_create_source(socket->gobj(), (GIOCondition)condition, Glib::unwrap(cancellable)),
100     Glib::function_pointer_cast<GSourceFunc>(&giomm_socketsource_callback))
101 {
102 }
103 
~SocketSource()104 SocketSource::~SocketSource() noexcept
105 {
106 }
107 
108 } // namespace Gio
109