📄 test_s2.c
字号:
if (target == NULL) goto error; rq = sip_request_create(msg_home(msg), method, name, target, NULL); sip_header_insert(msg, sip, (sip_header_t *)rq); } if (!d->local && sip->sip_from) d->local = sip_from_dup(d->home, sip->sip_from); if (!d->contact && sip->sip_contact) d->contact = sip_contact_dup(d->home, sip->sip_contact); if (!d->remote && sip->sip_to) d->remote = sip_to_dup(d->home, sip->sip_to); if (!d->target && sip->sip_request) d->target = sip_contact_create(d->home, (url_string_t *)sip->sip_request->rq_url, NULL); if (!d->call_id && sip->sip_call_id) d->call_id = sip_call_id_dup(d->home, sip->sip_call_id); if (!d->lseq && sip->sip_cseq) d->lseq = sip->sip_cseq->cs_seq; if (!d->local) d->local = sip_from_dup(d->home, s2->local); if (!d->contact) d->contact = sip_contact_dup(d->home, s2->contact); if (!d->remote) d->remote = sip_to_dup(d->home, s2->registration->aor); if (!d->call_id) d->call_id = sip_call_id_create(d->home, NULL); assert(d->local && d->contact); assert(d->remote && d->target); assert(d->call_id); if (tport == NULL) tport = d->tport; if (tport == NULL) tport = s2->registration->tport; if (tport == NULL && d->target->m_url->url_type == url_sips) tport = s2->tls.tport; if (tport == NULL) tport = s2->udp.tport; else if (tport == NULL) tport = s2->tcp.tport; else if (tport == NULL) tport = s2->tls.tport; assert(tport); *tpn = *tport_name(tport); if (tport_is_udp(tport)) { tpn->tpn_host = d->target->m_url->url_host; tpn->tpn_port = url_port(d->target->m_url); if (!tpn->tpn_port || !tpn->tpn_port[0]) tpn->tpn_port = url_port_default(d->target->m_url->url_type); } magic = tport_magic(tport); assert(magic != NULL); sip_cseq_init(cseq); cseq->cs_method = method; cseq->cs_method_name = name; if (d->invite && (method == sip_method_ack || method == sip_method_cancel)) { cseq->cs_seq = sip_object(d->invite)->sip_cseq->cs_seq; } else { cseq->cs_seq = ++d->lseq; } if (d->invite && method == sip_method_cancel) { *via = *sip_object(d->invite)->sip_via; } else { *via = *magic->via; via->v_params = v_params; v_params[0] = su_sprintf(msg_home(msg), "branch=z9hG4bK%lx", ++s2->tid); v_params[1] = NULL; } sip_content_length_init(l); if (sip->sip_payload) l->l_length = sip->sip_payload->pl_len; sip_add_tl(msg, sip, TAG_IF(!sip->sip_from, SIPTAG_FROM(d->local)), TAG_IF(!sip->sip_contact, SIPTAG_CONTACT(d->contact)), TAG_IF(!sip->sip_to, SIPTAG_TO(d->remote)), TAG_IF(!sip->sip_call_id, SIPTAG_CALL_ID(d->call_id)), TAG_IF(!sip->sip_cseq, SIPTAG_CSEQ(cseq)), SIPTAG_VIA(via), TAG_IF(!sip->sip_content_length, SIPTAG_CONTENT_LENGTH(l)), TAG_IF(!sip->sip_separator, SIPTAG_SEPARATOR_STR("\r\n")), TAG_END()); msg_serialize(msg, NULL); if (method == sip_method_invite) { msg_destroy(d->invite); d->invite = msg_ref_create(msg); } tport = tport_tsend(tport, msg, tpn, ta_tags(ta)); ta_end(ta); if (d->tport != tport) { tport_unref(d->tport); d->tport = tport_ref(tport); } return tport ? 0 : -1; error: ta_end(ta); return -1;}/** Save information from response. * * Send ACK for error messages to INVITE. */int s2_update_dialog(struct dialog *d, struct message *m){ int status = 0; if (m->sip->sip_status) status = m->sip->sip_status->st_status; if (100 < status && status < 300) { d->remote = sip_to_dup(d->home, m->sip->sip_to); if (m->sip->sip_contact) d->contact = sip_contact_dup(d->home, m->sip->sip_contact); } if (300 <= status && m->sip->sip_cseq && m->sip->sip_cseq->cs_method == sip_method_invite && d->invite) { msg_t *ack = s2_msg(0); sip_t *sip = sip_object(ack); sip_t *invite = sip_object(d->invite); sip_request_t rq[1]; sip_cseq_t cseq[1]; tp_name_t tpn[1]; *rq = *invite->sip_request; rq->rq_method = sip_method_ack, rq->rq_method_name = "ACK"; *cseq = *invite->sip_cseq; cseq->cs_method = sip_method_ack, cseq->cs_method_name = "ACK"; sip_add_tl(ack, sip, SIPTAG_REQUEST(rq), SIPTAG_VIA(invite->sip_via), SIPTAG_FROM(invite->sip_from), SIPTAG_TO(invite->sip_to), SIPTAG_CALL_ID(invite->sip_call_id), SIPTAG_CSEQ(cseq), SIPTAG_CONTENT_LENGTH_STR("0"), SIPTAG_SEPARATOR_STR("\r\n"), TAG_END()); *tpn = *tport_name(d->tport); if (!tport_is_secondary(d->tport) || !tport_is_clear_to_send(d->tport)) { tpn->tpn_host = rq->rq_url->url_host; tpn->tpn_port = rq->rq_url->url_port; } msg_serialize(ack, NULL); tport_tsend(d->tport, ack, tpn, TAG_END()); } return 0;}/* ---------------------------------------------------------------------- */ints2_save_register(struct message *rm){ sip_contact_t *contact, *m, **m_prev; sip_expires_t const *ex; sip_date_t const *date; sip_time_t now = rm->when.tv_sec, expires; msg_header_free_all(s2->home, (msg_header_t *)s2->registration->aor); msg_header_free_all(s2->home, (msg_header_t *)s2->registration->contact); tport_unref(s2->registration->tport); s2->registration->aor = NULL; s2->registration->contact = NULL; s2->registration->tport = NULL; if (rm == NULL) return 0; assert(rm && rm->sip && rm->sip->sip_request); assert(rm->sip->sip_request->rq_method == sip_method_register); ex = rm->sip->sip_expires; date = rm->sip->sip_date; contact = sip_contact_dup(s2->home, rm->sip->sip_contact); for (m_prev = &contact; *m_prev;) { m = *m_prev; expires = sip_contact_expires(m, ex, date, s2_default_registration_duration, now); if (expires) { char *p = su_sprintf(s2->home, "expires=%lu", (unsigned long)expires); msg_header_add_param(s2->home, m->m_common, p); m_prev = &m->m_next; } else { *m_prev = m->m_next; m->m_next = NULL; msg_header_free(s2->home, (msg_header_t *)m); } } if (contact == NULL) return 0; s2->registration->aor = sip_to_dup(s2->home, rm->sip->sip_to); s2->registration->contact = contact; s2->registration->tport = tport_ref(rm->tport); return 0;}/* ---------------------------------------------------------------------- */static char *s2_generate_tag(su_home_t *home){ s2_tag_generator += 1; return su_sprintf(home, "tag=N2-%s/%u", _s2case, s2_tag_generator);}void s2_case(char const *number, char const *title, char const *desciption){ _s2case = number;}/* ---------------------------------------------------------------------- *//* tport interface */static void s2_stack_recv(struct tester *s2, tport_t *tp, msg_t *msg, tp_magic_t *magic, su_time_t now){ struct message *next = calloc(1, sizeof *next), **prev; next->msg = msg; next->sip = sip_object(msg); next->when = now; next->tport = tport_ref(tp);#if 0 if (next->sip->sip_request) printf("nua sent: %s\n", next->sip->sip_request->rq_method_name); else printf("nua sent: SIP/2.0 %u %s\n", next->sip->sip_status->st_status, next->sip->sip_status->st_phrase);#endif for (prev = &s2->received; *prev; prev = &(*prev)->next) ; next->prev = prev, *prev = next;}static voids2_stack_error(struct tester *s2, tport_t *tp, int errcode, char const *remote){ fprintf(stderr, "%s(%p): error %d (%s) from %s\n", "nua_tester_error", (void *)tp, errcode, su_strerror(errcode), remote ? remote : "<unknown destination>");}static msg_t *s2_stack_alloc(struct tester *s2, int flags, char const data[], usize_t size, tport_t const *tport, tp_client_t *tpc){ return msg_create(s2->mclass, flags | s2->flags);}static msg_t *s2_msg(int flags){ return msg_create(s2->mclass, flags | s2->flags);}tp_stack_class_t const s2_stack[1] = {{ /* tpac_size */ (sizeof s2_stack), /* tpac_recv */ s2_stack_recv, /* tpac_error */ s2_stack_error, /* tpac_alloc */ s2_stack_alloc, }};/** Basic setup for test cases */void s2_setup_base(char const *hostname){ assert(s2 == NULL); su_init(); s2 = su_home_new(sizeof *s2); assert(s2 != NULL); s2->root = su_root_create(s2); assert(s2->root != NULL); su_root_threading(s2->root, 0); /* disable multithreading */ s2->local = sip_from_format(s2->home, "Bob <sip:bob@%s>", hostname ? hostname : "example.net"); if (hostname == NULL) hostname = "127.0.0.1"; s2->hostname = hostname; s2->tid = (unsigned long)time(NULL) * 510633671UL;}SOFIAPUBVAR su_log_t nua_log[];SOFIAPUBVAR su_log_t soa_log[];SOFIAPUBVAR su_log_t nea_log[];SOFIAPUBVAR su_log_t nta_log[];SOFIAPUBVAR su_log_t tport_log[];SOFIAPUBVAR su_log_t su_log_default[];voids2_setup_logs(int level){ assert(s2); su_log_soft_set_level(nua_log, level); su_log_soft_set_level(soa_log, level); su_log_soft_set_level(su_log_default, level); su_log_soft_set_level(nea_log, level); su_log_soft_set_level(nta_log, level); su_log_soft_set_level(tport_log, level);}static char const * default_protocols[] = { "udp", "tcp", NULL };voids2_setup_tport(char const * const *protocols, tag_type_t tag, tag_value_t value, ...){ ta_list ta; tp_name_t tpn[1]; int bound; tport_t *tp; assert(s2 != NULL); ta_start(ta, tag, value); if (s2->master == NULL) { s2->master = tport_tcreate(s2, s2_stack, s2->root, ta_tags(ta)); if (s2->master == NULL) { assert(s2->master); } s2->mclass = sip_default_mclass(); s2->flags = 0; } memset(tpn, 0, (sizeof tpn)); tpn->tpn_proto = "*"; tpn->tpn_host = s2->hostname; tpn->tpn_port = "*"; if (protocols == NULL) protocols = default_protocols; bound = tport_tbind(s2->master, tpn, protocols, TPTAG_SERVER(1), ta_tags(ta)); assert(bound != -1); tp = tport_primaries(s2->master); if (protocols == default_protocols && s2->contact == NULL) { *tpn = *tport_name(tp); s2->contact = sip_contact_format(s2->home, "<sip:%s:%s>", tpn->tpn_host, tpn->tpn_port); } for (;tp; tp = tport_next(tp)) { sip_via_t *v; sip_contact_t *m; tp_magic_t *magic; if (tport_magic(tp)) continue; *tpn = *tport_name(tp); v = sip_via_format(s2->home, "SIP/2.0/%s %s:%s", tpn->tpn_proto, tpn->tpn_host, tpn->tpn_port); assert(v != NULL); if (strncasecmp(tpn->tpn_proto, "tls", 3)) { m = sip_contact_format(s2->home, "<sip:%s:%s;transport=%s>", tpn->tpn_host, tpn->tpn_port, tpn->tpn_proto); if (s2->udp.contact == NULL && strcasecmp(tpn->tpn_proto, "udp") == 0) { s2->udp.tport = tport_ref(tp); s2->udp.contact = m; } if (s2->tcp.contact == NULL && strcasecmp(tpn->tpn_proto, "tcp") == 0) { s2->tcp.tport = tport_ref(tp); s2->tcp.contact = m; } } else if (strcasecmp(tpn->tpn_proto, "tls")) { m = sip_contact_format(s2->home, "<sips:%s:%s;transport=%s>", tpn->tpn_host, tpn->tpn_port, tpn->tpn_proto); } else { m = sip_contact_format(s2->home, "<sips:%s:%s>", tpn->tpn_host, tpn->tpn_port); if (s2->tls.contact == NULL) { s2->tls.tport = tport_ref(tp); s2->tls.contact = m; } } assert(m != NULL); magic = su_zalloc(s2->home, (sizeof *magic)); magic->via = v, magic->contact = m; if (s2->contact == NULL) s2->contact = m; tport_set_magic(tp, magic); }}/* ---------------------------------------------------------------------- *//* S2 DNS server */#include <sofia-resolv/sres_record.h>extern uint16_t _sres_default_port;static int s2_dns_query(struct tester *s2, su_wait_t *w, su_wakeup_arg_t *arg);void s2_setup_dns(void){ int n; su_socket_t socket; su_wait_t *wait; su_sockaddr_t su[1]; socklen_t sulen = sizeof su->su_sin; assert(s2->nua == NULL); assert(s2->root != NULL); memset(su, 0, sulen); su->su_len = sulen; su->su_family = AF_INET; /* su->su_port = htons(1053); */ socket = su_socket(su->su_family, SOCK_DGRAM, 0); n = bind(socket, &su->su_sa, sulen); assert(n == 0); n = getsockname(socket, &su->su_sa, &sulen); assert(n == 0); _sres_default_port = ntohs(su->su_port); wait = s2->dns.wait; n = su_wait_create(wait, socket, SU_WAIT_IN); assert(n == 0); s2->dns.reg = su_root_register(s2->root, wait, s2_dns_query, NULL, 0); assert(s2->dns.reg > 0); s2->dns.socket = socket;}staticstruct s2_dns_response { struct s2_dns_response *next; uint16_t qlen, dlen; struct m_header { /* Header defined in RFC 1035 section 4.1.1 (page 26) */ uint16_t mh_id; /* Query ID */ uint16_t mh_flags; /* Flags */ uint16_t mh_qdcount; /* Question record count */ uint16_t mh_ancount; /* Answer record count */ uint16_t mh_nscount; /* Authority records count */ uint16_t mh_arcount; /* Additional records count */ } header[1]; uint8_t data[1500];} *zonedata;enum { FLAGS_QR = (1 << 15), FLAGS_QUERY = (0 << 11), FLAGS_IQUERY = (1 << 11), FLAGS_STATUS = (2 << 11),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -