📄 tport.c
字号:
/* Register receiving function with events specified above */ if ((index = su_root_register(mr->mr_root, wait, wakeup, self, 0)) == -1) TPORT_CONNECT_ERROR(su_errno(), su_root_register); /* */ if (tport_setname(self, tpn->tpn_proto, (void *)ai->ai_addr, tpn->tpn_canon) == -1) TPORT_CONNECT_ERROR(su_errno(), tport_setname); self->tp_socket = s; self->tp_index = index; self->tp_events = events; self->tp_connected = ai->ai_socktype != SOCK_DGRAM; self->tp_conn_orient = 1;#if HAVE_SIGCOMP if (tpn->tpn_comp == pri->pri_primary->tp_name->tpn_comp) self->tp_name->tpn_comp = pri->pri_primary->tp_name->tpn_comp; if (!pri->pri_primary->tp_name->tpn_comp) self->tp_sigcomp->sc_infmt = format_is_noncomp;#endif#if HAVE_TLS if (pri->pri_primary->tp_tls) { self->tp_tls = tls_init_client(pri->pri_primary->tp_tls, s); if (!self->tp_tls) TPORT_CONNECT_ERROR(errno, tls_init_client); }#endif memcpy(self->tp_addr, ai->ai_addr, self->tp_addrlen = ai->ai_addrlen); SU_DEBUG_5(("%s(%p): %s " TPN_FORMAT "\n", __func__, self, "connecting to", TPN_ARGS(self->tp_name))); tprb_append(&pri->pri_secondary, self); return self;}/** Destroy a secondary transport. @internal */static void tport_zap_secondary(tport_t *self){ tport_master_t *mr; if (self == NULL) return; /* Remove from rbtree */ tprb_remove(&self->tp_pri->pri_secondary, self); if (self->tp_msg) { msg_destroy(self->tp_msg), self->tp_msg = NULL; SU_DEBUG_3(("%s(%p): zapped partially received message\n", __func__, self)); } if (self->tp_queue && self->tp_queue[self->tp_qhead]) { size_t n = 0, i, N = self->tp_params->tpp_qsize; for (i = self->tp_qhead; self->tp_queue[i]; i = (i + 1) % N) { msg_destroy(self->tp_queue[i]), self->tp_queue[i] = NULL; n++; } SU_DEBUG_3(("%s(%p): zapped %lu queued messages\n", __func__, self, (LU)n)); } if (self->tp_pused) { SU_DEBUG_3(("%s(%p): zapped with pending requests\n", __func__, self)); } mr = self->tp_master; if (self->tp_index) su_root_deregister(mr->mr_root, self->tp_index); self->tp_index = 0; if (self->tp_socket != -1) su_close(self->tp_socket); self->tp_socket = -1;#if HAVE_TLS if (self->tp_tls) tls_free(self->tp_tls);#endif#if HAVE_SIGCOMP if (self->tp_sigcomp) { tport_sigcomp_t *sc = self->tp_sigcomp; if (sc->sc_udvm) sigcomp_udvm_free(sc->sc_udvm), sc->sc_udvm = NULL; if (sc->sc_compressor) sigcomp_compressor_free(sc->sc_compressor), sc->sc_compressor = NULL; }#endif su_home_zap(self->tp_home);}/** Create a new transport reference. */tport_t *tport_incref(tport_t *tp){ if (tp) { if (tp->tp_refs >= 0) tp->tp_refs++; else if (tp->tp_refs == -1) tp->tp_refs = 1; } return tp;}/** Destroy a transport reference. */void tport_decref(tport_t **ttp){ assert(ttp); if (*ttp) { if ((*ttp)->tp_refs > 0) if (--(*ttp)->tp_refs == 0 && (*ttp)->tp_params->tpp_idle == 0) if (!tport_is_closed(*ttp)) tport_close(*ttp); *ttp = NULL; }}/** Get transport parameters. * * @param self pointer to a transport object * @param tag,value,... list of tags */int tport_get_params(tport_t const *self, tag_type_t tag, tag_value_t value, ...){ ta_list ta; int n; tport_params_t const *tpp; if (self == NULL) return su_seterrno(EINVAL); tpp = self->tp_params; ta_start(ta, tag, value); n = tl_tgets(ta_args(ta), TPTAG_MTU(tpp->tpp_mtu), TPTAG_REUSE(self->tp_reusable), TPTAG_CONNECT(tpp->tpp_conn_orient), TPTAG_QUEUESIZE(tpp->tpp_qsize), TPTAG_IDLE(tpp->tpp_idle), TPTAG_TIMEOUT(tpp->tpp_timeout), TPTAG_SDWN_ERROR(tpp->tpp_sdwn_error), TPTAG_DEBUG_DROP(tpp->tpp_drop), TPTAG_THRPSIZE(tpp->tpp_thrpsize), TPTAG_THRPRQSIZE(tpp->tpp_thrprqsize), TAG_END()); ta_end(ta); return n;}/** Set transport parameters. * * @param self pointer to a transport object * @param tag,value,... list of tags */int tport_set_params(tport_t *self, tag_type_t tag, tag_value_t value, ...){ ta_list ta; int n; tport_params_t tpp[1], *tpp0; int connect, sdwn_error, reusable; struct sigcomp_compartment *cc = NONE; if (self == NULL) return su_seterrno(EINVAL); memcpy(tpp, tpp0 = self->tp_params, sizeof *tpp); connect = tpp->tpp_conn_orient; sdwn_error = tpp->tpp_sdwn_error; reusable = self->tp_reusable; ta_start(ta, tag, value); n = tl_gets(ta_args(ta), TPTAG_MTU_REF(tpp->tpp_mtu), TAG_IF(!self->tp_queue, TPTAG_QUEUESIZE_REF(tpp->tpp_qsize)), TPTAG_IDLE_REF(tpp->tpp_idle), TPTAG_TIMEOUT_REF(tpp->tpp_timeout), TPTAG_DEBUG_DROP_REF(tpp->tpp_drop), TPTAG_THRPSIZE_REF(tpp->tpp_thrpsize), TPTAG_THRPRQSIZE_REF(tpp->tpp_thrprqsize), TPTAG_SIGCOMP_LIFETIME_REF(tpp->tpp_sigcomp_lifetime), TPTAG_CONNECT_REF(connect), TPTAG_SDWN_ERROR_REF(sdwn_error), TPTAG_REUSE_REF(reusable), TPTAG_COMPARTMENT_REF(cc), TAG_END()); ta_end(ta); if (n == 0) return 0; if (tpp->tpp_idle > 0 && tpp->tpp_idle < 2000) tpp->tpp_idle = 2000; if (tpp->tpp_timeout < 1000) tpp->tpp_timeout = 1000; if (tpp->tpp_drop > 1000) tpp->tpp_drop = 1000; if (tpp->tpp_thrprqsize > 0) tpp->tpp_thrprqsize = tpp0->tpp_thrprqsize; if (tpp->tpp_sigcomp_lifetime != 0 && tpp->tpp_sigcomp_lifetime < 30) tpp->tpp_sigcomp_lifetime = 30; if (tpp->tpp_qsize >= 1000) tpp->tpp_qsize = 1000; tpp->tpp_sdwn_error = sdwn_error; self->tp_reusable = reusable; /* Currently only primary UDP transport can *not* be connection oriented */ tpp->tpp_conn_orient = connect || !tport_is_primary(self) || !tport_is_dgram(self); if (tport_is_secondary(self) && self->tp_params == self->tp_pri->pri_primary->tp_params) { tpp0 = su_zalloc(self->tp_home, sizeof *tpp0); if (!tpp0) return -1; }#if HAVE_SIGCOMP if (cc != NONE && self == self->tp_master->mr_master) { if (self->tp_master->mr_compartment) sigcomp_compartment_unref(self->tp_master->mr_compartment); self->tp_master->mr_compartment = sigcomp_compartment_ref(cc); }#endif memcpy(tpp0, tpp, sizeof *tpp); return n;}/** Bind transport objects. * * @deprecated * Use tport_tbind(). */int tport_bind(tport_t *self, tp_name_t const *tpn, char const * const transports[], int flags){ return tport_tbind(self, tpn, transports, TAG_END());}/** Bind transport objects. * * @param self pointer to a transport object * @param tpn desired transport address * @param transports list of protocol names supported by stack * @param tag,value,... tagged argument list */int tport_tbind(tport_t *self, tp_name_t const *tpn, char const * const transports[], tag_type_t tag, tag_value_t value, ...){ ta_list ta; int server = 1, retval; tp_name_t mytpn[1]; tport_master_t *mr; if (self == NULL || tport_is_secondary(self) || tpn == NULL || transports == NULL) { su_seterrno(EINVAL); return -1; } *mytpn = *tpn; if (mytpn->tpn_ident == NULL) mytpn->tpn_ident = self->tp_ident; ta_start(ta, tag, value); tl_gets(ta_args(ta), TPTAG_SERVER_REF(server), TPTAG_IDENT_REF(mytpn->tpn_ident), TAG_END()); mr = self->tp_master; assert(mr); if (server) retval = tport_bind_server(mr, mytpn, transports, ta_args(ta)); else retval = tport_bind_client(mr, mytpn, transports, ta_args(ta)); ta_end(ta); return retval;}/** Bind primary transport objects used by a client-only application. * @internal */int tport_bind_client(tport_master_t *mr, tp_name_t const *tpn, char const * const transports[], tagi_t *tags){ int i; tport_primary_t *pri = NULL, **tbf; tport_t *tp; SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, mr, TPN_ARGS(tpn))); for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next) ; for (i = 0; transports[i]; i++) { su_addrinfo_t hints[1]; char const *proto = transports[i]; if (strcmp(proto, tpn->tpn_proto) != 0 && strcmp(tpn->tpn_proto, tpn_any) != 0) continue; /* Resolve protocol, skip unknown transport protocols */ if (getprotohints(hints, proto, AI_PASSIVE) < 0) continue; if (!(pri = tport_alloc_primary(mr))) break; tp = pri->pri_primary; #if HAVE_TLS if (strcasecmp(proto, "tls") == 0) { tp->tp_tls = tport_init_tls(tags); if (tp->tp_tls == NULL) break; }#endif pri->pri_family = hints->ai_family; pri->pri_socktype = hints->ai_socktype; pri->pri_protocol = hints->ai_protocol; tp->tp_name->tpn_proto = proto; tp->tp_name->tpn_host = "*"; tp->tp_name->tpn_port = "*"; tp->tp_name->tpn_canon = "*"; tp->tp_name->tpn_ident = su_strdup(tp->tp_home, tpn->tpn_ident); tport_init_compression(pri, tpn->tpn_comp, tags); } if (!pri) tport_zap_primary(*tbf); return pri ? 0 : -1;}/** Bind primary transport objects used by a server application. */int tport_bind_server(tport_master_t *mr, tp_name_t const *tpn, char const * const transports[], tagi_t *tags){ char hostname[256]; char const *proto, *canon = NULL, *host, *port; char port0[16]; int ephemeral_port; int i, error = 0, not_supported, family = 0; tport_primary_t *pri = NULL, **tbf; su_localinfo_t *li = NULL; unsigned p; unsigned short step = 0; struct tport_nat_s *nat;#if SU_HAVE_IN6 if (!mr->mr_boundserver) { /* Check if we can bind to IPv6 separately */ su_sockaddr_t su[1], su4[1]; socklen_t sulen, su4len; int s6, s4; s4 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); s6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); memset(su, 0, sizeof *su); su->su_len = sulen = (sizeof su->su_sin6); su->su_family = AF_INET6; memset(su4, 0, sizeof *su4); su4->su_len = su4len = (sizeof su->su_sin); su4->su_family = AF_INET; if (bind(s6, &su->su_sa, sulen) < 0) ; else if (getsockname(s6, &su->su_sa, &sulen) < 0) ; else if ((su4->su_port = su->su_port) != 0 && bind(s4, &su4->su_sa, su4len) == 0) mr->mr_bindv6only = 1; su_close(s6), su_close(s4); mr->mr_boundserver = 1; }#endif for (tbf = &mr->mr_primaries; *tbf; tbf = &(*tbf)->pri_next) ; SU_DEBUG_5(("%s(%p) to " TPN_FORMAT "\n", __func__, mr, TPN_ARGS(tpn))); nat = tport_nat_initialize_nat_traversal(mr, tpn, &transports, tags); if (!nat) SU_DEBUG_1(("%s: %s\n", __func__, strerror(errno))); if (tpn->tpn_host == NULL || strcmp(tpn->tpn_host, tpn_any) == 0) { /* Use a local IP address */ host = NULL; }#ifdef SU_HAVE_IN6 else if (tpn->tpn_host && tpn->tpn_host[0] == '[') { /* Remove [] around IPv6 addresses. */ host = strcpy(hostname, tpn->tpn_host + 1); hostname[strlen(hostname) - 1] = '\0'; }#endif else host = tpn->tpn_host; if (tpn->tpn_port != NULL && strlen(tpn->tpn_port) > 0 && strcmp(tpn->tpn_port, tpn_any) != 0) port = tpn->tpn_port, ephemeral_port = 0; else port = "", ephemeral_port = -1; /* XXX */ if (host && (strcmp(host, "0.0.0.0") == 0 || strcmp(host, "0") == 0)) host = NULL, family = AF_INET;#if SU_HAVE_IN6 else if (host && strcmp(host, "::") == 0) host = NULL, family = AF_INET6;#endif if (tpn->tpn_canon && strcmp(tpn->tpn_canon, tpn_any) && (host || tpn->tpn_canon != tpn->tpn_host)) canon = tpn->tpn_canon; else if (nat) { /* NULL if UPnP not present */ canon = tport_nat_get_external_ip_address(nat); } if (host == NULL) { su_localinfo_t hints[1] = {{ 0 }}; hints->li_flags = 0; hints->li_family = family; hints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE | LI_SCOPE_HOST; error = su_getlocalinfo(hints, &li); if (error) {#if SU_HAVE_IN6 SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", __func__, mr, family == AF_INET6 ? "ip6" : family == AF_INET ? "ip4" : "ip", su_gli_strerror(error)));#else SU_DEBUG_3(("%s(%p): su_getlocalinfo() for %s address: %s\n", __func__, mr, family == AF_INET ? "ip4" : "ip", su_gli_strerror(error)));#endif su_seterrno(ENOENT); return -1; } } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -