@@ -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+
273314void 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