xref: /6.0.3/platform/cbsocket/socket.cc (revision 0f8ec9fb)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2017 Couchbase, Inc.
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17
18#include <platform/socket.h>
19
20#include <event2/util.h>
21
22#include <cerrno>
23#include <gsl/gsl>
24
25#ifndef WIN32
26#include <netdb.h>
27#include <unistd.h>
28#endif
29
30namespace cb {
31namespace net {
32
33CBSOCKET_PUBLIC_API
34int closesocket(SOCKET s) {
35#ifdef WIN32
36    return ::closesocket(s);
37#else
38    return ::close(s);
39#endif
40
41}
42
43CBSOCKET_PUBLIC_API
44int get_socket_error() {
45#ifdef WIN32
46    return WSAGetLastError();
47#else
48    return errno;
49#endif
50}
51
52CBSOCKET_PUBLIC_API
53int bind(SOCKET sock, const struct sockaddr* name, socklen_t namelen) {
54    return ::bind(sock, name, namelen);
55}
56
57CBSOCKET_PUBLIC_API
58int listen(SOCKET sock, int backlog) {
59    return ::listen(sock, backlog);
60}
61
62
63CBSOCKET_PUBLIC_API
64SOCKET accept(SOCKET sock, struct sockaddr* addr, socklen_t* addrlen) {
65    return ::accept(sock, addr, addrlen);
66}
67
68CBSOCKET_PUBLIC_API
69int connect(SOCKET sock, const struct sockaddr* name, size_t namelen) {
70#ifdef WIN32
71    return ::connect(sock, name, gsl::narrow<int>(namelen));
72#else
73    return ::connect(sock, name, gsl::narrow<socklen_t>(namelen));
74#endif
75}
76
77CBSOCKET_PUBLIC_API
78SOCKET socket(int domain, int type, int protocol) {
79    return ::socket(domain, type, protocol);
80}
81
82CBSOCKET_PUBLIC_API
83int shutdown(SOCKET sock, int how) {
84    return ::shutdown(sock, how);
85}
86
87CBSOCKET_PUBLIC_API
88ssize_t send(SOCKET sock, const void* buffer, size_t length, int flags) {
89#ifdef WIN32
90    return ::send(sock, static_cast<const char*>(buffer), gsl::narrow<int>(length), flags);
91#else
92    return ::send(sock, buffer, length, flags);
93#endif
94}
95
96CBSOCKET_PUBLIC_API
97ssize_t sendmsg(SOCKET sock, const struct msghdr* message, int flags) {
98    return ::sendmsg(sock, message, flags);
99}
100
101CBSOCKET_PUBLIC_API
102ssize_t sendto(SOCKET sock,
103               const void* buffer,
104               size_t length,
105               int flags,
106               const struct sockaddr* dest_addr,
107               socklen_t dest_len) {
108#ifdef WIN32
109    return ::sendto(sock,
110                    static_cast<const char*>(buffer),
111                    int(length),
112                    flags,
113                    dest_addr,
114                    dest_len);
115#else
116    return ::sendto(sock, buffer, length, flags, dest_addr, dest_len);
117#endif
118}
119
120CBSOCKET_PUBLIC_API
121ssize_t recv(SOCKET sock, void* buffer, size_t length, int flags) {
122#ifdef WIN32
123    return ::recv(sock, static_cast<char*>(buffer), gsl::narrow<int>(length), flags);
124#else
125    return ::recv(sock, buffer, length, flags);
126#endif
127}
128
129CBSOCKET_PUBLIC_API
130ssize_t recvfrom(SOCKET sock,
131                 void* buffer,
132                 size_t length,
133                 int flags,
134                 struct sockaddr* address,
135                 socklen_t* address_len) {
136#ifdef WIN32
137    return ::recvfrom(sock,
138                      static_cast<char*>(buffer),
139                      int(length),
140                      flags,
141                      address,
142                      address_len);
143#else
144    return ::recvfrom(sock, buffer, length, flags, address, address_len);
145#endif
146}
147
148CBSOCKET_PUBLIC_API
149ssize_t recvmsg(SOCKET sock, struct msghdr* message, int flags) {
150#ifdef WIN32
151    int res = 0;
152    for (size_t ii = 0; ii < size_t(message->msg_iovlen); ii++) {
153        auto nr = cb::net::recv(sock,
154                                message->msg_iov[ii].iov_base,
155                                message->msg_iov[ii].iov_len,
156                                0);
157        if (nr == -1) {
158            return (res == 0) ? -1 : res;
159        }
160
161        res += nr;
162    }
163
164    return res;
165#else
166    return ::recvmsg(sock, message, flags);
167#endif
168}
169
170CBSOCKET_PUBLIC_API
171int socketpair(int domain, int type, int protocol, SOCKET socket_vector[2]) {
172    return evutil_socketpair(domain,
173                             type,
174                             protocol,
175                             reinterpret_cast<evutil_socket_t*>(socket_vector));
176}
177
178CBSOCKET_PUBLIC_API
179int getsockopt(SOCKET sock,
180               int level,
181               int option_name,
182               void* option_value,
183               socklen_t* option_len) {
184#ifdef WIN32
185    return ::getsockopt(sock,
186                        level,
187                        option_name,
188                        reinterpret_cast<char*>(option_value),
189                        option_len);
190#else
191    return ::getsockopt(sock, level, option_name, option_value, option_len);
192#endif
193}
194
195CBSOCKET_PUBLIC_API
196int setsockopt(SOCKET sock,
197               int level,
198               int option_name,
199               const void* option_value,
200               socklen_t option_len) {
201#ifdef WIN32
202    return ::setsockopt(sock,
203                        level,
204                        option_name,
205                        reinterpret_cast<const char*>(option_value),
206                        option_len);
207#else
208    return ::setsockopt(sock, level, option_name, option_value, option_len);
209#endif
210}
211
212CBSOCKET_PUBLIC_API
213int set_socket_noblocking(SOCKET sock) {
214    return evutil_make_socket_nonblocking(sock);
215}
216
217} // namespace net
218} // namespace cb
219