mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 10:25:55 +01:00 
			
		
		
		
	Changed buffer-per-socket to buffer-per-operation.
This is a difficult tradeoff to measure. I think large datagrams won't be used very frequently. So it is better to not lock a large buffer to each socket object and instead allocate and deallocate for each operation receiving a datagram larger than UDP_DATAGRAMSIZE.
This commit is contained in:
		| @@ -147,6 +147,7 @@ Support, Manual"> | ||||
| <a href="socket.html#connect">connect</a>, | ||||
| <a href="socket.html#connect">connect4</a>, | ||||
| <a href="socket.html#connect">connect6</a>, | ||||
| <a href="socket.html#datagramsize">_DATAGRAMSIZE</a>, | ||||
| <a href="socket.html#debug">_DEBUG</a>, | ||||
| <a href="dns.html#dns">dns</a>, | ||||
| <a href="socket.html#gettime">gettime</a>, | ||||
| @@ -158,6 +159,7 @@ Support, Manual"> | ||||
| <a href="socket.html#skip">skip</a>, | ||||
| <a href="socket.html#sleep">sleep</a>, | ||||
| <a href="socket.html#setsize">_SETSIZE</a>, | ||||
| <a href="socket.html#socketinvalid">_SOCKETINVALID</a>, | ||||
| <a href="socket.html#source">source</a>, | ||||
| <a href="tcp.html#socket.tcp">tcp</a>, | ||||
| <a href="tcp.html#socket.tcp4">tcp4</a>, | ||||
|   | ||||
| @@ -90,7 +90,7 @@ of connect are defined as simple helper functions that restrict the | ||||
|  | ||||
| <!-- debug ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=debug>  | ||||
| <p class=name id=debug> | ||||
| socket.<b>_DEBUG</b> | ||||
| </p> | ||||
|  | ||||
| @@ -99,6 +99,19 @@ This constant is set to <tt><b>true</b></tt> if the library was compiled | ||||
| with debug support. | ||||
| </p> | ||||
|  | ||||
| <!-- datagramsize +++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=debug> | ||||
| socket.<b>_DATAGRAMSIZE</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| Default datagram size used by calls to | ||||
| <a href="udp.html#receive"<tt>receive</tt></a> and | ||||
| <a href="udp.html#receivefrom"><tt>receivefrom</tt></a>. | ||||
| (Unless changed in compile time, the value is 8192.) | ||||
| </p> | ||||
|  | ||||
| <!-- get time +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=gettime>  | ||||
| @@ -393,6 +406,16 @@ The maximum number of sockets that the <a | ||||
| href=#select><tt>select</tt></a> function can handle.  | ||||
| </p> | ||||
|  | ||||
| <!-- socketinvalid ++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=socketinvalid> | ||||
| socket.<b>_SOCKETINVALID</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| The OS value for an invalid socket. | ||||
| </p> | ||||
|  | ||||
| <!-- try ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=try>  | ||||
|   | ||||
							
								
								
									
										33
									
								
								doc/udp.html
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								doc/udp.html
									
									
									
									
									
								
							| @@ -42,7 +42,7 @@ | ||||
