mirror of
				https://github.com/lunarmodules/luasocket.git
				synced 2025-10-31 02:15:38 +01:00 
			
		
		
		
	Merge branch 'git-sam' into diego-sam-mwild-integration
Conflicts in options.c were just due to independent small functions being close to each other. unix.c in mwild was broken, it wasn't using LUASOCKET_API. serial.c needed luaL_reg renamed, and to use LUASOCKET_API. makefile didn't respect standard DESTDIR and prefix makefile variables, and didn't allow LUAV variable to select lua version to build against. I've tested the top-level install-both target builds and installs against both lua5.1 and lua5.2, but not done further testing. Conflicts: README config gem/ltn012.tex makefile src/makefile src/options.c src/options.h src/tcp.c src/usocket.c
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| *.o | ||||
| *.so | ||||
| *.so.* | ||||
| @@ -42,9 +42,9 @@ Support, Manual"> | ||||
| <blockquote> | ||||
| <a href="dns.html">DNS (in socket)</a> | ||||
| <blockquote> | ||||
| <a href="dns.html#toip">toip</a>, | ||||
| <a href="dns.html#gethostname">gethostname</a>, | ||||
| <a href="dns.html#tohostname">tohostname</a>, | ||||
| <a href="dns.html#gethostname">gethostname</a>. | ||||
| <a href="dns.html#toip">toip</a>. | ||||
| </blockquote> | ||||
| </blockquote> | ||||
|  | ||||
| @@ -108,9 +108,9 @@ Support, Manual"> | ||||
| <a href="mime.html">MIME</a> | ||||
| <blockquote> | ||||
| <a href="mime.html#high">high-level</a>: | ||||
| <a href="mime.html#normalize">normalize</a>, | ||||
| <a href="mime.html#decode">decode</a>, | ||||
| <a href="mime.html#encode">encode</a>, | ||||
| <a href="mime.html#normalize">normalize</a>, | ||||
| <a href="mime.html#stuff">stuff</a>, | ||||
| <a href="mime.html#wrap">wrap</a>. | ||||
| </blockquote> | ||||
| @@ -120,10 +120,10 @@ Support, Manual"> | ||||
| <a href="mime.html#dot">dot</a>, | ||||
| <a href="mime.html#eol">eol</a>, | ||||
| <a href="mime.html#qp">qp</a>, | ||||
| <a href="mime.html#wrp">wrp</a>, | ||||
| <a href="mime.html#qpwrp">qpwrp</a>. | ||||
| <a href="mime.html#qpwrp">qpwrp</a>, | ||||
| <a href="mime.html#unb64">unb64</a>, | ||||
| <a href="mime.html#unqp">unqp</a>, | ||||
| <a href="mime.html#wrp">wrp</a>. | ||||
| </blockquote> | ||||
| </blockquote> | ||||
|  | ||||
| @@ -142,6 +142,8 @@ Support, Manual"> | ||||
| <blockquote> | ||||
| <a href="socket.html">Socket</a> | ||||
| <blockquote> | ||||
| <a href="socket.html#bind">bind</a>, | ||||
| <a href="socket.html#connect">connect</a>, | ||||
| <a href="socket.html#debug">_DEBUG</a>, | ||||
| <a href="dns.html#dns">dns</a>, | ||||
| <a href="socket.html#gettime">gettime</a>, | ||||
| @@ -169,11 +171,16 @@ Support, Manual"> | ||||
| <a href="tcp.html#bind">bind</a>, | ||||
| <a href="tcp.html#close">close</a>, | ||||
| <a href="tcp.html#connect">connect</a>, | ||||
| <a href="tcp.html#dirty">dirty</a>, | ||||
| <a href="tcp.html#getfd">getfd</a>, | ||||
| <a href="tcp.html#getoption">getoption</a>, | ||||
| <a href="tcp.html#getpeername">getpeername</a>, | ||||
| <a href="tcp.html#getsockname">getsockname</a>, | ||||
| <a href="tcp.html#getstats">getstats</a>, | ||||
| <a href="tcp.html#listen">listen</a>, | ||||
| <a href="tcp.html#receive">receive</a>, | ||||
| <a href="tcp.html#send">send</a>, | ||||
| <a href="tcp.html#setfd">setfd</a>, | ||||
| <a href="tcp.html#setoption">setoption</a>, | ||||
| <a href="tcp.html#setstats">setstats</a>, | ||||
| <a href="tcp.html#settimeout">settimeout</a>, | ||||
|   | ||||
| @@ -244,6 +244,10 @@ method or <tt>accept</tt> might block forever. | ||||
| it to <tt>select</tt>, it will be ignored. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| <b>Using select with non-socket objects</b>: Any object that implements <tt>getfd</tt> and <tt>dirty</tt> can be used with <tt>select</tt>, allowing objects from other libraries to be used within a <tt>socket.select</tt> driven loop. | ||||
| </p> | ||||
|  | ||||
| <!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=sink>  | ||||
|   | ||||
							
								
								
									
										95
									
								
								doc/tcp.html
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								doc/tcp.html
									
									
									
									
									
								
							| @@ -397,7 +397,40 @@ disables the Nagle's algorithm for the connection. | ||||
