-
-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of TURN TCP transport between client and server #111
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a coupe minor problems, but overall it looks good, thanks!
I noticed you closed and reopened the PR, it should not be needed, just push your changes on your branch and the tests will be run again.
|
||
return agent_direct_send(agent, &entry->record, buffer, size, ds); | ||
if (agent_direct_send2(agent, entry, buffer, size, ds) < 0) { | ||
JLOG_WARN("STUN message send failed, errno=%d", sockerrno); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cleaned up the sockerrno
after agent_direct_send()
as it's a bit clumsy (the function could internally make a last system call modifying errno), so you should do the same here.
|
||
return agent_direct_send(agent, &entry->record, buffer, len, ds); | ||
if (agent_direct_send2(agent, entry, buffer, len, ds) < 0) { | ||
JLOG_WARN("ChannelData message send failed, errno=%d", sockerrno); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here about sockerrno
.
socket_config.port_begin = agent->config.local_port_range_begin; | ||
socket_config.port_end = agent->config.local_port_range_end; | ||
switch (turn_server->transport) { | ||
case JUICE_TRANSPORT_UDP: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does UDP transport mean for the user? If I get it correctly, it opens a dedicated UDP socket to reach the server instead of using the one of the agent. What is the point of this mechanism?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my mind, the ideal is to replace the udp .c completely with transport .c, UDP, TCP and TLS are supported.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. While this is smart for factoring the code, it will cause issues, for instance reflexive candidates from TURN UDP servers will be incorrect, as they'll reflect the external address for the transport UDP socket instead of the agent one. I think the only way to keep them working is limiting the transport to TCP and use the agent socket for UDP, sadly.
} | ||
JLOG_DEBUG("Leaving agent thread"); | ||
agent_change_state(agent, JUICE_STATE_DISCONNECTED); | ||
mutex_unlock(&agent->mutex); | ||
} | ||
|
||
int agent_recv(juice_agent_t *agent) { | ||
int agent_recv(juice_agent_t *agent, agent_stun_entry_t *entry) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There could be a dedicated function to receive from entry transport as the logic looks quite decorelated.
if (agent_add_local_reflexive_candidate(agent, ICE_CANDIDATE_TYPE_SERVER_REFLEXIVE, | ||
&msg->mapped)) { | ||
JLOG_WARN("Failed to add local peer reflexive candidate from TURN mapped address"); | ||
if (entry->transport != JUICE_TRANSPORT_TCP) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that if the entry uses a secondary UDP socket for some reason, the reflexive candidate is useless anyway.
@@ -508,6 +508,39 @@ bool is_stun_datagram(const void *data, size_t size) { | |||
return true; | |||
} | |||
|
|||
bool is_stun_datagram2(const void *data, size_t size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference with is_stun_datagram
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference with
is_stun_datagram
?
TCP a stream-oriented transmission protocol, more than one packet may be received in one recv() call.
STUN Packet + STUN Packet + ...
STUN Packet + Non STUN Packet + ...
...
@@ -815,6 +928,9 @@ int agent_bookkeeping(juice_agent_t *agent, timestamp_t *next_timestamp) { | |||
continue; | |||
|
|||
if (entry->retransmissions >= 0) { | |||
if (entry->sock != INVALID_SOCKET && entry->transport == JUICE_TRANSPORT_TCP) | |||
transport_wait_for_connected(entry->sock, NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think blocking the whole thread until the transport connects is not acceptable, it would be better to asynchronously wait for the connection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I'll think about ways to do it asynchronously.
return false; | ||
} | ||
|
||
int transport_get_addrs(socket_t sock, addr_record_t *records, size_t count) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of functions copied from udp.c
that you could clean up. This one should be, for sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until the new transport.c is complete,do not break other code.
@@ -436,6 +437,35 @@ int agent_direct_send(juice_agent_t *agent, const addr_record_t *dst, const char | |||
return ret; | |||
} | |||
|
|||
int agent_direct_send2(juice_agent_t *agent, const agent_stun_entry_t *entry, const char *data, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name agent_direct_send2
is not very explicit, is there a reason for not modifying agent_direct_send()
since they have the same signature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modify the parameters of the function, but I don't want to break other code that relies on the original function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you changed dst
to entry
, my bad. You could call it something more explicit then, like agent_transport_send
.
A lot work to do, for TCP TURN, Close this PR first. |
Please continue working on the same PR as otherwise the messages history is kind of lost. It's totally fine to keep the PR open as you work on it and push changes. |
Okay, I reopen this PR now, and I will continue working on it. thx. |
bf558fb
to
3cfb554
Compare
Hi @xdyyll can you give me access to your fork and I can finish this PR? Or I can start a new PR |
@@ -72,6 +79,7 @@ typedef struct juice_turn_server { | |||
const char *username; | |||
const char *password; | |||
uint16_t port; | |||
juice_transport_t transport; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an issue now as it breaks the library interface and would require releasing a new major version.
test code: