SNode.C
Loading...
Searching...
No Matches
Socket.cpp
Go to the documentation of this file.
1/*
2 * SNode.C - a slim toolkit for network communication
3 * Copyright (C) Volker Christian <me@vchrist.at>
4 * 2020, 2021, 2022, 2023, 2024, 2025
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "net/un/dgram/Socket.h"
21
22#include "net/phy/dgram/PeerSocket.hpp" // IWYU pragma: keep
23#include "net/un/phy/PhysicalSocket.hpp"
24
25#ifndef DOXYGEN_SHOULD_SKIP_THIS
26
27#include <cerrno>
28#include <sys/uio.h>
29
30#endif /* DOXYGEN_SHOULD_SKIP_THIS */
31
32namespace net::un::dgram {
33
35 : Super(SOCK_DGRAM, 0) {
36 }
37
39 }
40
41 ssize_t Socket::sendFd(SocketAddress&& destAddress, int sendfd) {
42 return sendFd(destAddress, sendfd);
43 }
44
45 ssize_t Socket::sendFd(SocketAddress& destAddress, int sendfd) {
46 union {
47 struct cmsghdr cm;
48 char control[CMSG_SPACE(sizeof(int))] = {};
49 } control_un;
50
51 msghdr msg{};
52 msg.msg_name = const_cast<sockaddr*>(&destAddress.getSockAddr());
53 msg.msg_namelen = destAddress.getSockAddrLen();
54
55 msg.msg_control = control_un.control;
56 msg.msg_controllen = sizeof(control_un.control);
57
58 iovec iov[1];
59 msg.msg_iov = iov;
60 msg.msg_iovlen = 1;
61
62 char ptr = 0;
63 msg.msg_iov[0].iov_base = &ptr;
64 msg.msg_iov[0].iov_len = 1;
65
66 cmsghdr* cmptr = CMSG_FIRSTHDR(&msg);
67 cmptr->cmsg_level = SOL_SOCKET;
68 cmptr->cmsg_type = SCM_RIGHTS;
69 *reinterpret_cast<int*>(CMSG_DATA(cmptr)) = sendfd;
70 cmptr->cmsg_len = CMSG_LEN(sizeof(int));
71
72 return sendmsg(core::Descriptor::getFd(), &msg, 0);
73 }
74
75 ssize_t Socket::recvFd(int* recvfd) {
76 union {
77 struct cmsghdr cm;
78 char control[CMSG_SPACE(sizeof(int))] = {};
79 } control_un;
80
81 msghdr msg{};
82 msg.msg_control = control_un.control;
83 msg.msg_controllen = sizeof(control_un.control);
84
85 msg.msg_name = nullptr;
86 msg.msg_namelen = 0;
87
88 iovec iov[1];
89 msg.msg_iov = iov;
90 msg.msg_iovlen = 1;
91
92 char ptr = 0;
93 msg.msg_iov[0].iov_base = &ptr;
94 msg.msg_iov[0].iov_len = 1;
95
96 ssize_t n = 0;
97
98 if ((n = recvmsg(core::Descriptor::getFd(), &msg, 0)) > 0) {
99 cmsghdr* cmptr = nullptr;
100
101 if ((cmptr = CMSG_FIRSTHDR(&msg)) != nullptr && cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
102 if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS) {
103 errno = EBADE;
104 *recvfd = -1;
105 n = -1;
106 } else {
107 *recvfd = *reinterpret_cast<int*>(CMSG_DATA(cmptr));
108 }
109 } else {
110 errno = ENOMSG;
111 *recvfd = -1;
112 n = -1;
113 }
114 }
115
116 return n;
117 }
118
119} // namespace net::un::dgram
120
121template class net::phy::dgram::PeerSocket<net::un::SocketAddress>;
122template class net::un::phy::PhysicalSocket<net::phy::dgram::PeerSocket>;
ssize_t recvFd(int *recvfd)
Definition Socket.cpp:75
ssize_t sendFd(SocketAddress &&destAddress, int sendfd)
Definition Socket.cpp:41
ssize_t sendFd(SocketAddress &destAddress, int sendfd)
Definition Socket.cpp:45