~ubuntu-branches/ubuntu/wily/trafficserver/wily

« back to all changes in this revision

Viewing changes to iocore/net/UnixConnection.cc

  • Committer: Package Import Robot
  • Author(s): Adam Conrad
  • Date: 2012-12-17 22:28:16 UTC
  • mfrom: (5.1.8 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20121217222816-7xwjsx5k76zkb63d
Tags: 3.2.0-1ubuntu1
* Revert FreeBSD strerror_r() fixes that give errors with glibc 2.16.
* Apply patch from Konstantinos Margaritis to define barriers on ARM.

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
// Functions
46
46
//
47
47
int
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)
51
 
{
 
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
 
52
) {
52
53
  (void) c;
53
54
  ink_assert(fd == NO_FD);
54
55
  int res = 0;
55
56
  int enable_reuseaddr = 1;
56
57
 
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)
58
59
    goto Lerror;
59
60
 
60
61
  fd = res;
63
64
    goto Lerror;
64
65
  }
65
66
 
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) {
72
68
    goto Lerror;
73
69
  }
74
70
 
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);
79
72
 
80
73
#ifdef SET_CLOSE_ON_EXEC
81
74
  if ((res = safe_fcntl(fd, F_SETFD, 1)) < 0)
108
101
 
109
102
 
110
103
int
111
 
Connection::setup_mc_receive(unsigned int mc_ip, int mc_port,
112
 
                             bool non_blocking, Connection * sendChan, Continuation * c)
113
 
{
 
104
Connection::setup_mc_receive(
 
105
  sockaddr const* mc_addr,
 
106
  bool non_blocking, Connection * sendChan, Continuation * c
 
107
) {
114
108
  ink_assert(fd == NO_FD);
115
109
  (void) sendChan;
116
110
  (void) c;
117
111
  int res = 0;
118
112
  int enable_reuseaddr = 1;
119
113
 
120
 
  if ((res = socketManager.socket(AF_INET, SOCK_DGRAM, 0)) < 0)
 
114
  if ((res = socketManager.socket(mc_addr->sa_family, SOCK_DGRAM, 0)) < 0)
121
115
    goto Lerror;
122
116
 
123
117
  fd = res;
130
124
  if ((res = safe_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &enable_reuseaddr, sizeof(enable_reuseaddr)) < 0))
131
125
    goto Lerror;
132
126
 
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);
137
128
 
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)
139
130
    goto Lerror;
140
131
 
141
132
  if (non_blocking)
142
133
    if ((res = safe_nonblocking(fd)) < 0)
143
134
      goto Lerror;
144
135
 
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;
149
141
 
150
 
  if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_request, sizeof(mc_request)) < 0))
151
 
    goto Lerror;
 
142
    if ((res = safe_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mc_request, sizeof(mc_request)) < 0))
 
143
      goto Lerror;
 
144
  }
152
145
  return 0;
153
146
 
154
147
Lerror:
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
182
175
        /// success!
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
224
 
    ? INADDR_ANY
225
 
    : opt.local_addr;
226
 
  uint16_t local_port = NetVCOptions::ANY_PORT == opt.port_binding
227
 
    ? 0
228
 
    : opt.local_port;
229
 
  int sock_type = NetVCOptions::USE_UDP == opt.ip_proto
 
216
  IpEndpoint local_addr;
 
217
  sock_type = NetVCOptions::USE_UDP == opt.ip_proto
230
218
    ? SOCK_DGRAM
231
219
    : SOCK_STREAM;
232
 
 
233
 
  res = socketManager.socket(AF_INET, sock_type, 0);
 
220
  int family;
 
221
 
 
222
  // Need to do address calculations first, so we can determine the
 
223
  // address family for socket creation.
 
224
  ink_zero(local_addr);
 
225
 
 
226
  if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding ||
 
227
    NetVCOptions::INTF_ADDR == opt.addr_binding
 
228
  ) {
 
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();
 
235
  } else {
 
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);
 
240
  }
 
241
 
 
242
  res = socketManager.socket(family, sock_type, 0);
234
243
  if (-1 == res) return -errno;
235
244
 
236
245
  fd = res;
240
249
  // Try setting the various socket options, if requested.
241
250
 
242
251
  if (-1 == safe_setsockopt(fd,
243
 
                            SOL_SOCKET,
244
 
                            SO_REUSEADDR,
245
 
                            reinterpret_cast<char *>(&enable_reuseaddr),
246
 
                            sizeof(enable_reuseaddr)))
 
252
                            SOL_SOCKET,
 
253
                            SO_REUSEADDR,
 
254
                            reinterpret_cast<char *>(&enable_reuseaddr),
 
255
                            sizeof(enable_reuseaddr)))
247
256
    return -errno;
