30 #include <arpa/inet.h>
34 #include <sys/socket.h>
36 #include <sys/types.h>
58 fatal_if(
system ==
nullptr,
"Requires a system to share memory from!");
63 "The server path %s was occupied and will be replaced. Please "
64 "make sure there is no other server using the same path.",
72 sockaddr_un serv_addr = {};
73 serv_addr.sun_family = AF_UNIX;
75 sizeof(serv_addr.sun_path) - 1);
77 "%s: unix socket path truncated, expect '%s' but get '%s'",
79 int bind_retv = bind(
serverFd,
reinterpret_cast<sockaddr*
>(&serv_addr),
81 fatal_if(bind_retv != 0,
"%s: cannot bind unix socket: %s",
name().c_str(),
84 int listen_retv = listen(
serverFd, 1);
85 fatal_if(listen_retv != 0,
"%s: listen failed: %s",
name().c_str(),
95 warn_if(unlink_retv != 0,
"%s: cannot unlink unix socket: %s",
96 name().c_str(), strerror(errno));
98 warn_if(close_retv != 0,
"%s: cannot close unix socket: %s",
99 name().c_str(), strerror(errno));
118 char* char_buffer =
reinterpret_cast<char*
>(buffer);
120 ssize_t retv = recv(pfd.fd, char_buffer +
offset, size -
offset, 0);
123 }
else if (errno != EINTR) {
124 warn(
"%s: recv failed: %s",
name().c_str(), strerror(errno));
134 panic_if(revents & (POLLERR | POLLNVAL),
"%s: listen socket is broken",
137 panic_if(cli_fd < 0,
"%s: accept failed: %s",
name().c_str(),
139 panic_if(shmServer->clientSocketEvent.get(),
140 "%s: cannot serve two clients at once",
name().c_str());
141 inform(
"%s: accept new connection %d",
name().c_str(), cli_fd);
142 shmServer->clientSocketEvent.reset(
152 if (revents & (POLLHUP | POLLERR | POLLNVAL)) {
164 if (!tryReadAll(&req_type,
sizeof(req_type))) {
168 warn(
"%s: receive unknown request: %d",
name().c_str(),
169 static_cast<int>(req_type));
172 if (!tryReadAll(&request,
sizeof(request))) {
175 AddrRange range(request.start, request.end);
176 inform(
"%s: receive request: %s",
name().c_str(),
180 const auto& stores = shmServer->system->getPhysMem().getBackingStore();
181 auto it = std::find_if(
183 return entry.shmFd >= 0 && range.isSubset(entry.range);
185 if (it == stores.end()) {
186 warn(
"%s: cannot find backing store for %s",
name().c_str(),
190 inform(
"%s: find shared backing store for %s at %s, shm=%d:%lld",
192 it->range.to_string().c_str(), it->shmFd,
193 (
unsigned long long)it->shmOffset);
207 response.offset = it->shmOffset + (range.
start() - it->range.start());
208 iovec ios = {.iov_base = &response, .iov_len =
sizeof(response)};
214 char buf[CMSG_SPACE(
sizeof(it->shmFd))];
215 struct cmsghdr
align;
217 msg.msg_control = cmsgs.buf;
218 msg.msg_controllen =
sizeof(cmsgs.buf);
219 cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
220 cmsg->cmsg_level = SOL_SOCKET;
221 cmsg->cmsg_type = SCM_RIGHTS;
222 cmsg->cmsg_len = CMSG_LEN(
sizeof(it->shmFd));
223 memcpy(CMSG_DATA(cmsg), &it->shmFd,
sizeof(it->shmFd));
225 int retv = sendmsg(pfd.fd, &msg, 0);
227 warn(
"%s: sendmsg failed: %s",
name().c_str(), strerror(errno));
230 if (retv !=
sizeof(response)) {
231 warn(
"%s: failed to send all response at once",
name().c_str());
242 inform(
"%s: closing connection",
name().c_str());
244 shmServer->clientSocketEvent.reset();