static void stun_response_handler(int err, uint16_t scode, const char *reason, const struct stun_msg *msg, void *arg) { struct sip_udpconn *uc = arg; struct stun_attr *attr; (void)reason; if (err || scode) { err = err ? err : EPROTO; goto out; } attr = stun_msg_attr(msg, STUN_ATTR_XOR_MAPPED_ADDR); if (!attr) { attr = stun_msg_attr(msg, STUN_ATTR_MAPPED_ADDR); if (!attr) { err = EPROTO; goto out; } } if (!sa_isset(&uc->maddr, SA_ALL)) { uc->maddr = attr->v.sa; } else if (!sa_cmp(&uc->maddr, &attr->v.sa, SA_ALL)) { err = ENOTCONN; goto out; } out: if (err) { udpconn_close(uc, err); mem_deref(uc); } else { tmr_start(&uc->tmr_ka, sip_keepalive_wait(uc->ka_interval), udpconn_keepalive_handler, uc); } }
static void conn_keepalive_handler(void *arg) { struct sip_conn *conn = arg; struct mbuf mb; int err; mb.buf = crlfcrlf; mb.size = sizeof(crlfcrlf); mb.pos = 0; mb.end = 4; err = tcp_send(conn->tc, &mb); if (err) { conn_close(conn, err); mem_deref(conn); return; } tmr_start(&conn->tmr, TCP_KEEPALIVE_TIMEOUT * 1000, conn_tmr_handler, conn); tmr_start(&conn->tmr_ka, sip_keepalive_wait(conn->ka_interval), conn_keepalive_handler, conn); }
int sip_keepalive_tcp(struct sip_keepalive *ka, struct sip_conn *conn, uint32_t interval) { if (!ka || !conn) return EINVAL; if (!conn->tc || !conn->established) return ENOTCONN; list_append(&conn->kal, &ka->le, ka); if (!tmr_isrunning(&conn->tmr_ka)) { interval = MAX(interval ? interval : TCP_KEEPALIVE_INTVAL, TCP_KEEPALIVE_TIMEOUT * 2); conn->ka_interval = interval; tmr_start(&conn->tmr_ka, sip_keepalive_wait(conn->ka_interval), conn_keepalive_handler, conn); } return 0; }