/**@internal Set refresh in range min..max seconds in the future. */ void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, unsigned min, unsigned max) { su_duration_t max_defer = nua_dialog_usage_get_max_defer(du); unsigned delta; int make_deferrable = 0; if (max <= min) { max = min; delta = min * 1000; } else if (max_defer > 0 && (int)(max - min) >= max_defer / 1000) { delta = su_randint(min * 1000, max * 1000 - (max_defer + 999)); make_deferrable = 1; } else delta = su_randint(min * 1000, max * 1000); SU_DEBUG_7(("nua(): refresh %s in %.3f seconds (in [%u..%u]%s)\n", nua_dialog_usage_name(du), 1e-3 * delta, min, max, make_deferrable? ", deferrable" : "")); delta += delta == 0; nua_dialog_usage_set_refresh_timer(du, delta, make_deferrable); }
/**@internal Set refresh in range min..max seconds in the future. */ void nua_dialog_usage_set_refresh_range(nua_dialog_usage_t *du, unsigned min, unsigned max) { sip_time_t now = sip_now(), target; unsigned delta; if (max < min) max = min; if (min != max) delta = su_randint(min, max); else delta = min; if (now + delta >= now) target = now + delta; else target = SIP_TIME_MAX; SU_DEBUG_7(("nua(): refresh %s after %lu seconds (in [%u..%u])\n", nua_dialog_usage_name(du), target - now, min, max)); du->du_refquested = now; du->du_refresh = target; }
/** Receive datagram. * * @retval -1 error * @retval 0 end-of-stream * @retval 1 normal receive (should never happen) * @retval 2 incomplete recv, call me again (should never happen) * @retval 3 STUN keepalive, ignore */ int tport_recv_dgram(tport_t *self) { msg_t *msg; ssize_t n, veclen, N; su_addrinfo_t *ai; su_sockaddr_t *from; socklen_t fromlen; msg_iovec_t iovec[msg_n_fragments] = {{ 0 }}; uint8_t sample[1]; /* Simulate packet loss */ if (self->tp_params->tpp_drop && (unsigned)su_randint(0, 1000) < self->tp_params->tpp_drop) { su_recv(self->tp_socket, sample, 1, 0); SU_DEBUG_3(("tport(%p): simulated packet loss!\n", (void *)self)); return 0; } assert(self->tp_msg == NULL); #if nomore /* We used to resize the buffer, but it fragments the memory */ N = 65535; #else N = (ssize_t)su_getmsgsize(self->tp_socket); if (N == -1) { int err = su_errno(); SU_DEBUG_1(("%s(%p): su_getmsgsize(): %s (%d)\n", __func__, (void *)self, su_strerror(err), err)); return -1; } if (N == 0) { su_recv(self->tp_socket, sample, 1, 0); SU_DEBUG_3(("tport(%p): zero length packet", (void *)self)); return 0; } #endif veclen = tport_recv_iovec(self, &self->tp_msg, iovec, N, 1); if (veclen == -1) return -1; msg = self->tp_msg; ai = msg_addrinfo(msg); from = (su_sockaddr_t *)ai->ai_addr, fromlen = (socklen_t)(ai->ai_addrlen); n = su_vrecv(self->tp_socket, iovec, veclen, 0, from, &fromlen); ai->ai_addrlen = fromlen; if (n == SOCKET_ERROR) { int error = su_errno(); msg_destroy(msg); self->tp_msg = NULL; su_seterrno(error); if (su_is_blocking(error)) return 0; else return -1; } else if (n <= 1) { SU_DEBUG_1(("%s(%p): runt of "MOD_ZD" bytes\n", "tport_recv_dgram", (void *)self, n)); msg_destroy(msg), self->tp_msg = NULL; return 0; } tport_recv_bytes(self, n, n); SU_CANONIZE_SOCKADDR(from); if (self->tp_master->mr_dump_file) tport_dump_iovec(self, msg, n, iovec, veclen, "recv", "from"); *sample = *((uint8_t *)iovec[0].mv_base); /* Commit received data into buffer. This may relocate iovec contents */ msg_recv_commit(msg, n, 1); if ((sample[0] & 0xf8) == 0xf8) /* SigComp */ return tport_recv_comp_dgram(self, self->tp_comp, &self->tp_msg, from, fromlen); #if HAVE_SOFIA_STUN else if (sample[0] == 0 || sample[0] == 1) /* STUN request or response */ return tport_recv_stun_dgram(self, &self->tp_msg, from, fromlen); #endif else return 0; }