]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/admin_socket_client.cc
update sources to 12.2.10
[ceph.git] / ceph / src / common / admin_socket_client.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2011 New Dream Network
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
91327a77
AA
15#include <arpa/inet.h>
16#include <fcntl.h>
17#include <sys/socket.h>
18#include <sys/un.h>
19
7c673cae 20#include "common/admin_socket.h"
7c673cae
FG
21#include "common/errno.h"
22#include "common/safe_io.h"
23#include "common/admin_socket_client.h"
24
91327a77
AA
25#include "include/compat.h"
26#include "include/sock_compat.h"
7c673cae
FG
27
28using std::ostringstream;
29
30const char* get_rand_socket_path()
31{
32 static char *g_socket_path = NULL;
33
34 if (g_socket_path == NULL) {
35 char buf[512];
36 const char *tdir = getenv("TMPDIR");
37 if (tdir == NULL) {
38 tdir = "/tmp";
39 }
40 snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
41 "%s/perfcounters_test_socket.%ld.%ld",
42 tdir, (long int)getpid(), time(NULL));
43 g_socket_path = (char*)strdup(buf);
44 }
45 return g_socket_path;
46}
47
48static std::string asok_connect(const std::string &path, int *fd)
49{
91327a77 50 int socket_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
7c673cae
FG
51 if(socket_fd < 0) {
52 int err = errno;
53 ostringstream oss;
54 oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
55 return oss.str();
56 }
57
58 struct sockaddr_un address;
59 memset(&address, 0, sizeof(struct sockaddr_un));
60 address.sun_family = AF_UNIX;
61 snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
62
63 if (::connect(socket_fd, (struct sockaddr *) &address,
64 sizeof(struct sockaddr_un)) != 0) {
65 int err = errno;
66 ostringstream oss;
67 oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
68 close(socket_fd);
69 return oss.str();
70 }
71
72 struct timeval timer;
73 timer.tv_sec = 5;
74 timer.tv_usec = 0;
75 if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer))) {
76 int err = errno;
77 ostringstream oss;
78 oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
79 << cpp_strerror(err);
80 close(socket_fd);
81 return oss.str();
82 }
83 timer.tv_sec = 5;
84 timer.tv_usec = 0;
85 if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(timer))) {
86 int err = errno;
87 ostringstream oss;
88 oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
89 << cpp_strerror(err);
90 close(socket_fd);
91 return oss.str();
92 }
93
94 *fd = socket_fd;
95 return "";
96}
97
98static std::string asok_request(int socket_fd, std::string request)
99{
100 ssize_t res = safe_write(socket_fd, request.c_str(), request.length() + 1);
101 if (res < 0) {
102 int err = res;
103 ostringstream oss;
104 oss << "safe_write(" << socket_fd << ") failed to write request code: "
105 << cpp_strerror(err);
106 return oss.str();
107 }
108 return "";
109}
110
111AdminSocketClient::
112AdminSocketClient(const std::string &path)
113 : m_path(path)
114{
115}
116
117std::string AdminSocketClient::ping(bool *ok)
118{
119 std::string version;
120 std::string result = do_request("{\"prefix\":\"0\"}", &version);
121 *ok = result == "" && version.length() == 1;
122 return result;
123}
124
125std::string AdminSocketClient::do_request(std::string request, std::string *result)
126{
127 int socket_fd = 0, res;
128 std::string buffer;
129 uint32_t message_size_raw, message_size;
130
131 std::string err = asok_connect(m_path, &socket_fd);
132 if (!err.empty()) {
133 goto out;
134 }
135 err = asok_request(socket_fd, request);
136 if (!err.empty()) {
137 goto done;
138 }
139 res = safe_read_exact(socket_fd, &message_size_raw,
140 sizeof(message_size_raw));
141 if (res < 0) {
142 int e = res;
143 ostringstream oss;
144 oss << "safe_read(" << socket_fd << ") failed to read message size: "
145 << cpp_strerror(e);
146 err = oss.str();
147 goto done;
148 }
149 message_size = ntohl(message_size_raw);
150 buffer.resize(message_size, 0);
151 res = safe_read_exact(socket_fd, &buffer[0], message_size);
152 if (res < 0) {
153 int e = res;
154 ostringstream oss;
155 oss << "safe_read(" << socket_fd << ") failed: " << cpp_strerror(e);
156 err = oss.str();
157 goto done;
158 }
159 //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
160 std::swap(*result, buffer);
161done:
162 close(socket_fd);
163 out:
164 return err;
165}