| </ul> | ||||
|  | ||||
| <p class=return> | ||||
| The method returns 1 in case of success, or <b><tt>nil</tt></b> otherwise. | ||||
| The method returns 1 in case of success, or <b><tt>nil</tt></b> | ||||
| followed by an error message otherwise. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| Note: The descriptions above come from the man pages. | ||||
| </p> | ||||
|  | ||||
| <!-- getoption ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=getoption> | ||||
| client:<b>getoption(</b>option)</b><br> | ||||
| server:<b>getoption(</b>option)</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| Gets options for the TCP object. | ||||
| See <a href=#setoption><tt>setoption</tt></a> for description of the | ||||
| option names and values. | ||||
| </p> | ||||
|  | ||||
| <p class=parameters> | ||||
| <tt>Option</tt> is a string with the option name. | ||||
| <ul> | ||||
|  | ||||
| <li> '<tt>keepalive</tt>' | ||||
| <li> '<tt>linger</tt>' | ||||
| <li> '<tt>reuseaddr</tt>' | ||||
| <li> '<tt>tcp-nodelay</tt>' | ||||
| </ul> | ||||
|  | ||||
| <p class=return> | ||||
| The method returns the option <tt>value</tt> in case of success, or | ||||
| <b><tt>nil</tt></b> followed by an error message otherwise. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| @@ -508,6 +541,66 @@ This is the default mode; | ||||
| This function returns 1. | ||||
| </p> | ||||
|  | ||||
| <!-- dirty +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=dirty> | ||||
| master:<b>dirty()</b><br> | ||||
| client:<b>dirty()</b><br> | ||||
| server:<b>dirty()</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| Check the read buffer status. | ||||
| </p> | ||||
|  | ||||
| <p class=return> | ||||
| Returns <tt>true</tt> if there is any data in the read buffer, <tt>false</tt> otherwise. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| Note: <b>This is an internal method, any use is unlikely to be portable.</b> | ||||
| </p> | ||||
|  | ||||
| <!-- getfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=getfd> | ||||
| master:<b>getfd()</b><br> | ||||
| client:<b>getfd()</b><br> | ||||
| server:<b>getfd()</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| Returns the underling socket descriptor or handle associated to the object.  | ||||
| </p> | ||||
|  | ||||
| <p class=return> | ||||
| The descriptor or handle. In case the object has been closed, the return will be -1. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| Note: <b>This is an internal method, any use is unlikely to be portable.</b> | ||||
| </p> | ||||
|  | ||||
| <!-- setfd +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <p class=name id=setfd> | ||||
| master:<b>setfd(</b>fd<b>)</b><br> | ||||
| client:<b>setfd(</b>fd<b>)</b><br> | ||||
| server:<b>setfd(</b>fd<b>)</b> | ||||
| </p> | ||||
|  | ||||
| <p class=description> | ||||
| Sets the underling socket descriptor or handle associated to the object. The current one is simply replaced, not closed, and no other change to the object state is made. | ||||
| </p> | ||||
|  | ||||
| <p class=return> | ||||
| No return value. | ||||
| </p> | ||||
|  | ||||
| <p class=note> | ||||
| Note: <b>This is an internal method, any use is unlikely to be portable.</b> | ||||
| </p> | ||||
|  | ||||
| <!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | ||||
|  | ||||
| <div class=footer> | ||||
|   | ||||
| @@ -12,12 +12,3 @@ clean: | ||||
|  | ||||
| pdf: ltn012.pdf | ||||
| 	open ltn012.pdf | ||||
|  | ||||
| test: gem.so | ||||
|  | ||||
|  | ||||
| gem.o: gem.c | ||||
| 	gcc -c -o gem.o -Wall -ansi -W -O2 gem.c | ||||
|  | ||||
| gem.so: gem.o | ||||
| 	export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc -bundle -undefined dynamic_lookup -o gem.so gem.o | ||||
|   | ||||
							
								
								
									
										15
									
								
								makefile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								makefile
									
									
									
									
									
								
							| @@ -6,10 +6,19 @@ PLATS= macosx linux win32 | ||||
