]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/admin_socket_client.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / admin_socket_client.cc
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
15 #include "include/int_types.h"
16
17 #include "common/admin_socket.h"
18 #include "common/ceph_context.h"
19 #include "common/errno.h"
20 #include "common/safe_io.h"
21 #include "common/admin_socket_client.h"
22
23 #include <arpa/inet.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <map>
27 #include <poll.h>
28 #include <sstream>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <string>
34 #include <sys/socket.h>
35 #include <sys/types.h>
36 #include <sys/un.h>
37 #include <time.h>
38 #include <unistd.h>
39 #include <vector>
40
41 using std::ostringstream;
42
43 const char* get_rand_socket_path()
44 {
45 static char *g_socket_path = NULL;
46
47 if (g_socket_path == NULL) {
48 char buf[512];
49 const char *tdir = getenv("TMPDIR");
50 if (tdir == NULL) {
51 tdir = "/tmp";
52 }
53 snprintf(buf, sizeof(((struct sockaddr_un*)0)->sun_path),
54 "%s/perfcounters_test_socket.%ld.%ld",
55 tdir, (long int)getpid(), time(NULL));
56 g_socket_path = (char*)strdup(buf);
57 }
58 return g_socket_path;
59 }
60
61 static std::string asok_connect(const std::string &path, int *fd)
62 {
63 int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
64 if(socket_fd < 0) {
65 int err = errno;
66 ostringstream oss;
67 oss << "socket(PF_UNIX, SOCK_STREAM, 0) failed: " << cpp_strerror(err);
68 return oss.str();
69 }
70
71 struct sockaddr_un address;
72 memset(&address, 0, sizeof(struct sockaddr_un));
73 address.sun_family = AF_UNIX;
74 snprintf(address.sun_path, sizeof(address.sun_path), "%s", path.c_str());
75
76 if (::connect(socket_fd, (struct sockaddr *) &address,
77 sizeof(struct sockaddr_un)) != 0) {
78 int err = errno;
79 ostringstream oss;
80 oss << "connect(" << socket_fd << ") failed: " << cpp_strerror(err);
81 close(socket_fd);
82 return oss.str();
83 }
84
85 struct timeval timer;
86 timer.tv_sec = 5;
87 timer.tv_usec = 0;
88 if (::setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer))) {
89 int err = errno;
90 ostringstream oss;
91 oss << "setsockopt(" << socket_fd << ", SO_RCVTIMEO) failed: "
92 << cpp_strerror(err);
93 close(socket_fd);
94 return oss.str();
95 }
96 timer.tv_sec = 5;
97 timer.tv_usec = 0;
98 if (::setsockopt(socket_fd, SOL_SOCKET, SO_SNDTIMEO, &timer, sizeof(timer))) {
99 int err = errno;
100 ostringstream oss;
101 oss << "setsockopt(" << socket_fd << ", SO_SNDTIMEO) failed: "
102 << cpp_strerror(err);
103 close(socket_fd);
104 return oss.str();
105 }
106
107 *fd = socket_fd;
108 return "";
109 }
110
111 static std::string asok_request(int socket_fd, std::string request)
112 {
113 ssize_t res = safe_write(socket_fd, request.c_str(), request.length() + 1);
114 if (res < 0) {
115 int err = res;
116 ostringstream oss;
117 oss << "safe_write(" << socket_fd << ") failed to write request code: "
118 << cpp_strerror(err);
119 return oss.str();
120 }
121 return "";
122 }
123
124 AdminSocketClient::
125 AdminSocketClient(const std::string &path)
126 : m_path(path)
127 {
128 }
129
130 std::string AdminSocketClient::ping(bool *ok)
131 {
132 std::string version;
133 std::string result = do_request("{\"prefix\":\"0\"}", &version);
134 *ok = result == "" && version.length() == 1;
135 return result;
136 }
137
138 std::string AdminSocketClient::do_request(std::string request, std::string *result)
139 {
140 int socket_fd = 0, res;
141 std::string buffer;
142 uint32_t message_size_raw, message_size;
143
144 std::string err = asok_connect(m_path, &socket_fd);
145 if (!err.empty()) {
146 goto out;
147 }
148 err = asok_request(socket_fd, request);
149 if (!err.empty()) {
150 goto done;
151 }
152 res = safe_read_exact(socket_fd, &message_size_raw,
153 sizeof(message_size_raw));
154 if (res < 0) {
155 int e = res;
156 ostringstream oss;
157 oss << "safe_read(" << socket_fd << ") failed to read message size: "
158 << cpp_strerror(e);
159 err = oss.str();
160 goto done;
161 }
162 message_size = ntohl(message_size_raw);
163 buffer.resize(message_size, 0);
164 res = safe_read_exact(socket_fd, &buffer[0], message_size);
165 if (res < 0) {
166 int e = res;
167 ostringstream oss;
168 oss << "safe_read(" << socket_fd << ") failed: " << cpp_strerror(e);
169 err = oss.str();
170 goto done;
171 }
172 //printf("MESSAGE FROM SERVER: %s\n", buffer.c_str());
173 std::swap(*result, buffer);
174 done:
175 close(socket_fd);
176 out:
177 return err;
178 }