Example #1
0
static void udp_server_input_handler(evutil_socket_t fd, short what, void* arg)
{
	int cycle = 0;

	dtls_listener_relay_server_type* server = (dtls_listener_relay_server_type*)arg;
	ioa_socket_handle s = server->udp_listen_s;

	FUNCSTART;

	if (!(what & EV_READ)) {
		return;
	}

	//printf_server_socket(server, fd);

	ioa_network_buffer_handle *elem = NULL;

	start_udp_cycle:

	elem = (ioa_network_buffer_handle *)ioa_network_buffer_allocate(server->e);

	server->sm.m.sm.nd.nbh = elem;
	server->sm.m.sm.nd.recv_ttl = TTL_IGNORE;
	server->sm.m.sm.nd.recv_tos = TOS_IGNORE;
	server->sm.m.sm.can_resume = 1;

	addr_set_any(&(server->sm.m.sm.nd.src_addr));

	ssize_t bsize = 0;

	int flags = MSG_DONTWAIT;

	bsize = udp_recvfrom(fd, &(server->sm.m.sm.nd.src_addr), &(server->addr),
			(s08bits*)ioa_network_buffer_data(elem), (int)ioa_network_buffer_get_capacity_udp(),
			&(server->sm.m.sm.nd.recv_ttl), &(server->sm.m.sm.nd.recv_tos),
			server->e->cmsg, flags, NULL);

	int conn_reset = is_connreset();
	int to_block = would_block();

	if (bsize < 0) {

		if(to_block) {
			ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh);
			server->sm.m.sm.nd.nbh = NULL;
			FUNCEND;
			return;
		}

	#if defined(MSG_ERRQUEUE)

		//Linux
		int eflags = MSG_ERRQUEUE | MSG_DONTWAIT;
		static s08bits buffer[65535];
		u32bits errcode = 0;
		ioa_addr orig_addr;
		int ttl = 0;
		int tos = 0;
		int slen = server->slen0;
		udp_recvfrom(fd, &orig_addr, &(server->addr), buffer,
					(int) sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags,
					&errcode);
		//try again...
		do {
			bsize = recvfrom(fd, ioa_network_buffer_data(elem), ioa_network_buffer_get_capacity_udp(), flags, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr), (socklen_t*) &slen);
		} while (bsize < 0 && (errno == EINTR));

		conn_reset = is_connreset();
		to_block = would_block();

	#endif

		if(conn_reset) {
			ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh);
			server->sm.m.sm.nd.nbh = NULL;
			reopen_server_socket(server,fd);
			FUNCEND;
			return;
		}
	}

	if(bsize<0) {
		if(!to_block && !conn_reset) {
			int ern=errno;
			perror(__FUNCTION__);
			TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: recvfrom error %d\n",__FUNCTION__,ern);
		}
		ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh);
		server->sm.m.sm.nd.nbh = NULL;
		FUNCEND;
		return;
	}

	if (bsize > 0) {

		int rc = 0;
		ioa_network_buffer_set_size(elem, (size_t)bsize);

		if(server->connect_cb) {

			rc = create_new_connected_udp_socket(server, s);
			if(rc<0) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot handle UDP packet, size %d\n",(int)bsize);
			}

		} else {
			server->sm.m.sm.s = s;
			rc = handle_udp_packet(server, &(server->sm), server->e, server->ts);
		}

		if(rc < 0) {
			if(eve(server->e->verbose)) {
				TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot handle UDP event\n");
			}
		}
	}

	ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh);
	server->sm.m.sm.nd.nbh = NULL;

	if((bsize>0) && (cycle++<MAX_SINGLE_UDP_BATCH))
		goto start_udp_cycle;

	FUNCEND;
}
Example #2
0
void StunClient::processResponse(QByteArray resp, QString peer_addr)
{
    u08bits rbuf[STUN_BUFFER_SIZE];
    size_t rlen = 0;
    stun_buffer buf;
    QString mapped_addr;
    u08bits addr_buff[STUN_BUFFER_SIZE] = {0};

    rlen = resp.length();
    memcpy(rbuf, resp.data(), resp.length());

    buf.len = resp.length();
    memcpy(buf.buf, resp.data(), resp.length());

    if (!stun_is_command_message(&buf)) {
        qDebug()<<resp.length()<<("The response is not a STUN message")<<peer_addr;
        // should be a relayed raw UDP packet to peerA
        emit packetReceived(resp, peer_addr);
        return;
    }

    u16bits stun_method;
    u16bits stun_msg_type;
    stun_method = stun_get_method_str(buf.buf, buf.len);
    stun_msg_type = stun_get_msg_type_str(buf.buf, buf.len);
    qDebug()<<"method:"<<stun_method<<getMethodName(stun_method)<<",msg type:"<<stun_msg_type;

    if (stun_method == STUN_METHOD_BINDING) {
    } else {
        this->debugStunResponse(resp);
    }

    // channel data
    if (stun_is_indication(&buf)) {
        u16bits chan_no;
        size_t blen = 0;

        qDebug()<<"indication data:"<<buf.len;

        stun_attr_ref t_attr = stun_attr_get_first_by_type(&buf, STUN_ATTRIBUTE_DATA);
        const u08bits *t_value = stun_attr_get_value(t_attr);
        blen = stun_attr_get_len(t_attr);
        QString xor_peer_addr = getStunAddress(resp, STUN_ATTRIBUTE_XOR_PEER_ADDRESS);

        qDebug()<<"is chan msg:"<<stun_is_channel_message_str(t_value, &blen, &chan_no, 0);
        qDebug()<<"chan no:"<<chan_no<<blen<<xor_peer_addr;

        emit this->packetReceived(QByteArray((char*)t_value + 4, blen - 4), xor_peer_addr);

        return;
    }

    if (!stun_is_response(&buf)) {
        qDebug()<<resp.length()<<("The response is not a reponse message\n");
        return;
    }

    if (!stun_is_success_response(&buf)) {
        int err_code = 0;
        u08bits err_msg[1025] = "\0";
        size_t err_msg_size = sizeof(err_msg);
        if (stun_is_error_response(&buf, &err_code, err_msg, err_msg_size)) {
            printf("The response is an error %d (%s)\n", err_code, (char*) err_msg);
        } else {
            printf("The response is an unrecognized error\n");
        }

        
        // test unauth
        u08bits realm[128] = {0};
        u08bits nonce[256] = {0};
        
        if (stun_is_challenge_response_str(buf.buf, buf.len, &err_code, err_msg, err_msg_size, realm, nonce)) {
            qDebug()<<err_code;
            qDebug()<<err_code<<(char*)err_msg<<(char*)realm<<(char*)nonce;

            m_realm = QByteArray((char*)realm);
            m_nonce = QByteArray((char*)nonce);

            if (stun_method == STUN_METHOD_ALLOCATE) {
                this->allocate((char*)realm, (char*)nonce);
            }
            if (stun_method == STUN_METHOD_CHANNEL_BIND) {
                QThread::msleep(100);
                this->channelBind(m_peer_addr);
            }
        }

        if (err_code == 437) {
            assert(err_code != 437); // allocate mismatch
        }

        if (err_code == 438) {
            assert(err_code != 438); // stale nonce
        }

        if (err_code == 486) {
            assert(err_code != 486); // allocate quota reached
        }

        return;
    }


    if (stun_is_binding_response(&buf)) {
        ioa_addr reflexive_addr;
        addr_set_any(&reflexive_addr);
        if (stun_attr_get_first_addr(&buf, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &reflexive_addr, NULL) >= 0) {
            stun_attr_ref sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_OTHER_ADDRESS);
            if (sar) {
                // *rfc5780 = 1;
                printf("\n========================================\n");
                // printf("RFC 5780 response %d\n",++counter);
                ioa_addr other_addr;
                stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &other_addr, NULL);
                sar = stun_attr_get_first_by_type_str(buf.buf, buf.len, STUN_ATTRIBUTE_RESPONSE_ORIGIN);
                if (sar) {
                    ioa_addr response_origin;
                    stun_attr_get_addr_str((u08bits *) buf.buf, (size_t) buf.len, sar, &response_origin, NULL);
                    addr_debug_print(1, &response_origin, "Response origin: ");
                }
                addr_debug_print(1, &other_addr, "Other addr: ");
            }
            addr_debug_print(1, &reflexive_addr, "UDP reflexive addr");
            addr_to_string(&reflexive_addr, addr_buff);
        } else {
            printf("Cannot read the response\n");
        }

        // emit got addr
        if (strlen((char*)addr_buff) > 0) {
            mapped_addr = QString((char*)addr_buff);
            emit this->mappedAddressRecieved(mapped_addr);
        }
        return;
    } // end bind resp


    if (stun_method == STUN_METHOD_ALLOCATE) {
        m_relayed_addr = this->getStunAddress(resp, STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS);
        this->saveAllocatePuples(m_realm, m_nonce);
        emit this->allocateDone(m_relayed_addr);

        if (!m_channel_refresh_timer) {
            m_channel_refresh_timer = new QTimer();
            QObject::connect(m_channel_refresh_timer, &QTimer::timeout, this, &StunClient::onRefreshTimeout);
        }
        if (!m_channel_refresh_timer->isActive()) {
            m_channel_refresh_timer->start(m_channel_refresh_timeout);
        }
    }

    if (stun_method == STUN_METHOD_CREATE_PERMISSION) {
        if (!m_permission_keepalive_timer) {
            emit this->createPermissionDone();
        }

        if (!m_permission_keepalive_timer) {
            m_permission_keepalive_timer = new QTimer();
            QObject::connect(m_permission_keepalive_timer, &QTimer::timeout, this, &StunClient::onPermKATimeout);
        }
        if (!m_permission_keepalive_timer->isActive()) {
            m_permission_keepalive_timer->start(m_permission_keepalive_timeout);
        }
    }

    if (stun_method == STUN_METHOD_CHANNEL_BIND) {
        emit this->channelBindDone(m_relayed_addr);
    }

    if (stun_method == STUN_METHOD_REFRESH) {
        qDebug()<<"refresh responsed.";
    }
}