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