| # | ||||
| all: $(PLAT) | ||||
|  | ||||
| $(PLATS) none install local clean: | ||||
| $(PLATS) none install install-unix local clean: | ||||
| 	@cd src; $(MAKE) $@ | ||||
|  | ||||
| test: dummy | ||||
| test: | ||||
| 	lua test/hello.lua | ||||
|  | ||||
| .PHONY: dummy | ||||
| install-both: | ||||
| 	touch src/*.c | ||||
| 	@cd src; $(MAKE) $(PLAT) LUAV=5.1 | ||||
| 	@cd src; $(MAKE) install-unix LUAV=5.1 | ||||
| 	touch src/*.c | ||||
| 	@cd src; $(MAKE) $(PLAT) LUAV=5.2 | ||||
| 	@cd src; $(MAKE) install-unix LUAV=5.2 | ||||
|  | ||||
| .PHONY: test | ||||
|  | ||||
|   | ||||
							
								
								
									
										66
									
								
								src/makefile
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/makefile
									
									
									
									
									
								
							| @@ -1,30 +1,35 @@ | ||||
| PLAT?=macosx | ||||
| LUAV?=5.1 | ||||
| prefix=/usr/local | ||||
| #prefix=/opt/local | ||||
| #prefix=. | ||||
|  | ||||
| INSTALL_DATA=cp | ||||
| INSTALL_EXEC=cp | ||||
| #INSTALL_TOP=/opt/local | ||||
| INSTALL_TOP=./ | ||||
|  | ||||
| LUAINC_macosx=/usr/local/include | ||||
| #LUAINC_macosx=/opt/local/include | ||||
| LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.2.0-beta/src | ||||
| #LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.2.0-beta/src | ||||
| #LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.1.4/src | ||||
|  | ||||
| LUAINC_linux=/usr/include/lua5.1 | ||||
| #LUAINC_linux=/usr/local/include/lua$(LUAV) | ||||
| LUAINC_linux=/usr/include/lua$(LUAV) | ||||
| #LUAINC_linux=/usr/local/include | ||||
|  | ||||
| LUAINC_win32="../../lua-5.1.3/src" | ||||
| LUALIB_win32="../../lua-5.1.3" | ||||
|  | ||||
| #------ | ||||
| # Install directories | ||||
| # | ||||
| #INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.1 | ||||
| #INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.1 | ||||
| INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.2 | ||||
| INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.2 | ||||
|  | ||||
| INSTALL_DATA=cp | ||||
| INSTALL_EXEC=cp | ||||
| INSTALL_TOP=$(DESTDIR)$(prefix) | ||||
|  | ||||
| INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/$(LUAV) | ||||
| INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/$(LUAV) | ||||
|  | ||||
| INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket | ||||
| INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket | ||||
| #INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime | ||||
| INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/foo/mime | ||||
| INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime | ||||
| INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime | ||||
|  | ||||
| #------ | ||||
| @@ -78,7 +83,7 @@ LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \ | ||||
|     /MANIFESTFILE:"intermediate.manifest" \ | ||||
|     /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ | ||||
| 	/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \ | ||||
|     /MACHINE:X86 ws2_32.lib lua5.1.lib /OUT: | ||||
|     /MACHINE:X86 ws2_32.lib lua$(LUAV).lib /OUT: | ||||
| LD_win32=cl | ||||
| SOCKET_win32=wsocket.obj | ||||
|  | ||||
| @@ -97,6 +102,7 @@ MIME_V=1.0.3 | ||||
| SOCKET_SO=socket.$(SO).$(SOCKET_V) | ||||
| MIME_SO=mime.$(SO).$(MIME_V) | ||||
| UNIX_SO=unix.$(SO) | ||||
| SERIAL_SO=serial.$(SO) | ||||
| SOCKET=$(SOCKET_$(PLAT)) | ||||
|  | ||||
| #------ | ||||
| @@ -118,7 +124,7 @@ SOCKET_OBJS= \ | ||||
| 	timeout.$(O) \ | ||||
| 	buffer.$(O) \ | ||||
| 	io.$(O) \ | ||||
|     auxiliar.$(O) \ | ||||
| 	auxiliar.$(O) \ | ||||
| 	options.$(O) \ | ||||
| 	inet.$(O) \ | ||||
| 	$(SOCKET) \ | ||||
| @@ -147,6 +153,19 @@ UNIX_OBJS=\ | ||||
| 	unix.$(O) \ | ||||
| 	lua_typeerror.$(O) | ||||
|  | ||||
| #------ | ||||
| # Modules belonging to serial (device streams) | ||||
| # | ||||
| SERIAL_OBJS:=\ | ||||
| 	buffer.$(O) \ | ||||
| 	auxiliar.$(O) \ | ||||
| 	options.$(O) \ | ||||
| 	timeout.$(O) \ | ||||
| 	io.$(O) \ | ||||
| 	usocket.$(O) \ | ||||
| 	serial.$(O) \ | ||||
| 	lua_typeerror.$(O) | ||||
|  | ||||
| #------ | ||||
| # Files to install | ||||
| # | ||||
| @@ -169,13 +188,13 @@ TO_TOP_SHARE= \ | ||||
| default: $(PLAT) | ||||
|  | ||||
| macosx: | ||||
| 	$(MAKE) all PLAT=macosx | ||||
| 	$(MAKE) all-unix PLAT=macosx | ||||
|  | ||||
| win32: | ||||
| 	$(MAKE) all PLAT=win32 | ||||
|  | ||||
| linux: | ||||
| 	$(MAKE) all PLAT=linux | ||||
| 	$(MAKE) all-unix PLAT=linux | ||||
|  | ||||
| none: | ||||
| 	@echo "Please run" | ||||
| @@ -191,9 +210,14 @@ $(SOCKET_SO): $(SOCKET_OBJS) | ||||
| $(MIME_SO): $(MIME_OBJS) | ||||
| 	$(LD) $(MIME_OBJS) $(LDFLAGS)$@  | ||||
|  | ||||
| all-unix: all $(UNIX_SO) $(SERIAL_SO) | ||||
|  | ||||
| $(UNIX_SO): $(UNIX_OBJS) | ||||
| 	$(LD) $(UNIX_OBJS) $(LDFLAGS)$@  | ||||
|  | ||||
| $(SERIAL_SO): $(SERIAL_OBJS) | ||||
| 	$(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ | ||||
|  | ||||
| install:  | ||||
| 	mkdir -p $(INSTALL_TOP_SHARE) | ||||
| 	$(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE) | ||||
| @@ -204,12 +228,16 @@ install: | ||||
| 	mkdir -p $(INSTALL_MIME_LIB) | ||||
| 	$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO) | ||||
|  | ||||
| install-unix: install | ||||
| 	$(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO) | ||||
| 	$(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_LIB)/$(SERIAL_SO) | ||||
|  | ||||
| local: | ||||
| 	$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. | ||||
|  | ||||
| clean: | ||||
| 	rm -f $(SOCKET_SO) $(SOCKET_OBJS) | ||||
| 	rm -f $(MIME_SO) $(UNIX_SO) $(MIME_OBJS) $(UNIX_OBJS) | ||||
| 	rm -f $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS) | ||||
|  | ||||
| .PHONY: all $(PLATS) default clean echo none | ||||
|  | ||||
| @@ -228,6 +256,8 @@ mime.$(O): mime.c mime.h | ||||
| options.$(O): options.c auxiliar.h options.h socket.h io.h \ | ||||
| 	timeout.h usocket.h inet.h | ||||
| select.$(O): select.c socket.h io.h timeout.h usocket.h select.h | ||||
| serial.$(O): serial.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||||
|   options.h unix.h buffer.h | ||||
| tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||||
| 	inet.h options.h tcp.h buffer.h | ||||
| timeout.$(O): timeout.c auxiliar.h timeout.h | ||||
|   | ||||
| @@ -11,7 +11,6 @@ | ||||
| local base = _G | ||||
| local ltn12 = require("ltn12") | ||||
| local mime = require("mime.core") | ||||
| local io = require("io") | ||||
| local string = require("string") | ||||
| module("mime") | ||||
|  | ||||
|   | ||||
| @@ -21,6 +21,8 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); | ||||
| static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); | ||||
| static int opt_set(lua_State *L, p_socket ps, int level, int name,  | ||||
|         void *val, int len); | ||||
| static int opt_get(lua_State *L, p_socket ps, int level, int name,  | ||||
|         void *val, int* len); | ||||
|  | ||||
| /*=========================================================================*\ | ||||
| * Exported functions | ||||
| @@ -60,23 +62,43 @@ int opt_set_reuseaddr(lua_State *L, p_socket ps) | ||||
|     return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);  | ||||
| } | ||||
|  | ||||
| int opt_get_reuseaddr(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);  | ||||
| } | ||||
|  | ||||
| /* enables reuse of local port */ | ||||
| int opt_set_reuseport(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);  | ||||
| } | ||||
|  | ||||
| int opt_get_reuseport(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);  | ||||
| } | ||||
|  | ||||
| /* disables the Naggle algorithm */ | ||||
| int opt_set_tcp_nodelay(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);  | ||||
| } | ||||
|  | ||||
| int opt_get_tcp_nodelay(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | ||||
| } | ||||
|  | ||||
| int opt_set_keepalive(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);  | ||||
| } | ||||
|  | ||||
| int opt_get_keepalive(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);  | ||||
| } | ||||
|  | ||||
| int opt_set_dontroute(lua_State *L, p_socket ps) | ||||
| { | ||||
|     return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); | ||||
| @@ -114,6 +136,21 @@ int opt_set_linger(lua_State *L, p_socket ps) | ||||
|     return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); | ||||
| } | ||||
|  | ||||
| int opt_get_linger(lua_State *L, p_socket ps) | ||||
| { | ||||
|     struct linger li;                      /* obj, name */ | ||||
|     int len = sizeof(li); | ||||
|     int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len); | ||||
|     if (err) | ||||
|         return err; | ||||
|     lua_newtable(L); | ||||
|     lua_pushboolean(L, li.l_onoff); | ||||
|     lua_setfield(L, -2, "on"); | ||||
|     lua_pushinteger(L, li.l_linger); | ||||
|     lua_setfield(L, -2, "timeout"); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | ||||
| { | ||||
|     int val = (int) luaL_checknumber(L, 3);    /* obj, name, int */ | ||||
| @@ -184,6 +221,19 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) | ||||
|     return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||||
| } | ||||
|  | ||||
| static  | ||||
| int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) | ||||
| { | ||||
|     socklen_t socklen = *len; | ||||
|     if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, "getsockopt failed"); | ||||
|         return 2; | ||||
|     } | ||||
|     *len = socklen; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static  | ||||
| int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) | ||||
| { | ||||
| @@ -199,12 +249,10 @@ int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) | ||||
| static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) | ||||
| { | ||||
|     int val = 0; | ||||
|     socklen_t len = sizeof(val); | ||||
|     if (getsockopt(*ps, level, name, (char *) &val, &len) < 0) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, "getsockopt failed"); | ||||
|         return 2; | ||||
|     } | ||||
|     int len = sizeof(val); | ||||
|     int err = opt_get(L, ps, level, name, (char *) &val, &len); | ||||
|     if (err) | ||||
|         return err; | ||||
|     lua_pushboolean(L, val); | ||||
|     return 1; | ||||
| } | ||||
|   | ||||
| @@ -33,14 +33,18 @@ int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); | ||||
| int opt_set_ip_add_membership(lua_State *L, p_socket ps); | ||||
| int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); | ||||
| int opt_set_ip6_v6only(lua_State *L, p_socket ps); | ||||
| /* invokes the appropriate option handler */ | ||||
| int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||||
|  | ||||
| /* supported options for getoption */ | ||||
| int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||||
| int opt_get_tcp_nodelay(lua_State *L, p_socket ps); | ||||
| int opt_get_keepalive(lua_State *L, p_socket ps); | ||||
| int opt_get_linger(lua_State *L, p_socket ps); | ||||
| int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||||
| int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | ||||
| int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | ||||
|  | ||||
| /* invokes the appropriate option handler */ | ||||
| int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||||
| int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										183
									
								
								src/serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								src/serial.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | ||||
| /*=========================================================================*\ | ||||
| * Serial stream | ||||
| * LuaSocket toolkit | ||||
| \*=========================================================================*/ | ||||
| #include <string.h>  | ||||
|  | ||||
| #include "lua.h" | ||||
| #include "lauxlib.h" | ||||
|  | ||||
| #include "auxiliar.h" | ||||
| #include "socket.h" | ||||
| #include "options.h" | ||||
| #include "unix.h" | ||||
| #include <sys/un.h>  | ||||
|  | ||||
| /* | ||||
| Reuses userdata definition from unix.h, since it is useful for all | ||||
| stream-like objects. | ||||
|  | ||||
| If we stored the serial path for use in error messages or userdata | ||||
| printing, we might need our own userdata definition. | ||||
|  | ||||
| Group usage is semi-inherited from unix.c, but unnecessary since we | ||||
| have only one object type. | ||||
| */ | ||||
|  | ||||
| /*=========================================================================*\ | ||||
| * Internal function prototypes | ||||
| \*=========================================================================*/ | ||||
| static int global_create(lua_State *L); | ||||
| static int meth_send(lua_State *L); | ||||
| static int meth_receive(lua_State *L); | ||||
| static int meth_close(lua_State *L); | ||||
| static int meth_settimeout(lua_State *L); | ||||
| static int meth_getfd(lua_State *L); | ||||
| static int meth_setfd(lua_State *L); | ||||
| static int meth_dirty(lua_State *L); | ||||
| static int meth_getstats(lua_State *L); | ||||
| static int meth_setstats(lua_State *L); | ||||
|  | ||||
| /* serial object methods */ | ||||
| static luaL_Reg serial_methods[] = { | ||||
|     {"__gc",        meth_close}, | ||||
|     {"__tostring",  auxiliar_tostring}, | ||||
|     {"close",       meth_close}, | ||||
|     {"dirty",       meth_dirty}, | ||||
|     {"getfd",       meth_getfd}, | ||||
|     {"getstats",    meth_getstats}, | ||||
|     {"setstats",    meth_setstats}, | ||||
|     {"receive",     meth_receive}, | ||||
|     {"send",        meth_send}, | ||||
|     {"setfd",       meth_setfd}, | ||||
|     {"settimeout",  meth_settimeout}, | ||||
|     {NULL,          NULL} | ||||
| }; | ||||
|  | ||||
| /* our socket creation function */ | ||||
| static luaL_Reg func[] = { | ||||
|     {"serial", global_create}, | ||||
|     {NULL,          NULL} | ||||
| }; | ||||
|  | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Initializes module | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| LUASOCKET_API int luaopen_socket_serial(lua_State *L) { | ||||
|     /* create classes */ | ||||
|     auxiliar_newclass(L, "serial{client}", serial_methods); | ||||
|     /* create class groups */ | ||||
|     auxiliar_add2group(L, "serial{client}", "serial{any}"); | ||||
|     /* make sure the function ends up in the package table */ | ||||
|     luaL_openlib(L, "socket", func, 0); | ||||
|     /* return the function instead of the 'socket' table */ | ||||
|     lua_pushstring(L, "serial"); | ||||
|     lua_gettable(L, -2); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| /*=========================================================================*\ | ||||
| * Lua methods | ||||
| \*=========================================================================*/ | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Just call buffered IO methods | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_send(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||||
|     return buffer_meth_send(L, &un->buf); | ||||
| } | ||||
|  | ||||
| static int meth_receive(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||||
|     return buffer_meth_receive(L, &un->buf); | ||||
| } | ||||
|  | ||||
| static int meth_getstats(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||||
|     return buffer_meth_getstats(L, &un->buf); | ||||
| } | ||||
|  | ||||
| static int meth_setstats(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1); | ||||
|     return buffer_meth_setstats(L, &un->buf); | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Select support methods | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_getfd(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||||
|     lua_pushnumber(L, (int) un->sock); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| /* this is very dangerous, but can be handy for those that are brave enough */ | ||||
| static int meth_setfd(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||||
|     un->sock = (t_socket) luaL_checknumber(L, 2);  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static int meth_dirty(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||||
|     lua_pushboolean(L, !buffer_isempty(&un->buf)); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Closes socket used by object  | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_close(lua_State *L) | ||||
| { | ||||
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||||
|     socket_destroy(&un->sock); | ||||
|     lua_pushnumber(L, 1); | ||||
|     return 1; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Just call tm methods | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_settimeout(lua_State *L) { | ||||
|     p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); | ||||
|     return timeout_meth_settimeout(L, &un->tm); | ||||
| } | ||||
|  | ||||
| /*=========================================================================*\ | ||||
| * Library functions | ||||
| \*=========================================================================*/ | ||||
|  | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Creates a serial object  | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int global_create(lua_State *L) { | ||||
|     const char* path = luaL_checkstring(L, 1); | ||||
|  | ||||
|     /* allocate unix object */ | ||||
|     p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); | ||||
|  | ||||
|     /* open serial device */ | ||||
|     t_socket sock = open(path, O_NOCTTY|O_RDWR); | ||||
|  | ||||
|     /*printf("open %s on %d\n", path, sock);*/ | ||||
|  | ||||
|     if (sock < 0)  { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, socket_strerror(errno)); | ||||
|         lua_pushnumber(L, errno); | ||||
|         return 3; | ||||
|     } | ||||
|     /* set its type as client object */ | ||||
|     auxiliar_setclass(L, "serial{client}", -1); | ||||
|     /* initialize remaining structure fields */ | ||||
|     socket_setnonblocking(&sock); | ||||
|     un->sock = sock; | ||||
|     io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,  | ||||
|             (p_error) socket_ioerror, &un->sock); | ||||
|     timeout_init(&un->tm, -1, -1); | ||||
|     buffer_init(&un->buf, &un->io, &un->tm); | ||||
|     return 1; | ||||
| } | ||||
| @@ -67,6 +67,9 @@ const char *socket_strerror(int err); | ||||
| int socket_send(p_socket ps, const char *data, size_t count,  | ||||
|         size_t *sent, p_timeout tm); | ||||
| int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||||
| int socket_write(p_socket ps, const char *data, size_t count,  | ||||
|         size_t *sent, p_timeout tm); | ||||
| int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||||
| const char *socket_ioerror(p_socket ps, int err); | ||||
|  | ||||
| int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/tcp.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/tcp.c
									
									
									
									
									
								
							| @@ -33,6 +33,7 @@ static int meth_shutdown(lua_State *L); | ||||
| static int meth_receive(lua_State *L); | ||||
| static int meth_accept(lua_State *L); | ||||
| static int meth_close(lua_State *L); | ||||
| static int meth_getoption(lua_State *L); | ||||
| static int meth_setoption(lua_State *L); | ||||
| static int meth_settimeout(lua_State *L); | ||||
| static int meth_getfd(lua_State *L); | ||||
| @@ -49,6 +50,7 @@ static luaL_Reg tcp_methods[] = { | ||||
|     {"connect",     meth_connect}, | ||||
|     {"dirty",       meth_dirty}, | ||||
|     {"getfd",       meth_getfd}, | ||||
|     {"getoption",   meth_getoption}, | ||||
|     {"getpeername", meth_getpeername}, | ||||
|     {"getsockname", meth_getsockname}, | ||||
|     {"getstats",    meth_getstats}, | ||||
| @@ -66,6 +68,14 @@ static luaL_Reg tcp_methods[] = { | ||||
| }; | ||||
|  | ||||
| /* socket option handlers */ | ||||
| static t_opt optget[] = { | ||||
|     {"keepalive",   opt_get_keepalive}, | ||||
|     {"reuseaddr",   opt_get_reuseaddr}, | ||||
|     {"tcp-nodelay", opt_get_tcp_nodelay}, | ||||
|     {"linger",      opt_get_linger}, | ||||
|     {NULL,          NULL} | ||||
| }; | ||||
|  | ||||
| static t_opt optset[] = { | ||||
|     {"keepalive",   opt_set_keepalive}, | ||||
|     {"reuseaddr",   opt_set_reuseaddr}, | ||||
| @@ -130,6 +140,12 @@ static int meth_setstats(lua_State *L) { | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Just call option handler | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| static int meth_getoption(lua_State *L) | ||||
| { | ||||
|     p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||||
|     return opt_meth_getoption(L, optget, &tcp->sock); | ||||
| } | ||||
|  | ||||
| static int meth_setoption(lua_State *L) | ||||
| { | ||||
|     p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); | ||||
|   | ||||
| @@ -184,6 +184,9 @@ static int meth_receive(lua_State *L) { | ||||
|     count = MIN(count, sizeof(buffer)); | ||||
|     timeout_markstart(tm); | ||||
|     err = socket_recv(&udp->sock, buffer, count, &got, tm); | ||||
|     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||||
|     if (err == IO_CLOSED) | ||||
|         err = IO_DONE; | ||||
|     if (err != IO_DONE) { | ||||
|         lua_pushnil(L); | ||||
|         lua_pushstring(L, udp_strerror(err)); | ||||
| @@ -208,6 +211,9 @@ static int meth_receivefrom(lua_State *L) { | ||||
|     count = MIN(count, sizeof(buffer)); | ||||
|     err = socket_recvfrom(&udp->sock, buffer, count, &got, | ||||
|             (SA *) &addr, &addr_len, tm); | ||||
|     /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | ||||
|     if (err == IO_CLOSED) | ||||
|         err = IO_DONE; | ||||
|     if (err == IO_DONE) { | ||||
|         lua_pushlstring(L, buffer, got); | ||||
|         lua_pushstring(L, inet_ntoa(addr.sin_addr)); | ||||
|   | ||||
| @@ -39,7 +39,7 @@ static const char *unix_tryconnect(p_unix un, const char *path); | ||||
| static const char *unix_trybind(p_unix un, const char *path); | ||||
|  | ||||
| /* unix object methods */ | ||||
| static luaL_Reg un[] = { | ||||
| static luaL_Reg unix_methods[] = { | ||||
|     {"__gc",        meth_close}, | ||||
|     {"__tostring",  auxiliar_tostring}, | ||||
|     {"accept",      meth_accept}, | ||||
| @@ -82,9 +82,9 @@ static luaL_Reg func[] = { | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| int luaopen_socket_unix(lua_State *L) { | ||||
|     /* create classes */ | ||||
|     auxiliar_newclass(L, "unix{master}", un); | ||||
|     auxiliar_newclass(L, "unix{client}", un); | ||||
|     auxiliar_newclass(L, "unix{server}", un); | ||||
|     auxiliar_newclass(L, "unix{master}", unix_methods); | ||||
|     auxiliar_newclass(L, "unix{client}", unix_methods); | ||||
|     auxiliar_newclass(L, "unix{server}", unix_methods); | ||||
|     /* create class groups */ | ||||
|     auxiliar_add2group(L, "unix{master}", "unix{any}"); | ||||
|     auxiliar_add2group(L, "unix{client}", "unix{any}"); | ||||
|   | ||||
| @@ -21,6 +21,6 @@ typedef struct t_unix_ { | ||||
| } t_unix; | ||||
| typedef t_unix *p_unix; | ||||
|  | ||||
| int luaopen_socket_unix(lua_State *L); | ||||
| LUASOCKET_API int luaopen_socket_unix(lua_State *L); | ||||
|  | ||||
| #endif /* UNIX_H */ | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Wait for readable/writable/connected socket with timeout | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| #ifdef SOCKET_POLL | ||||
| #ifndef SOCKET_SELECT | ||||
| #include <sys/poll.h> | ||||
|  | ||||
| #define WAITFD_R        POLLIN | ||||
| @@ -49,6 +49,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) { | ||||
|     fd_set rfds, wfds, *rp, *wp; | ||||
|     struct timeval tv, *tp; | ||||
|     double t; | ||||
|     if (*ps >= FD_SETSIZE) return EINVAL; | ||||
|     if (timeout_iszero(tm)) return IO_TIMEOUT;  /* optimize timeout == 0 case */ | ||||
|     do { | ||||
|         /* must set bits within loop, because select may have modifed them */ | ||||
| @@ -213,14 +214,13 @@ int socket_send(p_socket ps, const char *data, size_t count, | ||||
|     for ( ;; ) { | ||||
|         long put = (long) send(*ps, data, count, 0); | ||||
|         /* if we sent anything, we are done */ | ||||
|         if (put > 0) { | ||||
|         if (put >= 0) { | ||||
|             *sent = put; | ||||
|             return IO_DONE; | ||||
|         } | ||||
|         err = errno; | ||||
|         /* send can't really return 0, but EPIPE means the connection was  | ||||
|            closed */ | ||||
|         if (put == 0 || err == EPIPE) return IO_CLOSED; | ||||
|         /* EPIPE means the connection was closed */ | ||||
|         if (err == EPIPE) return IO_CLOSED; | ||||
|         /* we call was interrupted, just try again */ | ||||
|         if (err == EINTR) continue; | ||||
|         /* if failed fatal reason, report error */ | ||||
| @@ -243,12 +243,12 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent, | ||||
|     if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||||
|     for ( ;; ) { | ||||
|         long put = (long) sendto(*ps, data, count, 0, addr, len);   | ||||
|         if (put > 0) { | ||||
|         if (put >= 0) { | ||||
|             *sent = put; | ||||
|             return IO_DONE; | ||||
|         } | ||||
|         err = errno; | ||||
|         if (put == 0 || err == EPIPE) return IO_CLOSED; | ||||
|         if (err == EPIPE) return IO_CLOSED; | ||||
|         if (err == EINTR) continue; | ||||
|         if (err != EAGAIN) return err; | ||||
|         if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||||
| @@ -301,6 +301,66 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, | ||||
|     return IO_UNKNOWN; | ||||
| } | ||||
|  | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Write with timeout | ||||
| * | ||||
| * socket_read and socket_write are cut-n-paste of socket_send and socket_recv, | ||||
| * with send/recv replaced with write/read. We can't just use write/read | ||||
| * in the socket version, because behaviour when size is zero is different. | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| int socket_write(p_socket ps, const char *data, size_t count,  | ||||
|         size_t *sent, p_timeout tm) | ||||
| { | ||||
|     int err; | ||||
|     *sent = 0; | ||||
|     /* avoid making system calls on closed sockets */ | ||||
|     if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||||
|     /* loop until we send something or we give up on error */ | ||||
|     for ( ;; ) { | ||||
|         long put = (long) write(*ps, data, count); | ||||
|         /* if we sent anything, we are done */ | ||||
|         if (put >= 0) { | ||||
|             *sent = put; | ||||
|             return IO_DONE; | ||||
|         } | ||||
|         err = errno; | ||||
|         /* EPIPE means the connection was closed */ | ||||
|         if (err == EPIPE) return IO_CLOSED; | ||||
|         /* we call was interrupted, just try again */ | ||||
|         if (err == EINTR) continue; | ||||
|         /* if failed fatal reason, report error */ | ||||
|         if (err != EAGAIN) return err; | ||||
|         /* wait until we can send something or we timeout */ | ||||
|         if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; | ||||
|     } | ||||
|     /* can't reach here */ | ||||
|     return IO_UNKNOWN; | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Read with timeout | ||||
| * See note for socket_write | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) { | ||||
|     int err; | ||||
|     *got = 0; | ||||
|     if (*ps == SOCKET_INVALID) return IO_CLOSED; | ||||
|     for ( ;; ) { | ||||
|         long taken = (long) read(*ps, data, count); | ||||
|         if (taken > 0) { | ||||
|             *got = taken; | ||||
|             return IO_DONE; | ||||
|         } | ||||
|         err = errno; | ||||
|         if (taken == 0) return IO_CLOSED; | ||||
|         if (err == EINTR) continue; | ||||
|         if (err != EAGAIN) return err;  | ||||
|         if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;  | ||||
|     } | ||||
|     return IO_UNKNOWN; | ||||
| } | ||||
|  | ||||
| /*-------------------------------------------------------------------------*\ | ||||
| * Put socket into blocking mode | ||||
| \*-------------------------------------------------------------------------*/ | ||||
| @@ -360,7 +420,7 @@ const char *socket_strerror(int err) { | ||||
|         case ECONNABORTED: return "closed"; | ||||
|         case ECONNRESET: return "closed"; | ||||
|         case ETIMEDOUT: return "timeout"; | ||||
|         default: return strerror(errno); | ||||
|         default: return strerror(err); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										32
									
								
								test/find-connect-limit
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										32
									
								
								test/find-connect-limit
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| #!/usr/bin/env lua | ||||
| --[[ | ||||
| Find out how many TCP connections we can make. | ||||
|  | ||||
| Use ulimit to increase the max number of descriptors: | ||||
|  | ||||
| ulimit -n 10000 | ||||
| ulimit -n | ||||
|  | ||||
| You'll probably need to be root to do this. | ||||
| ]] | ||||
|  | ||||
| require "socket" | ||||
|  | ||||
| host = arg[1] or "google.com" | ||||
| port = arg[2] or 80 | ||||
|  | ||||
| connections = {} | ||||
|  | ||||
| repeat | ||||
| 	c = assert(socket.connect(hostip or host, 80)) | ||||
| 	table.insert(connections, c) | ||||
|  | ||||
|         if not hostip then | ||||
|             hostip = c:getpeername() | ||||
|             print("resolved", host, "to", hostip) | ||||
|         end | ||||
|  | ||||
| 	print("connection #", #connections, c, "fd", c:getfd()) | ||||
|  | ||||
| until false | ||||
|  | ||||
							
								
								
									
										41
									
								
								test/tcp-getoptions
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										41
									
								
								test/tcp-getoptions
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| #!/usr/bin/env lua | ||||
|  | ||||
| require"socket" | ||||
|  | ||||
| port = 8765 | ||||
|  | ||||
| function options(o) | ||||
|     print("options for", o) | ||||
|  | ||||
|     for _, opt in ipairs{"keepalive", "reuseaddr", "tcp-nodelay"} do | ||||
|         print("getoption", opt, o:getoption(opt)) | ||||
|     end | ||||
|  | ||||
|     print("getoption", "linger", | ||||
|         "on", o:getoption("linger").on, | ||||
|         "timeout", o:getoption("linger").timeout) | ||||
| end | ||||
|  | ||||
| local m = socket.tcp() | ||||
|  | ||||
| options(m) | ||||
|  | ||||
| assert(m:bind("*", port)) | ||||
| assert(m:listen()) | ||||
|  | ||||
| options(m) | ||||
|  | ||||
| m:close() | ||||
|  | ||||
| local m = socket.bind("*", port) | ||||
|  | ||||
| options(m) | ||||
|  | ||||
| local c = socket.connect("localhost", port) | ||||
|  | ||||
| options(c) | ||||
|  | ||||
| local s = m:accept() | ||||
|  | ||||
| options(s) | ||||
|  | ||||
| @@ -7,7 +7,12 @@ while 1 do | ||||
|     print("server: waiting for client connection..."); | ||||
|     control = assert(server:accept()); | ||||
|     while 1 do  | ||||
|         command = assert(control:receive()); | ||||
|         command, emsg = control:receive(); | ||||
|         if emsg == "closed" then | ||||
|             control:close() | ||||
|             break | ||||
|         end | ||||
|         assert(command, emsg) | ||||
|         assert(control:send(ack)); | ||||
|         print(command); | ||||
| 		(load(command))(); | ||||
|   | ||||
							
								
								
									
										25
									
								
								test/udp-zero-length-send
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										25
									
								
								test/udp-zero-length-send
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| #!/usr/bin/lua | ||||
|  | ||||
| --[[ | ||||
| Show that luasocket returns an error message on zero-length UDP sends, | ||||
| even though the send is valid, and in fact the UDP packet is sent | ||||
| to the peer: | ||||
|  | ||||
| % sudo tcpdump -i lo -n | ||||
| tcpdump: verbose output suppressed, use -v or -vv for full protocol decode | ||||
| listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes | ||||
| 13:40:16.652808 IP 127.0.0.1.56573 > 127.0.0.1.5432: UDP, length 0 | ||||
|  | ||||
| ]] | ||||
|  | ||||
| require"socket" | ||||
|  | ||||
| s = assert(socket.udp()) | ||||
| r = assert(socket.udp()) | ||||
| assert(r:setsockname("*", 5432)) | ||||
| assert(s:setpeername("127.0.0.1", 5432)) | ||||
|  | ||||
| ssz, emsg = s:send("") | ||||
|  | ||||
| print(ssz == 0 and "OK" or "FAIL",[[send:("")]], ssz, emsg) | ||||
|  | ||||
							
								
								
									
										37
									
								
								test/udp-zero-length-send-recv
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										37
									
								
								test/udp-zero-length-send-recv
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| #!/usr/bin/lua | ||||
|  | ||||
| --[[ | ||||
| Show that luasocket returns an error message on zero-length UDP sends, | ||||
| even though the send is valid, and in fact the UDP packet is sent | ||||
| to the peer: | ||||
|  | ||||
| % sudo tcpdump -i lo -n | ||||
| tcpdump: verbose output suppressed, use -v or -vv for full protocol decode | ||||
| listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes | ||||
| 13:40:16.652808 IP 127.0.0.1.56573 > 127.0.0.1.5432: UDP, length 0 | ||||
|  | ||||
| ]] | ||||
|  | ||||
| require"socket" | ||||
|  | ||||
| s = assert(socket.udp()) | ||||
| r = assert(socket.udp()) | ||||
| assert(r:setsockname("*", 5432)) | ||||
| assert(s:setpeername("127.0.0.1", 5432)) | ||||
|  | ||||
| ok, emsg = s:send("") | ||||
| if ok ~= 0 then | ||||
|     print("send of zero failed with:", ok, emsg) | ||||
| end | ||||
|  | ||||
| assert(r:settimeout(2)) | ||||
|  | ||||
| ok, emsg = r:receive() | ||||
|  | ||||
| if not ok or string.len(ok) ~= 0 then | ||||
|     print("fail - receive of zero failed with:", ok, emsg) | ||||
|     os.exit(1) | ||||
| end | ||||
|  | ||||
| print"ok" | ||||
|  | ||||
		Reference in New Issue
	
	Block a user