1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #ifndef QNET_UNIX_P_H
41 #define QNET_UNIX_P_H
42
43 //
44 // W A R N I N G
45 // -------------
46 //
47 // This file is not part of the Qt API. It exists for the convenience
48 // of Qt code on Unix. This header file may change from version to
49 // version to version without notice, or even be removed.
50 //
51 // We mean it.
52 //
53
54 #include <QtNetwork/private/qtnetworkglobal_p.h>
55 #include "private/qcore_unix_p.h"
56
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <netinet/in.h>
60
61 #if defined(Q_OS_VXWORKS)
62 # include <sockLib.h>
63 #endif
64
65 // for inet_addr
66 #include <netdb.h>
67 #include <arpa/inet.h>
68 #if defined(Q_OS_VXWORKS)
69 # include <hostLib.h>
70 #else
71 # include <resolv.h>
72 #endif
73
74 QT_BEGIN_NAMESPACE
75
76 // Almost always the same. If not, specify in qplatformdefs.h.
77 #if !defined(QT_SOCKOPTLEN_T)
78 # define QT_SOCKOPTLEN_T QT_SOCKLEN_T
79 #endif
80
81 static inline int qt_safe_socket(int domain, int type, int protocol, int flags = 0)
82 {
83 Q_ASSERT((flags & ~O_NONBLOCK) == 0);
84
85 int fd;
86 #ifdef QT_THREADSAFE_CLOEXEC
87 int newtype = type | SOCK_CLOEXEC;
88 if (flags & O_NONBLOCK)
89 newtype |= SOCK_NONBLOCK;
90 fd = ::socket(domain, newtype, protocol);
91 return fd;
92 #else
93 fd = ::socket(domain, type, protocol);
94 if (fd == -1)
95 return -1;
96
97 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
98
99 // set non-block too?
100 if (flags & O_NONBLOCK)
101 ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
102
103 return fd;
104 #endif
105 }
106
107 static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags = 0)
108 {
109 Q_ASSERT((flags & ~O_NONBLOCK) == 0);
110
111 int fd;
112 #ifdef QT_THREADSAFE_CLOEXEC
113 // use accept4
114 int sockflags = SOCK_CLOEXEC;
115 if (flags & O_NONBLOCK)
116 sockflags |= SOCK_NONBLOCK;
117 # if defined(Q_OS_NETBSD)
118 fd = ::paccept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), NULL, sockflags);
119 # else
120 fd = ::accept4(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen), sockflags);
121 # endif
122 return fd;
123 #else
124 fd = ::accept(s, addr, static_cast<QT_SOCKLEN_T *>(addrlen));
125 if (fd == -1)
126 return -1;
127
128 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
129
130 // set non-block too?
131 if (flags & O_NONBLOCK)
132 ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
133
134 return fd;
135 #endif
136 }
137
qt_safe_listen(int s,int backlog)138 static inline int qt_safe_listen(int s, int backlog)
139 {
140 return ::listen(s, backlog);
141 }
142
qt_safe_connect(int sockfd,const struct sockaddr * addr,QT_SOCKLEN_T addrlen)143 static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SOCKLEN_T addrlen)
144 {
145 int ret;
146 // Solaris e.g. expects a non-const 2nd parameter
147 EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, const_cast<struct sockaddr *>(addr), addrlen));
148 return ret;
149 }
150 #undef QT_SOCKET_CONNECT
151 #define QT_SOCKET_CONNECT qt_safe_connect
152
153 #if defined(socket)
154 # undef socket
155 #endif
156 #if defined(accept)
157 # undef accept
158 #endif
159 #if defined(listen)
160 # undef listen
161 #endif
162
163 // VxWorks' headers specify 'int' instead of '...' for the 3rd ioctl() parameter.
164 template <typename T>
qt_safe_ioctl(int sockfd,unsigned long request,T arg)165 static inline int qt_safe_ioctl(int sockfd, unsigned long request, T arg)
166 {
167 #ifdef Q_OS_VXWORKS
168 return ::ioctl(sockfd, request, (int) arg);
169 #else
170 return ::ioctl(sockfd, request, arg);
171 #endif
172 }
173
qt_safe_sendmsg(int sockfd,const struct msghdr * msg,int flags)174 static inline int qt_safe_sendmsg(int sockfd, const struct msghdr *msg, int flags)
175 {
176 #ifdef MSG_NOSIGNAL
177 flags |= MSG_NOSIGNAL;
178 #else
179 qt_ignore_sigpipe();
180 #endif
181
182 int ret;
183 EINTR_LOOP(ret, ::sendmsg(sockfd, msg, flags));
184 return ret;
185 }
186
qt_safe_recvmsg(int sockfd,struct msghdr * msg,int flags)187 static inline int qt_safe_recvmsg(int sockfd, struct msghdr *msg, int flags)
188 {
189 int ret;
190
191 EINTR_LOOP(ret, ::recvmsg(sockfd, msg, flags));
192 return ret;
193 }
194
195 QT_END_NAMESPACE
196
197 #endif // QNET_UNIX_P_H
198