📄 test_s2.c
字号:
FLAGS_OPCODE = (15 << 11), /* mask */ FLAGS_AA = (1 << 10), /* */ FLAGS_TC = (1 << 9), FLAGS_RD = (1 << 8), FLAGS_RA = (1 << 7), FLAGS_RCODE = (15 << 0), /* mask of return code */ FLAGS_OK = 0, /* No error condition. */ FLAGS_FORMAT_ERR = 1, /* Server could not interpret query. */ FLAGS_SERVER_ERR = 2, /* Server error. */ FLAGS_NAME_ERR = 3, /* No domain name. */ FLAGS_UNIMPL_ERR = 4, /* Not implemented. */ FLAGS_AUTH_ERR = 5, /* Refused */};uint32_t s2_dns_ttl = 3600;static ints2_dns_query(struct tester *s2, su_wait_t *w, su_wakeup_arg_t *arg){ union { struct m_header header[1]; uint8_t buffer[1500]; } request; ssize_t len; su_socket_t socket; su_sockaddr_t su[1]; socklen_t sulen = sizeof su; uint16_t flags; struct s2_dns_response *r; size_t const hlen = sizeof r->header; (void)arg; socket = s2->dns.socket; len = su_recvfrom(socket, request.buffer, sizeof request.buffer, 0, &su->su_sa, &sulen); flags = ntohs(request.header->mh_flags); if (len < (ssize_t)hlen) return 0; if ((flags & FLAGS_QR) == FLAGS_QR) return 0; if ((flags & FLAGS_RCODE) != FLAGS_OK) return 0; if ((flags & FLAGS_OPCODE) != FLAGS_QUERY || ntohs(request.header->mh_qdcount) != 1) { flags |= FLAGS_QR | FLAGS_UNIMPL_ERR; request.header->mh_flags = htons(flags); su_sendto(socket, request.buffer, len, 0, &su->su_sa, sulen); return 0; } for (r = zonedata; r; r = r->next) { if (memcmp(r->data, request.buffer + hlen, r->qlen) == 0) break; } if (r) { flags |= FLAGS_QR | FLAGS_AA | FLAGS_OK; request.header->mh_flags = htons(flags); request.header->mh_ancount = htons(r->header->mh_ancount); request.header->mh_nscount = htons(r->header->mh_nscount); request.header->mh_arcount = htons(r->header->mh_arcount); memcpy(request.buffer + hlen + r->qlen, r->data + r->qlen, r->dlen - r->qlen); len = hlen + r->dlen; } else { flags |= FLAGS_QR | FLAGS_AA | FLAGS_NAME_ERR; } request.header->mh_flags = htons(flags); su_sendto(socket, request.buffer, len, 0, &su->su_sa, sulen); return 0;}static void put_uint16(struct s2_dns_response *m, uint16_t h){ uint8_t *p = m->data + m->dlen; assert(m->dlen + (sizeof h) < sizeof m->data); p[0] = h >> 8; p[1] = h; m->dlen += (sizeof h);}static void put_uint32(struct s2_dns_response *m, uint32_t w){ uint8_t *p = m->data + m->dlen; assert(m->dlen + (sizeof w) < sizeof m->data); p[0] = w >> 24; p[1] = w >> 16; p[2] = w >> 8; p[3] = w; m->dlen += (sizeof w);}static void put_domain(struct s2_dns_response *m, char const *domain){ char const *label; size_t llen; /* Copy domain into query label at a time */ for (label = domain; label && label[0]; label += llen) { assert(!(label[0] == '.' && label[1] != '\0')); llen = strcspn(label, "."); assert(llen < 64); assert(m->dlen + llen + 1 < sizeof m->data); m->data[m->dlen++] = (uint8_t)llen; if (llen == 0) return; memcpy(m->data + m->dlen, label, llen); m->dlen += (uint16_t)llen; if (label[llen] == '\0') break; if (label[llen + 1]) llen++; } assert(m->dlen < sizeof m->data); m->data[m->dlen++] = '\0';}static void put_string(struct s2_dns_response *m, char const *string){ uint8_t *p = m->data + m->dlen; size_t len = strlen(string); assert(len <= 255); assert(m->dlen + len + 1 < sizeof m->data); *p++ = (uint8_t)len; memcpy(p, string, len); m->dlen += len + 1;}static uint16_t put_len_at(struct s2_dns_response *m){ uint16_t at = m->dlen; assert(m->dlen + sizeof(at) < sizeof m->data); memset(m->data + m->dlen, 0, sizeof(at)); m->dlen += sizeof(at); return at;}static void put_len(struct s2_dns_response *m, uint16_t start){ uint8_t *p = m->data + start; uint16_t len = m->dlen - (start + 2); p[0] = len >> 8; p[1] = len;}static void put_data(struct s2_dns_response *m, void *data, uint16_t len){ assert(m->dlen + len < sizeof m->data); memcpy(m->data + m->dlen, data, len); m->dlen += len;}static void put_query(struct s2_dns_response *m, char const *domain, uint16_t qtype){ assert(m->header->mh_qdcount == 0); put_domain(m, domain), put_uint16(m, qtype), put_uint16(m, sres_class_in); m->header->mh_qdcount++; m->qlen = m->dlen;}static void put_a_record(struct s2_dns_response *m, char const *domain, struct in_addr addr){ uint16_t start; put_domain(m, domain); put_uint16(m, sres_type_a); put_uint16(m, sres_class_in); put_uint32(m, s2_dns_ttl); start = put_len_at(m); put_data(m, &addr, sizeof addr); put_len(m, start);}static void put_srv_record(struct s2_dns_response *m, char const *domain, uint16_t prio, uint16_t weight, uint16_t port, char const *target){ uint16_t start; put_domain(m, domain); put_uint16(m, sres_type_srv); put_uint16(m, sres_class_in); put_uint32(m, s2_dns_ttl); start = put_len_at(m); put_uint16(m, prio); put_uint16(m, weight); put_uint16(m, port); put_domain(m, target); put_len(m, start);}static void put_naptr_record(struct s2_dns_response *m, char const *domain, uint16_t order, uint16_t preference, char const *flags, char const *services, char const *regexp, char const *replace){ uint16_t start; put_domain(m, domain); put_uint16(m, sres_type_naptr); put_uint16(m, sres_class_in); put_uint32(m, s2_dns_ttl); start = put_len_at(m); put_uint16(m, order); put_uint16(m, preference); put_string(m, flags); put_string(m, services); put_string(m, regexp); put_domain(m, replace); put_len(m, start);}static void put_srv_record_from_uri(struct s2_dns_response *m, char const *base, uint16_t prio, uint16_t weight, url_t const *uri, char const *server){ char domain[1024] = "none"; char const *service = url_port(uri); uint16_t port; if (uri->url_type == url_sips) { strcpy(domain, "_sips._tcp."); } else if (uri->url_type == url_sip) { if (url_has_param(uri, "transport=udp")) { strcpy(domain, "_sip._udp."); } else if (url_has_param(uri, "transport=tcp")) { strcpy(domain, "_sip._tcp."); } } assert(strcmp(domain, "none")); strcat(domain, base); if (m->header->mh_qdcount == 0) put_query(m, domain, sres_type_srv); port = (uint16_t)strtoul(service, NULL, 10); put_srv_record(m, domain, prio, weight, port, server);}staticvoid s2_add_to_zone(struct s2_dns_response *_r){ size_t size = offsetof(struct s2_dns_response, data[_r->dlen]); struct s2_dns_response *r = malloc(size); assert(r); memcpy(r, _r, size); r->next = zonedata; zonedata = r;}static void make_server(char *server, char const *prefix, char const *domain){ strcpy(server, prefix); if (strlen(server) == 0 || server[strlen(server) - 1] != '.') { strcat(server, "."); strcat(server, domain); }}/** Set up DNS domain */void s2_dns_domain(char const *domain, int use_naptr, /* char *prefix, int priority, url_t const *uri, */ ...){ struct s2_dns_response m[1]; char server[1024], target[1024]; va_list va0, va; char const *prefix; int priority; url_t const *uri; struct in_addr localhost; assert(s2->dns.reg != 0); su_inet_pton(AF_INET, "127.0.0.1", &localhost); va_start(va0, use_naptr); if (use_naptr) { memset(m, 0, sizeof m); put_query(m, domain, sres_type_naptr); va_copy(va, va0); for (;(prefix = va_arg(va, char *));) { char *services = NULL; priority = va_arg(va, int); uri = va_arg(va, url_t *); assert(uri); if (uri->url_type == url_sips) { services = "SIPS+D2T"; strcpy(target, "_sips._tcp."); } else if (uri->url_type == url_sip) { if (url_has_param(uri, "transport=udp")) { services = "SIP+D2U"; strcpy(target, "_sip._udp."); } else if (url_has_param(uri, "transport=tcp")) { services = "SIP+D2T"; strcpy(target, "_sip._tcp."); } } strcat(target, domain); assert(services); put_naptr_record(m, domain, 1, priority, "s", services, "", target); m->header->mh_ancount++; } va_end(va); va_copy(va, va0); for (;(prefix = va_arg(va, char *));) { priority = va_arg(va, int); uri = va_arg(va, url_t *); assert(uri); make_server(server, prefix, domain); put_srv_record_from_uri(m, domain, priority, 10, uri, server); m->header->mh_arcount++; put_a_record(m, server, localhost); m->header->mh_arcount++; } va_end(va); s2_add_to_zone(m); } /* Add SRV records */ va_copy(va, va0); for (;(prefix = va_arg(va, char *));) { priority = va_arg(va, int); uri = va_arg(va, url_t *); assert(uri); make_server(server, prefix, domain); memset(m, 0, sizeof m); put_srv_record_from_uri(m, domain, priority, 10, uri, server); m->header->mh_ancount++; strcpy(server, prefix); strcat(server, domain); put_a_record(m, server, localhost); m->header->mh_arcount++; s2_add_to_zone(m); } va_end(va); /* Add A records */ va_copy(va, va0); for (;(prefix = va_arg(va, char *));) { (void)va_arg(va, int); (void)va_arg(va, url_t *); memset(m, 0, sizeof m); make_server(server, prefix, domain); put_query(m, server, sres_type_a); put_a_record(m, server, localhost); m->header->mh_ancount++; s2_add_to_zone(m); } va_end(va); va_end(va0);}voids2_teardown(void){ s2 = NULL; su_deinit();}/* ====================================================================== */#include <sofia-sip/sresolv.h>nua_t *s2_nua_setup(tag_type_t tag, tag_value_t value, ...){ ta_list ta; s2_setup_base(NULL); s2_setup_dns(); s2_setup_logs(0); s2_setup_tport(NULL, TPTAG_LOG(0), TAG_END()); assert(s2->contact); s2_dns_domain("example.org", 1, "s2", 1, s2->udp.contact->m_url, "s2", 1, s2->tcp.contact->m_url, NULL); ta_start(ta, tag, value); s2->nua = nua_create(s2->root, s2_nua_callback, s2, SIPTAG_FROM_STR("Alice <sip:alice@example.org>"), /* NUTAG_PROXY((url_string_t *)s2->contact->m_url), */ /* Use internal DNS server */ NUTAG_PROXY("sip:example.org"),#if HAVE_WIN32 SRESTAG_RESOLV_CONF("NUL"),#else SRESTAG_RESOLV_CONF("/dev/null"),#endif ta_tags(ta)); ta_end(ta); return s2->nua;}void s2_nua_teardown(void){ nua_destroy(s2->nua); s2->nua = NULL; s2_teardown();}/* ====================================================================== *//** Register NUA user. * * <pre> * A B * |-----REGISTER---->| * |<-----200 OK------| * | | * </pre> */void s2_register_setup(void){ nua_handle_t *nh; struct message *m; assert(s2 && s2->nua); assert(!s2->registration->nh); nh = nua_handle(s2->nua, NULL, TAG_END()); nua_register(nh, TAG_END()); m = s2_wait_for_request(SIP_METHOD_REGISTER); assert(m); s2_save_register(m); s2_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); s2_free_message(m); assert(s2->registration->contact != NULL); s2_check_event(nua_r_register, 200); s2->registration->nh = nh;}/** Un-register NUA user. * * <pre> * A B * |-----REGISTER---->| * |<-----200 OK------| * | | * </pre> */void s2_register_teardown(void){ if (s2 && s2->registration->nh) { nua_handle_t *nh = s2->registration->nh; struct message *m; nua_unregister(nh, TAG_END()); m = s2_wait_for_request(SIP_METHOD_REGISTER); assert(m); s2_save_register(m); s2_respond_to(m, NULL, SIP_200_OK, SIPTAG_CONTACT(s2->registration->contact), TAG_END()); assert(s2->registration->contact == NULL); s2_free_message(m); s2_check_event(nua_r_unregister, 200); nua_handle_destroy(nh); s2->registration->nh = NULL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -