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
53d18e51
Commit
53d18e51
authored
Jul 24, 2008
by
Youness Alaoui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated API for the transport utility functions
parent
f4134f02
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
58 additions
and
352 deletions
+58
-352
stun/usages/trans.c
stun/usages/trans.c
+43
-279
stun/usages/trans.h
stun/usages/trans.h
+15
-73
No files found.
stun/usages/trans.c
View file @
53d18e51
...
@@ -50,40 +50,21 @@
...
@@ -50,40 +50,21 @@
# include <poll.h>
# include <poll.h>
#endif
#endif
#include "stun/stunagent.h"
#include "trans.h"
#include "trans.h"
#define TRANS_OWN_FD 0x1
/* descriptor belongs to us */
int
stun_trans_init
(
stun_trans_t
*
tr
,
int
fd
,
#define TRANS_RELIABLE 0x2
/* reliable transport */
const
struct
sockaddr
*
srv
,
socklen_t
srvlen
)
#define TRANS_FGPRINT 0x4
/* whether to use FINGERPRINT */
int
stun_trans_init
(
stun_trans_t
*
restrict
tr
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
)
{
{
int
sotype
;
socklen_t
solen
=
sizeof
(
sotype
);
assert
(
fd
!=
-
1
);
assert
(
fd
!=
-
1
);
if
(
srvlen
>
sizeof
(
tr
->
sock
.
dst
))
if
(
srvlen
>
sizeof
(
tr
->
dst
))
return
ENOBUFS
;
return
ENOBUFS
;
tr
->
flags
=
0
;
tr
->
own_fd
=
-
1
;
tr
->
msg
.
offset
=
0
;
tr
->
fd
=
fd
;
tr
->
sock
.
fd
=
fd
;
memcpy
(
&
tr
->
sock
.
dst
,
srv
,
tr
->
sock
.
dstlen
=
srvlen
);
tr
->
key
.
length
=
0
;
tr
->
key
.
value
=
NULL
;
assert
(
getsockopt
(
fd
,
SOL_SOCKET
,
SO_TYPE
,
&
sotype
,
&
solen
)
==
0
);
tr
->
dstlen
=
srvlen
;
(
void
)
getsockopt
(
fd
,
SOL_SOCKET
,
SO_TYPE
,
&
sotype
,
&
solen
);
memcpy
(
&
tr
->
dst
,
srv
,
srvlen
);
switch
(
sotype
)
{
case
SOCK_STREAM
:
case
SOCK_SEQPACKET
:
tr
->
flags
|=
TRANS_RELIABLE
;
}
return
0
;
return
0
;
}
}
...
@@ -149,7 +130,7 @@ int stun_trans_create (stun_trans_t *restrict tr, int type, int proto,
...
@@ -149,7 +130,7 @@ int stun_trans_create (stun_trans_t *restrict tr, int type, int proto,
if
(
val
)
if
(
val
)
goto
error
;
goto
error
;
tr
->
flags
|=
TRANS_OWN_FD
;
tr
->
own_fd
=
tr
->
fd
;
return
0
;
return
0
;
error:
error:
...
@@ -162,15 +143,14 @@ void stun_trans_deinit (stun_trans_t *tr)
...
@@ -162,15 +143,14 @@ void stun_trans_deinit (stun_trans_t *tr)
{
{
int
saved
=
errno
;
int
saved
=
errno
;
assert
(
tr
->
sock
.
fd
!=
-
1
);
assert
(
tr
->
fd
!=
-
1
);
if
(
tr
->
flags
&
TRANS_OWN_FD
)
if
(
tr
->
own_fd
!=
-
1
)
close
(
tr
->
sock
.
fd
);
close
(
tr
->
own_fd
);
free
(
tr
->
key
.
value
);
tr
->
own_fd
=
-
1
;
tr
->
fd
=
-
1
;
#ifndef NDEBUG
tr
->
sock
.
fd
=
-
1
;
#endif
errno
=
saved
;
errno
=
saved
;
}
}
...
@@ -183,33 +163,6 @@ void stun_trans_deinit (stun_trans_t *tr)
...
@@ -183,33 +163,6 @@ void stun_trans_deinit (stun_trans_t *tr)
#endif
#endif
static
int
stun_trans_send
(
stun_trans_t
*
tr
);
int
stun_trans_start
(
stun_trans_t
*
tr
)
{
int
val
;
tr
->
msg
.
offset
=
0
;
if
(
tr
->
flags
&
TRANS_RELIABLE
)
/*
* FIXME: wait for three-way handshake, somewhere
*/
stun_timer_start_reliable
(
&
tr
->
timer
);
else
stun_timer_start
(
&
tr
->
timer
);
stun_debug
(
"STUN transaction @%p started (timeout: %ums)
\n
"
,
tr
,
stun_trans_timeout
(
tr
));
val
=
stun_trans_send
(
tr
);
if
(
val
)
return
val
;
return
0
;
}
static
int
stun_err_dequeue
(
int
fd
)
static
int
stun_err_dequeue
(
int
fd
)
{
{
#ifdef MSG_ERRQUEUE
#ifdef MSG_ERRQUEUE
...
@@ -226,7 +179,19 @@ static int stun_err_dequeue (int fd)
...
@@ -226,7 +179,19 @@ static int stun_err_dequeue (int fd)
}
}
ssize_t
stun_sendto
(
int
fd
,
const
uint8_t
*
buf
,
size_t
len
,
ssize_t
stun_trans_send
(
stun_trans_t
*
tr
,
const
uint8_t
*
buf
,
size_t
len
)
{
return
stun_trans_sendto
(
tr
,
buf
,
len
,
(
struct
sockaddr
*
)
&
tr
->
dst
,
tr
->
dstlen
);
}
ssize_t
stun_trans_recv
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
maxlen
)
{
return
stun_trans_recvfrom
(
tr
,
buf
,
maxlen
,
NULL
,
NULL
);
}
ssize_t
stun_trans_sendto
(
stun_trans_t
*
tr
,
const
uint8_t
*
buf
,
size_t
len
,
const
struct
sockaddr
*
dst
,
socklen_t
dstlen
)
const
struct
sockaddr
*
dst
,
socklen_t
dstlen
)
{
{
static
const
int
flags
=
MSG_DONTWAIT
|
MSG_NOSIGNAL
;
static
const
int
flags
=
MSG_DONTWAIT
|
MSG_NOSIGNAL
;
...
@@ -235,17 +200,17 @@ ssize_t stun_sendto (int fd, const uint8_t *buf, size_t len,
...
@@ -235,17 +200,17 @@ ssize_t stun_sendto (int fd, const uint8_t *buf, size_t len,
do
do
{
{
if
(
dstlen
>
0
)
if
(
dstlen
>
0
)
val
=
sendto
(
fd
,
buf
,
len
,
flags
,
dst
,
dstlen
);
val
=
sendto
(
tr
->
fd
,
buf
,
len
,
flags
,
dst
,
dstlen
);
else
else
val
=
send
(
fd
,
buf
,
len
,
flags
);
val
=
send
(
tr
->
fd
,
buf
,
len
,
flags
);
}
}
while
((
val
==
-
1
)
&&
stun_err_dequeue
(
fd
));
while
((
val
==
-
1
)
&&
stun_err_dequeue
(
tr
->
fd
));
return
val
;
return
val
;
}
}
ssize_t
stun_
recvfrom
(
int
fd
,
uint8_t
*
buf
,
size_t
maxlen
,
ssize_t
stun_
trans_recvfrom
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
maxlen
,
struct
sockaddr
*
restrict
dst
,
struct
sockaddr
*
restrict
dst
,
socklen_t
*
restrict
dstlen
)
socklen_t
*
restrict
dstlen
)
{
{
...
@@ -253,90 +218,22 @@ ssize_t stun_recvfrom (int fd, uint8_t *buf, size_t maxlen,
...
@@ -253,90 +218,22 @@ ssize_t stun_recvfrom (int fd, uint8_t *buf, size_t maxlen,
ssize_t
val
;
ssize_t
val
;
if
(
dstlen
!=
NULL
)
if
(
dstlen
!=
NULL
)
val
=
recvfrom
(
fd
,
buf
,
maxlen
,
flags
,
dst
,
dstlen
);
val
=
recvfrom
(
tr
->
fd
,
buf
,
maxlen
,
flags
,
dst
,
dstlen
);
else
else
val
=
recv
(
fd
,
buf
,
maxlen
,
flags
);
val
=
recv
(
tr
->
fd
,
buf
,
maxlen
,
flags
);
if
((
val
==
-
1
)
&&
stun_err_dequeue
(
fd
))
if
((
val
==
-
1
)
&&
stun_err_dequeue
(
tr
->
fd
))
errno
=
EAGAIN
;
errno
=
EAGAIN
;
return
val
;
return
val
;
}
}
unsigned
stun_trans_timeout
(
const
stun_trans_t
*
tr
)
{
assert
(
tr
!=
NULL
);
assert
(
tr
->
sock
.
fd
!=
-
1
);
return
stun_timer_remainder
(
&
tr
->
timer
);
}
int
stun_trans_fd
(
const
stun_trans_t
*
tr
)
int
stun_trans_fd
(
const
stun_trans_t
*
tr
)
{
{
assert
(
tr
!=
NULL
);
assert
(
tr
!=
NULL
);
assert
(
tr
->
sock
.
fd
!=
-
1
);
return
tr
->
fd
;
return
tr
->
sock
.
fd
;
}
bool
stun_trans_reading
(
const
stun_trans_t
*
tr
)
{
(
void
)
tr
;
return
true
;
}
bool
stun_trans_writing
(
const
stun_trans_t
*
tr
)
{
(
void
)
tr
;
return
false
;
}
/**
* Try to send STUN request/indication
*/
static
int
stun_trans_send
(
stun_trans_t
*
tr
)
{
const
uint8_t
*
data
=
tr
->
msg
.
buf
+
tr
->
msg
.
offset
;
size_t
len
=
tr
->
msg
.
length
-
tr
->
msg
.
offset
;
ssize_t
val
;
val
=
stun_sendto
(
tr
->
sock
.
fd
,
data
,
len
,
(
struct
sockaddr
*
)
&
tr
->
sock
.
dst
,
tr
->
sock
.
dstlen
);
if
(
val
<
0
)
return
errno
;
/* Message sent succesfully! */
tr
->
msg
.
offset
+=
val
;
assert
(
tr
->
msg
.
offset
<=
tr
->
msg
.
length
);
return
0
;
}
int
stun_trans_tick
(
stun_trans_t
*
tr
)
{
assert
(
tr
->
sock
.
fd
!=
-
1
);
switch
(
stun_timer_refresh
(
&
tr
->
timer
))
{
case
-
1
:
stun_debug
(
"STUN transaction @%p failed: time out.
\n
"
,
tr
);
return
ETIMEDOUT
;
// fatal error!
case
0
:
/* Retransmit can only happen with non reliable transport */
assert
((
tr
->
flags
&
TRANS_RELIABLE
)
==
0
);
tr
->
msg
.
offset
=
0
;
stun_trans_send
(
tr
);
stun_debug
(
"STUN transaction @%p retransmitted (timeout: %ums).
\n
"
,
tr
,
stun_trans_timeout
(
tr
));
}
return
EAGAIN
;
}
}
...
@@ -346,156 +243,23 @@ int stun_trans_tick (stun_trans_t *tr)
...
@@ -346,156 +243,23 @@ int stun_trans_tick (stun_trans_t *tr)
* @return ETIMEDOUT if the transaction has timed out, or 0 if an incoming
* @return ETIMEDOUT if the transaction has timed out, or 0 if an incoming
* message needs to be processed.
* message needs to be processed.
*/
*/
static
int
stun_trans_wait
(
stun_trans_t
*
tr
)
int
stun_trans_poll
(
stun_trans_t
*
tr
,
unsigned
int
delay
)
{
{
#ifdef HAVE_POLL
#ifdef HAVE_POLL
int
val
=
0
;
struct
pollfd
ufd
;
do
{
struct
pollfd
ufd
;
unsigned
delay
=
stun_trans_timeout
(
tr
);
memset
(
&
ufd
,
0
,
sizeof
(
ufd
));
memset
(
&
ufd
,
0
,
sizeof
(
ufd
));
ufd
.
fd
=
stun_trans_fd
(
tr
);
ufd
.
fd
=
stun_trans_fd
(
tr
);
if
(
stun_trans_writing
(
tr
))
ufd
.
events
|=
POLLIN
;
ufd
.
events
|=
POLLOUT
;
if
(
stun_trans_reading
(
tr
))
ufd
.
events
|=
POLLIN
;
if
(
poll
(
&
ufd
,
1
,
delay
)
<=
0
)
if
(
poll
(
&
ufd
,
1
,
delay
)
<=
0
)
{
{
return
EAGAIN
;
val
=
stun_trans_tick
(
tr
);
continue
;
}
val
=
0
;
}
}
while
(
val
==
EAGAIN
);
return
val
;
return
0
;
#else
#else
(
void
)
tr
;
(
void
)
tr
;
return
ENOSYS
;
return
ENOSYS
;
#endif
#endif
}
}
int
stun_trans_recv
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
buflen
)
{
for
(;;)
{
ssize_t
val
=
stun_trans_wait
(
tr
);
if
(
val
)
{
errno
=
val
/* = ETIMEDOUT */
;
return
-
1
;
}
val
=
stun_recv
(
tr
->
sock
.
fd
,
buf
,
buflen
);
if
(
val
>=
0
)
return
val
;
}
}
int
stun_trans_preprocess
(
StunAgent
*
agent
,
stun_trans_t
*
restrict
tr
,
int
*
pcode
,
const
void
*
restrict
buf
,
size_t
len
)
{
StunValidationStatus
valid
;
assert
(
pcode
!=
NULL
);
*
pcode
=
-
1
;
valid
=
stun_agent_validate
(
agent
,
&
tr
->
message
,
buf
,
len
,
NULL
,
NULL
);
if
(
valid
==
STUN_VALIDATION_UNKNOWN_ATTRIBUTE
)
return
EPROTO
;
if
(
valid
!=
STUN_VALIDATION_SUCCESS
)
return
EAGAIN
;
switch
(
stun_message_get_class
(
&
tr
->
message
))
{
case
STUN_REQUEST
:
case
STUN_INDICATION
:
return
EAGAIN
;
break
;
case
STUN_RESPONSE
:
break
;
case
STUN_ERROR
:
if
(
stun_message_find_error
(
&
tr
->
message
,
pcode
)
!=
0
)
return
EAGAIN
;
// missing ERROR-CODE: ignore message
break
;
}
stun_debug
(
"Received %u-bytes STUN message
\n
"
,
(
unsigned
)
len
);
/* NOTE: currently we ignore unauthenticated messages if the context
* is authenticated, for security reasons. */
if
(
*
pcode
>=
0
)
{
stun_debug
(
" STUN error message received (code: %d)
\n
"
,
*
pcode
);
/* ALTERNATE-SERVER mechanism */
if
((
tr
->
key
.
value
!=
NULL
)
&&
((
*
pcode
/
100
)
==
3
))
{
struct
sockaddr_storage
srv
;
socklen_t
slen
=
sizeof
(
srv
);
if
(
stun_message_find_addr
(
&
tr
->
message
,
STUN_ATTRIBUTE_ALTERNATE_SERVER
,
(
struct
sockaddr
*
)
&
srv
,
&
slen
))
{
stun_debug
(
" Unexpectedly missing ALTERNATE-SERVER attribute
\n
"
);
return
ECONNREFUSED
;
}
if
(
tr
->
sock
.
dstlen
==
0
)
{
if
(
connect
(
tr
->
sock
.
fd
,
(
struct
sockaddr
*
)
&
srv
,
slen
))
{
/* This error case includes address family mismatch */
stun_debug
(
" Error switching to alternate server: %s
\n
"
,
strerror
(
errno
));
return
ECONNREFUSED
;
}
}
else
{
if
((
tr
->
sock
.
dst
.
ss_family
!=
srv
.
ss_family
)
||
(
slen
>
sizeof
(
tr
->
sock
.
dst
)))
{
stun_debug
(
" Unsupported alternate server
\n
"
);
return
ECONNREFUSED
;
}
memcpy
(
&
tr
->
sock
.
dst
,
&
srv
,
tr
->
sock
.
dstlen
=
slen
);
}
stun_debug
(
" Restarting with alternate server
\n
"
);
if
(
stun_trans_start
(
tr
)
==
0
)
return
EAGAIN
;
stun_debug
(
" Restart failed!
\n
"
);
}
return
ECONNREFUSED
;
}
return
0
;
}
ssize_t
stun_send
(
int
fd
,
const
uint8_t
*
buf
,
size_t
len
)
{
return
stun_sendto
(
fd
,
buf
,
len
,
NULL
,
0
);
}
ssize_t
stun_recv
(
int
fd
,
uint8_t
*
buf
,
size_t
maxlen
)
{
return
stun_recvfrom
(
fd
,
buf
,
maxlen
,
NULL
,
NULL
);
}
stun/usages/trans.h
View file @
53d18e51
...
@@ -44,33 +44,14 @@
...
@@ -44,33 +44,14 @@
# include <sys/types.h>
# include <sys/types.h>
# include <sys/socket.h>
# include <sys/socket.h>
# include "timer.h"
#include "stun/stunagent.h"
typedef
struct
stun_trans_s
typedef
struct
stun_trans_s
{
{
stun_timer_t
timer
;
unsigned
flags
;
int
fd
;
int
own_fd
;
struct
socklen_t
dstlen
;
{
struct
sockaddr_storage
dst
;
size_t
length
,
offset
;
uint8_t
buf
[
STUN_MAX_MESSAGE_SIZE
];
}
msg
;
StunMessage
message
;
struct
{
int
fd
;
socklen_t
dstlen
;
struct
sockaddr_storage
dst
;
}
sock
;
struct
{
size_t
length
;
uint8_t
*
value
;
}
key
;
}
stun_trans_t
;
}
stun_trans_t
;
...
@@ -86,8 +67,8 @@ extern "C" {
...
@@ -86,8 +67,8 @@ extern "C" {
* @param srv STUN server socket address (ignored if @a srvlen is 0)
* @param srv STUN server socket address (ignored if @a srvlen is 0)
* @param srvlen STUN server socket address length (or 0 @a fd is connected)
* @param srvlen STUN server socket address length (or 0 @a fd is connected)
*/
*/
int
stun_trans_init
(
stun_trans_t
*
restrict
tr
,
int
fd
,
int
stun_trans_init
(
stun_trans_t
*
tr
,
int
fd
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
);
const
struct
sockaddr
*
srv
,
socklen_t
srvlen
);
/**
/**
* Initializes a new STUN request transaction with its dedicated socket
* Initializes a new STUN request transaction with its dedicated socket
...
@@ -98,24 +79,14 @@ int stun_trans_init (stun_trans_t *restrict tr, int fd,
...
@@ -98,24 +79,14 @@ int stun_trans_init (stun_trans_t *restrict tr, int fd,
* @param srv STUN server socket address (ignored if @a srvlen is 0)
* @param srv STUN server socket address (ignored if @a srvlen is 0)
* @param srvlen STUN server socket address length (or 0 @a fd is connected)
* @param srvlen STUN server socket address length (or 0 @a fd is connected)
*/
*/
int
stun_trans_create
(
stun_trans_t
*
restrict
tr
,
int
sotype
,
int
proto
,
int
stun_trans_create
(
stun_trans_t
*
tr
,
int
sotype
,
int
proto
,
const
struct
sockaddr
*
restrict
srv
,
socklen_t
srvlen
);
const
struct
sockaddr
*
srv
,
socklen_t
srvlen
);
/**
/**
* Releases resources allocated by stun_trans_init() or stun_trans_create(),
* Releases resources allocated by stun_trans_init() or stun_trans_create(),
* and cancel the transaction if still pending.
* and cancel the transaction if still pending.
*/
*/
void
stun_trans_deinit
(
stun_trans_t
*
restrict
tr
);
void
stun_trans_deinit
(
stun_trans_t
*
tr
);
int
stun_trans_start
(
stun_trans_t
*
restrict
tr
);
/**
* This is meant to integrate with I/O pooling loops and event frameworks.
*
* @return recommended maximum delay (in milliseconds) to wait for a
* response.
*/
unsigned
stun_trans_timeout
(
const
stun_trans_t
*
tr
);
/**
/**
* This is meant to integrate with I/O polling loops and event frameworks.
* This is meant to integrate with I/O polling loops and event frameworks.
...
@@ -124,36 +95,7 @@ unsigned stun_trans_timeout (const stun_trans_t *tr);
...
@@ -124,36 +95,7 @@ unsigned stun_trans_timeout (const stun_trans_t *tr);
* Always succeeds.
* Always succeeds.
*/
*/
int
stun_trans_fd
(
const
stun_trans_t
*
tr
);
int
stun_trans_fd
(
const
stun_trans_t
*
tr
);
int
stun_trans_poll
(
stun_trans_t
*
tr
,
unsigned
int
delay
);
/**
* This is meant to integrate with I/O polling loops and event frameworks.
*
* @return whether the transaction waits for input (from the network).
*/
bool
stun_trans_reading
(
const
stun_trans_t
*
tr
);
/**
* This is meant to integrate with I/O polling loops and event frameworks.
*
* @return whether the transaction waits for output (to the network).
*/
bool
stun_trans_writing
(
const
stun_trans_t
*
tr
);
/**
* Refreshes a STUN request transaction state according to current time,
* retransmits request if needed. This function should be called when
* stun_trans_timeout() reaches zero
*
* @return ETIMEDOUT if the transaction has timed out, or EAGAIN if it is
* still pending.
*/
int
stun_trans_tick
(
stun_trans_t
*
tr
);
int
stun_trans_recv
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
buflen
);
int
stun_trans_preprocess
(
StunAgent
*
agent
,
stun_trans_t
*
restrict
tr
,
int
*
code
,
const
void
*
restrict
buf
,
size_t
len
);
/**
/**
* Safe wrapper around sendto()
* Safe wrapper around sendto()
...
@@ -165,16 +107,16 @@ int stun_trans_preprocess (StunAgent *agent,
...
@@ -165,16 +107,16 @@ int stun_trans_preprocess (StunAgent *agent,
* This can be used to send non-requests message, i.e. whenever the
* This can be used to send non-requests message, i.e. whenever the
* transaction is not used.
* transaction is not used.
*/
*/
ssize_t
stun_
sendto
(
int
fd
,
const
uint8_t
*
buf
,
size_t
len
,
ssize_t
stun_
trans_sendto
(
stun_trans_t
*
tr
,
const
uint8_t
*
buf
,
size_t
len
,
const
struct
sockaddr
*
dst
,
socklen_t
dstlen
);
const
struct
sockaddr
*
dst
,
socklen_t
dstlen
);
ssize_t
stun_
recvfrom
(
int
fd
,
uint8_t
*
buf
,
size_t
maxlen
,
ssize_t
stun_
trans_recvfrom
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
maxlen
,
struct
sockaddr
*
restrict
src
,
struct
sockaddr
*
restrict
src
,
socklen_t
*
restrict
srclen
);
socklen_t
*
restrict
srclen
);
ssize_t
stun_
send
(
int
fd
,
const
uint8_t
*
buf
,
size_t
len
);
ssize_t
stun_
trans_send
(
stun_trans_t
*
tr
,
const
uint8_t
*
buf
,
size_t
len
);
ssize_t
stun_
recv
(
int
fd
,
uint8_t
*
buf
,
size_t
maxlen
);
ssize_t
stun_
trans_recv
(
stun_trans_t
*
tr
,
uint8_t
*
buf
,
size_t
maxlen
);
# ifdef __cplusplus
# 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