Fix: syscall event rule: emission sites not compared in is_equal
[lttng-tools.git] / src / bin / lttng-relayd / connection.cpp
... / ...
CommitLineData
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
20bool connection_get(struct relay_connection *conn)
21{
22 return urcu_ref_get_unless_zero(&conn->ref);
23}
24
25struct 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 }
44end:
45 return conn;
46}
47
48int 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);
80end:
81 return ret;
82}
83
84struct 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);
101end:
102 return conn;
103}
104
105static 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
121static void destroy_connection(struct relay_connection *conn)
122{
123 call_rcu(&conn->rcu_node, rcu_free_connection);
124}
125
126static 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
151void 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
157void 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
165int 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.022954 seconds and 4 git commands to generate.