| 28 | constexpr std::size_t max_length = 1024; |
| 29 | |
| 30 | int main(int argc, char* argv[]) |
| 31 | { |
| 32 | try |
| 33 | { |
| 34 | if (argc != 2) |
| 35 | { |
| 36 | std::cerr << "Usage: fd_passing_stream_client <serversocket>\n"; |
| 37 | return 1; |
| 38 | } |
| 39 | |
| 40 | boost::asio::io_context io_context; |
| 41 | |
| 42 | stream_protocol::socket s(io_context); |
| 43 | s.connect(stream_protocol::endpoint(argv[1])); |
| 44 | |
| 45 | std::cout << "Enter path to write to: "; |
| 46 | char request[max_length]; |
| 47 | std::cin.getline(request, max_length); |
| 48 | size_t request_length = std::strlen(request); |
| 49 | boost::asio::write(s, boost::asio::buffer(request, request_length)); |
| 50 | |
| 51 | char reply[max_length]; |
| 52 | struct msghdr msg = {}; |
| 53 | struct iovec iov = { reply, sizeof(reply) }; |
| 54 | msg.msg_iov = &iov; |
| 55 | msg.msg_iovlen = 1; |
| 56 | |
| 57 | union |
| 58 | { |
| 59 | struct cmsghdr align; |
| 60 | char buf[CMSG_SPACE(sizeof(int))]; |
| 61 | } cmsgu; |
| 62 | msg.msg_control = cmsgu.buf; |
| 63 | msg.msg_controllen = sizeof(cmsgu.buf); |
| 64 | |
| 65 | ::recvmsg(s.native_handle(), &msg, 0); |
| 66 | |
| 67 | int fd = -1; |
| 68 | struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); |
| 69 | while (cmsg != NULL) |
| 70 | { |
| 71 | if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) |
| 72 | { |
| 73 | std::memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); |
| 74 | break; |
| 75 | } |
| 76 | cmsg = CMSG_NXTHDR(&msg, cmsg); |
| 77 | } |
| 78 | |
| 79 | if (fd != -1) |
| 80 | { |
| 81 | std::cout << "File descriptor received is: " << fd << "\n"; |
| 82 | FILE* f(::fdopen(fd, "w+")); |
| 83 | if (f) |
| 84 | { |
| 85 | ::fprintf(f, "stream_client writing to received fd #%d\n", fd); |
| 86 | ::fclose(f); |
| 87 | } |