Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libnice
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
libnice
Commits
77bc5bcf
Commit
77bc5bcf
authored
Jul 24, 2008
by
Youness Alaoui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored stun bind usage
parent
f6632bda
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
164 additions
and
511 deletions
+164
-511
stun/usages/bind.c
stun/usages/bind.c
+148
-361
stun/usages/bind.h
stun/usages/bind.h
+16
-150
No files found.
stun/usages/bind.c
View file @
77bc5bcf
...
...
@@ -52,412 +52,199 @@
#include <unistd.h>
#include <sys/time.h>
#include <fcntl.h>
/** Non-blocking mode STUN binding discovery */
#include "timer.h"
#include "trans.h"
struct
stun_bind_s
{
stun_trans_t
trans
;
StunAgent
agent
;
};
/** Initialization/deinitization */
/**
* Initializes a STUN Binding discovery context. Does not send anything.
* This allows customization of the STUN Binding Request.
*
* @param context pointer to an opaque pointer that will be passed to
* stun_bind_resume() afterward
* @param fd socket to use for discovery, or -1 to create one
* @param srv STUN server socket address
* @param srvlen STUN server socket address length
*
* @return 0 on success, a standard error value otherwise.
*/
static
int
stun_bind_alloc
(
stun_bind_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
int
compat
)
{
int
val
;
stun_bind_t
*
ctx
=
malloc
(
sizeof
(
*
ctx
));
if
(
ctx
==
NULL
)
return
ENOMEM
;
memset
(
ctx
,
0
,
sizeof
(
*
ctx
));
*
context
=
ctx
;
val
=
(
fd
!=
-
1
)
?
stun_trans_init
(
&
ctx
->
trans
,
fd
,
srv
,
srvlen
)
:
stun_trans_create
(
&
ctx
->
trans
,
SOCK_DGRAM
,
0
,
srv
,
srvlen
);
if
(
val
)
{
free
(
ctx
);
return
val
;
}
if
(
compat
==
1
)
{
stun_agent_init
(
&
ctx
->
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_RFC3489
,
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
}
else
{
stun_agent_init
(
&
ctx
->
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_3489BIS
,
STUN_AGENT_USAGE_ADD_SERVER
|
STUN_AGENT_USAGE_USE_FINGERPRINT
);
}
stun_agent_init_request
(
&
ctx
->
agent
,
&
ctx
->
trans
.
message
,
ctx
->
trans
.
msg
.
buf
,
sizeof
(
ctx
->
trans
.
msg
.
buf
),
STUN_BINDING
);
ctx
->
trans
.
msg
.
length
=
ctx
->
trans
.
message
.
buffer_len
;
return
0
;
}
int
stun_bind_start
(
stun_bind_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
int
compat
)
{
stun_bind_t
*
ctx
;
int
val
=
stun_bind_alloc
(
context
,
fd
,
srv
,
srvlen
,
compat
);
if
(
val
)
return
val
;
ctx
=
*
context
;
val
=
stun_agent_finish_message
(
&
ctx
->
agent
,
&
ctx
->
trans
.
message
,
NULL
,
0
);
if
(
val
==
0
)
goto
error
;
ctx
->
trans
.
msg
.
length
=
val
;
val
=
stun_trans_start
(
&
ctx
->
trans
);
if
(
val
)
goto
error
;
return
0
;
error:
stun_bind_cancel
(
ctx
);
return
val
;
}
void
stun_bind_cancel
(
stun_bind_t
*
context
)
{
stun_trans_deinit
(
&
context
->
trans
);
free
(
context
);
}
/** Timer and retransmission handling */
/** Non-blocking mode STUN binding discovery */
unsigned
stun_bind_timeout
(
const
stun_bind_t
*
context
)
size_t
stun_usage_bind_create
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buffer
,
size_t
buffer_len
)
{
assert
(
context
!=
NULL
);
return
stun_trans_timeout
(
&
context
->
trans
);
}
stun_agent_init_request
(
agent
,
msg
,
buffer
,
buffer_len
,
STUN_BINDING
);
int
stun_bind_elapse
(
stun_bind_t
*
context
)
{
int
val
=
stun_trans_tick
(
&
context
->
trans
);
if
(
val
!=
EAGAIN
)
stun_bind_cancel
(
context
);
return
val
;
return
stun_agent_finish_message
(
agent
,
msg
,
NULL
,
0
);
}
/** Incoming packets handling */
int
stun_bind_process
(
stun_bind_t
*
restrict
ctx
,
const
void
*
restrict
buf
,
size_t
len
,
struct
sockaddr
*
restrict
addr
,
socklen_t
*
addrlen
)
StunUsageBindReturn
stun_usage_bind_process
(
StunMessage
*
msg
,
struct
sockaddr
*
addr
,
socklen_t
*
addrlen
,
struct
sockaddr
*
alternate_server
,
socklen_t
*
alternate_server_len
)
{
int
val
,
code
;
assert
(
ctx
!=
NULL
);
int
val
,
code
=
-
1
;
val
=
stun_trans_preprocess
(
&
ctx
->
agent
,
&
ctx
->
trans
,
&
code
,
buf
,
len
);
switch
(
val
)
switch
(
stun_message_get_class
(
msg
))
{
case
EAGAIN
:
return
EAGAIN
;
case
0
:
case
STUN_REQUEST
:
case
STUN_INDICATION
:
return
STUN_USAGE_BIND_RETURN_RETRY
;
case
STUN_RESPONSE
:
break
;
default:
if
(
code
==
STUN_ERROR_ROLE_CONFLICT
)
val
=
ECONNRESET
;
stun_bind_cancel
(
ctx
);
return
val
;
case
STUN_ERROR
:
if
(
stun_message_find_error
(
msg
,
&
code
)
!=
0
)
{
/* missing ERROR-CODE: ignore message */
return
STUN_USAGE_BIND_RETURN_RETRY
;
}
/* NOTE: currently we ignore unauthenticated messages if the context
* is authenticated, for security reasons. */
stun_debug
(
" STUN error message received (code: %d)
\n
"
,
code
);
/* ALTERNATE-SERVER mechanism */
if
((
code
/
100
)
==
3
)
{
if
(
stun_message_find_addr
(
msg
,
STUN_ATTRIBUTE_ALTERNATE_SERVER
,
alternate_server
,
alternate_server_len
))
{
stun_debug
(
" Unexpectedly missing ALTERNATE-SERVER attribute
\n
"
);
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
stun_debug
(
"Found alternate server
\n
"
);
return
STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER
;
}
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
val
=
stun_message_find_xor_addr
(
&
ctx
->
trans
.
message
,
stun_debug
(
"Received %u-bytes STUN message
\n
"
,
stun_message_length
(
msg
));
val
=
stun_message_find_xor_addr
(
msg
,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS
,
addr
,
addrlen
);
if
(
val
)
{
stun_debug
(
" No XOR-MAPPED-ADDRESS: %s
\n
"
,
strerror
(
val
));
val
=
stun_message_find_addr
(
&
ctx
->
trans
.
message
,
val
=
stun_message_find_addr
(
msg
,
STUN_ATTRIBUTE_MAPPED_ADDRESS
,
addr
,
addrlen
);
if
(
val
)
{
stun_debug
(
" No MAPPED-ADDRESS: %s
\n
"
,
strerror
(
val
));
stun_bind_cancel
(
ctx
);
return
val
;
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
}
stun_debug
(
" Mapped address found!
\n
"
);
stun_bind_cancel
(
ctx
)
;
return
0
;
return
STUN_USAGE_BIND_RETURN_SUCCESS
;
}
/** B
locking mode STUN binding discovery
*/
/** B
inding keep-alive (Binding discovery indication!)
*/
int
stun_bind_run
(
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
struct
sockaddr
*
restrict
addr
,
socklen_t
*
addrlen
,
int
compat
)
size_t
stun_usage_bind_keepalive
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buf
,
size_t
len
)
{
stun_bind_t
*
ctx
;
uint8_t
buf
[
STUN_MAX_MESSAGE_SIZE
];
ssize_t
val
;
val
=
stun_bind_start
(
&
ctx
,
fd
,
srv
,
srvlen
,
compat
);
if
(
val
)
return
val
;
do
{
val
=
stun_trans_recv
(
&
ctx
->
trans
,
buf
,
sizeof
(
buf
));
if
(
val
==
-
1
)
{
val
=
errno
;
continue
;
}
val
=
stun_bind_process
(
ctx
,
buf
,
val
,
addr
,
addrlen
);
}
while
(
val
==
EAGAIN
);
return
val
;
stun_agent_init_indication
(
agent
,
msg
,
buf
,
len
,
STUN_BINDING
);
return
stun_agent_finish_message
(
agent
,
msg
,
NULL
,
0
);
}
/** ICE keep-alives (Binding discovery indication!) */
int
stun_bind_keepalive
(
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
int
compat
)
/** Blocking mode STUN binding discovery */
StunUsageBindReturn
stun_usage_bind_run
(
const
struct
sockaddr
*
srv
,
socklen_t
srvlen
,
struct
sockaddr
*
addr
,
socklen_t
*
addrlen
)
{
uint8_t
buf
[
28
]
;
s
ize_t
len
=
sizeof
(
buf
)
;
stun_timer_t
timer
;
s
tun_trans_t
trans
;
StunAgent
agent
;
StunMessage
req
;
uint8_t
req_buf
[
STUN_MAX_MESSAGE_SIZE
];
StunMessage
msg
;
if
(
compat
==
1
)
{
stun_agent_init
(
&
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_RFC3489
,
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS
|
STUN_AGENT_USAGE_IGNORE_CREDENTIALS
);
}
else
{
stun_agent_init
(
&
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_3489BIS
,
STUN_AGENT_USAGE_ADD_SERVER
|
STUN_AGENT_USAGE_USE_FINGERPRINT
);
}
stun_agent_init_indication
(
&
agent
,
&
msg
,
buf
,
sizeof
(
buf
),
STUN_BINDING
);
len
=
stun_agent_finish_message
(
&
agent
,
&
msg
,
NULL
,
0
);
assert
(
len
==
sizeof
(
buf
));
/* NOTE: hopefully, this is only needed for non-stream sockets */
if
(
stun_sendto
(
fd
,
buf
,
len
,
srv
,
srvlen
)
==
-
1
)
return
errno
;
return
0
;
}
int
stun_conncheck_start
(
stun_bind_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
const
char
*
username
,
const
char
*
password
,
bool
cand_use
,
bool
controlling
,
uint32_t
priority
,
uint64_t
tie
,
uint32_t
compat
)
{
uint8_t
buf
[
STUN_MAX_MESSAGE_SIZE
];
StunValidationStatus
valid
;
size_t
len
;
ssize_t
ret
;
int
val
;
stun_bind_t
*
ctx
;
assert
(
username
!=
NULL
);
assert
(
password
!=
NULL
);
val
=
stun_bind_alloc
(
context
,
fd
,
srv
,
srvlen
,
compat
);
if
(
val
)
return
val
;
ctx
=
*
context
;
if
(
compat
!=
1
)
{
ctx
->
trans
.
key
.
length
=
strlen
(
password
);
ctx
->
trans
.
key
.
value
=
malloc
(
ctx
->
trans
.
key
.
length
);
if
(
ctx
->
trans
.
key
.
value
==
NULL
)
{
val
=
ENOMEM
;
goto
error
;
}
memcpy
(
ctx
->
trans
.
key
.
value
,
password
,
ctx
->
trans
.
key
.
length
);
struct
sockaddr_storage
alternate_server
;
socklen_t
alternate_server_len
=
sizeof
(
alternate_server
);
StunUsageBindReturn
bind_ret
;
stun_agent_init
(
&
agent
,
STUN_ALL_KNOWN_ATTRIBUTES
,
STUN_COMPATIBILITY_3489BIS
,
STUN_AGENT_USAGE_ADD_SERVER
|
STUN_AGENT_USAGE_USE_FINGERPRINT
);
len
=
stun_usage_bind_create
(
&
agent
,
&
req
,
req_buf
,
sizeof
(
req_buf
));
ret
=
stun_trans_create
(
&
trans
,
SOCK_DGRAM
,
0
,
srv
,
srvlen
);
if
(
ret
)
{
errno
=
ret
;
stun_debug
(
"STUN transaction failed: couldn't create transport.
\n
"
);
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
if
(
compat
!=
1
)
{
if
(
cand_use
)
{
val
=
stun_message_append_flag
(
&
ctx
->
trans
.
message
,
STUN_ATTRIBUTE_USE_CANDIDATE
);
if
(
val
)
goto
error
;
}
val
=
stun_message_append32
(
&
ctx
->
trans
.
message
,
STUN_ATTRIBUTE_PRIORITY
,
priority
);
if
(
val
)
goto
error
;
val
=
stun_message_append64
(
&
ctx
->
trans
.
message
,
controlling
?
STUN_ATTRIBUTE_ICE_CONTROLLING
:
STUN_ATTRIBUTE_ICE_CONTROLLED
,
tie
);
if
(
val
)
goto
error
;
}
if
(
username
)
{
val
=
stun_message_append_string
(
&
ctx
->
trans
.
message
,
STUN_ATTRIBUTE_USERNAME
,
username
);
if
(
val
)
goto
error
;
val
=
stun_trans_send
(
&
trans
,
req_buf
,
len
);
if
(
val
<
-
1
)
{
stun_debug
(
"STUN transaction failed: couldn't send request.
\n
"
);
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
val
=
stun_agent_finish_message
(
&
ctx
->
agent
,
&
ctx
->
trans
.
message
,
compat
==
1
?
NULL
:
(
const
uint8_t
*
)
password
,
compat
==
1
?
0
:
strlen
(
password
));
stun_timer_start
(
&
timer
);
stun_debug
(
"STUN transaction started (timeout %dms).
\n
"
,
stun_timer_remainder
(
&
timer
));
if
(
val
==
0
)
goto
error
;
ctx
->
trans
.
msg
.
length
=
val
;
val
=
stun_trans_start
(
&
ctx
->
trans
);
if
(
val
)
goto
error
;
return
0
;
error:
stun_bind_cancel
(
ctx
);
return
val
;
}
/** STUN NAT control */
struct
stun_nested_s
{
stun_bind_t
*
bind
;
struct
sockaddr_storage
mapped
;
uint32_t
refresh
;
uint32_t
bootnonce
;
};
int
stun_nested_start
(
stun_nested_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
mapad
,
const
struct
sockaddr
*
restrict
natad
,
socklen_t
adlen
,
uint32_t
refresh
,
int
compat
)
{
stun_nested_t
*
ctx
;
int
val
;
if
(
adlen
>
sizeof
(
ctx
->
mapped
))
return
ENOBUFS
;
ctx
=
malloc
(
sizeof
(
*
ctx
));
memcpy
(
&
ctx
->
mapped
,
mapad
,
adlen
);
ctx
->
refresh
=
0
;
ctx
->
bootnonce
=
0
;
/* TODO: forcily set port to 3478 */
val
=
stun_bind_alloc
(
&
ctx
->
bind
,
fd
,
natad
,
adlen
,
compat
);
if
(
val
)
return
val
;
*
context
=
ctx
;
val
=
stun_message_append32
(
&
ctx
->
bind
->
trans
.
message
,
STUN_ATTRIBUTE_REFRESH_INTERVAL
,
refresh
);
if
(
val
)
goto
error
;
val
=
stun_agent_finish_message
(
&
ctx
->
bind
->
agent
,
&
ctx
->
bind
->
trans
.
message
,
NULL
,
0
);
if
(
val
)
goto
error
;
val
=
stun_trans_start
(
&
ctx
->
bind
->
trans
);
if
(
val
)
goto
error
;
return
0
;
error:
stun_bind_cancel
(
ctx
->
bind
);
return
val
;
}
int
stun_nested_process
(
stun_nested_t
*
restrict
ctx
,
const
void
*
restrict
buf
,
size_t
len
,
struct
sockaddr
*
restrict
intad
,
socklen_t
*
adlen
)
{
struct
sockaddr_storage
mapped
;
socklen_t
mappedlen
=
sizeof
(
mapped
);
int
val
;
assert
(
ctx
!=
NULL
);
val
=
stun_bind_process
(
ctx
->
bind
,
buf
,
len
,
(
struct
sockaddr
*
)
&
mapped
,
&
mappedlen
);
if
(
val
)
return
val
;
/* Mapped address mistmatch! (FIXME: what are we really supposed to do
* in this case???) */
if
(
sockaddrcmp
((
struct
sockaddr
*
)
&
mapped
,
(
struct
sockaddr
*
)
&
ctx
->
mapped
))
do
{
stun_debug
(
" Mapped address mismatch! (Symmetric NAT?)
\n
"
);
return
ECONNREFUSED
;
}
for
(;;)
{
unsigned
delay
=
stun_timer_remainder
(
&
timer
);
ret
=
stun_trans_poll
(
&
trans
,
delay
);
if
(
ret
==
EAGAIN
)
{
switch
(
stun_timer_refresh
(
&
timer
))
{
case
-
1
:
stun_debug
(
"STUN transaction failed: time out.
\n
"
);
return
STUN_USAGE_BIND_RETURN_TIMEOUT
;
// fatal error!
case
0
:
stun_debug
(
"STUN transaction retransmitted (timeout %dms).
\n
"
,
stun_timer_remainder
(
&
timer
));
val
=
stun_trans_send
(
&
trans
,
req_buf
,
len
);
if
(
val
<
-
1
)
{
stun_debug
(
"STUN transaction failed: couldn't resend request.
\n
"
);
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
ret
=
EAGAIN
;
continue
;
}
}
val
=
stun_trans_recv
(
&
trans
,
buf
,
sizeof
(
buf
));
if
(
val
>=
0
)
{
break
;
}
}
val
=
stun_message_find_xor_addr
(
&
ctx
->
bind
->
trans
.
message
,
STUN_ATTRIBUTE_XOR_INTERNAL_ADDRESS
,
intad
,
adlen
);
if
(
val
)
{
stun_debug
(
" No XOR-INTERNAL-ADDRESS: %s
\n
"
,
strerror
(
val
));
return
val
;
valid
=
stun_agent_validate
(
&
agent
,
&
msg
,
buf
,
val
,
NULL
,
NULL
);
if
(
valid
==
STUN_VALIDATION_UNKNOWN_ATTRIBUTE
)
return
STUN_USAGE_BIND_RETURN_ERROR
;
if
(
valid
!=
STUN_VALIDATION_SUCCESS
)
{
ret
=
EAGAIN
;
}
else
{
bind_ret
=
stun_usage_bind_process
(
&
msg
,
addr
,
addrlen
,
(
struct
sockaddr
*
)
&
alternate_server
,
&
alternate_server_len
);
if
(
bind_ret
==
STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER
)
{
stun_trans_deinit
(
&
trans
);
ret
=
stun_trans_create
(
&
trans
,
SOCK_DGRAM
,
0
,
(
struct
sockaddr
*
)
&
alternate_server
,
alternate_server_len
);
if
(
ret
)
{
errno
=
ret
;
return
STUN_USAGE_BIND_RETURN_ERROR
;
}
val
=
stun_trans_send
(
&
trans
,
req_buf
,
len
);
if
(
val
<
-
1
)
return
STUN_USAGE_BIND_RETURN_ERROR
;
stun_timer_start
(
&
timer
);
ret
=
EAGAIN
;
}
else
if
(
bind_ret
==
STUN_USAGE_BIND_RETURN_RETRY
)
{
ret
=
EAGAIN
;
}
else
{
return
bind_ret
;
}
}
}
while
(
ret
==
EAGAIN
);
stun_message_find32
(
&
ctx
->
bind
->
trans
.
message
,
STUN_ATTRIBUTE_REFRESH_INTERVAL
,
&
ctx
->
refresh
);
/* TODO: give this to caller */
stun_debug
(
" Internal address found!
\n
"
);
stun_bind_cancel
(
ctx
->
bind
);
ctx
->
bind
=
NULL
;
return
0
;
return
STUN_USAGE_BIND_RETURN_SUCCESS
;
}
stun/usages/bind.h
View file @
77bc5bcf
...
...
@@ -41,12 +41,6 @@
* @brief STUN binding discovery
*/
# ifndef IPPORT_STUN
/** Default port for STUN binding discovery */
# define IPPORT_STUN 3478
# endif
typedef
struct
stun_bind_s
stun_bind_t
;
# include <stdbool.h>
# include <stdint.h>
...
...
@@ -56,156 +50,28 @@ typedef struct stun_bind_s stun_bind_t;
extern
"C"
{
# endif
/**
* Performs STUN Binding discovery in blocking mode.
*
* @param fd socket to use for binding discovery, or -1 to create one
* @param srv STUN server socket address
* @param srvlen STUN server socket address byte length
* @param addr [OUT] pointer to a socket address structure to hold
* discovered binding (Remember that it can be an IPv6 even if the socket
* local family is IPv4, so you should use a sockaddr_storage buffer)
* @param addrlen [IN/OUT] pointer to the byte length of addr, set to the byte
* length of the binding socket address on return.
*
* @return 0 on success, a standard error value in case of error.
* In case of error, addr and addrlen are undefined.
*/
int
stun_bind_run
(
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
struct
sockaddr
*
restrict
addr
,
socklen_t
*
addrlen
,
int
compat
);
/**
* Starts STUN Binding discovery in non-blocking mode.
*
* @param context pointer to an opaque pointer that will be passed to
* other stun_bind_*() functions afterward
* @param fd socket to use for discovery, or -1 to create one
* @param srv STUN server socket address
* @param srvlen STUN server socket address length
*
* @return 0 on success, a standard error value otherwise.
*/
int
stun_bind_start
(
stun_bind_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
int
compat
);
/**
* Aborts a running STUN Binding discovery.
* @param context binding discovery (or conncheck) context pointer
* to be released.
*/
void
stun_bind_cancel
(
stun_bind_t
*
context
);
/**
* This is meant to integrate with I/O pooling loops and event frameworks.
*
* @param context binding discovery (or conncheck) context pointer
* @return recommended maximum delay (in milliseconds) to wait for a
* response.
*/
unsigned
stun_bind_timeout
(
const
stun_bind_t
*
context
);
/**
* Handles retransmission timeout, and sends request retransmit if needed.
* This should be called whenever event polling indicates that
* stun_bind_timeout() has elapsed. It is however safe to call this earlier
* (in which case retransmission will not occur) or later (in which case
* late retransmission will be done).
*
* @param context binding discovery (or conncheck) context pointer
*
* @return ETIMEDOUT if the transaction has timed out, or EAGAIN if it is
* still pending.
*
* If anything except EAGAIN (but including zero) is returned, the context
* is free'd and must no longer be used.
*/
int
stun_bind_elapse
(
stun_bind_t
*
context
);
/**
* Gives data to be processed within the context of a STUN Binding discovery
* or ICE connectivity check.
*
* @param context context (from stun_bind_start() or stun_conncheck_start())
* @param buf pointer to received data to be processed
* @param len byte length of data at @a buf
* @param addr socket address pointer to receive mapped address in case of
* successful processing
* @param addrlen [IN/OUT] pointer to the size of the socket address buffer
* at @a addr upon entry, set to the useful size on success
*
* @return 0 on success, an error code otherwise:
* - EAGAIN: ignored invalid message (non-fatal error)
* - ECONNRESET: role conflict error from server
* - ECONNREFUSED: any other fatal error message from server
* - EPROTO: unsupported message from server
* - ENOENT: no mapped address in message from server
* - EAFNOSUPPORT: unsupported mapped address family from server
* - EINVAL: invalid mapped address from server
*
* If anything except EAGAIN (but including zero) is returned, the context
* is free'd and must no longer be used.
*/
int
stun_bind_process
(
stun_bind_t
*
restrict
context
,
const
void
*
restrict
buf
,
size_t
len
,
struct
sockaddr
*
restrict
addr
,
socklen_t
*
addrlen
);
typedef
enum
{
STUN_USAGE_BIND_RETURN_SUCCESS
,
STUN_USAGE_BIND_RETURN_ERROR
,
STUN_USAGE_BIND_RETURN_RETRY
,
STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER
,
STUN_USAGE_BIND_RETURN_TIMEOUT
,
}
StunUsageBindReturn
;
/**
* Sends a STUN Binding indication, aka ICE keep-alive packet.
*
* @param fd socket descriptor to send packet through
* @param srv destination socket address (possibly NULL if connected)
* @param srvlen destination socket address length (possibly 0)
* @return 0 on success, an error code from sendto() otherwise.
*/
int
stun_bind_keepalive
(
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
int
compat
);
/**
* Starts a connectivity check using STUN Binding discovery.
*
* @param context pointer to an opaque pointer that will be passed to
* stun_bind_resume() afterward
* @param fd socket to use for discovery, or -1 to create one
* @param srv STUN server socket address
* @param srvlen STUN server socket address length
* @param username nul-terminated username for authentication
* (need not be kept valid after return)
* @param password nul-terminated shared secret (ICE password)
* (need not be kept valid after return)
* @param cand_use whether to include a USE-CANDIDATE flag
* @param priority host-byte order PRIORITY value
* @param controlling whether we are in controlling (true) or
* controlled (false) state
* @param tie control tie breaker value (host-byte order)
*
* @return 0 on success, a standard error value otherwise.
*/
int
stun_conncheck_start
(
stun_bind_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
,
const
char
*
username
,
const
char
*
password
,
bool
cand_use
,
bool
controlling
,
uint32_t
priority
,
uint64_t
tie
,
uint32_t
compat
);
/**
* <b>Provisional</b> and incomplete STUN NAT control API
* Subject to change.
*/
typedef
struct
stun_nested_s
stun_nested_t
;
int
stun_nested_start
(
stun_nested_t
**
restrict
context
,
int
fd
,
const
struct
sockaddr
*
restrict
mapad
,
const
struct
sockaddr
*
restrict
natad
,
socklen_t
adlen
,
uint32_t
refresh
,
int
compat
);
size_t
stun_usage_bind_create
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buffer
,
size_t
buffer_len
);
int
stun_nested_process
(
stun_nested_t
*
restrict
ctx
,
const
void
*
restrict
buf
,
size_t
len
,
struct
sockaddr
*
restrict
intad
,
socklen_t
*
ad
len
);
StunUsageBindReturn
stun_usage_bind_process
(
StunMessage
*
msg
,
struct
sockaddr
*
addr
,
socklen_t
*
addr
len
,
struct
sockaddr
*
alternate_server
,
socklen_t
*
alternate_server_
len
);
size_t
stun_usage_bind_keepalive
(
StunAgent
*
agent
,
StunMessage
*
msg
,
uint8_t
*
buf
,
size_t
len
);
StunUsageBindReturn
stun_usage_bind_run
(
const
struct
sockaddr
*
srv
,
socklen_t
srvlen
,
struct
sockaddr
*
addr
,
socklen_t
*
addrlen
);
# ifdef __cplusplus
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment