diff options
author | Diego Nehab <diego.nehab@gmail.com> | 2012-07-31 22:04:06 -0700 |
---|---|---|
committer | Diego Nehab <diego.nehab@gmail.com> | 2012-07-31 22:04:06 -0700 |
commit | 6370b61414e33564539933df9a79f332d3b2cf58 (patch) | |
tree | f7ee8bf0f5ea1b22046b1c3ffb04b09a28b6e76c | |
parent | 5616f3a0aec74b93814b4d4f6b8271a9cfbdd678 (diff) | |
parent | 7503bb0ca3f4f6216d48185d7a92e6ba5ef6d124 (diff) | |
download | luasocket-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.c | 109 |
1 files changed, 84 insertions, 25 deletions
@@ -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 | \*-------------------------------------------------------------------------*/ |
202 | static int meth_receivefrom(lua_State *L) { | 223 | static 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 | /*-------------------------------------------------------------------------*\ |