static gpointer stun_thread_func (const gpointer user_data) { StunAgent oldagent; StunAgent newagent; int sock = GPOINTER_TO_INT (user_data); int exit_code = -1; g_mutex_lock (stun_thread_mutex_ptr); g_cond_signal (stun_thread_signal_ptr); g_mutex_unlock (stun_thread_mutex_ptr); stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); while (!exit_stun_thread) { g_debug ("Ready to process next datagram"); dgram_process (sock, &oldagent, &newagent); } exit_code = close (sock); g_thread_exit (GINT_TO_POINTER (exit_code)); return NULL; }
static gpointer stun_thread_func (const gpointer user_data) { StunAgent oldagent; StunAgent newagent; int sock; int exit_code = -1; sock = listen_socket (IPPORT_STUN); if (sock == -1) { g_assert_not_reached (); } stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); while (!exit_stun_thread) { g_debug ("Ready to process next datagram"); dgram_process (sock, &oldagent, &newagent); } exit_code = close (sock); g_thread_exit (GINT_TO_POINTER (exit_code)); return NULL; }
static int run (int family, int protocol, unsigned port) { StunAgent oldagent; StunAgent newagent; int sock = listen_socket (family, SOCK_DGRAM, protocol, port); if (sock == -1) return -1; stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); for (;;) dgram_process (sock, &oldagent, &newagent); }
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) { struct sockaddr_storage addr; uint8_t buf[STUN_MAX_MESSAGE_SIZE]; char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))]; struct iovec iov = { buf, sizeof (buf) }; StunMessage request; StunMessage response; StunValidationStatus validation; StunAgent *agent = NULL; struct msghdr mh = { .msg_name = (struct sockaddr *)&addr, .msg_namelen = sizeof (addr), .msg_iov = &iov, .msg_iovlen = 1, .msg_control = ctlbuf, .msg_controllen = sizeof (ctlbuf) }; size_t len = recv_safe (sock, &mh); if (len == (size_t)-1) return -1; validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0); if (validation == STUN_VALIDATION_SUCCESS) { agent = newagent; } else { validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0); agent = oldagent; } /* Unknown attributes */ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) { stun_agent_build_unknown_attributes_error (agent, &response, buf, sizeof (buf), &request); goto send_buf; } /* Mal-formatted packets */ if (validation != STUN_VALIDATION_SUCCESS || stun_message_get_class (&request) != STUN_REQUEST) { return -1; } switch (stun_message_get_method (&request)) { case STUN_BINDING: stun_agent_init_response (agent, &response, buf, sizeof (buf), &request); if (stun_message_has_cookie (&request)) stun_message_append_xor_addr (&response, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); else stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS, mh.msg_name, mh.msg_namelen); break; default: stun_agent_init_error (agent, &response, buf, sizeof (buf), &request, STUN_ERROR_BAD_REQUEST); } iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0); send_buf: len = send_safe (sock, &mh); return (len < iov.iov_len) ? -1 : 0; } static int run (int family, int protocol, unsigned port) { StunAgent oldagent; StunAgent newagent; int sock = listen_socket (family, SOCK_DGRAM, protocol, port); if (sock == -1) return -1; stun_agent_init (&oldagent, known_attributes, STUN_COMPATIBILITY_RFC3489, 0); stun_agent_init (&newagent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT); for (;;) dgram_process (sock, &oldagent, &newagent); }