248
257
 
 
258
  if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding) {
 
259
    static char const * const DEBUG_TEXT = "::open setsockopt() IP_TRANSPARENT";
 
260
#if TS_USE_TPROXY
 
261
    int value = 1;
 
262
    if (-1 == safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT,
 
263
                              reinterpret_cast<char*>(&value), sizeof(value)
 
264
                              )) {
 
265
      Debug("socket", "%s - fail %d:%s", DEBUG_TEXT, errno, strerror(errno));
 
266
      return -errno;
 
267
    } else {
 
268
      Debug("socket", "%s set", DEBUG_TEXT);
 
269
    }
 
270
#else
 
271
    Debug("socket", "%s - requested but TPROXY not configured", DEBUG_TEXT);
 
272
#endif
 
273
  }
 
274
 
249
275
  if (!opt.f_blocking_connect && -1 == safe_nonblocking(fd))
250
276
    return -errno;
251
277
 
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))
257
 
        rbufsz -= 1024;
 
283
        rbufsz -= 1024;
258
284
      Debug("socket", "::open: recv_bufsize = %d of %d\n", rbufsz, opt.socket_recv_bufsize);
259
285
    }
260
286
  }
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))
266
 
        sbufsz -= 1024;
 
292
        sbufsz -= 1024;
267
293
      Debug("socket", "::open: send_bufsize = %d of %d\n", sbufsz, opt.socket_send_bufsize);
268
294
    }
269
295
  }
270
296
 
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");
275
 
    }
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");
279
 
    }
280
 
  }
281
 
 
282
 
  if (NetVCOptions::FOREIGN_ADDR == opt.addr_binding && local_addr) {
283
 
    static char const * const DEBUG_TEXT = "::open setsockopt() IP_TRANSPARENT";
284
 
#if TS_USE_TPROXY
285
 
    int value = 1;
286
 
    if (-1 == safe_setsockopt(fd, SOL_IP, TS_IP_TRANSPARENT,
287
 
                              reinterpret_cast<char*>(&value), sizeof(value)
288
 
                              )) {
289
 
      Debug("socket", "%s - fail %d:%s", DEBUG_TEXT, errno, strerror(errno));
290
 
      return -errno;
291
 
    } else {
292
 
      Debug("socket", "%s set", DEBUG_TEXT);
293
 
    }
294
 
#else
295
 
    Debug("socket", "%s - requested but TPROXY not configured", DEBUG_TEXT);
296
 
#endif
297
 
  }
298
 
 
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),
307
 
                                   sizeof(bind_sa)))
 
297
  // apply dynamic options
 
298
  apply_options(opt);
 
299
 
 
300
  if (-1 == socketManager.ink_bind(fd, &local_addr.sa, ats_ip_size(&local_addr.sa)))
308
301
    return -errno;
309
302
 
310
303
  cleanup.reset();
313
306
}
314
307
 
315
308
int
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);
320
313
 
321
314
  int res;
322
315
 
323
 
  this->setRemote(addr, port);
 
316
  this->setRemote(target);
324
317
 
325
318
  cleaner<Connection> cleanup(this, &Connection::_cleanup); // mark for close until we succeed.
326
319
 
327
 
  res = ::connect(fd,
328
 
                  reinterpret_cast<struct sockaddr *>(&sa),
329
 
                  sizeof(struct sockaddr_in));
 
320
  res = ::connect(fd, target, ats_ip_size(target));
 
321
 
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.
335
327
  if (-1 == res 
336
328
      && (opt.f_blocking_connect
337
 
          || ! (EINPROGRESS == errno || EWOULDBLOCK == errno))) {
 
329
          || ! (EINPROGRESS == errno || EWOULDBLOCK == errno))) {
338
330
    return -errno;
339
331
  } else if (opt.f_blocking_connect && !opt.f_blocking) {
340
332
    if (-1 == safe_nonblocking(fd)) return -errno;
352
344
{
353
345
  this->close();
354
346
}
 
347
 
 
348
void
 
349
Connection::apply_options(NetVCOptions const& opt)
 
350
{
 
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");
 
357
    }
 
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");
 
361
    }
 
362
  }
 
363
 
 
364
#if TS_HAS_SO_MARK
 
365
  uint32_t mark = opt.packet_mark;
 
366
  safe_setsockopt(fd, SOL_SOCKET, SO_MARK, reinterpret_cast<char *>(&mark), sizeof(uint32_t));
 
367
#endif
 
368
 
 
369
#if TS_HAS_IP_TOS
 
370
  uint32_t tos = opt.packet_tos;
 
371
  safe_setsockopt(fd, IPPROTO_IP, IP_TOS, reinterpret_cast<char *>(&tos), sizeof(uint32_t));
 
372
#endif
 
373
 
 
374
}