patch: add turnc_send() and turnc_recv()
This commit is contained in:
parent
7f973a8bc8
commit
3a209fa607
2 changed files with 155 additions and 1 deletions
|
@ -22,6 +22,8 @@ int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto,
|
|||
void *sock, int layer, const struct sa *srv,
|
||||
const char *username, const char *password,
|
||||
uint32_t lifetime, turnc_h *th, void *arg);
|
||||
int turnc_send(struct turnc *turnc, const struct sa *dst, struct mbuf *mb);
|
||||
int turnc_recv(struct turnc *turnc, struct sa *src, struct mbuf *mb);
|
||||
int turnc_add_perm(struct turnc *turnc, const struct sa *peer,
|
||||
turnc_perm_h *ph, void *arg);
|
||||
int turnc_add_chan(struct turnc *turnc, const struct sa *peer,
|
||||
|
|
154
src/turn/turnc.c
154
src/turn/turnc.c
|
@ -234,7 +234,7 @@ static int refresh_request(struct turnc *t, uint32_t lifetime, bool reset_ls,
|
|||
}
|
||||
|
||||
|
||||
static inline size_t stun_indlen(struct sa *sa)
|
||||
static inline size_t stun_indlen(const struct sa *sa)
|
||||
{
|
||||
size_t len = STUN_HEADER_SIZE + STUN_ATTR_HEADER_SIZE * 2;
|
||||
|
||||
|
@ -460,6 +460,158 @@ int turnc_alloc(struct turnc **turncp, const struct stun_conf *conf, int proto,
|
|||
}
|
||||
|
||||
|
||||
int turnc_send(struct turnc *turnc, const struct sa *dst, struct mbuf *mb)
|
||||
{
|
||||
size_t pos, indlen;
|
||||
struct chan *chan;
|
||||
int err;
|
||||
|
||||
if (!turnc || !dst || !mb)
|
||||
return EINVAL;
|
||||
|
||||
chan = turnc_chan_find_peer(turnc, dst);
|
||||
if (chan) {
|
||||
struct chan_hdr hdr;
|
||||
|
||||
if (mb->pos < CHAN_HDR_SIZE)
|
||||
return EINVAL;
|
||||
|
||||
hdr.nr = turnc_chan_numb(chan);
|
||||
hdr.len = mbuf_get_left(mb);
|
||||
|
||||
mb->pos -= CHAN_HDR_SIZE;
|
||||
pos = mb->pos;
|
||||
|
||||
err = turnc_chan_hdr_encode(&hdr, mb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (turnc->proto == IPPROTO_TCP) {
|
||||
|
||||
mb->pos = mb->end;
|
||||
|
||||
/* padding */
|
||||
while (hdr.len++ & 0x03) {
|
||||
err = mbuf_write_u8(mb, 0x00);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
mb->pos = pos;
|
||||
}
|
||||
else {
|
||||
indlen = stun_indlen(dst);
|
||||
|
||||
if (mb->pos < indlen)
|
||||
return EINVAL;
|
||||
|
||||
mb->pos -= indlen;
|
||||
pos = mb->pos;
|
||||
|
||||
err = stun_msg_encode(mb, STUN_METHOD_SEND,
|
||||
STUN_CLASS_INDICATION, sendind_tid,
|
||||
NULL, NULL, 0, false, 0x00, 2,
|
||||
STUN_ATTR_XOR_PEER_ADDR, dst,
|
||||
STUN_ATTR_DATA, mb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
mb->pos = pos;
|
||||
}
|
||||
|
||||
switch (turnc->proto) {
|
||||
|
||||
case IPPROTO_UDP:
|
||||
err = udp_send(turnc->sock, &turnc->srv, mb);
|
||||
break;
|
||||
|
||||
case IPPROTO_TCP:
|
||||
err = tcp_send(turnc->sock, mb);
|
||||
break;
|
||||
|
||||
default:
|
||||
err = EPROTONOSUPPORT;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int turnc_recv(struct turnc *turnc, struct sa *src, struct mbuf *mb)
|
||||
{
|
||||
struct stun_attr *peer, *data;
|
||||
struct stun_unknown_attr ua;
|
||||
struct stun_msg *msg;
|
||||
int err = 0;
|
||||
|
||||
if (!turnc || !src || !mb)
|
||||
return EINVAL;
|
||||
|
||||
if (stun_msg_decode(&msg, mb, &ua)) {
|
||||
|
||||
struct chan_hdr hdr;
|
||||
struct chan *chan;
|
||||
|
||||
if (turnc_chan_hdr_decode(&hdr, mb))
|
||||
return EBADMSG;
|
||||
|
||||
if (mbuf_get_left(mb) < hdr.len)
|
||||
return EBADMSG;
|
||||
|
||||
chan = turnc_chan_find_numb(turnc, hdr.nr);
|
||||
if (!chan)
|
||||
return EBADMSG;
|
||||
|
||||
*src = *turnc_chan_peer(chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (stun_msg_class(msg)) {
|
||||
|
||||
case STUN_CLASS_INDICATION:
|
||||
if (ua.typec > 0) {
|
||||
err = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (stun_msg_method(msg) != STUN_METHOD_DATA) {
|
||||
err = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
peer = stun_msg_attr(msg, STUN_ATTR_XOR_PEER_ADDR);
|
||||
data = stun_msg_attr(msg, STUN_ATTR_DATA);
|
||||
if (!peer || !data) {
|
||||
err = EPROTO;
|
||||
break;
|
||||
}
|
||||
|
||||
*src = peer->v.xor_peer_addr;
|
||||
|
||||
mb->pos = data->v.data.pos;
|
||||
mb->end = data->v.data.end;
|
||||
break;
|
||||
|
||||
case STUN_CLASS_ERROR_RESP:
|
||||
case STUN_CLASS_SUCCESS_RESP:
|
||||
(void)stun_ctrans_recv(turnc->stun, msg, &ua);
|
||||
mb->pos = mb->end;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
mem_deref(msg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
bool turnc_request_loops(struct loop_state *ls, uint16_t scode)
|
||||
{
|
||||
bool loop = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue