668a61e7a1a6b3674191a54964569bc6eba52982
[lttng-tools.git] / src / bin / lttng-relayd / connection.cpp
1 /*
2 * Copyright (C) 2013 Julien Desfossez <jdesfossez@efficios.com>
3 * Copyright (C) 2013 David Goulet <dgoulet@efficios.com>
4 * Copyright (C) 2015 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
10 #define _LGPL_SOURCE
11 #include "connection.hpp"
12 #include "stream.hpp"
13 #include "viewer-session.hpp"
14
15 #include <common/common.hpp>
16 #include <common/urcu.hpp>
17
18 #include <urcu/rculist.h>
19
20 bool connection_get(struct relay_connection *conn)
21 {
22 return urcu_ref_get_unless_zero(&conn->ref);
23 }
24
25 struct relay_connection *connection_get_by_sock(struct lttng_ht *relay_connections_ht, int sock)
26 {
27 struct lttng_ht_node_ulong *node;
28 struct lttng_ht_iter iter;
29 struct relay_connection *conn = nullptr;
30
31 LTTNG_ASSERT(sock >= 0);
32
33 lttng::urcu::read_lock_guard read_lock;
34 lttng_ht_lookup(relay_connections_ht, (void *) ((unsigned long) sock), &iter);
35 node = lttng_ht_iter_get_node_ulong(&iter);
36 if (!node) {
37 DBG2("Relay connection by sock %d not found", sock);
38 goto end;
39 }
40 conn = lttng::utils::container_of(node, &relay_connection::sock_n);
41 if (!connection_get(conn)) {
42 conn = nullptr;
43 }
44 end:
45 return conn;
46 }
47
48 int connection_reset_protocol_state(struct relay_connection *connection)
49 {
50 int ret = 0;
51
52 switch (connection->type) {
53 case RELAY_DATA:
54 connection->protocol.data.state_id = DATA_CONNECTION_STATE_RECEIVE_HEADER;
55 memset(&connection->protocol.data.state.receive_header,
56 0,
57 sizeof(connection->protocol.data.state.receive_header));
58 connection->protocol.data.state.receive_header.left_to_receive =
59 sizeof(struct lttcomm_relayd_data_hdr);
60 break;
61 case RELAY_CONTROL:
62 connection->protocol.ctrl.state_id = CTRL_CONNECTION_STATE_RECEIVE_HEADER;
63 memset(&connection->protocol.ctrl.state.receive_header,
64 0,
65 sizeof(connection->protocol.ctrl.state.receive_header));
66 connection->protocol.data.state.receive_header.left_to_receive =
67 sizeof(struct lttcomm_relayd_hdr);
68 ret = lttng_dynamic_buffer_set_size(&connection->protocol.ctrl.reception_buffer,
69 sizeof(struct lttcomm_relayd_hdr));
70 if (ret) {
71 ERR("Failed to reinitialize control connection reception buffer size to %zu bytes.",
72 sizeof(struct lttcomm_relayd_hdr));
73 goto end;
74 }
75 break;
76 default:
77 goto end;
78 }
79 DBG("Reset communication state of relay connection (fd = %i)", connection->sock->fd);
80 end:
81 return ret;
82 }
83
84 struct relay_connection *connection_create(struct lttcomm_sock *sock, enum connection_type type)
85 {
86 struct relay_connection *conn;
87
88 conn = zmalloc<relay_connection>();
89 if (!conn) {
90 PERROR("zmalloc relay connection");
91 goto end;
92 }
93 urcu_ref_init(&conn->ref);
94 conn->type = type;
95 conn->sock = sock;
96 lttng_ht_node_init_ulong(&conn->sock_n, (unsigned long) conn->sock->fd);
97 if (conn->type == RELAY_CONTROL) {
98 lttng_dynamic_buffer_init(&conn->protocol.ctrl.reception_buffer);
99 }
100 connection_reset_protocol_state(conn);
101 end:
102 return conn;
103 }
104
105 static void rcu_free_connection(struct rcu_head *head)
106 {
107 struct relay_connection *conn =
108 lttng::utils::container_of(head, &relay_connection::rcu_node);
109
110 lttcomm_destroy_sock(conn->sock);
111 if (conn->viewer_session) {
112 viewer_session_destroy(conn->viewer_session);
113 conn->viewer_session = nullptr;
114 }
115 if (conn->type == RELAY_CONTROL) {
116 lttng_dynamic_buffer_reset(&conn->protocol.ctrl.reception_buffer);
117 }
118 free(conn);
119 }
120
121 static void destroy_connection(struct relay_connection *conn)
122 {
123 call_rcu(&conn->rcu_node, rcu_free_connection);
124 }
125
126 static void connection_release(struct urcu_ref *ref)
127 {
128 struct relay_connection *conn = lttng::utils::container_of(ref, &relay_connection::ref);
129
130 if (conn->in_socket_ht) {
131 struct lttng_ht_iter iter;
132 int ret;
133
134 iter.iter.node = &conn->sock_n.node;
135 ret = lttng_ht_del(conn->socket_ht, &iter);
136 LTTNG_ASSERT(!ret);
137 }
138
139 if (conn->session) {
140 if (session_close(conn->session)) {
141 ERR("session_close");
142 }
143 conn->session = nullptr;
144 }
145 if (conn->viewer_session) {
146 viewer_session_close(conn->viewer_session);
147 }
148 destroy_connection(conn);
149 }
150
151 void connection_put(struct relay_connection *conn)
152 {
153 lttng::urcu::read_lock_guard read_lock;
154 urcu_ref_put(&conn->ref, connection_release);
155 }
156
157 void connection_ht_add(struct lttng_ht *relay_connections_ht, struct relay_connection *conn)
158 {
159 LTTNG_ASSERT(!conn->in_socket_ht);
160 lttng_ht_add_unique_ulong(relay_connections_ht, &conn->sock_n);
161 conn->in_socket_ht = true;
162 conn->socket_ht = relay_connections_ht;
163 }
164
165 int connection_set_session(struct relay_connection *conn, struct relay_session *session)
166 {
167 int ret = 0;
168
169 LTTNG_ASSERT(conn);
170 LTTNG_ASSERT(session);
171 LTTNG_ASSERT(!conn->session);
172
173 if (connection_get(conn)) {
174 if (session_get(session)) {
175 conn->session = session;
176 } else {
177 ERR("Failed to get session reference in connection_set_session()");
178 ret = -1;
179 }
180 connection_put(conn);
181 } else {
182 ERR("Failed to get connection reference in connection_set_session()");
183 ret = -1;
184 }
185 return ret;
186 }
This page took 0.032098 seconds and 4 git commands to generate.