Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
R
RIOT
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
cm-projects
RIOT
Commits
af1eca90
Commit
af1eca90
authored
8 years ago
by
Ken Bannister
Browse files
Options
Downloads
Patches
Plain Diff
gcoap: Rebase messaging on sock API
parent
fa815993
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
sys/include/net/gcoap.h
+56
-25
56 additions, 25 deletions
sys/include/net/gcoap.h
sys/net/application_layer/coap/gcoap.c
+86
-150
86 additions, 150 deletions
sys/net/application_layer/coap/gcoap.c
with
142 additions
and
175 deletions
sys/include/net/gcoap.h
+
56
−
25
View file @
af1eca90
...
@@ -9,14 +9,21 @@
...
@@ -9,14 +9,21 @@
/**
/**
* @defgroup net_gcoap CoAP
* @defgroup net_gcoap CoAP
* @ingroup net
* @ingroup net
* @brief sock-based implementation of CoAP protocol, RFC 7252
* @brief High-level interface to CoAP messaging
*
*
* ## Architecture ##
* gcoap provides a high-level interface for writing CoAP messages via RIOT's
* Requests and responses are exchanged via an asynchronous RIOT message
* sock networking API. gcoap internalizes network event processing so an
* processing thread. Depends on nanocoap for base level structs and
* application only needs to focus on request/response handling. For a server,
* functionality.
* gcoap accepts a list of resource paths with callbacks for writing the
*
* response. For a client, gcoap provides a function to send a request, with a
* Uses a single UDP port for communication to support RFC 6282 compression.
* callback for reading the server response. Generation of the request or
* response requires from one to three well-defined steps, depending on
* inclusion of a payload.
*
* gcoap allocates a RIOT message processing thread, so a single instance can
* serve multiple applications. This approach also means gcoap uses a single UDP
* port, which supports RFC 6282 compression. Internally, gcoap depends on the
* nanocoap package for base level structs and functionality.
*
*
* ## Server Operation ##
* ## Server Operation ##
*
*
...
@@ -61,11 +68,10 @@
...
@@ -61,11 +68,10 @@
*
*
* ## Client Operation ##
* ## Client Operation ##
*
*
* gcoap uses RIOT's asynchronous messaging facility to send and receive
* Client operation includes two phases: creating and sending a request, and
* messages. So, client operation includes two phases: creating and sending a
* handling the response aynchronously in a client supplied callback. See
* request, and handling the response aynchronously in a client supplied
* `examples/gcoap/gcoap_cli.c` for a simple example of sending a request and
* callback. See `examples/gcoap/gcoap_cli.c` for a simple example of sending
* reading the response.
* a request and reading the response.
*
*
* ### Creating a request ###
* ### Creating a request ###
*
*
...
@@ -85,8 +91,8 @@
...
@@ -85,8 +91,8 @@
* as described above. The gcoap_request() function is inline, and uses those
* as described above. The gcoap_request() function is inline, and uses those
* two functions.
* two functions.
*
*
* Finally, call gcoap_req_send()
with
the destination
host a
nd
po
r
t, as well
* Finally, call gcoap_req_send
2
()
for
the destination
e
ndpo
in
t, as well
as a
*
as a
callback function for the host's response.
* callback function for the host's response.
*
*
* ### Handling the response ###
* ### Handling the response ###
*
*
...
@@ -114,13 +120,13 @@
...
@@ -114,13 +120,13 @@
* header and the payload. So, gcoap provides space in the buffer for them in
* header and the payload. So, gcoap provides space in the buffer for them in
* the request/response ...init() function, and then writes them during
* the request/response ...init() function, and then writes them during
* gcoap_finish(). We trade some inefficiency/work in the buffer for
* gcoap_finish(). We trade some inefficiency/work in the buffer for
* simplicity
for
the
user
.
* simplicity
in
the
API
.
*
*
* ### Waiting for a response ###
* ### Waiting for a response ###
*
*
* We take advantage of RIOT's
GNRC stack
by using an xtimer to wait
for a
* We take advantage of RIOT's
asynchronous messaging
by using an xtimer to wait
* response, so the gcoap thread does not block while waiting. The user is
*
for a
response, so the gcoap thread does not block while waiting. The user is
* notified via the same callback whether the message is received or the wait
* notified via the same callback
,
whether the message is received or the wait
* times out. We track the response with an entry in the
* times out. We track the response with an entry in the
* `_coap_state.open_reqs` array.
* `_coap_state.open_reqs` array.
*
*
...
@@ -135,9 +141,7 @@
...
@@ -135,9 +141,7 @@
#ifndef GCOAP_H
#ifndef GCOAP_H
#define GCOAP_H
#define GCOAP_H
#include
"net/gnrc.h"
#include
"net/sock/udp.h"
#include
"net/gnrc/ipv6.h"
#include
"net/gnrc/udp.h"
#include
"nanocoap.h"
#include
"nanocoap.h"
#include
"xtimer.h"
#include
"xtimer.h"
...
@@ -199,15 +203,27 @@ extern "C" {
...
@@ -199,15 +203,27 @@ extern "C" {
#define GCOAP_MEMO_ERR (4)
/**< Error processing response packet */
#define GCOAP_MEMO_ERR (4)
/**< Error processing response packet */
/** @} */
/** @} */
/** @brief Time in usec that the event loop waits for an incoming CoAP message */
#define GCOAP_RECV_TIMEOUT (1 * US_PER_SEC)
/**
/**
*
* @brief Default time to wait for a non-confirmable response, in usec
* @brief Default time to wait for a non-confirmable response, in usec
*
*
* Set to 0 to disable timeout.
* Set to 0 to disable timeout.
*/
*/
#define GCOAP_NON_TIMEOUT (5000000U)
#define GCOAP_NON_TIMEOUT (5000000U)
/** @brief Identifies a gcoap-specific timeout IPC message */
/** @brief Identifies waiting timed out for a response to a sent message. */
#define GCOAP_NETAPI_MSG_TYPE_TIMEOUT (0x1501)
#define GCOAP_MSG_TYPE_TIMEOUT (0x1501)
/**
* @brief Identifies a request to interrupt listening for an incoming message
* on a sock.
*
* Allows the event loop to process IPC messages.
*/
#define GCOAP_MSG_TYPE_INTR (0x1502)
/**
/**
* @brief A modular collection of resources for a server
* @brief A modular collection of resources for a server
...
@@ -243,7 +259,6 @@ typedef struct {
...
@@ -243,7 +259,6 @@ typedef struct {
* @brief Container for the state of gcoap itself
* @brief Container for the state of gcoap itself
*/
*/
typedef
struct
{
typedef
struct
{
gnrc_netreg_entry_t
netreg_port
;
/**< Registration for IP port */
gcoap_listener_t
*
listeners
;
/**< List of registered listeners */
gcoap_listener_t
*
listeners
;
/**< List of registered listeners */
gcoap_request_memo_t
open_reqs
[
GCOAP_REQ_WAITING_MAX
];
gcoap_request_memo_t
open_reqs
[
GCOAP_REQ_WAITING_MAX
];
/**< Storage for open requests; if first
/**< Storage for open requests; if first
...
@@ -322,9 +337,25 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
...
@@ -322,9 +337,25 @@ static inline ssize_t gcoap_request(coap_pkt_t *pdu, uint8_t *buf, size_t len,
:
-
1
;
:
-
1
;
}
}
/**
* @brief Sends a buffer containing a CoAP request to the provided endpoint.
*
* @param[in] buf Buffer containing the PDU
* @param[in] len Length of the buffer
* @param[in] remote Destination for the packet
* @param[in] resp_handler Callback when response received
*
* @return length of the packet
* @return 0 if cannot send
*/
size_t
gcoap_req_send2
(
uint8_t
*
buf
,
size_t
len
,
sock_udp_ep_t
*
remote
,
gcoap_resp_handler_t
resp_handler
);
/**
/**
* @brief Sends a buffer containing a CoAP request to the provided host/port.
* @brief Sends a buffer containing a CoAP request to the provided host/port.
*
*
* @deprecated Please use @ref gcoap_req_send2() instead
*
* @param[in] buf Buffer containing the PDU
* @param[in] buf Buffer containing the PDU
* @param[in] len Length of the buffer
* @param[in] len Length of the buffer
* @param[in] addr Destination for the packet
* @param[in] addr Destination for the packet
...
...
This diff is collapsed.
Click to expand it.
sys/net/application_layer/coap/gcoap.c
+
86
−
150
View file @
af1eca90
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*/
*/
/**
/**
* @ingroup net_g
nrc_
coap
* @ingroup net_gcoap
* @{
* @{
*
*
* @file
* @file
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
*/
*/
#include
<errno.h>
#include
<errno.h>
#include
"net/g
nrc/
coap.h"
#include
"net/gcoap.h"
#include
"random.h"
#include
"random.h"
#include
"thread.h"
#include
"thread.h"
...
@@ -31,14 +31,11 @@
...
@@ -31,14 +31,11 @@
/* Internal functions */
/* Internal functions */
static
void
*
_event_loop
(
void
*
arg
);
static
void
*
_event_loop
(
void
*
arg
);
static
int
_register_port
(
gnrc_netreg_entry_t
*
netreg_port
,
uint16_t
port
);
static
void
_listen
(
sock_udp_t
*
sock
);
static
void
_receive
(
gnrc_pktsnip_t
*
pkt
,
ipv6_addr_t
*
src
,
uint16_t
port
);
static
size_t
_send
(
gnrc_pktsnip_t
*
coap_snip
,
ipv6_addr_t
*
addr
,
uint16_t
port
);
static
ssize_t
_well_known_core_handler
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
ssize_t
_well_known_core_handler
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
ssize_t
_write_options
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
ssize_t
_write_options
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
size_t
_handle_req
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
size_t
_handle_req
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
ssize_t
_finish_pdu
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
ssize_t
_finish_pdu
(
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
static
size_t
_send_buf
(
uint8_t
*
buf
,
size_t
len
,
ipv6_addr_t
*
src
,
uint16_t
port
);
static
void
_expire_request
(
gcoap_request_memo_t
*
memo
);
static
void
_expire_request
(
gcoap_request_memo_t
*
memo
);
static
void
_find_req_memo
(
gcoap_request_memo_t
**
memo_ptr
,
coap_pkt_t
*
pdu
,
static
void
_find_req_memo
(
gcoap_request_memo_t
**
memo_ptr
,
coap_pkt_t
*
pdu
,
uint8_t
*
buf
,
size_t
len
);
uint8_t
*
buf
,
size_t
len
);
...
@@ -55,97 +52,91 @@ static gcoap_listener_t _default_listener = {
...
@@ -55,97 +52,91 @@ static gcoap_listener_t _default_listener = {
};
};
static
gcoap_state_t
_coap_state
=
{
static
gcoap_state_t
_coap_state
=
{
.
netreg_port
=
GNRC_NETREG_ENTRY_INIT_PID
(
0
,
KERNEL_PID_UNDEF
),
.
listeners
=
&
_default_listener
,
.
listeners
=
&
_default_listener
,
};
};
static
kernel_pid_t
_pid
=
KERNEL_PID_UNDEF
;
static
kernel_pid_t
_pid
=
KERNEL_PID_UNDEF
;
static
char
_msg_stack
[
GCOAP_STACK_SIZE
];
static
char
_msg_stack
[
GCOAP_STACK_SIZE
];
static
sock_udp_t
_sock
;
/* Event/Message loop for gcoap _pid thread. */
/* Event/Message loop for gcoap _pid thread. */
static
void
*
_event_loop
(
void
*
arg
)
static
void
*
_event_loop
(
void
*
arg
)
{
{
msg_t
msg_rcvd
,
msg_queue
[
GCOAP_MSG_QUEUE_SIZE
];
msg_t
msg_rcvd
,
msg_queue
[
GCOAP_MSG_QUEUE_SIZE
];
gnrc_pktsnip_t
*
pkt
,
*
udp_snip
,
*
ipv6_snip
;
ipv6_addr_t
*
src_addr
;
uint16_t
port
;
(
void
)
arg
;
(
void
)
arg
;
msg_init_queue
(
msg_queue
,
GCOAP_MSG_QUEUE_SIZE
);
while
(
1
)
{
msg_receive
(
&
msg_rcvd
);
switch
(
msg_rcvd
.
type
)
{
msg_init_queue
(
msg_queue
,
GCOAP_MSG_QUEUE_SIZE
);
case
GNRC_NETAPI_MSG_TYPE_RCV
:
/* find client from UDP destination port */
DEBUG
(
"coap: GNRC_NETAPI_MSG_TYPE_RCV
\n
"
);
pkt
=
(
gnrc_pktsnip_t
*
)
msg_rcvd
.
content
.
ptr
;
if
(
pkt
->
type
!=
GNRC_NETTYPE_UNDEF
)
{
gnrc_pktbuf_release
(
pkt
);
break
;
}
udp_snip
=
pkt
->
next
;
if
(
udp_snip
->
type
!=
GNRC_NETTYPE_UDP
)
{
gnrc_pktbuf_release
(
pkt
);
break
;
}
/* read source port and address */
port
=
byteorder_ntohs
(((
udp_hdr_t
*
)
udp_snip
->
data
)
->
src_port
);
LL_SEARCH_SCALAR
(
udp_snip
,
ipv6_snip
,
type
,
GNRC_NETTYPE_IPV6
);
sock_udp_ep_t
local
;
assert
(
ipv6_snip
!=
NULL
);
memset
(
&
local
,
0
,
sizeof
(
sock_udp_ep_t
));
src_addr
=
&
((
ipv6_hdr_t
*
)
ipv6_snip
->
data
)
->
src
;
local
.
family
=
AF_INET6
;
local
.
netif
=
SOCK_ADDR_ANY_NETIF
;
local
.
port
=
GCOAP_PORT
;
_receive
(
pkt
,
src_addr
,
port
);
int
res
=
sock_udp_create
(
&
_sock
,
&
local
,
NULL
,
0
);
break
;
if
(
res
<
0
)
{
DEBUG
(
"gcoap: cannot create sock: %d
\n
"
,
res
);
return
0
;
}
case
GCOAP_NETAPI_MSG_TYPE_TIMEOUT
:
while
(
1
)
{
_expire_request
((
gcoap_request_memo_t
*
)
msg_rcvd
.
content
.
ptr
);
res
=
msg_try_receive
(
&
msg_rcvd
);
break
;
default:
if
(
res
>
0
)
{
break
;
switch
(
msg_rcvd
.
type
)
{
case
GCOAP_MSG_TYPE_TIMEOUT
:
_expire_request
((
gcoap_request_memo_t
*
)
msg_rcvd
.
content
.
ptr
);
break
;
case
GCOAP_MSG_TYPE_INTR
:
/* next _listen() timeout will account for open requests */
break
;
default:
break
;
}
}
}
_listen
(
&
_sock
);
}
}
return
0
;
return
0
;
}
}
/*
Handles incoming network IPC
message. */
/*
Listen for an incoming CoAP
message. */
static
void
_
receive
(
gnrc_pktsnip_t
*
pkt
,
ipv6_addr_t
*
src
,
uint16_t
port
)
static
void
_
listen
(
sock_udp_t
*
sock
)
{
{
coap_pkt_t
pdu
;
coap_pkt_t
pdu
;
uint8_t
buf
[
GCOAP_PDU_BUF_SIZE
];
uint8_t
buf
[
GCOAP_PDU_BUF_SIZE
];
s
ize_t
pdu_len
=
0
;
s
ock_udp_ep_t
remote
;
gcoap_request_memo_t
*
memo
=
NULL
;
gcoap_request_memo_t
*
memo
=
NULL
;
uint8_t
open_reqs
;
/* If too big, handle below based on request vs. response */
gcoap_op_state
(
&
open_reqs
);
size_t
pkt_size
=
(
pkt
->
size
>
sizeof
(
buf
))
?
sizeof
(
buf
)
:
pkt
->
size
;
/* Copy request into temporary buffer, and parse it as CoAP. */
ssize_t
res
=
sock_udp_recv
(
sock
,
buf
,
sizeof
(
buf
),
memcpy
(
buf
,
pkt
->
data
,
pkt_size
);
open_reqs
>
0
?
GCOAP_RECV_TIMEOUT
:
SOCK_NO_TIMEOUT
,
&
remote
);
if
(
res
<=
0
)
{
#if ENABLE_DEBUG
if
(
res
<
0
&&
res
!=
-
ETIMEDOUT
)
{
DEBUG
(
"gcoap: udp recv failure: %d
\n
"
,
res
);
}
#endif
return
;
}
int
result
=
coap_parse
(
&
pdu
,
buf
,
pkt_size
);
res
=
coap_parse
(
&
pdu
,
buf
,
res
);
if
(
res
ult
<
0
)
{
if
(
res
<
0
)
{
DEBUG
(
"gcoap: parse failure: %d
\n
"
,
res
ult
);
DEBUG
(
"gcoap: parse failure: %d
\n
"
,
res
);
/* If a response, can't clear memo, but it will timeout later. */
/* If a response, can't clear memo, but it will timeout later. */
goto
exit
;
return
;
}
}
/* incoming request */
/* incoming request */
if
(
coap_get_code_class
(
&
pdu
)
==
COAP_CLASS_REQ
)
{
if
(
coap_get_code_class
(
&
pdu
)
==
COAP_CLASS_REQ
)
{
if
(
pkt
->
size
>
sizeof
(
buf
))
{
size_t
pdu_len
=
_handle_req
(
&
pdu
,
buf
,
sizeof
(
buf
));
DEBUG
(
"gcoap: request too big: %u
\n
"
,
pkt
->
size
);
pdu_len
=
gcoap_response
(
&
pdu
,
buf
,
sizeof
(
buf
),
COAP_CODE_REQUEST_ENTITY_TOO_LARGE
);
}
else
{
pdu_len
=
_handle_req
(
&
pdu
,
buf
,
sizeof
(
buf
));
}
if
(
pdu_len
>
0
)
{
if
(
pdu_len
>
0
)
{
_send_buf
(
buf
,
pdu_len
,
src
,
port
);
sock_udp_send
(
sock
,
buf
,
pdu_len
,
&
remote
);
}
}
}
}
/* incoming response */
/* incoming response */
...
@@ -153,17 +144,10 @@ static void _receive(gnrc_pktsnip_t *pkt, ipv6_addr_t *src, uint16_t port)
...
@@ -153,17 +144,10 @@ static void _receive(gnrc_pktsnip_t *pkt, ipv6_addr_t *src, uint16_t port)
_find_req_memo
(
&
memo
,
&
pdu
,
buf
,
sizeof
(
buf
));
_find_req_memo
(
&
memo
,
&
pdu
,
buf
,
sizeof
(
buf
));
if
(
memo
)
{
if
(
memo
)
{
xtimer_remove
(
&
memo
->
response_timer
);
xtimer_remove
(
&
memo
->
response_timer
);
if
(
pkt
->
size
>
sizeof
(
buf
))
{
memo
->
state
=
GCOAP_MEMO_ERR
;
DEBUG
(
"gcoap: response too big: %u
\n
"
,
pkt
->
size
);
}
memo
->
resp_handler
(
memo
->
state
,
&
pdu
);
memo
->
resp_handler
(
memo
->
state
,
&
pdu
);
memo
->
state
=
GCOAP_MEMO_UNUSED
;
memo
->
state
=
GCOAP_MEMO_UNUSED
;
}
}
}
}
exit:
gnrc_pktbuf_release
(
pkt
);
}
}
/*
/*
...
@@ -296,77 +280,6 @@ static void _expire_request(gcoap_request_memo_t *memo)
...
@@ -296,77 +280,6 @@ static void _expire_request(gcoap_request_memo_t *memo)
}
}
}
}
/* Registers receive/send port with GNRC registry. */
static
int
_register_port
(
gnrc_netreg_entry_t
*
netreg_port
,
uint16_t
port
)
{
if
(
!
gnrc_netreg_lookup
(
GNRC_NETTYPE_UDP
,
port
))
{
gnrc_netreg_entry_init_pid
(
netreg_port
,
port
,
_pid
);
gnrc_netreg_register
(
GNRC_NETTYPE_UDP
,
netreg_port
);
DEBUG
(
"coap: registered UDP port %"
PRIu32
"
\n
"
,
netreg_port
->
demux_ctx
);
return
0
;
}
else
{
return
-
EINVAL
;
}
}
/*
* Sends a CoAP message to the provided host/port.
*
* @return Length of the packet
* @return 0 if cannot send
*/
static
size_t
_send
(
gnrc_pktsnip_t
*
coap_snip
,
ipv6_addr_t
*
addr
,
uint16_t
port
)
{
gnrc_pktsnip_t
*
udp
,
*
ip
;
size_t
pktlen
;
/* allocate UDP header */
udp
=
gnrc_udp_hdr_build
(
coap_snip
,
(
uint16_t
)
_coap_state
.
netreg_port
.
demux_ctx
,
port
);
if
(
udp
==
NULL
)
{
DEBUG
(
"gcoap: unable to allocate UDP header
\n
"
);
gnrc_pktbuf_release
(
coap_snip
);
return
0
;
}
/* allocate IPv6 header */
ip
=
gnrc_ipv6_hdr_build
(
udp
,
NULL
,
addr
);
if
(
ip
==
NULL
)
{
DEBUG
(
"gcoap: unable to allocate IPv6 header
\n
"
);
gnrc_pktbuf_release
(
udp
);
return
0
;
}
pktlen
=
gnrc_pkt_len
(
ip
);
/* count length now; snips deallocated after send */
/* send message */
if
(
!
gnrc_netapi_dispatch_send
(
GNRC_NETTYPE_UDP
,
GNRC_NETREG_DEMUX_CTX_ALL
,
ip
))
{
DEBUG
(
"gcoap: unable to locate UDP thread
\n
"
);
gnrc_pktbuf_release
(
ip
);
return
0
;
}
return
pktlen
;
}
/*
* Copies the request/response buffer to a pktsnip and sends it.
*
* @return Length of the packet
* @return 0 if cannot send
*/
static
size_t
_send_buf
(
uint8_t
*
buf
,
size_t
len
,
ipv6_addr_t
*
src
,
uint16_t
port
)
{
gnrc_pktsnip_t
*
snip
;
snip
=
gnrc_pktbuf_add
(
NULL
,
NULL
,
len
,
GNRC_NETTYPE_UNDEF
);
if
(
!
snip
)
{
return
0
;
}
memcpy
(
snip
->
data
,
buf
,
len
);
return
_send
(
snip
,
src
,
port
);
}
/*
/*
* Handler for /.well-known/core. Lists registered handlers, except for
* Handler for /.well-known/core. Lists registered handlers, except for
* /.well-known/core itself.
* /.well-known/core itself.
...
@@ -456,10 +369,6 @@ kernel_pid_t gcoap_init(void)
...
@@ -456,10 +369,6 @@ kernel_pid_t gcoap_init(void)
_pid
=
thread_create
(
_msg_stack
,
sizeof
(
_msg_stack
),
THREAD_PRIORITY_MAIN
-
1
,
_pid
=
thread_create
(
_msg_stack
,
sizeof
(
_msg_stack
),
THREAD_PRIORITY_MAIN
-
1
,
THREAD_CREATE_STACKTEST
,
_event_loop
,
NULL
,
"coap"
);
THREAD_CREATE_STACKTEST
,
_event_loop
,
NULL
,
"coap"
);
/* must establish pid first */
if
(
_register_port
(
&
_coap_state
.
netreg_port
,
GCOAP_PORT
)
<
0
)
{
return
-
EINVAL
;
}
/* Blank list of open requests so we know if an entry is available. */
/* Blank list of open requests so we know if an entry is available. */
memset
(
&
_coap_state
.
open_reqs
[
0
],
0
,
sizeof
(
_coap_state
.
open_reqs
));
memset
(
&
_coap_state
.
open_reqs
[
0
],
0
,
sizeof
(
_coap_state
.
open_reqs
));
/* randomize initial value */
/* randomize initial value */
...
@@ -529,8 +438,23 @@ ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format)
...
@@ -529,8 +438,23 @@ ssize_t gcoap_finish(coap_pkt_t *pdu, size_t payload_len, unsigned format)
size_t
gcoap_req_send
(
uint8_t
*
buf
,
size_t
len
,
ipv6_addr_t
*
addr
,
uint16_t
port
,
size_t
gcoap_req_send
(
uint8_t
*
buf
,
size_t
len
,
ipv6_addr_t
*
addr
,
uint16_t
port
,
gcoap_resp_handler_t
resp_handler
)
gcoap_resp_handler_t
resp_handler
)
{
sock_udp_ep_t
remote
;
remote
.
family
=
AF_INET6
;
remote
.
netif
=
SOCK_ADDR_ANY_NETIF
;
remote
.
port
=
port
;
memcpy
(
&
remote
.
addr
.
ipv6
[
0
],
&
addr
->
u8
[
0
],
sizeof
(
addr
->
u8
));
return
gcoap_req_send2
(
buf
,
len
,
&
remote
,
resp_handler
);
}
size_t
gcoap_req_send2
(
uint8_t
*
buf
,
size_t
len
,
sock_udp_ep_t
*
remote
,
gcoap_resp_handler_t
resp_handler
)
{
{
gcoap_request_memo_t
*
memo
=
NULL
;
gcoap_request_memo_t
*
memo
=
NULL
;
assert
(
remote
!=
NULL
);
assert
(
resp_handler
!=
NULL
);
assert
(
resp_handler
!=
NULL
);
/* Find empty slot in list of open requests. */
/* Find empty slot in list of open requests. */
...
@@ -545,16 +469,28 @@ size_t gcoap_req_send(uint8_t *buf, size_t len, ipv6_addr_t *addr, uint16_t port
...
@@ -545,16 +469,28 @@ size_t gcoap_req_send(uint8_t *buf, size_t len, ipv6_addr_t *addr, uint16_t port
memcpy
(
&
memo
->
hdr_buf
[
0
],
buf
,
GCOAP_HEADER_MAXLEN
);
memcpy
(
&
memo
->
hdr_buf
[
0
],
buf
,
GCOAP_HEADER_MAXLEN
);
memo
->
resp_handler
=
resp_handler
;
memo
->
resp_handler
=
resp_handler
;
size_t
res
=
_send_buf
(
buf
,
len
,
addr
,
port
);
size_t
res
=
sock_udp_send
(
&
_sock
,
buf
,
len
,
remote
);
if
(
res
&&
(
GCOAP_NON_TIMEOUT
>
0
))
{
if
(
res
&&
(
GCOAP_NON_TIMEOUT
>
0
))
{
/* start response wait timer */
/* interrupt sock listening (to set a listen timeout) */
memo
->
timeout_msg
.
type
=
GCOAP_NETAPI_MSG_TYPE_TIMEOUT
;
msg_t
mbox_msg
;
memo
->
timeout_msg
.
content
.
ptr
=
(
char
*
)
memo
;
mbox_msg
.
type
=
GCOAP_MSG_TYPE_INTR
;
xtimer_set_msg
(
&
memo
->
response_timer
,
GCOAP_NON_TIMEOUT
,
mbox_msg
.
content
.
value
=
0
;
&
memo
->
timeout_msg
,
_pid
);
if
(
mbox_try_put
(
&
_sock
.
reg
.
mbox
,
&
mbox_msg
))
{
/* start response wait timer */
memo
->
timeout_msg
.
type
=
GCOAP_MSG_TYPE_TIMEOUT
;
memo
->
timeout_msg
.
content
.
ptr
=
(
char
*
)
memo
;
xtimer_set_msg
(
&
memo
->
response_timer
,
GCOAP_NON_TIMEOUT
,
&
memo
->
timeout_msg
,
_pid
);
}
else
{
memo
->
state
=
GCOAP_MEMO_UNUSED
;
DEBUG
(
"gcoap: can't wake up mbox; no timeout for msg
\n
"
);
}
}
}
else
if
(
!
res
)
{
else
if
(
!
res
)
{
memo
->
state
=
GCOAP_MEMO_UNUSED
;
memo
->
state
=
GCOAP_MEMO_UNUSED
;
DEBUG
(
"gcoap: sock send failed: %d
\n
"
,
res
);
}
}
return
res
;
return
res
;
}
else
{
}
else
{
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment