diff --git a/examples/pico/CMakeLists.txt b/examples/pico/CMakeLists.txt index cbf80a1..3f265fa 100644 --- a/examples/pico/CMakeLists.txt +++ b/examples/pico/CMakeLists.txt @@ -95,7 +95,7 @@ target_compile_definitions(peer PRIVATE CONFIG_USE_USRSCTP=0 CONFIG_MBEDTLS_2_X=1 CONFIG_DATA_BUFFER_SIZE=512 - CONFIG_AUDIO_BUFFER_SIZE=2048 + CONFIG_AUDIO_BUFFER_SIZE=4096 CONFIG_HTTP_BUFFER_SIZE=1024 CONFIG_SDP_BUFFER_SIZE=4096 HTTP_DO_NOT_USE_CUSTOM_CONFIG diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7721f87..14f89d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ project(lib) -file(GLOB SRCS "*.c") +file(GLOB SRCS "stun.c" "rtp.c" "peer_connection.c" "agent.c" "dtls_srtp.c" "*.c") file(GLOB HEADERS "peer.h" "peer_connection.h" "peer_signaling.h") diff --git a/src/agent.c b/src/agent.c index 0e50ab8..7c55b55 100644 --- a/src/agent.c +++ b/src/agent.c @@ -13,7 +13,7 @@ #include "utils.h" #define AGENT_POLL_TIMEOUT 1 -#define AGENT_CONNCHECK_MAX 1000 +#define AGENT_CONNCHECK_MAX 500 #define AGENT_CONNCHECK_PERIOD 100 #define AGENT_STUN_RECV_MAXTIMES 1000 @@ -61,9 +61,10 @@ static int agent_socket_recv(Agent* agent, Address* addr, uint8_t* buf, int len) int maxfd = -1; fd_set rfds; struct timeval tv; - int addr_type[] = { AF_INET, + int addr_type[] = { + AF_INET, #if CONFIG_IPV6 - AF_INET6, + AF_INET6, #endif }; @@ -124,9 +125,10 @@ static int agent_create_host_addr(Agent* agent) { int i, j; const char* iface_prefx[] = {CONFIG_IFACE_PREFIX}; IceCandidate* ice_candidate; - int addr_type[] = { AF_INET, + int addr_type[] = { + AF_INET, #if CONFIG_IPV6 - AF_INET6, + AF_INET6, #endif }; @@ -228,9 +230,51 @@ static int agent_create_turn_addr(Agent* agent, Address* serv_addr, const char* } stun_parse_msg_buf(&recv_msg); + memcpy(&turn_addr, &recv_msg.relayed_addr, sizeof(Address)); IceCandidate* ice_candidate = agent->local_candidates + agent->local_candidates_count++; ice_candidate_create(ice_candidate, agent->local_candidates_count, ICE_CANDIDATE_TYPE_RELAY, &turn_addr); + + memcpy(&ice_candidate->raddr, &recv_msg.mapped_addr, sizeof(Address)); + memcpy(&ice_candidate->serv_addr, serv_addr, sizeof(Address)); + strcpy(ice_candidate->realm, recv_msg.realm); + strcpy(ice_candidate->nonce, recv_msg.nonce); + + ice_candidate->username = username; + ice_candidate->credential = credential; + return ret; +} + +static int agent_refresh_turn(Agent* agent, IceCandidatePair* pair) { + int ret = -1; + StunMessage send_msg; + StunMessage recv_msg; + memset(&recv_msg, 0, sizeof(recv_msg)); + memset(&send_msg, 0, sizeof(send_msg)); + stun_msg_create(&send_msg, STUN_METHOD_REFRESH); + stun_msg_write_attr(&send_msg, STUN_ATTR_TYPE_USERNAME, strlen(pair->local->username), (char*)pair->local->username); + stun_msg_write_attr(&send_msg, STUN_ATTR_TYPE_REALM, strlen(pair->local->realm), (char*)pair->local->realm); + stun_msg_write_attr(&send_msg, STUN_ATTR_TYPE_NONCE, strlen(pair->local->nonce), (char*)pair->local->nonce); + stun_msg_finish(&send_msg, STUN_CREDENTIAL_LONG_TERM, pair->local->credential, strlen(pair->local->credential)); + + ret = agent_socket_send(agent, &pair->local->serv_addr, send_msg.buf, send_msg.size); + if (ret < 0) { + LOGE("Failed to send TURN Refresh Request."); + return -1; + } + + ret = agent_socket_recv_attempts(agent, NULL, recv_msg.buf, sizeof(recv_msg.buf), AGENT_STUN_RECV_MAXTIMES); + if (ret <= 0) { + LOGD("Failed to receive TURN Refresh Response."); + return ret; + } + + stun_parse_msg_buf(&recv_msg); + if (recv_msg.error_code == 438) { + strcpy(pair->local->nonce, recv_msg.nonce); + return 0; + } + return ret; } @@ -299,10 +343,22 @@ void agent_get_local_description(Agent* agent, char* description, int length) { } int agent_send(Agent* agent, const uint8_t* buf, int len) { + if (agent->nominated_pair->local->type == ICE_CANDIDATE_TYPE_RELAY) { + char* channel_data_buf = malloc(len + 4); + + *(uint16_t*)channel_data_buf = htons(agent->nominated_pair->channel_number); + *(uint16_t*)(channel_data_buf + 2) = htons(len); + memcpy(channel_data_buf + 4, buf, len); + int sent_size = agent_socket_send(agent, &agent->nominated_pair->local->serv_addr, (const uint8_t*)channel_data_buf, len + 4); + LOGD("Sent data to TURN server: %d", sent_size); + free(channel_data_buf); + return sent_size - 4; + } + return agent_socket_send(agent, &agent->nominated_pair->remote->addr, buf, len); } -static void agent_create_binding_response(Agent* agent, StunMessage* msg, Address* addr) { +void agent_create_binding_response(Agent* agent, StunMessage* msg, Address* addr) { int size = 0; char username[584]; char mapped_address[32]; @@ -320,7 +376,7 @@ static void agent_create_binding_response(Agent* agent, StunMessage* msg, Addres stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->local_upwd, strlen(agent->local_upwd)); } -static void agent_create_binding_request(Agent* agent, StunMessage* msg) { +void agent_create_binding_request(Agent* agent, StunMessage* msg) { uint64_t tie_breaker = 0; // always be controlled // send binding request stun_msg_create(msg, STUN_CLASS_REQUEST | STUN_METHOD_BINDING); @@ -338,6 +394,24 @@ static void agent_create_binding_request(Agent* agent, StunMessage* msg) { stun_msg_finish(msg, STUN_CREDENTIAL_SHORT_TERM, agent->remote_upwd, strlen(agent->remote_upwd)); } +void agent_create_channel_bind_request(Agent* agent, StunMessage* msg, IceCandidatePair* pair) { + int size = 0; + char mapped_address[32]; + uint8_t mask[16]; + stun_msg_create(msg, STUN_CLASS_REQUEST | STUN_METHOD_CHANNEL_BIND); + char channel_number_buf[4]; + memset(channel_number_buf, 0, sizeof(channel_number_buf)); + *(uint16_t*)channel_number_buf = htons(pair->channel_number); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_CHANNEL_NUMBER, 4, channel_number_buf); + *((uint32_t*)mask) = htonl(MAGIC_COOKIE); + size = stun_set_mapped_address(mapped_address, mask, &(pair->remote->addr)); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_XOR_PEER_ADDRESS, size, mapped_address); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_USERNAME, strlen(pair->local->username), (char*)pair->local->username); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_REALM, strlen(pair->local->realm), (char*)pair->local->realm); + stun_msg_write_attr(msg, STUN_ATTR_TYPE_NONCE, strlen(pair->local->nonce), (char*)pair->local->nonce); + stun_msg_finish(msg, STUN_CREDENTIAL_LONG_TERM, pair->local->credential, strlen(pair->local->credential)); +} + void agent_process_stun_request(Agent* agent, StunMessage* stun_msg, Address* addr) { StunMessage msg; StunHeader* header; @@ -347,7 +421,7 @@ void agent_process_stun_request(Agent* agent, StunMessage* stun_msg, Address* ad header = (StunHeader*)stun_msg->buf; memcpy(agent->transaction_id, header->transaction_id, sizeof(header->transaction_id)); agent_create_binding_response(agent, &msg, addr); - agent_socket_send(agent, addr, msg.buf, msg.size); + agent_send(agent, msg.buf, msg.size); agent->binding_request_time = ports_get_epoch_time(); } break; @@ -364,6 +438,7 @@ void agent_process_stun_response(Agent* agent, StunMessage* stun_msg) { } break; default: + LOGD("Unknown STUN method: %d", stun_msg->stunmethod); break; } } @@ -372,7 +447,20 @@ int agent_recv(Agent* agent, uint8_t* buf, int len) { int ret = -1; StunMessage stun_msg; Address addr; - if ((ret = agent_socket_recv(agent, &addr, buf, len)) > 0 && stun_probe(buf, len) == 0) { + + ret = agent_socket_recv(agent, &addr, buf, len); + + if (agent->nominated_pair->local->type == ICE_CANDIDATE_TYPE_RELAY) { + if (ret > 0) { + if (*(uint16_t*)buf == htons(agent->nominated_pair->channel_number)) { + memcpy(buf, buf + 4, ret - 4); + ret -= 4; + } + } else + return 0; + } + + if (ret > 0 && stun_probe(buf, len) == 0) { memcpy(stun_msg.buf, buf, ret); stun_msg.size = ret; stun_parse_msg_buf(&stun_msg); @@ -388,11 +476,38 @@ int agent_recv(Agent* agent, uint8_t* buf, int len) { default: break; } - ret = 0; + return agent_recv(agent, buf, len); } return ret; } +void agent_create_relay_channel(Agent* agent, IceCandidatePair* pair, int wait_response) { + char addr_string[ADDRSTRLEN]; + + addr_to_string(&pair->local->serv_addr, addr_string, sizeof(addr_string)); + LOGD("create channel bind request relay server addr: %s, port: %d", addr_string, pair->local->serv_addr.port); + addr_to_string(&pair->local->addr, addr_string, sizeof(addr_string)); + LOGD("to remote ip: %s, port: %d", addr_string, pair->remote->addr.port); + + StunMessage msg; + memset(&msg, 0, sizeof(msg)); + agent_create_channel_bind_request(agent, &msg, pair); + + agent_socket_send(agent, &pair->local->serv_addr, msg.buf, msg.size); + if (wait_response) { + StunMessage recv_msg; + int ret = agent_socket_recv_attempts(agent, NULL, recv_msg.buf, sizeof(recv_msg.buf), AGENT_STUN_RECV_MAXTIMES); + + if (ret > 0) { + stun_parse_msg_buf(&recv_msg); + } + + if (ret <= 0 || recv_msg.stunclass != STUN_CLASS_RESPONSE) { + LOGW("Failed to receive TURN Channel Binding Response."); + } + } +} + void agent_set_remote_description(Agent* agent, char* description) { /* a=ice-ufrag:Iexb @@ -402,7 +517,6 @@ void agent_set_remote_description(Agent* agent, char* description) { int i, j; LOGD("Set remote description:\n%s", description); - char* line_start = description; char* line_end = NULL; @@ -433,6 +547,7 @@ void agent_set_remote_description(Agent* agent, char* description) { LOGD("remote upwd: %s", agent->remote_upwd); // Please set gather candidates before set remote description + for (i = 0; i < agent->local_candidates_count; i++) { for (j = 0; j < agent->remote_candidates_count; j++) { if (agent->local_candidates[i].addr.family == agent->remote_candidates[j].addr.family) { @@ -440,6 +555,12 @@ void agent_set_remote_description(Agent* agent, char* description) { agent->candidate_pairs[agent->candidate_pairs_num].remote = &agent->remote_candidates[j]; agent->candidate_pairs[agent->candidate_pairs_num].priority = agent->local_candidates[i].priority + agent->remote_candidates[j].priority; agent->candidate_pairs[agent->candidate_pairs_num].state = ICE_CANDIDATE_STATE_FROZEN; + + if (agent->local_candidates[i].type == ICE_CANDIDATE_TYPE_RELAY) { + agent->candidate_pairs[agent->candidate_pairs_num].channel_number = 0x4000 + j; + agent_create_relay_channel(agent, &agent->candidate_pairs[agent->candidate_pairs_num], 1); + agent->refresh_relay_time = ports_get_epoch_time(); + } agent->candidate_pairs_num++; } } @@ -453,7 +574,7 @@ int agent_connectivity_check(Agent* agent) { StunMessage msg; if (agent->nominated_pair->state != ICE_CANDIDATE_STATE_INPROGRESS) { - LOGI("nominated pair is not in progress"); + LOGI("nominated pair is not in progress %d", agent->nominated_pair->state); return -1; } @@ -463,7 +584,7 @@ int agent_connectivity_check(Agent* agent) { addr_to_string(&agent->nominated_pair->remote->addr, addr_string, sizeof(addr_string)); LOGD("send binding request to remote ip: %s, port: %d", addr_string, agent->nominated_pair->remote->addr.port); agent_create_binding_request(agent, &msg); - agent_socket_send(agent, &agent->nominated_pair->remote->addr, msg.buf, msg.size); + agent_send(agent, msg.buf, msg.size); } agent_recv(agent, buf, sizeof(buf)); @@ -500,3 +621,12 @@ int agent_select_candidate_pair(Agent* agent) { // all candidate pairs are failed return -1; } + +void agent_refresh_relay_channel(Agent* agent) { + int ret = agent_refresh_turn(agent, agent->selected_pair); + if (ret == 0) + agent_refresh_turn(agent, agent->selected_pair); + agent_create_relay_channel(agent, agent->selected_pair, 0); + + agent->refresh_relay_time = ports_get_epoch_time(); +} \ No newline at end of file diff --git a/src/agent.h b/src/agent.h index 86da0e5..01c43ff 100644 --- a/src/agent.h +++ b/src/agent.h @@ -59,6 +59,7 @@ struct Agent { Address host_addr; int b_host_addr; uint64_t binding_request_time; + uint64_t refresh_relay_time; AgentState state; AgentMode mode; @@ -82,6 +83,8 @@ int agent_recv(Agent* agent, uint8_t* buf, int len); void agent_set_remote_description(Agent* agent, char* description); +void agent_create_permission(Agent* agent, const char* username, const char* credential); + int agent_select_candidate_pair(Agent* agent); int agent_connectivity_check(Agent* agent); @@ -92,4 +95,6 @@ int agent_create(Agent* agent); void agent_destroy(Agent* agent); +void agent_refresh_relay_channel(Agent* agent); + #endif // AGENT_H_ diff --git a/src/config.h b/src/config.h index 4ee0124..23fa3fd 100644 --- a/src/config.h +++ b/src/config.h @@ -2,7 +2,7 @@ #define CONFIG_H_ // uncomment this if you want to handshake with a aiortc -// #define CONFIG_DTLS_USE_ECDSA 1 +#define CONFIG_DTLS_USE_ECDSA 1 #define SCTP_MTU (1200) #define CONFIG_MTU (1300) @@ -61,8 +61,9 @@ #define CONFIG_TLS_READ_TIMEOUT 3000 #endif -#define AUDIO_LATENCY 20 // ms +#define AUDIO_LATENCY 40 // ms #define KEEPALIVE_CONNCHECK 10000 +#define REFRESH_RELAY_SESSION 200000 #define CONFIG_IPV6 0 // empty will use first active interface #define CONFIG_IFACE_PREFIX "" diff --git a/src/dtls_srtp.c b/src/dtls_srtp.c index c0d8c97..b9a7463 100644 --- a/src/dtls_srtp.c +++ b/src/dtls_srtp.c @@ -236,6 +236,12 @@ void dtls_srtp_deinit(DtlsSrtp* dtls_srtp) { srtp_dealloc(dtls_srtp->srtp_out); } } +static void set_policy_key(unsigned char* policy_key, uint8_t* key_material, int idx) { + int key_start = idx * SRTP_MASTER_KEY_LENGTH; + int salt_start = 2 * SRTP_MASTER_KEY_LENGTH + idx * SRTP_MASTER_SALT_LENGTH; + memcpy(policy_key, key_material + key_start, SRTP_MASTER_KEY_LENGTH); + memcpy(policy_key + SRTP_MASTER_KEY_LENGTH, key_material + salt_start, SRTP_MASTER_SALT_LENGTH); +} static int dtls_srtp_key_derivation(DtlsSrtp* dtls_srtp, const unsigned char* master_secret, size_t secret_len, const unsigned char* randbytes, size_t randbytes_len, mbedtls_tls_prf_types tls_prf_type) { int ret; @@ -277,15 +283,18 @@ static int dtls_srtp_key_derivation(DtlsSrtp* dtls_srtp, const unsigned char* ma srtp_crypto_policy_set_rtp_default(&dtls_srtp->remote_policy.rtp); srtp_crypto_policy_set_rtcp_default(&dtls_srtp->remote_policy.rtcp); - memcpy(dtls_srtp->remote_policy_key, key_material, SRTP_MASTER_KEY_LENGTH); - memcpy(dtls_srtp->remote_policy_key + SRTP_MASTER_KEY_LENGTH, key_material + SRTP_MASTER_KEY_LENGTH + SRTP_MASTER_KEY_LENGTH, SRTP_MASTER_SALT_LENGTH); + if (dtls_srtp->role == DTLS_SRTP_ROLE_SERVER) + set_policy_key(dtls_srtp->remote_policy_key, key_material, 0); + else + set_policy_key(dtls_srtp->remote_policy_key, key_material, 1); dtls_srtp->remote_policy.ssrc.type = ssrc_any_inbound; dtls_srtp->remote_policy.key = dtls_srtp->remote_policy_key; dtls_srtp->remote_policy.next = NULL; - - if (srtp_create(&dtls_srtp->srtp_in, &dtls_srtp->remote_policy) != srtp_err_status_ok) { - LOGD("Error creating inbound SRTP session for component"); + srtp_init(); + srtp_err_status_t err = srtp_create(&dtls_srtp->srtp_in, &dtls_srtp->remote_policy); + if (err != srtp_err_status_ok) { + LOGI("Error creating inbound SRTP session for component %d", err); return -1; } @@ -297,8 +306,10 @@ static int dtls_srtp_key_derivation(DtlsSrtp* dtls_srtp, const unsigned char* ma srtp_crypto_policy_set_rtp_default(&dtls_srtp->local_policy.rtp); srtp_crypto_policy_set_rtcp_default(&dtls_srtp->local_policy.rtcp); - memcpy(dtls_srtp->local_policy_key, key_material + SRTP_MASTER_KEY_LENGTH, SRTP_MASTER_KEY_LENGTH); - memcpy(dtls_srtp->local_policy_key + SRTP_MASTER_KEY_LENGTH, key_material + SRTP_MASTER_KEY_LENGTH + SRTP_MASTER_KEY_LENGTH + SRTP_MASTER_SALT_LENGTH, SRTP_MASTER_SALT_LENGTH); + if (dtls_srtp->role == DTLS_SRTP_ROLE_SERVER) + set_policy_key(dtls_srtp->local_policy_key, key_material, 1); + else + set_policy_key(dtls_srtp->local_policy_key, key_material, 0); dtls_srtp->local_policy.ssrc.type = ssrc_any_outbound; dtls_srtp->local_policy.key = dtls_srtp->local_policy_key; @@ -309,7 +320,7 @@ static int dtls_srtp_key_derivation(DtlsSrtp* dtls_srtp, const unsigned char* ma return -1; } - LOGI("Created outbound SRTP session"); + LOGI("Created outbound SRTP session"); dtls_srtp->state = DTLS_SRTP_STATE_CONNECTED; return 0; } @@ -334,7 +345,6 @@ static void dtls_srtp_key_derivation_cb(void* context, mbedtls_tls_prf_types tls_prf_type) { #endif DtlsSrtp* dtls_srtp = (DtlsSrtp*)context; - unsigned char master_secret[48]; unsigned char randbytes[64]; diff --git a/src/ice.h b/src/ice.h index 2628a54..d6684bd 100644 --- a/src/ice.h +++ b/src/ice.h @@ -40,6 +40,14 @@ struct IceCandidate { IceCandidateState state; Address addr; Address raddr; + + Address serv_addr; + + const char* username; + const char* credential; + + char realm[64]; + char nonce[64]; }; typedef struct IceCandidatePair IceCandidatePair; @@ -50,6 +58,8 @@ struct IceCandidatePair { IceCandidate* remote; int conncheck; uint64_t priority; + + uint16_t channel_number; }; void ice_candidate_create(IceCandidate* ice_candidate, int foundation, IceCandidateType type, Address* addr); diff --git a/src/peer_connection.c b/src/peer_connection.c index 069b0cf..c39a71f 100644 --- a/src/peer_connection.c +++ b/src/peer_connection.c @@ -86,7 +86,7 @@ static int peer_connection_dtls_srtp_send(void* ctx, const uint8_t* buf, size_t DtlsSrtp* dtls_srtp = (DtlsSrtp*)ctx; PeerConnection* pc = (PeerConnection*)dtls_srtp->user_data; - // LOGD("send %.4x %.4x, %ld", *(uint16_t*)buf, *(uint16_t*)(buf + 2), len); + LOGD("peer_connection_dtls_srtp_send %4x %4x, %d", *(uint16_t*)buf, *(uint16_t*)(buf + 2), (int)len); return agent_send(&pc->agent, buf, len); } @@ -331,7 +331,6 @@ static void peer_connection_state_new(PeerConnection* pc, DtlsSrtpRole role, int pc->dtls_srtp.udp_send = peer_connection_dtls_srtp_send; pc->sctp.connected = 0; - if (isOfferer) { agent_clear_candidates(&pc->agent); pc->agent.mode = AGENT_MODE_CONTROLLING; @@ -360,7 +359,7 @@ static void peer_connection_state_new(PeerConnection* pc, DtlsSrtpRole role, int sdp_append_h264(&pc->local_sdp); sdp_append(&pc->local_sdp, "a=fingerprint:sha-256 %s", pc->dtls_srtp.local_fingerprint); sdp_append(&pc->local_sdp, peer_connection_dtls_role_setup_value(role)); - strcat(pc->local_sdp.content, description); + memmove(pc->local_sdp.content + strlen(pc->local_sdp.content), description, sizeof(pc->local_sdp.content) - strlen(pc->local_sdp.content) - 1); } switch (pc->config.audio_codec) { @@ -369,7 +368,7 @@ static void peer_connection_state_new(PeerConnection* pc, DtlsSrtpRole role, int sdp_append_pcma(&pc->local_sdp); sdp_append(&pc->local_sdp, "a=fingerprint:sha-256 %s", pc->dtls_srtp.local_fingerprint); sdp_append(&pc->local_sdp, peer_connection_dtls_role_setup_value(role)); - strcat(pc->local_sdp.content, description); + memmove(pc->local_sdp.content + strlen(pc->local_sdp.content), description, sizeof(pc->local_sdp.content) - strlen(pc->local_sdp.content) - 1); break; case CODEC_PCMU: @@ -377,14 +376,14 @@ static void peer_connection_state_new(PeerConnection* pc, DtlsSrtpRole role, int sdp_append_pcmu(&pc->local_sdp); sdp_append(&pc->local_sdp, "a=fingerprint:sha-256 %s", pc->dtls_srtp.local_fingerprint); sdp_append(&pc->local_sdp, peer_connection_dtls_role_setup_value(role)); - strcat(pc->local_sdp.content, description); + memmove(pc->local_sdp.content + strlen(pc->local_sdp.content), description, sizeof(pc->local_sdp.content) - strlen(pc->local_sdp.content) - 1); break; case CODEC_OPUS: sdp_append_opus(&pc->local_sdp); sdp_append(&pc->local_sdp, "a=fingerprint:sha-256 %s", pc->dtls_srtp.local_fingerprint); sdp_append(&pc->local_sdp, peer_connection_dtls_role_setup_value(role)); - strcat(pc->local_sdp.content, description); + memmove(pc->local_sdp.content + strlen(pc->local_sdp.content), description, sizeof(pc->local_sdp.content) - strlen(pc->local_sdp.content) - 1); default: break; @@ -394,7 +393,7 @@ static void peer_connection_state_new(PeerConnection* pc, DtlsSrtpRole role, int sdp_append_datachannel(&pc->local_sdp); sdp_append(&pc->local_sdp, "a=fingerprint:sha-256 %s", pc->dtls_srtp.local_fingerprint); sdp_append(&pc->local_sdp, peer_connection_dtls_role_setup_value(role)); - strcat(pc->local_sdp.content, description); + memmove(pc->local_sdp.content + strlen(pc->local_sdp.content), description, sizeof(pc->local_sdp.content) - strlen(pc->local_sdp.content) - 1); } pc->b_local_description_created = 1; @@ -410,12 +409,11 @@ int peer_connection_loop(PeerConnection* pc) { uint32_t ssrc = 0; memset(pc->agent_buf, 0, sizeof(pc->agent_buf)); pc->agent_ret = -1; - switch (pc->state) { case PEER_CONNECTION_NEW: if (!pc->b_local_description_created) { - peer_connection_state_new(pc, DTLS_SRTP_ROLE_SERVER, 1); + peer_connection_state_new(pc, DTLS_SRTP_ROLE_CLIENT, 1); } break; @@ -429,6 +427,7 @@ int peer_connection_loop(PeerConnection* pc) { case PEER_CONNECTION_CONNECTED: + LOGD("DTLS-SRTP handshake start"); if (dtls_srtp_handshake(&pc->dtls_srtp, NULL) == 0) { LOGD("DTLS-SRTP handshake done"); @@ -508,6 +507,11 @@ int peer_connection_loop(PeerConnection* pc) { STATE_CHANGED(pc, PEER_CONNECTION_CLOSED); } + if (pc->agent.selected_pair->local->type == ICE_CANDIDATE_TYPE_RELAY && + REFRESH_RELAY_SESSION > 0 && + (ports_get_epoch_time() - pc->agent.refresh_relay_time) > REFRESH_RELAY_SESSION) { + agent_refresh_relay_channel(&pc->agent); + } break; case PEER_CONNECTION_FAILED: break; @@ -574,6 +578,7 @@ void peer_connection_set_remote_description(PeerConnection* pc, const char* sdp_ } agent_set_remote_description(&pc->agent, (char*)sdp_text); + STATE_CHANGED(pc, PEER_CONNECTION_CHECKING); } diff --git a/src/peer_connection.h b/src/peer_connection.h index dca3271..5379533 100644 --- a/src/peer_connection.h +++ b/src/peer_connection.h @@ -61,7 +61,6 @@ typedef struct IceServer { const char* urls; const char* username; const char* credential; - } IceServer; typedef struct PeerConfiguration { diff --git a/src/rtp.c b/src/rtp.c index 3898b84..52d731c 100644 --- a/src/rtp.c +++ b/src/rtp.c @@ -207,7 +207,7 @@ void rtp_encoder_init(RtpEncoder* rtp_encoder, MediaCodec codec, RtpOnPacket on_ case CODEC_OPUS: rtp_encoder->type = PT_OPUS; rtp_encoder->ssrc = SSRC_OPUS; - rtp_encoder->timestamp_increment = AUDIO_LATENCY * 48000 / 1000; + rtp_encoder->timestamp_increment = AUDIO_LATENCY * 16000 / 1000; rtp_encoder->encode_func = rtp_encoder_encode_generic; break; default: diff --git a/src/stun.c b/src/stun.c index 0b17202..607de2b 100644 --- a/src/stun.c +++ b/src/stun.c @@ -59,6 +59,7 @@ void stun_msg_create(StunMessage* msg, uint16_t type) { int stun_set_mapped_address(char* value, uint8_t* mask, Address* addr) { int ret, i; char addr_string[ADDRSTRLEN]; + value[0] = 0; uint8_t* family = (uint8_t*)(value + 1); uint16_t* port = (uint16_t*)(value + 2); uint32_t* val32 = (uint32_t*)(value + 4); @@ -173,6 +174,10 @@ void stun_parse_msg_buf(StunMessage* msg) { sprintf(message_integrity_hex + 2 * i, "%02x", (uint8_t)msg->message_integrity[i]); } + break; + case STUN_ATTR_TYPE_ERROR_CODE: + msg->error_code = attr->value[2] * 100 + attr->value[3]; + LOGD("Error Code: %d", msg->error_code); break; case STUN_ATTR_TYPE_LIFETIME: break; diff --git a/src/stun.h b/src/stun.h index 801133b..b68ab4b 100644 --- a/src/stun.h +++ b/src/stun.h @@ -31,6 +31,12 @@ typedef enum StunMethod { STUN_METHOD_BINDING = 0x0001, STUN_METHOD_ALLOCATE = 0x0003, + STUN_METHOD_REFRESH = 0x0004, + STUN_METHOD_SEND = 0x0006, + STUN_METHOD_DATA = 0x0007, + STUN_METHOD_CREATE_PERMISSION = 0x0008, + STUN_METHOD_CHANNEL_BIND = 0x0009, + } StunMethod; typedef enum StunAttrType { @@ -38,7 +44,10 @@ typedef enum StunAttrType { STUN_ATTR_TYPE_MAPPED_ADDRESS = 0x0001, STUN_ATTR_TYPE_USERNAME = 0x0006, STUN_ATTR_TYPE_MESSAGE_INTEGRITY = 0x0008, + STUN_ATTR_TYPE_ERROR_CODE = 0x0009, + STUN_ATTR_TYPE_CHANNEL_NUMBER = 0x000c, STUN_ATTR_TYPE_LIFETIME = 0x000d, + STUN_ATTR_TYPE_XOR_PEER_ADDRESS = 0x0012, STUN_ATTR_TYPE_REALM = 0x0014, STUN_ATTR_TYPE_NONCE = 0x0015, STUN_ATTR_TYPE_XOR_RELAYED_ADDRESS = 0x0016, @@ -94,11 +103,13 @@ struct StunMessage { Address relayed_addr; uint8_t buf[STUN_ATTR_BUF_SIZE]; size_t size; + int16_t error_code; }; void stun_msg_create(StunMessage* msg, uint16_t type); int stun_set_mapped_address(char* value, uint8_t* mask, Address* addr); +int stun_set_mapped_address_test(char* value, uint8_t* mask, Address* addr); void stun_get_mapped_address(char* value, uint8_t* mask, Address* addr);