aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego.nehab@gmail.com>2012-07-31 22:04:06 -0700
committerDiego Nehab <diego.nehab@gmail.com>2012-07-31 22:04:06 -0700
commit6370b61414e33564539933df9a79f332d3b2cf58 (patch)
treef7ee8bf0f5ea1b22046b1c3ffb04b09a28b6e76c
parent5616f3a0aec74b93814b4d4f6b8271a9cfbdd678 (diff)
parent7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124 (diff)
downloadluasocket-6370b61414e33564539933df9a79f332d3b2cf58.tar.gz
luasocket-6370b61414e33564539933df9a79f332d3b2cf58.tar.bz2
luasocket-6370b61414e33564539933df9a79f332d3b2cf58.zip
Merge pull request #20 from Florob/sendto
IPv6 support for udp:sendto() and udp:receivefrom()
-rw-r--r--src/udp.c109
1 files changed, 84 insertions, 25 deletions
diff --git a/src/udp.c b/src/udp.c
index 0241cc5..bdf584b 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -153,16 +153,37 @@ static int meth_sendto(lua_State *L) {
153 const char *ip = luaL_checkstring(L, 3); 153 const char *ip = luaL_checkstring(L, 3);
154 unsigned short port = (unsigned short) luaL_checknumber(L, 4); 154 unsigned short port = (unsigned short) luaL_checknumber(L, 4);
155 p_timeout tm = &udp->tm; 155 p_timeout tm = &udp->tm;
156 struct sockaddr_in addr;
157 int err; 156 int err;
158 memset(&addr, 0, sizeof(addr)); 157 switch (udp->family) {
159 if (!inet_aton(ip, &addr.sin_addr)) 158 case PF_INET: {
160 luaL_argerror(L, 3, "invalid ip address"); 159 struct sockaddr_in addr;
161 addr.sin_family = AF_INET; 160 memset(&addr, 0, sizeof(addr));
162 addr.sin_port = htons(port); 161 if (!inet_pton(AF_INET, ip, &addr.sin_addr))
163 timeout_markstart(tm); 162 luaL_argerror(L, 3, "invalid ip address");
164 err = socket_sendto(&udp->sock, data, count, &sent, 163 addr.sin_family = AF_INET;
165 (SA *) &addr, sizeof(addr), tm); 164 addr.sin_port = htons(port);
165 timeout_markstart(tm);
166 err = socket_sendto(&udp->sock, data, count, &sent,
167 (SA *) &addr, sizeof(addr), tm);
168 break;
169 }
170 case PF_INET6: {
171 struct sockaddr_in6 addr;
172 memset(&addr, 0, sizeof(addr));
173 if (!inet_pton(AF_INET6, ip, &addr.sin6_addr))
174 luaL_argerror(L, 3, "invalid ip address");
175 addr.sin6_family = AF_INET6;
176 addr.sin6_port = htons(port);
177 timeout_markstart(tm);
178 err = socket_sendto(&udp->sock, data, count, &sent,
179 (SA *) &addr, sizeof(addr), tm);
180 break;
181 }
182 default:
183 lua_pushnil(L);
184 lua_pushfstring(L, "unknown family %d", udp->family);
185 return 2;
186 }
166 if (err != IO_DONE) { 187 if (err != IO_DONE) {
167 lua_pushnil(L); 188 lua_pushnil(L);
168 lua_pushstring(L, udp_strerror(err)); 189 lua_pushstring(L, udp_strerror(err));
@@ -201,29 +222,67 @@ static int meth_receive(lua_State *L) {
201\*-------------------------------------------------------------------------*/ 222\*-------------------------------------------------------------------------*/
202static int meth_receivefrom(lua_State *L) { 223static int meth_receivefrom(lua_State *L) {
203 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 224 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
204 struct sockaddr_in addr;
205 socklen_t addr_len = sizeof(addr);
206 char buffer[UDP_DATAGRAMSIZE]; 225 char buffer[UDP_DATAGRAMSIZE];
207 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 226 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
208 int err; 227 int err;
209 p_timeout tm = &udp->tm; 228 p_timeout tm = &udp->tm;
210 timeout_markstart(tm); 229 timeout_markstart(tm);
211 count = MIN(count, sizeof(buffer)); 230 count = MIN(count, sizeof(buffer));
212 err = socket_recvfrom(&udp->sock, buffer, count, &got, 231 switch (udp->family) {
213 (SA *) &addr, &addr_len, tm); 232 case PF_INET: {
214 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 233 struct sockaddr_in addr;
215 if (err == IO_CLOSED) 234 socklen_t addr_len = sizeof(addr);
216 err = IO_DONE; 235 err = socket_recvfrom(&udp->sock, buffer, count, &got,
217 if (err == IO_DONE) { 236 (SA *) &addr, &addr_len, tm);
218 lua_pushlstring(L, buffer, got); 237 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
219 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 238 if (err == IO_CLOSED)
220 lua_pushnumber(L, ntohs(addr.sin_port)); 239 err = IO_DONE;
221 return 3; 240 if (err == IO_DONE) {
222 } else { 241 char addrstr[INET_ADDRSTRLEN];
223 lua_pushnil(L); 242 lua_pushlstring(L, buffer, got);
224 lua_pushstring(L, udp_strerror(err)); 243 if (!inet_ntop(AF_INET, &addr.sin_addr,
225 return 2; 244 addrstr, sizeof(addrstr))) {
245 lua_pushnil(L);
246 lua_pushstring(L, "invalid source address");
247 return 2;
248 }
249 lua_pushstring(L, addrstr);
250 lua_pushnumber(L, ntohs(addr.sin_port));
251 return 3;
252 }
253 break;
254 }
255 case PF_INET6: {
256 struct sockaddr_in6 addr;
257 socklen_t addr_len = sizeof(addr);
258 err = socket_recvfrom(&udp->sock, buffer, count, &got,
259 (SA *) &addr, &addr_len, tm);
260 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
261 if (err == IO_CLOSED)
262 err = IO_DONE;
263 if (err == IO_DONE) {
264 char addrstr[INET6_ADDRSTRLEN];
265 lua_pushlstring(L, buffer, got);
266 if (!inet_ntop(AF_INET6, &addr.sin6_addr,
267 addrstr, sizeof(addrstr))) {
268 lua_pushnil(L);
269 lua_pushstring(L, "invalid source address");
270 return 2;
271 }
272 lua_pushstring(L, addrstr);
273 lua_pushnumber(L, ntohs(addr.sin6_port));
274 return 3;
275 }
276 break;
277 }
278 default:
279 lua_pushnil(L);
280 lua_pushfstring(L, "unknown family %d", udp->family);
281 return 2;
226 } 282 }
283 lua_pushnil(L);
284 lua_pushstring(L, udp_strerror(err));
285 return 2;
227} 286}
228 287
229/*-------------------------------------------------------------------------*\ 288/*-------------------------------------------------------------------------*\