aboutsummaryrefslogtreecommitdiff
path: root/src/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/udp.c')
-rw-r--r--src/udp.c157
1 files changed, 60 insertions, 97 deletions
diff --git a/src/udp.c b/src/udp.c
index 5945dca..8638b1d 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -3,6 +3,7 @@
3* LuaSocket toolkit 3* LuaSocket toolkit
4\*=========================================================================*/ 4\*=========================================================================*/
5#include <string.h> 5#include <string.h>
6#include <stdlib.h>
6 7
7#include "lua.h" 8#include "lua.h"
8#include "lauxlib.h" 9#include "lauxlib.h"
@@ -68,25 +69,34 @@ static luaL_Reg udp_methods[] = {
68 69
69/* socket options for setoption */ 70/* socket options for setoption */
70static t_opt optset[] = { 71static t_opt optset[] = {
71 {"dontroute", opt_set_dontroute}, 72 {"dontroute", opt_set_dontroute},
72 {"broadcast", opt_set_broadcast}, 73 {"broadcast", opt_set_broadcast},
73 {"reuseaddr", opt_set_reuseaddr}, 74 {"reuseaddr", opt_set_reuseaddr},
74 {"reuseport", opt_set_reuseport}, 75 {"reuseport", opt_set_reuseport},
75 {"ip-multicast-if", opt_set_ip_multicast_if}, 76 {"ip-multicast-if", opt_set_ip_multicast_if},
76 {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, 77 {"ip-multicast-ttl", opt_set_ip_multicast_ttl},
77 {"ip-multicast-loop", opt_set_ip_multicast_loop}, 78 {"ip-multicast-loop", opt_set_ip_multicast_loop},
78 {"ip-add-membership", opt_set_ip_add_membership}, 79 {"ip-add-membership", opt_set_ip_add_membership},
79 {"ip-drop-membership", opt_set_ip_drop_membersip}, 80 {"ip-drop-membership", opt_set_ip_drop_membersip},
80 {"ipv6-v6only", opt_set_ip6_v6only}, 81 {"ipv6-unicast-hops", opt_set_ip6_unicast_hops},
81 {NULL, NULL} 82 {"ipv6-multicast-hops", opt_set_ip6_unicast_hops},
83 {"ipv6-multicast-loop", opt_set_ip6_multicast_loop},
84 {"ipv6-add-membership", opt_set_ip6_add_membership},
85 {"ipv6-drop-membership", opt_set_ip6_drop_membersip},
86 {"ipv6-v6only", opt_set_ip6_v6only},
87 {NULL, NULL}
82}; 88};
83 89
84/* socket options for getoption */ 90/* socket options for getoption */
85static t_opt optget[] = { 91static t_opt optget[] = {
86 {"ip-multicast-if", opt_get_ip_multicast_if}, 92 {"ip-multicast-if", opt_get_ip_multicast_if},
87 {"ip-multicast-loop", opt_get_ip_multicast_loop}, 93 {"ip-multicast-loop", opt_get_ip_multicast_loop},
88 {"error", opt_get_error}, 94 {"error", opt_get_error},
89 {NULL, NULL} 95 {"ipv6-unicast-hops", opt_get_ip6_unicast_hops},
96 {"ipv6-multicast-hops", opt_get_ip6_unicast_hops},
97 {"ipv6-multicast-loop", opt_get_ip6_multicast_loop},
98 {"ipv6-v6only", opt_get_ip6_v6only},
99 {NULL, NULL}
90}; 100};
91 101
92/* functions in library namespace */ 102/* functions in library namespace */
@@ -156,39 +166,24 @@ static int meth_sendto(lua_State *L) {
156 size_t count, sent = 0; 166 size_t count, sent = 0;
157 const char *data = luaL_checklstring(L, 2, &count); 167 const char *data = luaL_checklstring(L, 2, &count);
158 const char *ip = luaL_checkstring(L, 3); 168 const char *ip = luaL_checkstring(L, 3);
159 unsigned short port = (unsigned short) luaL_checknumber(L, 4); 169 const char *port = luaL_checkstring(L, 4);
160 p_timeout tm = &udp->tm; 170 p_timeout tm = &udp->tm;
161 int err; 171 int err;
162 switch (udp->family) { 172 struct addrinfo aihint;
163 case PF_INET: { 173 struct addrinfo *ai;
164 struct sockaddr_in addr; 174 memset(&aihint, 0, sizeof(aihint));
165 memset(&addr, 0, sizeof(addr)); 175 aihint.ai_family = udp->family;
166 if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) 176 aihint.ai_socktype = SOCK_DGRAM;
167 luaL_argerror(L, 3, "invalid ip address"); 177 aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
168 addr.sin_family = AF_INET; 178 if ((err = getaddrinfo(ip, port, &aihint, &ai))) {
169 addr.sin_port = htons(port);
170 timeout_markstart(tm);
171 err = socket_sendto(&udp->sock, data, count, &sent,
172 (SA *) &addr, sizeof(addr), tm);
173 break;
174 }
175 case PF_INET6: {
176 struct sockaddr_in6 addr;
177 memset(&addr, 0, sizeof(addr));
178 if (inet_pton(AF_INET6, ip, &addr.sin6_addr) != 1)
179 luaL_argerror(L, 3, "invalid ip address");
180 addr.sin6_family = AF_INET6;
181 addr.sin6_port = htons(port);
182 timeout_markstart(tm);
183 err = socket_sendto(&udp->sock, data, count, &sent,
184 (SA *) &addr, sizeof(addr), tm);
185 break;
186 }
187 default:
188 lua_pushnil(L); 179 lua_pushnil(L);
189 lua_pushfstring(L, "unknown family %d", udp->family); 180 lua_pushstring(L, udp_strerror(err));
190 return 2; 181 return 2;
191 } 182 }
183 timeout_markstart(tm);
184 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
185 ai->ai_addrlen, tm);
186 freeaddrinfo(ai);
192 if (err != IO_DONE) { 187 if (err != IO_DONE) {
193 lua_pushnil(L); 188 lua_pushnil(L);
194 lua_pushstring(L, udp_strerror(err)); 189 lua_pushstring(L, udp_strerror(err));
@@ -225,71 +220,39 @@ static int meth_receive(lua_State *L) {
225/*-------------------------------------------------------------------------*\ 220/*-------------------------------------------------------------------------*\
226* Receives data and sender from a UDP socket 221* Receives data and sender from a UDP socket
227\*-------------------------------------------------------------------------*/ 222\*-------------------------------------------------------------------------*/
228static int meth_receivefrom(lua_State *L) { 223static int meth_receivefrom(lua_State *L)
224{
229 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 225 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
230 char buffer[UDP_DATAGRAMSIZE]; 226 char buffer[UDP_DATAGRAMSIZE];
231 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 227 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
232 int err; 228 int err;
233 p_timeout tm = &udp->tm; 229 p_timeout tm = &udp->tm;
230 struct sockaddr_storage addr;
231 socklen_t addr_len = sizeof(addr);
232 char addrstr[INET6_ADDRSTRLEN];
233 char portstr[6];
234 timeout_markstart(tm); 234 timeout_markstart(tm);
235 count = MIN(count, sizeof(buffer)); 235 count = MIN(count, sizeof(buffer));
236 switch (udp->family) { 236 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr,
237 case PF_INET: { 237 &addr_len, tm);
238 struct sockaddr_in addr; 238 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
239 socklen_t addr_len = sizeof(addr); 239 if (err == IO_CLOSED)
240 err = socket_recvfrom(&udp->sock, buffer, count, &got, 240 err = IO_DONE;
241 (SA *) &addr, &addr_len, tm); 241 if (err != IO_DONE) {
242 /* Unlike TCP, recv() of zero is not closed, 242 lua_pushnil(L);
243 * but a zero-length packet. */ 243 lua_pushstring(L, udp_strerror(err));
244 if (err == IO_CLOSED) 244 return 2;
245 err = IO_DONE;
246 if (err == IO_DONE) {
247 char addrstr[INET_ADDRSTRLEN];
248 lua_pushlstring(L, buffer, got);
249 if (!inet_ntop(AF_INET, &addr.sin_addr,
250 addrstr, sizeof(addrstr))) {
251 lua_pushnil(L);
252 lua_pushstring(L, "invalid source address");
253 return 2;
254 }
255 lua_pushstring(L, addrstr);
256 lua_pushnumber(L, ntohs(addr.sin_port));
257 return 3;
258 }
259 break;
260 }
261 case PF_INET6: {
262 struct sockaddr_in6 addr;
263 socklen_t addr_len = sizeof(addr);
264 err = socket_recvfrom(&udp->sock, buffer, count, &got,
265 (SA *) &addr, &addr_len, tm);
266 /* Unlike TCP, recv() of zero is not closed,
267 * but a zero-length packet. */
268 if (err == IO_CLOSED)
269 err = IO_DONE;
270 if (err == IO_DONE) {
271 char addrstr[INET6_ADDRSTRLEN];
272 lua_pushlstring(L, buffer, got);
273 if (!inet_ntop(AF_INET6, &addr.sin6_addr,
274 addrstr, sizeof(addrstr))) {
275 lua_pushnil(L);
276 lua_pushstring(L, "invalid source address");
277 return 2;
278 }
279 lua_pushstring(L, addrstr);
280 lua_pushnumber(L, ntohs(addr.sin6_port));
281 return 3;
282 }
283 break;
284 } 245 }
285 default: 246 if ((err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
247 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV))) {
286 lua_pushnil(L); 248 lua_pushnil(L);
287 lua_pushfstring(L, "unknown family %d", udp->family); 249 lua_pushstring(L, gai_strerror(err));
288 return 2; 250 return 2;
289 } 251 }
290 lua_pushnil(L); 252 lua_pushlstring(L, buffer, got);
291 lua_pushstring(L, udp_strerror(err)); 253 lua_pushstring(L, addrstr);
292 return 2; 254 lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
255 return 3;
293} 256}
294 257
295/*-------------------------------------------------------------------------*\ 258/*-------------------------------------------------------------------------*\