Skip to content

Commit 22a4293

Browse files
committed
Add macOS support for TOS on IPv4 over IPv6
1 parent b5a38db commit 22a4293

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

src/socket.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,50 @@ CSocket::~CSocket()
270270
#endif
271271
}
272272

273+
#if defined( Q_OS_DARWIN )
274+
// sendto_ipv4_with_tos - helper function for macOS to set TOS when sending IPv4 over IPv6 socket
275+
static ssize_t sendto_ipv4_with_tos ( int fd, const void* buf, size_t len, int flags, const struct sockaddr* dest, socklen_t destlen, int tos )
276+
{
277+
// For a description of 'struct cmsghdr' and the 'CMSG_xxx' macros, see 'man 3 cmsg' on a Linux machine.
278+
// The macOS man pages are less descriptive, but the API is the same, being based on the BSD socket interface.
279+
280+
// The cmsg buffer is only set up once (tos doesn't change) so can be static
281+
static union
282+
{
283+
unsigned char cbuf[CMSG_SPACE ( sizeof ( int ) )];
284+
struct cmsghdr h;
285+
} u;
286+
static socklen_t clen = 0;
287+
288+
if ( clen == 0 )
289+
{
290+
// set up the cmsg buffer
291+
memset ( u.cbuf, 0, sizeof ( u.cbuf ) );
292+
293+
u.h.cmsg_level = IPPROTO_IP;
294+
u.h.cmsg_type = IP_TOS;
295+
u.h.cmsg_len = CMSG_LEN ( sizeof ( int ) );
296+
memcpy ( CMSG_DATA ( &u.h ), &tos, sizeof ( int ) );
297+
clen = (socklen_t) u.h.cmsg_len;
298+
}
299+
300+
struct iovec iov;
301+
iov.iov_base = const_cast<void*> ( buf );
302+
iov.iov_len = len;
303+
304+
struct msghdr msg;
305+
306+
msg.msg_name = const_cast<sockaddr*> ( dest );
307+
msg.msg_namelen = destlen;
308+
msg.msg_iov = &iov;
309+
msg.msg_iovlen = 1;
310+
msg.msg_control = (void*) u.cbuf;
311+
msg.msg_controllen = clen;
312+
313+
return sendmsg ( fd, &msg, flags );
314+
}
315+
#endif
316+
273317
void CSocket::SendPacket ( const CVector<uint8_t>& vecbySendBuf, const CHostAddress& HostAddr )
274318
{
275319
int status = 0;
@@ -309,12 +353,23 @@ void CSocket::SendPacket ( const CVector<uint8_t>& vecbySendBuf, const CHostAddr
309353
addr[2] = htonl ( 0xFFFF );
310354
addr[3] = htonl ( HostAddr.InetAddr.toIPv4Address() );
311355

356+
#if defined( Q_OS_DARWIN )
357+
// In macOS we need to set TOS explicitly when sending IPv4 over IPv6 socket
358+
status = sendto_ipv4_with_tos ( UdpSocket,
359+
(const char*) &( (CVector<uint8_t>) vecbySendBuf )[0],
360+
iVecSizeOut,
361+
0,
362+
&UdpSocketAddr.sa,
363+
sizeof ( UdpSocketAddr.sa6 ),
364+
(int) iQosNumber );
365+
#else
312366
status = sendto ( UdpSocket,
313367
(const char*) &( (CVector<uint8_t>) vecbySendBuf )[0],
314368
iVecSizeOut,
315369
0,
316370
&UdpSocketAddr.sa,
317371
sizeof ( UdpSocketAddr.sa6 ) );
372+
#endif
318373
}
319374
else
320375
{

0 commit comments

Comments
 (0)