2 * nixio - Linux I/O library for lua
4 * Copyright (C) 2009 Steven Barth <steven@midlink.org>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <arpa/inet.h>
31 * send() / sendto() helper
33 static int nixio_sock__sendto(lua_State
*L
, int to
) {
34 nixio_sock
*sock
= nixio__checksock(L
);
35 struct sockaddr
*addr
= NULL
;
39 const char *address
= luaL_checklstring(L
, 3, NULL
);
40 uint16_t port
= (uint16_t)luaL_checkinteger(L
, 4);
41 struct sockaddr_storage addrstor
;
42 addr
= (struct sockaddr
*)&addrstor
;
43 if (sock
->domain
== AF_INET
) {
44 struct sockaddr_in
*inetaddr
= (struct sockaddr_in
*)addr
;
45 if (inet_pton(sock
->domain
, address
, &inetaddr
->sin_addr
) < 0) {
46 return luaL_argerror(L
, 3, "invalid address");
48 inetaddr
->sin_port
= htons(port
);
49 alen
= sizeof(*inetaddr
);
50 } else if (sock
->domain
== AF_INET6
) {
51 struct sockaddr_in6
*inet6addr
= (struct sockaddr_in6
*)addr
;
52 if (inet_pton(sock
->domain
, address
, &inet6addr
->sin6_addr
) < 0) {
53 return luaL_argerror(L
, 3, "invalid address");
55 inet6addr
->sin6_port
= htons(port
);
56 alen
= sizeof(*inet6addr
);
58 return luaL_argerror(L
, 1, "supported families: inet, inet6");
64 const char *data
= luaL_checklstring(L
, 2, &len
);
66 sent
= sendto(sock
->fd
, data
, len
, 0, addr
, alen
);
67 } while(sent
== -1 && errno
== EINTR
);
69 lua_pushinteger(L
, sent
);
72 return nixio__perror(L
);
79 static int nixio_sock_send(lua_State
*L
) {
80 return nixio_sock__sendto(L
, 0);
84 * sendto(data, address, port)
86 static int nixio_sock_sendto(lua_State
*L
) {
87 return nixio_sock__sendto(L
, 1);
92 * recv() / recvfrom() helper
94 static int nixio_sock__recvfrom(lua_State
*L
, int from
) {
95 nixio_sock
*sock
= nixio__checksock(L
);
96 char buffer
[NIXIO_BUFFERSIZE
];
97 struct sockaddr_storage addrobj
;
98 int req
= luaL_checkinteger(L
, 2);
101 if (from
&& sock
->domain
!= AF_INET
&& sock
->domain
!= AF_INET6
) {
102 return luaL_argerror(L
, 1, "supported families: inet, inet6");
105 struct sockaddr
*addr
= (from
) ? (struct sockaddr
*)&addrobj
: NULL
;
106 socklen_t alen
= (from
) ? sizeof(addrobj
) : 0;
108 /* We limit the readsize to NIXIO_BUFFERSIZE */
109 req
= (req
> NIXIO_BUFFERSIZE
) ? NIXIO_BUFFERSIZE
: req
;
112 readc
= recvfrom(sock
->fd
, buffer
, req
, 0, addr
, &alen
);
113 } while (readc
== -1 && errno
== EINTR
);
116 return nixio__perror(L
);
118 lua_pushlstring(L
, buffer
, readc
);
123 char ipaddr
[INET6_ADDRSTRLEN
];
127 if (addrobj
.ss_family
== AF_INET
) {
128 struct sockaddr_in
*inetaddr
= (struct sockaddr_in
*)addr
;
129 port
= inetaddr
->sin_port
;
130 binaddr
= &inetaddr
->sin_addr
;
131 } else if (addrobj
.ss_family
== AF_INET6
) {
132 struct sockaddr_in6
*inet6addr
= (struct sockaddr_in6
*)addr
;
133 port
= inet6addr
->sin6_port
;
134 binaddr
= &inet6addr
->sin6_addr
;
136 return luaL_error(L
, "unknown address family");
139 if (!inet_ntop(addrobj
.ss_family
, binaddr
, ipaddr
, sizeof(ipaddr
))) {
140 return nixio__perror(L
);
143 lua_pushstring(L
, ipaddr
);
144 lua_pushinteger(L
, ntohs(port
));
154 static int nixio_sock_recv(lua_State
*L
) {
155 return nixio_sock__recvfrom(L
, 0);
161 static int nixio_sock_recvfrom(lua_State
*L
) {
162 return nixio_sock__recvfrom(L
, 1);
167 static const luaL_reg M
[] = {
168 {"send", nixio_sock_send
},
169 {"sendto", nixio_sock_sendto
},
170 {"recv", nixio_sock_recv
},
171 {"recvfrom",nixio_sock_recvfrom
},
175 void nixio_open_io(lua_State
*L
) {
176 lua_pushvalue(L
, -2);
177 luaL_register(L
, NULL
, M
);