3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "src/core/lib/iomgr/port.h"
21 // This test won't work except with posix sockets enabled
22 #ifdef GRPC_POSIX_SOCKET_UTILS_COMMON
25 #include <netinet/in.h>
26 #include <netinet/ip.h>
29 #include <grpc/support/alloc.h>
30 #include <grpc/support/log.h>
31 #include <grpc/support/sync.h>
33 #include "src/core/lib/gpr/useful.h"
34 #include "src/core/lib/iomgr/socket_mutator.h"
35 #include "src/core/lib/iomgr/socket_utils_posix.h"
36 #include "test/core/util/test_config.h"
38 struct test_socket_mutator {
39 grpc_socket_mutator base;
43 static bool mutate_fd(int fd, grpc_socket_mutator* mutator) {
45 socklen_t intlen = sizeof(newval);
46 struct test_socket_mutator* m =
47 reinterpret_cast<struct test_socket_mutator*>(mutator);
49 if (0 != setsockopt(fd, IPPROTO_IP, IP_TOS, &m->option_value,
50 sizeof(m->option_value))) {
53 if (0 != getsockopt(fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
56 if (newval != m->option_value) {
62 static bool mutate_fd_2(const grpc_mutate_socket_info* info,
63 grpc_socket_mutator* mutator) {
65 socklen_t intlen = sizeof(newval);
66 struct test_socket_mutator* m =
67 reinterpret_cast<struct test_socket_mutator*>(mutator);
69 if (0 != setsockopt(info->fd, IPPROTO_IP, IP_TOS, &m->option_value,
70 sizeof(m->option_value))) {
73 if (0 != getsockopt(info->fd, IPPROTO_IP, IP_TOS, &newval, &intlen)) {
76 if (newval != m->option_value) {
82 static void destroy_test_mutator(grpc_socket_mutator* mutator) {
83 struct test_socket_mutator* m =
84 reinterpret_cast<struct test_socket_mutator*>(mutator);
88 static int compare_test_mutator(grpc_socket_mutator* a,
89 grpc_socket_mutator* b) {
90 struct test_socket_mutator* ma =
91 reinterpret_cast<struct test_socket_mutator*>(a);
92 struct test_socket_mutator* mb =
93 reinterpret_cast<struct test_socket_mutator*>(b);
94 return GPR_ICMP(ma->option_value, mb->option_value);
97 static const grpc_socket_mutator_vtable mutator_vtable = {
98 mutate_fd, compare_test_mutator, destroy_test_mutator, nullptr};
100 static const grpc_socket_mutator_vtable mutator_vtable2 = {
101 nullptr, compare_test_mutator, destroy_test_mutator, mutate_fd_2};
103 static void test_with_vtable(const grpc_socket_mutator_vtable* vtable) {
104 int sock = socket(PF_INET, SOCK_STREAM, 0);
105 GPR_ASSERT(sock > 0);
107 struct test_socket_mutator mutator;
108 grpc_socket_mutator_init(&mutator.base, vtable);
110 mutator.option_value = IPTOS_LOWDELAY;
111 GPR_ASSERT(GRPC_LOG_IF_ERROR(
112 "set_socket_with_mutator",
113 grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
114 (grpc_socket_mutator*)&mutator)));
116 mutator.option_value = IPTOS_THROUGHPUT;
117 GPR_ASSERT(GRPC_LOG_IF_ERROR(
118 "set_socket_with_mutator",
119 grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
120 (grpc_socket_mutator*)&mutator)));
122 mutator.option_value = IPTOS_RELIABILITY;
123 GPR_ASSERT(GRPC_LOG_IF_ERROR(
124 "set_socket_with_mutator",
125 grpc_set_socket_with_mutator(sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
126 (grpc_socket_mutator*)&mutator)));
128 mutator.option_value = -1;
129 auto err = grpc_set_socket_with_mutator(
130 sock, GRPC_FD_CLIENT_CONNECTION_USAGE,
131 reinterpret_cast<grpc_socket_mutator*>(&mutator));
132 GPR_ASSERT(err != GRPC_ERROR_NONE);
133 GRPC_ERROR_UNREF(err);
136 int main(int argc, char** argv) {
138 grpc::testing::TestEnvironment env(argc, argv);
140 sock = socket(PF_INET, SOCK_STREAM, 0);
141 GPR_ASSERT(sock > 0);
143 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
144 grpc_set_socket_nonblocking(sock, 1)));
145 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_nonblocking",
146 grpc_set_socket_nonblocking(sock, 0)));
147 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
148 grpc_set_socket_cloexec(sock, 1)));
149 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_cloexec",
150 grpc_set_socket_cloexec(sock, 0)));
151 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
152 grpc_set_socket_reuse_addr(sock, 1)));
153 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_reuse_addr",
154 grpc_set_socket_reuse_addr(sock, 0)));
155 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
156 grpc_set_socket_low_latency(sock, 1)));
157 GPR_ASSERT(GRPC_LOG_IF_ERROR("set_socket_low_latency",
158 grpc_set_socket_low_latency(sock, 0)));
160 test_with_vtable(&mutator_vtable);
161 test_with_vtable(&mutator_vtable2);
168 #else /* GRPC_POSIX_SOCKET_UTILS_COMMON */
170 int main(int argc, char** argv) { return 1; }
172 #endif /* GRPC_POSIX_SOCKET_UTILS_COMMON */