48
Connection::setup_mc_send(unsigned int mc_ip, int mc_port,
49
unsigned int my_ip, int my_port,
50
bool non_blocking, unsigned char mc_ttl, bool mc_loopback, Continuation * c)
48
Connection::setup_mc_send(
49
sockaddr const* mc_addr,
50
sockaddr const* my_addr,
51
bool non_blocking, unsigned char mc_ttl, bool mc_loopback, Continuation * c
53
54
ink_assert(fd == NO_FD);
55
56
int enable_reuseaddr = 1;
57
if ((res = socketManager.mc_socket(AF_INET, SOCK_DGRAM, 0, non_blocking)) < 0)
58
if ((res = socketManager.mc_socket(my_addr->sa_family, SOCK_DGRAM, 0, non_blocking)) < 0)
66
struct sockaddr_in bind_sa;
67
memset(&bind_sa, 0, sizeof(bind_sa));
68
bind_sa.sin_family = AF_INET;
69
bind_sa.sin_port = htons(my_port);
70
bind_sa.sin_addr.s_addr = my_ip;
71
if ((res = socketManager.ink_bind(fd, (struct sockaddr *) &bind_sa, sizeof(bind_sa), IPPROTO_UDP)) < 0) {
67
if ((res = socketManager.ink_bind(fd, my_addr, ats_ip_size(my_addr), IPPROTO_UDP)) < 0) {
75
sa.ss_family = AF_INET;
76
((struct sockaddr_in *)(&sa))->sin_port = htons(mc_port);
77
((struct sockaddr_in *)(&sa))->sin_addr.s_addr = mc_ip;
78
memset(&(((struct sockaddr_in *)(&sa))->sin_zero), 0, 8);
71
ats_ip_copy(&addr, mc_addr);
80
73
#ifdef SET_CLOSE_ON_EXEC
81
74
if ((res = safe_fcntl(fd, F_SETFD, 1)) < 0)
111
Connection::setup_mc_receive(unsigned int mc_ip, int mc_port,
112
bool non_blocking, Connection * sendChan, Continuation * c)
104
Connection::setup_mc_receive(
105
sockaddr const* mc_addr,
106
bool non_blocking, Connection * sendChan, Continuation * c
114
108
ink_assert(fd == NO_FD);
118
112
int enable_reuseaddr = 1;
120
if ((res = socketManager.socket(AF_INET, SOCK_DGRAM, 0)) < 0)
114
if ((res = socketManager.socket(mc_addr->sa_family, SOCK_DGRAM, 0)) < 0)
130
124
if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable_reuseaddr, sizeof(enable_reuseaddr)) < 0))
133
memset(&sa, 0, sizeof(sa));
134
sa.ss_family = AF_INET;
135
((struct sockaddr_in *)(&sa))->sin_addr.s_addr = mc_ip;
136
((struct sockaddr_in *)(&sa))->sin_port = htons(mc_port);
127
ats_ip_copy(&addr, mc_addr);
138
if ((res = socketManager.ink_bind(fd, (struct sockaddr *) &sa, sizeof(sa), IPPROTO_TCP)) < 0)
129
if ((res = socketManager.ink_bind(fd, &addr.sa, ats_ip_size(&addr.sa), IPPROTO_TCP)) < 0)
141
132
if (non_blocking)
142
133
if ((res = safe_nonblocking(fd)) < 0)
145
struct ip_mreq mc_request;
146
// Add ourselves to the MultiCast group
147
mc_request.imr_multiaddr.s_addr = mc_ip;
148
mc_request.imr_interface.s_addr = htonl(INADDR_ANY);
136
if (ats_is_ip4(&addr)) {
137
struct ip_mreq mc_request;
138
// Add ourselves to the MultiCast group
139
mc_request.imr_multiaddr.s_addr = ats_ip4_addr_cast(mc_addr);
140
mc_request.imr_interface.s_addr = INADDR_ANY;
150
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_request, sizeof(mc_request)) < 0))
142
if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_request, sizeof(mc_request)) < 0))
177
170
self::some_method (...) {
178
171
/// allocate resource
179
172
cleaner<self> clean_up(this, &self::cleanup);
180
// modify or check the resource
173
// modify or check the resource
181
174
if (fail) return FAILURE; // cleanup() is called
183
176
clean_up.reset(); // cleanup() not called after this
220
213
ink_assert(fd == NO_FD);
221
214
int enable_reuseaddr = 1; // used for sockopt setting
222
215
int res = 0; // temp result
223
uint32_t local_addr = NetVCOptions::ANY_ADDR == opt.addr_binding
226
uint16_t local_port = NetVCOptions::ANY_PORT == opt.port_binding
229
int sock_type = NetVCOptions::USE_UDP == opt.ip_proto
216
IpEndpoint local_addr;
217
sock_type = NetVCOptions::USE_UDP == opt.ip_proto
233
res = socketManager.socket(AF_INET, sock_type, 0);
222
// Need to do address calculations first, so we can determine the
223
// address family for socket creation.
224
ink_zero(local_addr);
226
if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding ||
227
NetVCOptions::INTF_ADDR == opt.addr_binding
229
// Same for now, transparency for foreign addresses must be handled
230
// *after* the socket is created, and we need to do this calculation
231
// before the socket to get the IP family correct.
232
ink_release_assert(opt.local_ip.isValid());
233
local_addr.assign(opt.local_ip, htons(opt.local_port));
234
family = opt.local_ip.family();
236
// No local address specified, so use family option if possible.
237
family = ats_is_ip(opt.ip_family) ? opt.ip_family : AF_INET;
238
local_addr.setToAnyAddr(family);
239
local_addr.port() = htons(opt.local_port);
242
res = socketManager.socket(family, sock_type, 0);
234
243
if (-1 == res) return -errno;
240
249
// Try setting the various socket options, if requested.
242
251
if (-1 == safe_setsockopt(fd,
245
reinterpret_cast<char *>(&enable_reuseaddr),
246
sizeof(enable_reuseaddr)))
254
reinterpret_cast<char *>(&enable_reuseaddr),
255
sizeof(enable_reuseaddr)))
258
if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding) {
259
static char const * const DEBUG_TEXT = "::open setsockopt() IP_TRANSPARENT";
262
if (-1 == safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT,
263
reinterpret_cast<char*>(&value), sizeof(value)
265
Debug("socket", "%s - fail %d:%s", DEBUG_TEXT, errno, strerror(errno));
268
Debug("socket", "%s set", DEBUG_TEXT);
271
Debug("socket", "%s - requested but TPROXY not configured", DEBUG_TEXT);
249
275
if (!opt.f_blocking_connect && -1 == safe_nonblocking(fd))
254
280
// Round down until success
255
281
int rbufsz = ROUNDUP(opt.socket_recv_bufsize, 1024);
256
282
while (rbufsz && !socketManager.set_rcvbuf_size(fd, rbufsz))
258
284
Debug("socket", "::open: recv_bufsize = %d of %d\n", rbufsz, opt.socket_recv_bufsize);
263
289
// Round down until success
264
290
int sbufsz = ROUNDUP(opt.socket_send_bufsize, 1024);
265
291
while (sbufsz && !socketManager.set_sndbuf_size(fd, sbufsz))
267
293
Debug("socket", "::open: send_bufsize = %d of %d\n", sbufsz, opt.socket_send_bufsize);
271
if (SOCK_STREAM == sock_type) {
272
if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_NO_DELAY) {
273
safe_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, ON, sizeof(int));
274
Debug("socket", "::open: setsockopt() TCP_NODELAY on socket");
276
if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_KEEP_ALIVE) {
277
safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, ON, sizeof(int));
278
Debug("socket", "::open: setsockopt() SO_KEEPALIVE on socket");
282
if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding && local_addr) {
283
static char const * const DEBUG_TEXT = "::open setsockopt() IP_TRANSPARENT";
286
if (-1 == safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT,
287
reinterpret_cast<char*>(&value), sizeof(value)
289
Debug("socket", "%s - fail %d:%s", DEBUG_TEXT, errno, strerror(errno));
292
Debug("socket", "%s set", DEBUG_TEXT);
295
Debug("socket", "%s - requested but TPROXY not configured", DEBUG_TEXT);
299
// Local address/port.
300
struct sockaddr_in bind_sa;
301
memset(&bind_sa, 0, sizeof(bind_sa));
302
bind_sa.sin_family = AF_INET;
303
bind_sa.sin_port = htons(local_port);
304
bind_sa.sin_addr.s_addr = local_addr;
305
if (-1 == socketManager.ink_bind(fd,
306
reinterpret_cast<struct sockaddr *>(&bind_sa),
297
// apply dynamic options
300
if (-1 == socketManager.ink_bind(fd, &local_addr.sa, ats_ip_size(&local_addr.sa)))
316
Connection::connect(uint32_t addr, uint16_t port, NetVCOptions const& opt) {
309
Connection::connect(sockaddr const* target, NetVCOptions const& opt) {
317
310
ink_assert(fd != NO_FD);
318
311
ink_assert(is_bound);
319
312
ink_assert(!is_connected);
323
this->setRemote(addr, port);
316
this->setRemote(target);
325
318
cleaner<Connection> cleanup(this, &Connection::_cleanup); // mark for close until we succeed.
328
reinterpret_cast<struct sockaddr *>(&sa),
329
sizeof(struct sockaddr_in));
320
res = ::connect(fd, target, ats_ip_size(target));
330
322
// It's only really an error if either the connect was blocking
331
323
// or it wasn't blocking and the error was other than EINPROGRESS.
332
324
// (Is EWOULDBLOCK ok? Does that start the connect?)
334
326
// and IO blocking differ, by turning it on or off as needed.
336
328
&& (opt.f_blocking_connect
337
|| ! (EINPROGRESS == errno || EWOULDBLOCK == errno))) {
329
|| ! (EINPROGRESS == errno || EWOULDBLOCK == errno))) {
339
331
} else if (opt.f_blocking_connect && !opt.f_blocking) {
340
332
if (-1 == safe_nonblocking(fd)) return -errno;
349
Connection::apply_options(NetVCOptions const& opt)
351
// Set options which can be changed after a connection is established
352
// ignore other changes
353
if (SOCK_STREAM == sock_type) {
354
if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_NO_DELAY) {
355
safe_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, SOCKOPT_ON, sizeof(int));
356
Debug("socket", "::open: setsockopt() TCP_NODELAY on socket");
358
if (opt.sockopt_flags & NetVCOptions::SOCK_OPT_KEEP_ALIVE) {
359
safe_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, SOCKOPT_ON, sizeof(int));
360
Debug("socket", "::open: setsockopt() SO_KEEPALIVE on socket");
365
uint32_t mark = opt.packet_mark;
366
safe_setsockopt(fd, SOL_SOCKET, SO_MARK, reinterpret_cast<char *>(&mark), sizeof(uint32_t));
370
uint32_t tos = opt.packet_tos;
371
safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));