Skip to content

Commit 800e86f

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

1 file changed

Lines changed: 52 additions & 0 deletions

File tree

src/socket.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,47 @@ 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+
// The cmsg buffer is only set up once (tos doesn't change) so can be static
278+
static union
279+
{
280+
unsigned char cbuf[CMSG_SPACE ( sizeof ( int ) )];
281+
struct cmsghdr h;
282+
} u;
283+
static socklen_t clen = 0;
284+
285+
if ( clen == 0 )
286+
{
287+
// set up the cmsg buffer
288+
memset ( u.cbuf, 0, sizeof ( u.cbuf ) );
289+
290+
u.h.cmsg_level = IPPROTO_IP;
291+
u.h.cmsg_type = IP_TOS;
292+
u.h.cmsg_len = CMSG_LEN ( sizeof ( int ) );
293+
memcpy ( CMSG_DATA ( &u.h ), &tos, sizeof ( int ) );
294+
clen = (socklen_t) u.h.cmsg_len;
295+
}
296+
297+
struct iovec iov;
298+
iov.iov_base = const_cast<void*> ( buf );
299+
iov.iov_len = len;
300+
301+
struct msghdr msg;
302+
303+
msg.msg_name = const_cast<sockaddr*> ( dest );
304+
msg.msg_namelen = destlen;
305+
msg.msg_iov = &iov;
306+
msg.msg_iovlen = 1;
307+
msg.msg_control = (void*) u.cbuf;
308+
msg.msg_controllen = clen;
309+
310+
return sendmsg ( fd, &msg, flags );
311+
}
312+
#endif
313+
273314
void CSocket::SendPacket ( const CVector<uint8_t>& vecbySendBuf, const CHostAddress& HostAddr )
274315
{
275316
int status = 0;
@@ -309,12 +350,23 @@ void CSocket::SendPacket ( const CVector<uint8_t>& vecbySendBuf, const CHostAddr
309350
addr[2] = htonl ( 0xFFFF );
310351
addr[3] = htonl ( HostAddr.InetAddr.toIPv4Address() );
311352

353+
#if defined( Q_OS_DARWIN )
354+
// In macOS we need to set TOS explicitly when sending IPv4 over IPv6 socket
355+
status = sendto_ipv4_with_tos ( UdpSocket,
356+
(const char*) &( (CVector<uint8_t>) vecbySendBuf )[0],
357+
iVecSizeOut,
358+
0,
359+
&UdpSocketAddr.sa,
360+
sizeof ( UdpSocketAddr.sa6 ),
361+
(int) iQosNumber );
362+
#else
312363
status = sendto ( UdpSocket,
313364
(const char*) &( (CVector<uint8_t>) vecbySendBuf )[0],
314365
iVecSizeOut,
315366
0,
316367
&UdpSocketAddr.sa,
317368
sizeof ( UdpSocketAddr.sa6 ) );
369+
#endif
318370
}
319371
else
320372
{

0 commit comments

Comments
 (0)