1 /*
2 * Copyright (c) 2002-2018 Balabit
3 * Copyright (c) 2018 Laszlo Budai <laszlo.budai@balabit.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "transport/multitransport.h"
26 #include "transport/transport-factory-registry.h"
27 #include "messages.h"
28
multitransport_add_factory(MultiTransport * self,TransportFactory * transport_factory)29 void multitransport_add_factory(MultiTransport *self, TransportFactory *transport_factory)
30 {
31 transport_factory_registry_add(self->registry, transport_factory);
32 }
33
34 static void
_do_transport_switch(MultiTransport * self,LogTransport * new_transport,const TransportFactory * new_transport_factory)35 _do_transport_switch(MultiTransport *self, LogTransport *new_transport, const TransportFactory *new_transport_factory)
36 {
37 self->super.fd = log_transport_release_fd(self->active_transport);
38 self->super.cond = new_transport->cond;
39 log_transport_free(self->active_transport);
40 self->active_transport = new_transport;
41 self->active_transport_factory = new_transport_factory;
42 }
43
44 static const TransportFactory *
_lookup_transport_factory(TransportFactoryRegistry * registry,const TransportFactoryId * factory_id)45 _lookup_transport_factory(TransportFactoryRegistry *registry, const TransportFactoryId *factory_id)
46 {
47 const TransportFactory *factory = transport_factory_registry_lookup(registry, factory_id);
48
49 if (!factory)
50 {
51 msg_error("Requested transport not found",
52 evt_tag_str("transport", transport_factory_id_get_transport_name(factory_id)));
53 return NULL;
54 }
55
56 return factory;
57 }
58
59 static LogTransport *
_construct_transport(const TransportFactory * factory,gint fd)60 _construct_transport(const TransportFactory *factory, gint fd)
61 {
62 LogTransport *transport = transport_factory_construct_transport(factory, fd);
63 const TransportFactoryId *factory_id = transport_factory_get_id(factory);
64
65 if (!transport)
66 {
67 msg_error("Failed to construct transport",
68 evt_tag_str("transport", transport_factory_id_get_transport_name(factory_id)));
69 return NULL;
70 }
71
72 return transport;
73 }
74
multitransport_switch(MultiTransport * self,const TransportFactoryId * factory_id)75 gboolean multitransport_switch(MultiTransport *self, const TransportFactoryId *factory_id)
76 {
77 msg_debug("Transport switch requested",
78 evt_tag_str("active-transport", self->active_transport->name),
79 evt_tag_str("requested-transport", transport_factory_id_get_transport_name(factory_id)));
80
81 const TransportFactory *transport_factory = _lookup_transport_factory(self->registry, factory_id);
82 if (!transport_factory)
83 return FALSE;
84
85 LogTransport *transport = _construct_transport(transport_factory, self->super.fd);
86 if (!transport)
87 return FALSE;
88
89 _do_transport_switch(self, transport, transport_factory);
90
91 msg_debug("Transport switch succeeded",
92 evt_tag_str("new-active-transport", self->active_transport->name));
93
94 return TRUE;
95 }
96
97 gboolean
multitransport_contains_factory(MultiTransport * self,const TransportFactoryId * factory_id)98 multitransport_contains_factory(MultiTransport *self, const TransportFactoryId *factory_id)
99 {
100 const TransportFactory *factory = transport_factory_registry_lookup(self->registry, factory_id);
101
102 return (factory != NULL);
103 }
104
105 static gssize
_multitransport_write(LogTransport * s,gpointer buf,gsize count)106 _multitransport_write(LogTransport *s, gpointer buf, gsize count)
107 {
108 MultiTransport *self = (MultiTransport *)s;
109 gssize r = log_transport_write(self->active_transport, buf, count);
110 self->super.cond = self->active_transport->cond;
111
112 return r;
113 }
114
115 static gssize
_multitransport_read(LogTransport * s,gpointer buf,gsize count,LogTransportAuxData * aux)116 _multitransport_read(LogTransport *s, gpointer buf, gsize count, LogTransportAuxData *aux)
117 {
118 MultiTransport *self = (MultiTransport *)s;
119 gssize r = log_transport_read(self->active_transport, buf, count, aux);
120 self->super.cond = self->active_transport->cond;
121
122 return r;
123 }
124
125 static void
_multitransport_free(LogTransport * s)126 _multitransport_free(LogTransport *s)
127 {
128 MultiTransport *self = (MultiTransport *)s;
129 s->fd = log_transport_release_fd(self->active_transport);
130 log_transport_free(self->active_transport);
131 transport_factory_registry_free(self->registry);
132 log_transport_free_method(s);
133 }
134
135 LogTransport *
multitransport_new(TransportFactory * default_transport_factory,gint fd)136 multitransport_new(TransportFactory *default_transport_factory, gint fd)
137 {
138 MultiTransport *self = g_new0(MultiTransport, 1);
139 self->registry = transport_factory_registry_new();
140 transport_factory_registry_add(self->registry, default_transport_factory);
141
142 log_transport_init_instance(&self->super, fd);
143 self->super.read = _multitransport_read;
144 self->super.write = _multitransport_write;
145 self->super.free_fn = _multitransport_free;
146 self->active_transport = transport_factory_construct_transport(default_transport_factory, fd);
147 self->active_transport_factory = default_transport_factory;
148
149 return &self->super;
150 }
151