• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* coap_io_lwip.h -- Network I/O functions for libcoap on lwIP
2  *
3  * Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
4  *               2014 chrysn <chrysn@fsfe.org>
5  *
6  * SPDX-License-Identifier: BSD-2-Clause
7  *
8  * This file is part of the CoAP library libcoap. Please see
9  * README for terms of use.
10  */
11 
12 #include "coap3/coap_internal.h"
13 #include <lwip/udp.h>
14 
15 #if NO_SYS
16 pthread_mutex_t lwprot_mutex = PTHREAD_MUTEX_INITIALIZER;
17 pthread_t lwprot_thread = (pthread_t)0xDEAD;
18 int lwprot_count = 0;
19 #endif
20 
21 #if 0
22 void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
23 {
24         target->port = packet->srcport;
25         memcpy(&target->addr, ip_current_src_addr(), sizeof(ip_addr_t));
26 }
27 #endif
coap_packet_get_memmapped(coap_packet_t * packet,unsigned char ** address,size_t * length)28 void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
29 {
30         LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", packet->pbuf->tot_len == packet->pbuf->len);
31         *address = packet->pbuf->payload;
32         *length = packet->pbuf->tot_len;
33 }
coap_free_packet(coap_packet_t * packet)34 void coap_free_packet(coap_packet_t *packet)
35 {
36         if (packet->pbuf)
37                 pbuf_free(packet->pbuf);
38         coap_free_type(COAP_PACKET, packet);
39 }
40 
coap_packet_extract_pbuf(coap_packet_t * packet)41 struct pbuf *coap_packet_extract_pbuf(coap_packet_t *packet)
42 {
43         struct pbuf *ret = packet->pbuf;
44         packet->pbuf = NULL;
45         return ret;
46 }
47 
48 
49 /** Callback from lwIP when a package was received.
50  *
51  * The current implementation deals this to coap_dispatch immediately, but
52  * other mechanisms (as storing the package in a queue and later fetching it
53  * when coap_io_do_io is called) can be envisioned.
54  *
55  * It handles everything coap_io_do_io does on other implementations.
56  */
coap_recv(void * arg,struct udp_pcb * upcb,struct pbuf * p,const ip_addr_t * addr,u16_t port)57 static void coap_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
58 {
59   coap_endpoint_t *ep = (coap_endpoint_t*)arg;
60   coap_pdu_t *pdu = NULL;
61   coap_session_t *session;
62   coap_tick_t now;
63   coap_packet_t *packet;
64 
65   if (p->len < 4) {
66     /* Minimum size of CoAP header - ignore runt */
67     return;
68   }
69 
70   packet = coap_malloc_type(COAP_PACKET, sizeof(coap_packet_t));
71 
72   /* this is fatal because due to the short life of the packet, never should there be more than one coap_packet_t required */
73   LWIP_ASSERT("Insufficient coap_packet_t resources.", packet != NULL);
74   packet->pbuf = p;
75   /* Need to do this as there may be holes in addr_info */
76   memset(&packet->addr_info, 0, sizeof(packet->addr_info));
77   packet->addr_info.remote.port = port;
78   packet->addr_info.remote.addr = *addr;
79   packet->addr_info.local.port = upcb->local_port;
80   packet->addr_info.local.addr = *ip_current_dest_addr();
81   packet->ifindex = netif_get_index(ip_current_netif());
82 
83   pdu = coap_pdu_from_pbuf(p);
84   if (!pdu)
85     goto error;
86 
87   if (!coap_pdu_parse(ep->proto, p->payload, p->len, pdu)) {
88     goto error;
89   }
90 
91   coap_ticks(&now);
92   session = coap_endpoint_get_session(ep, packet, now);
93   if (!session)
94     goto error;
95   LWIP_ASSERT("Proto not supported for LWIP", COAP_PROTO_NOT_RELIABLE(session->proto));
96   coap_dispatch(ep->context, session, pdu);
97 
98   coap_delete_pdu(pdu);
99   packet->pbuf = NULL;
100   coap_free_packet(packet);
101   return;
102 
103 error:
104   /*
105    * https://tools.ietf.org/html/rfc7252#section-4.2 MUST send RST
106    * https://tools.ietf.org/html/rfc7252#section-4.3 MAY send RST
107    */
108   coap_send_rst(session, pdu);
109   coap_delete_pdu(pdu);
110   if (packet) {
111     packet->pbuf = NULL;
112     coap_free_packet(packet);
113   }
114   return;
115 }
116 
117 coap_endpoint_t *
coap_new_endpoint(coap_context_t * context,const coap_address_t * addr,coap_proto_t proto)118 coap_new_endpoint(coap_context_t *context, const coap_address_t *addr, coap_proto_t proto) {
119         coap_endpoint_t *result;
120         err_t err;
121 
122         LWIP_ASSERT("Proto not supported for LWIP endpoints", proto == COAP_PROTO_UDP);
123 
124         result = coap_malloc_type(COAP_ENDPOINT, sizeof(coap_endpoint_t));
125         if (!result) return NULL;
126 
127         result->sock.pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
128         if (result->sock.pcb == NULL) goto error;
129 
130         udp_recv(result->sock.pcb, coap_recv, (void*)result);
131         err = udp_bind(result->sock.pcb, &addr->addr, addr->port);
132         if (err) {
133                 udp_remove(result->sock.pcb);
134                 goto error;
135         }
136 
137         result->default_mtu = COAP_DEFAULT_MTU;
138         result->context = context;
139         result->proto = proto;
140 
141         return result;
142 
143 error:
144         coap_free_type(COAP_ENDPOINT, result);
145         return NULL;
146 }
147 
coap_free_endpoint(coap_endpoint_t * ep)148 void coap_free_endpoint(coap_endpoint_t *ep)
149 {
150         udp_remove(ep->sock.pcb);
151         coap_free_type(COAP_ENDPOINT, ep);
152 }
153 
154 ssize_t
coap_socket_send_pdu(coap_socket_t * sock,coap_session_t * session,coap_pdu_t * pdu)155 coap_socket_send_pdu(coap_socket_t *sock, coap_session_t *session,
156   coap_pdu_t *pdu) {
157   /* FIXME: we can't check this here with the existing infrastructure, but we
158   * should actually check that the pdu is not held by anyone but us. the
159   * respective pbuf is already exclusively owned by the pdu. */
160 
161   pbuf_realloc(pdu->pbuf, pdu->used_size + coap_pdu_parse_header_size(session->proto, pdu->pbuf->payload));
162   udp_sendto(sock->pcb, pdu->pbuf, &session->addr_info.remote.addr,
163     session->addr_info.remote.port);
164   return pdu->used_size;
165 }
166 
167 ssize_t
coap_socket_send(coap_socket_t * sock,coap_session_t * session,const uint8_t * data,size_t data_len)168 coap_socket_send(coap_socket_t *sock, coap_session_t *session,
169   const uint8_t *data, size_t data_len ) {
170   /* Not implemented, use coap_socket_send_pdu instead */
171   return -1;
172 }
173 
174 int
coap_socket_bind_udp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)175 coap_socket_bind_udp(coap_socket_t *sock,
176   const coap_address_t *listen_addr,
177   coap_address_t *bound_addr) {
178   return 0;
179 }
180 
181 int
coap_socket_connect_udp(coap_socket_t * sock,const coap_address_t * local_if,const coap_address_t * server,int default_port,coap_address_t * local_addr,coap_address_t * remote_addr)182 coap_socket_connect_udp(coap_socket_t *sock,
183   const coap_address_t *local_if,
184   const coap_address_t *server,
185   int default_port,
186   coap_address_t *local_addr,
187   coap_address_t *remote_addr) {
188   return 0;
189 }
190 
191 int
coap_socket_connect_tcp1(coap_socket_t * sock,const coap_address_t * local_if,const coap_address_t * server,int default_port,coap_address_t * local_addr,coap_address_t * remote_addr)192 coap_socket_connect_tcp1(coap_socket_t *sock,
193                          const coap_address_t *local_if,
194                          const coap_address_t *server,
195                          int default_port,
196                          coap_address_t *local_addr,
197                          coap_address_t *remote_addr) {
198   return 0;
199 }
200 
201 int
coap_socket_connect_tcp2(coap_socket_t * sock,coap_address_t * local_addr,coap_address_t * remote_addr)202 coap_socket_connect_tcp2(coap_socket_t *sock,
203                          coap_address_t *local_addr,
204                          coap_address_t *remote_addr) {
205   return 0;
206 }
207 
208 int
coap_socket_bind_tcp(coap_socket_t * sock,const coap_address_t * listen_addr,coap_address_t * bound_addr)209 coap_socket_bind_tcp(coap_socket_t *sock,
210                      const coap_address_t *listen_addr,
211                      coap_address_t *bound_addr) {
212   return 0;
213 }
214 
215 int
coap_socket_accept_tcp(coap_socket_t * server,coap_socket_t * new_client,coap_address_t * local_addr,coap_address_t * remote_addr)216 coap_socket_accept_tcp(coap_socket_t *server,
217                         coap_socket_t *new_client,
218                         coap_address_t *local_addr,
219                         coap_address_t *remote_addr) {
220   return 0;
221 }
222 
223 ssize_t
coap_socket_write(coap_socket_t * sock,const uint8_t * data,size_t data_len)224 coap_socket_write(coap_socket_t *sock, const uint8_t *data, size_t data_len) {
225   return -1;
226 }
227 
228 ssize_t
coap_socket_read(coap_socket_t * sock,uint8_t * data,size_t data_len)229 coap_socket_read(coap_socket_t *sock, uint8_t *data, size_t data_len) {
230   return -1;
231 }
232 
coap_socket_close(coap_socket_t * sock)233 void coap_socket_close(coap_socket_t *sock) {
234   return;
235 }
236 
237