-------------------------------------------------------------------------*\ * Send data through unconnected udp socket \*-------------------------------------------------------------------------*/
| 176 | * Send data through unconnected udp socket |
| 177 | \*-------------------------------------------------------------------------*/ |
| 178 | static int meth_sendto(lua_State *L) { |
| 179 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); |
| 180 | size_t count, sent = 0; |
| 181 | const char *data = luaL_checklstring(L, 2, &count); |
| 182 | const char *ip = luaL_checkstring(L, 3); |
| 183 | const char *port = luaL_checkstring(L, 4); |
| 184 | p_timeout tm = &udp->tm; |
| 185 | int err; |
| 186 | struct addrinfo aihint; |
| 187 | struct addrinfo *ai; |
| 188 | memset(&aihint, 0, sizeof(aihint)); |
| 189 | aihint.ai_family = udp->family; |
| 190 | aihint.ai_socktype = SOCK_DGRAM; |
| 191 | aihint.ai_flags = AI_NUMERICHOST; |
| 192 | #ifdef AI_NUMERICSERV |
| 193 | aihint.ai_flags |= AI_NUMERICSERV; |
| 194 | #endif |
| 195 | err = getaddrinfo(ip, port, &aihint, &ai); |
| 196 | if (err) { |
| 197 | lua_pushnil(L); |
| 198 | lua_pushstring(L, gai_strerror(err)); |
| 199 | return 2; |
| 200 | } |
| 201 | |
| 202 | /* create socket if on first sendto if AF_UNSPEC was set */ |
| 203 | if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { |
| 204 | struct addrinfo *ap; |
| 205 | const char *errstr = NULL; |
| 206 | for (ap = ai; ap != NULL; ap = ap->ai_next) { |
| 207 | errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); |
| 208 | if (errstr == NULL) { |
| 209 | socket_setnonblocking(&udp->sock); |
| 210 | udp->family = ap->ai_family; |
| 211 | break; |
| 212 | } |
| 213 | } |
| 214 | if (errstr != NULL) { |
| 215 | lua_pushnil(L); |
| 216 | lua_pushstring(L, errstr); |
| 217 | freeaddrinfo(ai); |
| 218 | return 2; |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | timeout_markstart(tm); |
| 223 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, |
| 224 | (socklen_t) ai->ai_addrlen, tm); |
| 225 | freeaddrinfo(ai); |
| 226 | if (err != IO_DONE) { |
| 227 | lua_pushnil(L); |
| 228 | lua_pushstring(L, udp_strerror(err)); |
| 229 | return 2; |
| 230 | } |
| 231 | lua_pushnumber(L, (lua_Number) sent); |
| 232 | return 1; |
| 233 | } |
| 234 | |
| 235 | /*-------------------------------------------------------------------------*\ |
nothing calls this directly
no test coverage detected