+ int send_streams = 0;
+ ssize_t ret;
+ uint32_t nb_streams = 0;
+ enum lttng_viewer_seek seek_type;
+ struct lttng_viewer_attach_session_request request;
+ struct lttng_viewer_attach_session_response response;
+ struct relay_session *session;
+
+ assert(conn);
+
+ health_code_update();
+
+ /* Receive the request from the connected client. */
+ ret = recv_request(conn->sock, &request, sizeof(request));
+ if (ret < 0) {
+ goto error;
+ }
+
+ health_code_update();
+
+ if (!conn->viewer_session) {
+ DBG("Client trying to attach before creating a live viewer session");
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_NO_SESSION);
+ goto send_reply;
+ }
+
+ rcu_read_lock();
+ session = session_find_by_id(conn->sessions_ht,
+ be64toh(request.session_id));
+ if (!session) {
+ DBG("Relay session %" PRIu64 " not found",
+ be64toh(request.session_id));
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_UNK);
+ goto send_reply;
+ }
+ session_viewer_attach(session);
+ DBG("Attach session ID %" PRIu64 " received", be64toh(request.session_id));
+
+ if (uatomic_read(&session->viewer_refcount) > 1) {
+ DBG("Already a viewer attached");
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_ALREADY);
+ session_viewer_detach(session);
+ goto send_reply;
+ } else if (session->live_timer == 0) {
+ DBG("Not live session");
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_NOT_LIVE);
+ goto send_reply;
+ } else {
+ send_streams = 1;
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_OK);
+ cds_list_add(&session->viewer_session_list,
+ &conn->viewer_session->sessions_head);
+ }
+
+ switch (be32toh(request.seek)) {
+ case LTTNG_VIEWER_SEEK_BEGINNING:
+ case LTTNG_VIEWER_SEEK_LAST:
+ seek_type = be32toh(request.seek);
+ break;
+ default:
+ ERR("Wrong seek parameter");
+ response.status = htobe32(LTTNG_VIEWER_ATTACH_SEEK_ERR);
+ send_streams = 0;
+ goto send_reply;
+ }