155
169
return stun_agent_finish_message (agent, msg, NULL, 0);
174
typedef struct stun_trans_s
180
struct sockaddr_storage dst;
185
STUN_USAGE_TRANS_RETURN_SUCCESS,
186
STUN_USAGE_TRANS_RETURN_ERROR,
187
STUN_USAGE_TRANS_RETURN_RETRY,
188
STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS,
189
STUN_USAGE_TRANS_RETURN_UNSUPPORTED,
190
} StunUsageTransReturn;
195
static StunUsageTransReturn
196
stun_trans_init (StunTransport *tr, int fd,
197
const struct sockaddr *srv, socklen_t srvlen)
201
if ((size_t) srvlen > sizeof (tr->dst))
202
return STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS;
208
memcpy (&tr->dst, srv, srvlen);
210
return STUN_USAGE_TRANS_RETURN_SUCCESS;
215
* Creates and connects a socket. This is useful when a socket is to be used
216
* for multiple consecutive transactions (e.g. TURN).
218
static int stun_socket (int family, int type, int proto)
220
int fd = socket (family, type, proto);
225
fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC);
228
fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK);
232
if (type == SOCK_DGRAM)
234
/* Linux specifics for ICMP errors on non-connected sockets */
239
setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
242
setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
252
static StunUsageTransReturn
253
stun_trans_create (StunTransport *tr, int type, int proto,
254
const struct sockaddr *srv, socklen_t srvlen)
256
StunUsageTransReturn val = STUN_USAGE_TRANS_RETURN_ERROR;
259
if ((size_t) srvlen < sizeof(*srv))
260
return STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS;
262
fd = stun_socket (srv->sa_family, type, proto);
264
return STUN_USAGE_TRANS_RETURN_ERROR;
266
if (connect (fd, srv, srvlen) &&
268
(WSAGetLastError () != WSAEINPROGRESS)) {
270
(errno != EINPROGRESS)) {
275
val = stun_trans_init (tr, fd, NULL, 0);
280
return STUN_USAGE_TRANS_RETURN_SUCCESS;
288
static void stun_trans_deinit (StunTransport *tr)
292
assert (tr->fd != -1);
294
if (tr->own_fd != -1)
305
# define MSG_DONTWAIT 0
308
# define MSG_NOSIGNAL 0
312
static int stun_err_dequeue (int fd)
316
int saved_errno = errno, ret;
318
memset (&hdr, 0, sizeof (hdr));
319
ret = (recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0);
329
stun_trans_sendto (StunTransport *tr, const uint8_t *buf, size_t len,
330
const struct sockaddr *dst, socklen_t dstlen)
332
static const int flags = MSG_DONTWAIT | MSG_NOSIGNAL;
338
val = sendto (tr->fd, (void *)buf, len, flags, dst, dstlen);
340
val = send (tr->fd, (void *)buf, len, flags);
342
while ((val == -1) && stun_err_dequeue (tr->fd));
349
stun_trans_recvfrom (StunTransport *tr, uint8_t *buf, size_t maxlen,
350
struct sockaddr * dst,
353
static const int flags = MSG_DONTWAIT | MSG_NOSIGNAL;
357
val = recvfrom (tr->fd, (void *)buf, maxlen, flags, dst, dstlen);
359
val = recv (tr->fd, (void *)buf, maxlen, flags);
362
stun_err_dequeue (tr->fd);
369
stun_trans_send (StunTransport *tr, const uint8_t *buf, size_t len)
371
return stun_trans_sendto (tr, buf, len,
372
(struct sockaddr *)&tr->dst, tr->dstlen);
376
stun_trans_recv (StunTransport *tr, uint8_t *buf, size_t maxlen)
378
return stun_trans_recvfrom (tr, buf, maxlen, NULL, NULL);
382
static int stun_trans_fd (const StunTransport *tr)
390
* Waits for a response or timeout to occur.
392
* @return ETIMEDOUT if the transaction has timed out, or 0 if an incoming
393
* message needs to be processed.
395
static StunUsageTransReturn
396
stun_trans_poll (StunTransport *tr, unsigned int delay)
401
memset (&ufd, 0, sizeof (ufd));
402
ufd.fd = stun_trans_fd (tr);
404
ufd.events |= POLLIN;
406
if (poll (&ufd, 1, delay) <= 0) {
407
return STUN_USAGE_TRANS_RETURN_RETRY;
410
return STUN_USAGE_TRANS_RETURN_SUCCESS;
413
return STUN_USAGE_TRANS_RETURN_UNSUPPORTED;
158
419
/** Blocking mode STUN binding discovery */
159
420
StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
160
421
socklen_t srvlen, struct sockaddr *addr, socklen_t *addrlen)
166
427
uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];