コード例 #1
0
int tport_stream_init_primary(tport_primary_t *pri,
			      su_socket_t socket,
			      tp_name_t tpn[1],
			      su_addrinfo_t *ai,
			      tagi_t const *tags,
			      char const **return_culprit)
{
  pri->pri_primary->tp_socket = socket;

  /* Set IP TOS if set */
  tport_set_tos(socket, ai, pri->pri_params->tpp_tos);

#if defined(__linux__)
  /* Linux does not allow reusing TCP port while this one is open,
     so we can safely call su_setreuseaddr() before bind(). */
  su_setreuseaddr(socket, 1);
#endif

  if (tport_bind_socket(socket, ai, return_culprit) == -1)
    return -1;

  if (listen(socket, pri->pri_params->tpp_qsize) == SOCKET_ERROR)
    return *return_culprit = "listen", -1;

#if !defined(__linux__)
  /* Allow reusing TCP sockets
   *
   * On Solaris & BSD, call setreuseaddr() after bind in order to avoid
   * binding to a port owned by an existing server.
   */
  su_setreuseaddr(socket, 1);
#endif

  pri->pri_primary->tp_events = SU_WAIT_ACCEPT;
  pri->pri_primary->tp_conn_orient = 1;

  return 0;
}
コード例 #2
0
int tport_udp_init_primary(tport_primary_t *pri,
			   tp_name_t tpn[1],
			   su_addrinfo_t *ai,
			   tagi_t const *tags,
			   char const **return_culprit)
{
  unsigned rmem = 0, wmem = 0;
  int events = SU_WAIT_IN;
  int s;
#if HAVE_IP_ADD_MEMBERSHIP
  su_sockaddr_t *su = (su_sockaddr_t *)ai->ai_addr;
#endif
  int const one = 1; (void)one;

  s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  if (s == INVALID_SOCKET)
    return *return_culprit = "socket", -1;

  pri->pri_primary->tp_socket = s;

  if (tport_bind_socket(s, ai, return_culprit) < 0)
    return -1;

  tport_set_tos(s, ai, pri->pri_params->tpp_tos);

#if HAVE_IP_ADD_MEMBERSHIP
  if (ai->ai_family == AF_INET &&
      IN_MULTICAST(ntohl(su->su_sin.sin_addr.s_addr))) {
    /* Try to join to the multicast group */
    /* Bind to the SIP address like
       <sip:88.77.66.55:5060;maddr=224.0.1.75;transport=udp> */
    struct ip_mreq imr[1];
    struct in_addr iface;

    memset(imr, 0, sizeof imr);

    imr->imr_multiaddr = su->su_sin.sin_addr;

    if (host_is_ip4_address(tpn->tpn_canon) &&
	su_inet_pton(AF_INET, tpn->tpn_canon, &iface) > 0) {
      imr->imr_interface = iface;
    }

    if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, imr, (sizeof imr)) < 0) {
      SU_DEBUG_3(("setsockopt(%s): %s\n",
		  "IP_ADD_MEMBERSHIP", su_strerror(su_errno())));
    }
#if HAVE_IP_MULTICAST_LOOP
    else
      if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof one) < 0) {
	SU_DEBUG_3(("setsockopt(%s): %s\n",
		    "IP_MULTICAST_LOOP", su_strerror(su_errno())));
    }
#endif
  }
#endif

#if HAVE_IP_MTU_DISCOVER
  {
    /* Turn off DF flag on Linux */
    int dont = IP_PMTUDISC_DONT;
    if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, &dont, sizeof(dont)) < 0) {
	SU_DEBUG_3(("setsockopt(%s): %s\n",
		    "IP_MTU_DISCOVER", su_strerror(su_errno())));
    }
  }
#endif

#if HAVE_IP_RECVERR
  if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
    if (setsockopt(s, IPPROTO_IP, IP_RECVERR, &one, sizeof(one)) < 0) {
      if (ai->ai_family == AF_INET)
	SU_DEBUG_3(("setsockopt(%s): %s\n",
		    "IPVRECVERR", su_strerror(su_errno())));
    }
    events |= SU_WAIT_ERR;
  }
#endif
#if HAVE_IPV6_RECVERR
  if (ai->ai_family == AF_INET6) {
    if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVERR, &one, sizeof(one)) < 0)
      SU_DEBUG_3(("setsockopt(IPV6_RECVERR): %s\n", su_strerror(su_errno())));
    events |= SU_WAIT_ERR;
  }
#endif

  tl_gets(tags,
	  TPTAG_UDP_RMEM_REF(rmem),
	  TPTAG_UDP_WMEM_REF(wmem),
	  TAG_END());

  if (rmem != 0 &&
#if HAVE_SO_RCVBUFFORCE
      setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&rmem, sizeof rmem) < 0 &&
#endif
      setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void *)&rmem, sizeof rmem) < 0) {
    SU_DEBUG_3(("setsockopt(SO_RCVBUF): %s\n",
		su_strerror(su_errno())));
  }

  if (wmem != 0 &&
#if HAVE_SO_SNDBUFFORCE
      setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void *)&wmem, sizeof wmem) < 0 &&
#endif
      setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *)&wmem, sizeof wmem) < 0) {
    SU_DEBUG_3(("setsockopt(SO_SNDBUF): %s\n",
		su_strerror(su_errno())));
  }

  pri->pri_primary->tp_events = events;

  tport_init_compressor(pri->pri_primary, tpn->tpn_comp, tags);

  tport_check_trunc(pri->pri_primary, ai);

#if HAVE_SOFIA_STUN
  tport_stun_server_add_socket(pri->pri_primary);
#endif

  return 0;
}