| <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class="name" id="socket.udp"> | ||||
| socket.<b>udp(</b>[buffersize]<b>)</b> | ||||
| socket.<b>udp()</b> | ||||
| </p> | ||||
|  | ||||
| <p class="description"> | ||||
| @@ -62,13 +62,6 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | ||||
| is used to connect the object. | ||||
| </p> | ||||
|  | ||||
| <p class="parameters"> | ||||
| The optional <tt>buffersize</tt> parameter | ||||
| specifies the size of the largest datagram that will | ||||
| ever be received by the UDP object. The default value is | ||||
| 8192. | ||||
| </p> | ||||
|  | ||||
| <p class="return"> | ||||
| In case of success, a new unconnected UDP object | ||||
| returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | ||||
| @@ -92,7 +85,7 @@ href=#setoption><tt>setoption</tt></a> will fail. | ||||
| <!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class="name" id="socket.udp"> | ||||
| socket.<b>udp4(</b>[buffersize]<b>)</b> | ||||
| socket.<b>udp4()</b> | ||||
| </p> | ||||
|  | ||||
| <p class="description"> | ||||
| @@ -112,13 +105,6 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | ||||
| is used to connect the object. | ||||
| </p> | ||||
|  | ||||
| <p class="parameters"> | ||||
| The optional <tt>buffersize</tt> parameter | ||||
| specifies the size of the largest datagram that will | ||||
| ever be received by the UDP object. The default value is | ||||
| 8192. | ||||
| </p> | ||||
|  | ||||
| <p class="return"> | ||||
| In case of success, a new unconnected UDP object | ||||
| returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | ||||
| @@ -128,7 +114,7 @@ an error message. | ||||
| <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class="name" id="socket.udp6"> | ||||
| socket.<b>udp6(</b>[buffersize]<b>)</b> | ||||
| socket.<b>udp6()</b> | ||||
| </p> | ||||
|  | ||||
| <p class="description"> | ||||
| @@ -148,13 +134,6 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | ||||
| is used to connect the object. | ||||
| </p> | ||||
|  | ||||
| <p class="parameters"> | ||||
| The optional <tt>buffersize</tt> parameter | ||||
| specifies the size of the largest datagram that will | ||||
| ever be received by the UDP object. The default value is | ||||
| 8192. | ||||
| </p> | ||||
|  | ||||
| <p class="return"> | ||||
| In case of success, a new unconnected UDP object | ||||
| returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | ||||
| @@ -261,8 +240,10 @@ the excess bytes are discarded. If there are less then | ||||
| <tt>size</tt> bytes available in the current datagram, the | ||||
| available bytes are returned. | ||||
| If <tt>size</tt> is omitted, the | ||||
| <tt>buffersize</tt> argument at creation time is used | ||||
| (which defaults to 8192 bytes). | ||||
| compile-time constant <a | ||||
| href=socket.html#datagramsize><tt>socket._DATAGRAMSIZE</tt></a> is used | ||||
| (it defaults to 8192 bytes). Larger sizes will cause a | ||||
| temporary buffer to be allocated for the operation. | ||||
| </p> | ||||
|  | ||||
| <p class="return"> | ||||
|   | ||||
| @@ -39,7 +39,10 @@ static luaL_Reg func[] = { | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| int select_open(lua_State *L) { | ||||
|     lua_pushstring(L, "_SETSIZE"); | ||||
|     lua_pushnumber(L, FD_SETSIZE); | ||||
|     lua_pushinteger(L, FD_SETSIZE); | ||||
|     lua_rawset(L, -3); | ||||
|     lua_pushstring(L, "_SOCKETINVALID"); | ||||
|     lua_pushinteger(L, SOCKET_INVALID); | ||||
|     lua_rawset(L, -3); | ||||
|     luaL_setfuncs(L, func, 0); | ||||
|     return 0; | ||||
|   | ||||
							
								
								
									
										58
									
								
								src/udp.c
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								src/udp.c
									
									
									
									
									
								
							| @@ -41,7 +41,6 @@ static int meth_setpeername(lua_State *L); | ||||
| static int meth_close(lua_State *L); | ||||
| static int meth_setoption(lua_State *L); | ||||
| static int meth_getoption(lua_State *L); | ||||
| static int meth_getbufferlength(lua_State *L); | ||||
| static int meth_settimeout(lua_State *L); | ||||
| static int meth_getfd(lua_State *L); | ||||
| static int meth_setfd(lua_State *L); | ||||
| @@ -64,7 +63,6 @@ static luaL_Reg udp_methods[] = { | ||||
|     {"setfd",       meth_setfd}, | ||||
|     {"setoption",   meth_setoption}, | ||||
|     {"getoption",   meth_getoption}, | ||||
|     {"getoption",   meth_getbufferlength}, | ||||
|     {"setpeername", meth_setpeername}, | ||||
|     {"setsockname", meth_setsockname}, | ||||
|     {"settimeout",  meth_settimeout}, | ||||
| @@ -118,8 +116,7 @@ static luaL_Reg func[] = { | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Initializes module | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| int udp_open(lua_State *L) | ||||
| { | ||||
| int udp_open(lua_State *L) { | ||||
|     /* create classes */ | ||||
|     auxiliar_newclass(L, "udp{connected}", udp_methods); | ||||
|     auxiliar_newclass(L, "udp{unconnected}", udp_methods); | ||||
| @@ -130,6 +127,10 @@ int udp_open(lua_State *L) | ||||
|     auxiliar_add2group(L, "udp{unconnected}", "select{able}"); | ||||
|     /* define library functions */ | ||||
|     luaL_setfuncs(L, func, 0); | ||||
|     /* export default UDP size */ | ||||
|     lua_pushliteral(L, "_DATAGRAMSIZE"); | ||||
|     lua_pushinteger(L, UDP_DATAGRAMSIZE); | ||||
|     lua_rawset(L, -3); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -205,30 +206,26 @@ static int meth_sendto(lua_State *L) { | ||||
| static int meth_receive(lua_State *L) { | ||||
|     p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||||
|     char buf[UDP_DATAGRAMSIZE]; | ||||
|     size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); | ||||
|     char *dgram = len > sizeof(buf)? udp->buf: buf; | ||||
|     size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); | ||||
|     size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||||
|     char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||||
|     int err; | ||||
|     p_timeout tm = &udp->tm; | ||||
|     timeout_markstart(tm); | ||||
|     wanted = MIN(wanted, len); | ||||
|     if (!dgram) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushliteral(L, "out of memory"); | ||||
|         return 2; | ||||
|     } | ||||
|     err = socket_recv(&udp->sock, dgram, wanted, &got, tm); | ||||
|     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||||
|     if (err != IO_DONE && err != IO_CLOSED ) { | ||||
|     if (err != IO_DONE && err != IO_CLOSED) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, udp_strerror(err)); | ||||
|         if (wanted > sizeof(buf)) free(dgram); | ||||
|         return 2; | ||||
|     } | ||||
|     lua_pushlstring(L, dgram, got); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Receives data from a UDP socket | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_getbufferlength(lua_State *L) { | ||||
|     p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||||
|     lua_pushinteger(L, MAX(UDP_DATAGRAMSIZE, udp->len)); | ||||
|     if (wanted > sizeof(buf)) free(dgram); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| @@ -238,9 +235,8 @@ static int meth_getbufferlength(lua_State *L) { | ||||
| static int meth_receivefrom(lua_State *L) { | ||||
|     p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | ||||
|     char buf[UDP_DATAGRAMSIZE]; | ||||
|     size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); | ||||
|     char *dgram = len > sizeof(buf)? udp->buf: buf; | ||||
|     size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); | ||||
|     size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); | ||||
|     char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; | ||||
|     struct sockaddr_storage addr; | ||||
|     socklen_t addr_len = sizeof(addr); | ||||
|     char addrstr[INET6_ADDRSTRLEN]; | ||||
| @@ -248,13 +244,18 @@ static int meth_receivefrom(lua_State *L) { | ||||
|     int err; | ||||
|     p_timeout tm = &udp->tm; | ||||
|     timeout_markstart(tm); | ||||
|     wanted = MIN(wanted, len); | ||||
|     if (!dgram) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushliteral(L, "out of memory"); | ||||
|         return 2; | ||||
|     } | ||||
|     err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, | ||||
|             &addr_len, tm); | ||||
|     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||||
|     if (err != IO_DONE && err != IO_CLOSED) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, udp_strerror(err)); | ||||
|         if (wanted > sizeof(buf)) free(dgram); | ||||
|         return 2; | ||||
|     } | ||||
|     err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, | ||||
| @@ -262,19 +263,20 @@ static int meth_receivefrom(lua_State *L) { | ||||
| 	if (err) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, gai_strerror(err)); | ||||
|         if (wanted > sizeof(buf)) free(dgram); | ||||
|         return 2; | ||||
|     } | ||||
|     lua_pushlstring(L, dgram, got); | ||||
|     lua_pushstring(L, addrstr); | ||||
|     lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); | ||||
|     if (wanted > sizeof(buf)) free(dgram); | ||||
|     return 3; | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Returns family as string | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_getfamily(lua_State *L) | ||||
| { | ||||
| static int meth_getfamily(lua_State *L) { | ||||
|     p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||||
|     if (udp->family == AF_INET6) { | ||||
|         lua_pushliteral(L, "inet6"); | ||||
| @@ -419,19 +421,13 @@ static int meth_setsockname(lua_State *L) { | ||||
| * Creates a master udp object | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int udp_create(lua_State *L, int family) { | ||||
|     p_udp udp = NULL; | ||||
|     /* optional length for private datagram buffer. this is useful when | ||||
|      * you need larger datagrams than UDP_DATAGRAMSIZE */ | ||||
|     size_t len = (size_t) luaL_optinteger(L, 1, 0); | ||||
|     if (len <= UDP_DATAGRAMSIZE) len = 0; | ||||
|     /* allocate udp object */ | ||||
|     udp = (p_udp) lua_newuserdata(L, sizeof(t_udp) + len - 1); | ||||
|     p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | ||||
|     auxiliar_setclass(L, "udp{unconnected}", -1); | ||||
|     /* if family is AF_UNSPEC, we leave the socket invalid and | ||||
|      * store AF_UNSPEC into family. This will allow it to later be | ||||
|      * replaced with an AF_INET6 or AF_INET socket upon first use. */ | ||||
|     udp->sock = SOCKET_INVALID; | ||||
|     udp->len = len; | ||||
|     timeout_init(&udp->tm, -1, -1); | ||||
|     udp->family = family; | ||||
|     if (family != AF_UNSPEC) { | ||||
|   | ||||
| @@ -23,8 +23,6 @@ typedef struct t_udp_ { | ||||
|     t_socket sock; | ||||
|     t_timeout tm; | ||||
|     int family; | ||||
|     size_t len; /* length of datagram buffer below */ | ||||
|     char buf[1]; /* allocate larger structure to hold actual buffer */ | ||||
| } t_udp; | ||||
| typedef t_udp *p_udp; | ||||
|  | ||||
|   | ||||
| @@ -669,7 +669,6 @@ local udp_methods = { | ||||
|     "settimeout" | ||||
| } | ||||
|  | ||||
|  | ||||
| ------------------------------------------------------------------------ | ||||
| test_methods(socket.udp(), udp_methods) | ||||
| do local sock = socket.tcp6() | ||||
|   | ||||
		Reference in New Issue
	
	Block a user