Contiki-NG
Loading...
Searching...
No Matches
udp-socket.c
1/*
2 * Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 */
31
32#include "contiki-net.h"
33#include "udp-socket.h"
34
35#include <string.h>
36
37#if UIP_UDP
38PROCESS(udp_socket_process, "UDP socket process");
39
40static uint8_t buf[UIP_BUFSIZE];
41
42/*---------------------------------------------------------------------------*/
43static void
44init(void)
45{
46 static uint8_t inited = 0;
47 if(!inited) {
48 inited = 1;
49 process_start(&udp_socket_process, NULL);
50 }
51}
52/*---------------------------------------------------------------------------*/
53int
54udp_socket_register(struct udp_socket *c,
55 void *ptr,
56 udp_socket_input_callback_t input_callback)
57{
58 init();
59
60 if(c == NULL) {
61 return -1;
62 }
63 c->ptr = ptr;
64 c->input_callback = input_callback;
65
66 c->p = PROCESS_CURRENT();
67 PROCESS_CONTEXT_BEGIN(&udp_socket_process);
68 c->udp_conn = udp_new(NULL, 0, c);
70
71 if(c->udp_conn == NULL) {
72 return -1;
73 }
74 return 1;
75}
76/*---------------------------------------------------------------------------*/
77int
78udp_socket_close(struct udp_socket *c)
79{
80 if(c == NULL) {
81 return -1;
82 }
83 if(c->udp_conn != NULL) {
84 uip_udp_remove(c->udp_conn);
85 return 1;
86 }
87 return -1;
88}
89/*---------------------------------------------------------------------------*/
90int
91udp_socket_bind(struct udp_socket *c,
92 uint16_t local_port)
93{
94 if(c == NULL || c->udp_conn == NULL) {
95 return -1;
96 }
97 udp_bind(c->udp_conn, UIP_HTONS(local_port));
98
99 return 1;
100}
101/*---------------------------------------------------------------------------*/
102int
103udp_socket_connect(struct udp_socket *c,
104 const uip_ipaddr_t *remote_addr,
105 uint16_t remote_port)
106{
107 if(c == NULL || c->udp_conn == NULL) {
108 return -1;
109 }
110
111 if(remote_addr != NULL) {
112 uip_ipaddr_copy(&c->udp_conn->ripaddr, remote_addr);
113 }
114 c->udp_conn->rport = UIP_HTONS(remote_port);
115 return 1;
116}
117/*---------------------------------------------------------------------------*/
118int
119udp_socket_send(struct udp_socket *c,
120 const void *data, uint16_t datalen)
121{
122 if(c == NULL || c->udp_conn == NULL) {
123 return -1;
124 }
125
126 uip_udp_packet_send(c->udp_conn, data, datalen);
127 return datalen;
128}
129/*---------------------------------------------------------------------------*/
130int
131udp_socket_sendto(struct udp_socket *c,
132 const void *data, uint16_t datalen,
133 const uip_ipaddr_t *to,
134 uint16_t port)
135{
136 if(c == NULL || c->udp_conn == NULL) {
137 return -1;
138 }
139
140 if(c->udp_conn != NULL) {
141 uip_udp_packet_sendto(c->udp_conn, data, datalen,
142 to, UIP_HTONS(port));
143 return datalen;
144 }
145 return -1;
146}
147/*---------------------------------------------------------------------------*/
148PROCESS_THREAD(udp_socket_process, ev, data)
149{
150 struct udp_socket *c;
152
153 while(1) {
155 if(ev == tcpip_event) {
156
157 /* An appstate pointer is passed to use from the IP stack
158 through the 'data' pointer. We registered this appstate when
159 we did the udp_new() call in udp_socket_register() as the
160 struct udp_socket pointer. So we extract this
161 pointer and use it when calling the reception callback. */
162 c = (struct udp_socket *)data;
163
164 /* Defensive coding: although the appstate *should* be non-null
165 here, we make sure to avoid the program crashing on us. */
166 if(c != NULL) {
167
168 /* If we were called because of incoming data, we should call
169 the reception callback. */
170 if(uip_newdata() && c->input_callback != NULL) {
171 /* Copy the data from the uIP data buffer into our own
172 buffer to avoid the uIP buffer being messed with by the
173 callee. */
174 memcpy(buf, uip_appdata, uip_datalen());
175
176 /* Call the client process. We use the PROCESS_CONTEXT
177 mechanism to temporarily switch process context to the
178 client process. */
180 c->input_callback(c, c->ptr,
181 &(UIP_IP_BUF->srcipaddr),
182 UIP_HTONS(UIP_UDP_BUF->srcport),
183 &(UIP_IP_BUF->destipaddr),
184 UIP_HTONS(UIP_UDP_BUF->destport),
185 buf, uip_datalen());
187 }
188 }
189 }
190 }
191
192 PROCESS_END();
193}
194#endif /* UIP_UDP */
195/*---------------------------------------------------------------------------*/
#define PROCESS(name, strname)
Declare a process.
Definition process.h:308
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition process.h:142
#define PROCESS_CURRENT()
Get a pointer to the currently running process.
Definition process.h:404
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition process.h:121
#define PROCESS_END()
Define the end of a process.
Definition process.h:132
void process_start(struct process *p, process_data_t data)
Start a process.
Definition process.c:121
#define PROCESS_CONTEXT_BEGIN(p)
Switch context to another process.
Definition process.h:428
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition process.h:274
#define PROCESS_CONTEXT_END(p)
End a context switch.
Definition process.h:442
process_event_t tcpip_event
The uIP event.
Definition tcpip.c:62
struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
Definition tcpip.c:264
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Definition tcpip.h:259
void * uip_appdata
Pointer to the application data in the packet buffer.
Definition uip6.c:148
#define UIP_IP_BUF
Direct access to IPv6 header.
Definition uip.h:71
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer.
Definition uip.h:593
#define uip_newdata()
Is new incoming data available?
Definition uip.h:680
#define uip_udp_remove(conn)
Remove a UDP connection.
Definition uip.h:818
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition uip.h:1157
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition uip.h:969
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Definition uipopt.h:93
uip_ipaddr_t ripaddr
The IP address of the remote peer.
Definition uip.h:1310
uint16_t rport
The remote port number in network byte order.
Definition uip.h:1312