3232#endif
3333
3434#include <lunatik.h>
35+ #include "luadata.h"
3536
3637#define luasocket_msgaddr (msg , addr , size ) \
3738do { \
@@ -117,7 +118,7 @@ LUNATIK_PRIVATECHECKER(luasocket_check, struct socket *);
117118* address family) specify the destination.
118119*
119120* @function send
120- * @tparam string message The string message to send.
121+ * @tparam string|data message The message to send; a data object avoids string allocation .
121122* @tparam[opt] integer|string addr The destination address.
122123*
123124* - For `AF_INET` (IPv4) sockets: An integer representing the IPv4 address (e.g., from `net.aton()`).
@@ -146,7 +147,14 @@ static int luasocket_send(lua_State *L)
146147
147148 luasocket_setmsg (msg );
148149
149- vec .iov_base = (void * )luaL_checklstring (L , 2 , & len );
150+ if (lua_isuserdata (L , 2 )) {
151+ luadata_t * data = lunatik_checkclass (L , 2 , "data" , LUNATIK_OPT_SINGLE )-> private ;
152+ lunatik_argchecknull (L , data -> ptr , 2 );
153+ vec .iov_base = data -> ptr ;
154+ len = data -> size ;
155+ }
156+ else
157+ vec .iov_base = (void * )luaL_checklstring (L , 2 , & len );
150158 vec .iov_len = len ;
151159
152160 if (unlikely (nargs >= 3 )) {
@@ -163,32 +171,21 @@ static int luasocket_send(lua_State *L)
163171* Receives a message from the socket.
164172*
165173* @function receive
166- * @tparam integer length The maximum number of bytes to receive.
167- * @tparam[opt=0] integer flags Optional message flags (e.g., `socket.msg.PEEK`).
168- * See the `socket.msg` table for available flags. These can be OR'd together.
169- * @tparam[opt=false] boolean from If `true`, the function also returns the sender's address
170- * and port (for `AF_INET`). This is typically used with connectionless sockets (`SOCK_DGRAM`).
171- * @treturn string The received message (as a string of bytes).
172- * @treturn[opt] integer|string addr If `from` is true, the sender's address.
173- * - For `AF_INET`: An integer representing the IPv4 address (can be converted with `net.ntoa()`).
174- * - For other families: A packed string representing the sender's address.
175- * @treturn[opt] integer port If `from` is true and the family is `AF_INET`, the sender's port number.
174+ * @tparam integer|data buffer Maximum bytes to receive, or a data object to receive into.
175+ * @tparam[opt=0] integer flags Message flags (e.g., `socket.msg.PEEK`).
176+ * @tparam[opt=false] boolean from If `true`, also returns sender address and port (`AF_INET`).
177+ * @treturn string|integer Received bytes as a string, or byte count when a data object is passed.
178+ * @treturn[opt] integer|string addr Sender address if `from` is true.
179+ * @treturn[opt] integer port Sender port if `from` is true and family is `AF_INET`.
176180* @raise Error if the receive operation fails.
177- * @usage
178- * -- For a connected TCP socket:
179- * local data = tcp_conn_sock:receive(1024)
180- * if data then print("Received:", data) end
181- *
182- * -- For a UDP socket, getting sender info:
183- * local data, sender_ip_int, sender_port = udp_sock:receive(1500, 0, true)
184- * if data then print("Received from " .. net.ntoa(sender_ip_int) .. ":" .. sender_port .. ": " .. data) end
185181* @see socket.msg
186182* @see net.ntoa
187183*/
188184static int luasocket_receive (lua_State * L )
189185{
190186 struct socket * socket = luasocket_check (L , 1 );
191- size_t len = (size_t )luaL_checkinteger (L , 2 );
187+ int isdata = lua_isuserdata (L , 2 );
188+ size_t len ;
192189 luaL_Buffer B ;
193190 struct kvec vec ;
194191 struct msghdr msg ;
@@ -199,14 +196,23 @@ static int luasocket_receive(lua_State *L)
199196
200197 luasocket_setmsg (msg );
201198
202- vec .iov_base = (void * )luaL_buffinitsize (L , & B , len );
199+ if (isdata ) {
200+ luadata_t * data = lunatik_checkclass (L , 2 , "data" , LUNATIK_OPT_SINGLE )-> private ;
201+ lunatik_argchecknull (L , data -> ptr , 2 );
202+ vec .iov_base = data -> ptr ;
203+ len = data -> size ;
204+ }
205+ else {
206+ len = (size_t )luaL_checkinteger (L , 2 );
207+ vec .iov_base = (void * )luaL_buffinitsize (L , & B , len );
208+ }
203209 vec .iov_len = len ;
204210
205211 if (unlikely (from ))
206212 luasocket_msgaddr (msg , addr , sizeof (addr ));
207213
208214 lunatik_tryret (L , ret , kernel_recvmsg , socket , & msg , & vec , 1 , len , flags );
209- luaL_pushresultsize (& B , ret );
215+ isdata ? lua_pushinteger ( L , ret ) : luaL_pushresultsize (& B , ret );
210216
211217 return unlikely (from ) ? luasocket_pushaddr (L , (struct sockaddr_storage * )msg .msg_name ) + 1 : 1 ;
212218}
0 commit comments