mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 12:08:21 +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:
commit
4b671f4551
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.o
|
||||||
|
*.so
|
||||||
|
*.so.*
|
@ -42,9 +42,9 @@ Support, Manual">
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<a href="dns.html">DNS (in socket)</a>
|
<a href="dns.html">DNS (in socket)</a>
|
||||||
<blockquote>
|
<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#tohostname">tohostname</a>,
|
||||||
<a href="dns.html#gethostname">gethostname</a>.
|
<a href="dns.html#toip">toip</a>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -108,9 +108,9 @@ Support, Manual">
|
|||||||
<a href="mime.html">MIME</a>
|
<a href="mime.html">MIME</a>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<a href="mime.html#high">high-level</a>:
|
<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#decode">decode</a>,
|
||||||
<a href="mime.html#encode">encode</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#stuff">stuff</a>,
|
||||||
<a href="mime.html#wrap">wrap</a>.
|
<a href="mime.html#wrap">wrap</a>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
@ -120,10 +120,10 @@ Support, Manual">
|
|||||||
<a href="mime.html#dot">dot</a>,
|
<a href="mime.html#dot">dot</a>,
|
||||||
<a href="mime.html#eol">eol</a>,
|
<a href="mime.html#eol">eol</a>,
|
||||||
<a href="mime.html#qp">qp</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#unb64">unb64</a>,
|
||||||
<a href="mime.html#unqp">unqp</a>,
|
<a href="mime.html#unqp">unqp</a>,
|
||||||
|
<a href="mime.html#wrp">wrp</a>.
|
||||||
</blockquote>
|
</blockquote>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -142,6 +142,8 @@ Support, Manual">
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<a href="socket.html">Socket</a>
|
<a href="socket.html">Socket</a>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
|
<a href="socket.html#bind">bind</a>,
|
||||||
|
<a href="socket.html#connect">connect</a>,
|
||||||
<a href="socket.html#debug">_DEBUG</a>,
|
<a href="socket.html#debug">_DEBUG</a>,
|
||||||
<a href="dns.html#dns">dns</a>,
|
<a href="dns.html#dns">dns</a>,
|
||||||
<a href="socket.html#gettime">gettime</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#bind">bind</a>,
|
||||||
<a href="tcp.html#close">close</a>,
|
<a href="tcp.html#close">close</a>,
|
||||||
<a href="tcp.html#connect">connect</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#getpeername">getpeername</a>,
|
||||||
<a href="tcp.html#getsockname">getsockname</a>,
|
<a href="tcp.html#getsockname">getsockname</a>,
|
||||||
<a href="tcp.html#getstats">getstats</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#receive">receive</a>,
|
||||||
<a href="tcp.html#send">send</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#setoption">setoption</a>,
|
||||||
<a href="tcp.html#setstats">setstats</a>,
|
<a href="tcp.html#setstats">setstats</a>,
|
||||||
<a href="tcp.html#settimeout">settimeout</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.
|
it to <tt>select</tt>, it will be ignored.
|
||||||
</p>
|
</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 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
<!-- sink ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||||
|
|
||||||
<p class=name id=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>
|
</ul>
|
||||||
|
|
||||||
<p class=return>
|
<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>
|
||||||
|
|
||||||
<p class=note>
|
<p class=note>
|
||||||
@ -508,6 +541,66 @@ This is the default mode;
|
|||||||
This function returns 1.
|
This function returns 1.
|
||||||
</p>
|
</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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
<!-- footer +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
|
||||||
|
|
||||||
<div class=footer>
|
<div class=footer>
|
||||||
|
@ -12,12 +12,3 @@ clean:
|
|||||||
|
|
||||||
pdf: ltn012.pdf
|
pdf: ltn012.pdf
|
||||||
open 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)
|
all: $(PLAT)
|
||||||
|
|
||||||
$(PLATS) none install local clean:
|
$(PLATS) none install install-unix local clean:
|
||||||
@cd src; $(MAKE) $@
|
@cd src; $(MAKE) $@
|
||||||
|
|
||||||
test: dummy
|
test:
|
||||||
lua test/hello.lua
|
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
|
PLAT?=macosx
|
||||||
|
LUAV?=5.1
|
||||||
|
prefix=/usr/local
|
||||||
|
#prefix=/opt/local
|
||||||
|
#prefix=.
|
||||||
|
|
||||||
INSTALL_DATA=cp
|
LUAINC_macosx=/usr/local/include
|
||||||
INSTALL_EXEC=cp
|
|
||||||
#INSTALL_TOP=/opt/local
|
|
||||||
INSTALL_TOP=./
|
|
||||||
|
|
||||||
#LUAINC_macosx=/opt/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_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"
|
LUAINC_win32="../../lua-5.1.3/src"
|
||||||
LUALIB_win32="../../lua-5.1.3"
|
LUALIB_win32="../../lua-5.1.3"
|
||||||
|
|
||||||
#------
|
#------
|
||||||
# Install directories
|
# Install directories
|
||||||
#
|
#
|
||||||
#INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.1
|
|
||||||
#INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.1
|
INSTALL_DATA=cp
|
||||||
INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.2
|
INSTALL_EXEC=cp
|
||||||
INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.2
|
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_SHARE=$(INSTALL_TOP_SHARE)/socket
|
||||||
INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket
|
INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket
|
||||||
#INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
|
INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
|
||||||
INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/foo/mime
|
|
||||||
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
|
INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
|
||||||
|
|
||||||
#------
|
#------
|
||||||
@ -78,7 +83,7 @@ LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \
|
|||||||
/MANIFESTFILE:"intermediate.manifest" \
|
/MANIFESTFILE:"intermediate.manifest" \
|
||||||
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
|
/MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
|
||||||
/SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \
|
/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
|
LD_win32=cl
|
||||||
SOCKET_win32=wsocket.obj
|
SOCKET_win32=wsocket.obj
|
||||||
|
|
||||||
@ -97,6 +102,7 @@ MIME_V=1.0.3
|
|||||||
SOCKET_SO=socket.$(SO).$(SOCKET_V)
|
SOCKET_SO=socket.$(SO).$(SOCKET_V)
|
||||||
MIME_SO=mime.$(SO).$(MIME_V)
|
MIME_SO=mime.$(SO).$(MIME_V)
|
||||||
UNIX_SO=unix.$(SO)
|
UNIX_SO=unix.$(SO)
|
||||||
|
SERIAL_SO=serial.$(SO)
|
||||||
SOCKET=$(SOCKET_$(PLAT))
|
SOCKET=$(SOCKET_$(PLAT))
|
||||||
|
|
||||||
#------
|
#------
|
||||||
@ -118,7 +124,7 @@ SOCKET_OBJS= \
|
|||||||
timeout.$(O) \
|
timeout.$(O) \
|
||||||
buffer.$(O) \
|
buffer.$(O) \
|
||||||
io.$(O) \
|
io.$(O) \
|
||||||
auxiliar.$(O) \
|
auxiliar.$(O) \
|
||||||
options.$(O) \
|
options.$(O) \
|
||||||
inet.$(O) \
|
inet.$(O) \
|
||||||
$(SOCKET) \
|
$(SOCKET) \
|
||||||
@ -147,6 +153,19 @@ UNIX_OBJS=\
|
|||||||
unix.$(O) \
|
unix.$(O) \
|
||||||
lua_typeerror.$(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
|
# Files to install
|
||||||
#
|
#
|
||||||
@ -169,13 +188,13 @@ TO_TOP_SHARE= \
|
|||||||
default: $(PLAT)
|
default: $(PLAT)
|
||||||
|
|
||||||
macosx:
|
macosx:
|
||||||
$(MAKE) all PLAT=macosx
|
$(MAKE) all-unix PLAT=macosx
|
||||||
|
|
||||||
win32:
|
win32:
|
||||||
$(MAKE) all PLAT=win32
|
$(MAKE) all PLAT=win32
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
$(MAKE) all PLAT=linux
|
$(MAKE) all-unix PLAT=linux
|
||||||
|
|
||||||
none:
|
none:
|
||||||
@echo "Please run"
|
@echo "Please run"
|
||||||
@ -191,9 +210,14 @@ $(SOCKET_SO): $(SOCKET_OBJS)
|
|||||||
$(MIME_SO): $(MIME_OBJS)
|
$(MIME_SO): $(MIME_OBJS)
|
||||||
$(LD) $(MIME_OBJS) $(LDFLAGS)$@
|
$(LD) $(MIME_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
|
all-unix: all $(UNIX_SO) $(SERIAL_SO)
|
||||||
|
|
||||||
$(UNIX_SO): $(UNIX_OBJS)
|
$(UNIX_SO): $(UNIX_OBJS)
|
||||||
$(LD) $(UNIX_OBJS) $(LDFLAGS)$@
|
$(LD) $(UNIX_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
|
$(SERIAL_SO): $(SERIAL_OBJS)
|
||||||
|
$(LD) $(SERIAL_OBJS) $(LDFLAGS)$@
|
||||||
|
|
||||||
install:
|
install:
|
||||||
mkdir -p $(INSTALL_TOP_SHARE)
|
mkdir -p $(INSTALL_TOP_SHARE)
|
||||||
$(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE)
|
$(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE)
|
||||||
@ -204,12 +228,16 @@ install:
|
|||||||
mkdir -p $(INSTALL_MIME_LIB)
|
mkdir -p $(INSTALL_MIME_LIB)
|
||||||
$(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO)
|
$(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:
|
local:
|
||||||
$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
|
$(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(SOCKET_SO) $(SOCKET_OBJS)
|
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
|
.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 \
|
options.$(O): options.c auxiliar.h options.h socket.h io.h \
|
||||||
timeout.h usocket.h inet.h
|
timeout.h usocket.h inet.h
|
||||||
select.$(O): select.c socket.h io.h timeout.h usocket.h select.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 \
|
tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
|
||||||
inet.h options.h tcp.h buffer.h
|
inet.h options.h tcp.h buffer.h
|
||||||
timeout.$(O): timeout.c auxiliar.h timeout.h
|
timeout.$(O): timeout.c auxiliar.h timeout.h
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
local base = _G
|
local base = _G
|
||||||
local ltn12 = require("ltn12")
|
local ltn12 = require("ltn12")
|
||||||
local mime = require("mime.core")
|
local mime = require("mime.core")
|
||||||
local io = require("io")
|
|
||||||
local string = require("string")
|
local string = require("string")
|
||||||
module("mime")
|
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_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,
|
static int opt_set(lua_State *L, p_socket ps, int level, int name,
|
||||||
void *val, int len);
|
void *val, int len);
|
||||||
|
static int opt_get(lua_State *L, p_socket ps, int level, int name,
|
||||||
|
void *val, int* len);
|
||||||
|
|
||||||
/*=========================================================================*\
|
/*=========================================================================*\
|
||||||
* Exported functions
|
* 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);
|
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 */
|
/* enables reuse of local port */
|
||||||
int opt_set_reuseport(lua_State *L, p_socket ps)
|
int opt_set_reuseport(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
|
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 */
|
/* disables the Naggle algorithm */
|
||||||
int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
|
int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
|
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)
|
int opt_set_keepalive(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
|
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)
|
int opt_set_dontroute(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
|
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));
|
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 opt_set_ip_multicast_ttl(lua_State *L, p_socket ps)
|
||||||
{
|
{
|
||||||
int val = (int) luaL_checknumber(L, 3); /* obj, name, int */
|
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));
|
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
|
static
|
||||||
int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
|
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)
|
static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
|
||||||
{
|
{
|
||||||
int val = 0;
|
int val = 0;
|
||||||
socklen_t len = sizeof(val);
|
int len = sizeof(val);
|
||||||
if (getsockopt(*ps, level, name, (char *) &val, &len) < 0) {
|
int err = opt_get(L, ps, level, name, (char *) &val, &len);
|
||||||
lua_pushnil(L);
|
if (err)
|
||||||
lua_pushstring(L, "getsockopt failed");
|
return err;
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
lua_pushboolean(L, val);
|
lua_pushboolean(L, val);
|
||||||
return 1;
|
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_add_membership(lua_State *L, p_socket ps);
|
||||||
int opt_set_ip_drop_membersip(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);
|
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 */
|
/* 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_loop(lua_State *L, p_socket ps);
|
||||||
int opt_get_ip_multicast_if(lua_State *L, p_socket ps);
|
int opt_get_ip_multicast_if(lua_State *L, p_socket ps);
|
||||||
|
|
||||||
/* invokes the appropriate option handler */
|
/* 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);
|
int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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,
|
int socket_send(p_socket ps, const char *data, size_t count,
|
||||||
size_t *sent, p_timeout tm);
|
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_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);
|
const char *socket_ioerror(p_socket ps, int err);
|
||||||
|
|
||||||
int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
|
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_receive(lua_State *L);
|
||||||
static int meth_accept(lua_State *L);
|
static int meth_accept(lua_State *L);
|
||||||
static int meth_close(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_setoption(lua_State *L);
|
||||||
static int meth_settimeout(lua_State *L);
|
static int meth_settimeout(lua_State *L);
|
||||||
static int meth_getfd(lua_State *L);
|
static int meth_getfd(lua_State *L);
|
||||||
@ -49,6 +50,7 @@ static luaL_Reg tcp_methods[] = {
|
|||||||
{"connect", meth_connect},
|
{"connect", meth_connect},
|
||||||
{"dirty", meth_dirty},
|
{"dirty", meth_dirty},
|
||||||
{"getfd", meth_getfd},
|
{"getfd", meth_getfd},
|
||||||
|
{"getoption", meth_getoption},
|
||||||
{"getpeername", meth_getpeername},
|
{"getpeername", meth_getpeername},
|
||||||
{"getsockname", meth_getsockname},
|
{"getsockname", meth_getsockname},
|
||||||
{"getstats", meth_getstats},
|
{"getstats", meth_getstats},
|
||||||
@ -66,6 +68,14 @@ static luaL_Reg tcp_methods[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* socket option handlers */
|
/* 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[] = {
|
static t_opt optset[] = {
|
||||||
{"keepalive", opt_set_keepalive},
|
{"keepalive", opt_set_keepalive},
|
||||||
{"reuseaddr", opt_set_reuseaddr},
|
{"reuseaddr", opt_set_reuseaddr},
|
||||||
@ -130,6 +140,12 @@ static int meth_setstats(lua_State *L) {
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Just call option handler
|
* 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)
|
static int meth_setoption(lua_State *L)
|
||||||
{
|
{
|
||||||
p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
|
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));
|
count = MIN(count, sizeof(buffer));
|
||||||
timeout_markstart(tm);
|
timeout_markstart(tm);
|
||||||
err = socket_recv(&udp->sock, buffer, count, &got, 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) {
|
if (err != IO_DONE) {
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
lua_pushstring(L, udp_strerror(err));
|
lua_pushstring(L, udp_strerror(err));
|
||||||
@ -208,6 +211,9 @@ static int meth_receivefrom(lua_State *L) {
|
|||||||
count = MIN(count, sizeof(buffer));
|
count = MIN(count, sizeof(buffer));
|
||||||
err = socket_recvfrom(&udp->sock, buffer, count, &got,
|
err = socket_recvfrom(&udp->sock, buffer, count, &got,
|
||||||
(SA *) &addr, &addr_len, tm);
|
(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) {
|
if (err == IO_DONE) {
|
||||||
lua_pushlstring(L, buffer, got);
|
lua_pushlstring(L, buffer, got);
|
||||||
lua_pushstring(L, inet_ntoa(addr.sin_addr));
|
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);
|
static const char *unix_trybind(p_unix un, const char *path);
|
||||||
|
|
||||||
/* unix object methods */
|
/* unix object methods */
|
||||||
static luaL_Reg un[] = {
|
static luaL_Reg unix_methods[] = {
|
||||||
{"__gc", meth_close},
|
{"__gc", meth_close},
|
||||||
{"__tostring", auxiliar_tostring},
|
{"__tostring", auxiliar_tostring},
|
||||||
{"accept", meth_accept},
|
{"accept", meth_accept},
|
||||||
@ -82,9 +82,9 @@ static luaL_Reg func[] = {
|
|||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
int luaopen_socket_unix(lua_State *L) {
|
int luaopen_socket_unix(lua_State *L) {
|
||||||
/* create classes */
|
/* create classes */
|
||||||
auxiliar_newclass(L, "unix{master}", un);
|
auxiliar_newclass(L, "unix{master}", unix_methods);
|
||||||
auxiliar_newclass(L, "unix{client}", un);
|
auxiliar_newclass(L, "unix{client}", unix_methods);
|
||||||
auxiliar_newclass(L, "unix{server}", un);
|
auxiliar_newclass(L, "unix{server}", unix_methods);
|
||||||
/* create class groups */
|
/* create class groups */
|
||||||
auxiliar_add2group(L, "unix{master}", "unix{any}");
|
auxiliar_add2group(L, "unix{master}", "unix{any}");
|
||||||
auxiliar_add2group(L, "unix{client}", "unix{any}");
|
auxiliar_add2group(L, "unix{client}", "unix{any}");
|
||||||
|
@ -21,6 +21,6 @@ typedef struct t_unix_ {
|
|||||||
} t_unix;
|
} t_unix;
|
||||||
typedef t_unix *p_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 */
|
#endif /* UNIX_H */
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
/*-------------------------------------------------------------------------*\
|
/*-------------------------------------------------------------------------*\
|
||||||
* Wait for readable/writable/connected socket with timeout
|
* Wait for readable/writable/connected socket with timeout
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
#ifdef SOCKET_POLL
|
#ifndef SOCKET_SELECT
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
|
|
||||||
#define WAITFD_R POLLIN
|
#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;
|
fd_set rfds, wfds, *rp, *wp;
|
||||||
struct timeval tv, *tp;
|
struct timeval tv, *tp;
|
||||||
double t;
|
double t;
|
||||||
|
if (*ps >= FD_SETSIZE) return EINVAL;
|
||||||
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
|
||||||
do {
|
do {
|
||||||
/* must set bits within loop, because select may have modifed them */
|
/* 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 ( ;; ) {
|
for ( ;; ) {
|
||||||
long put = (long) send(*ps, data, count, 0);
|
long put = (long) send(*ps, data, count, 0);
|
||||||
/* if we sent anything, we are done */
|
/* if we sent anything, we are done */
|
||||||
if (put > 0) {
|
if (put >= 0) {
|
||||||
*sent = put;
|
*sent = put;
|
||||||
return IO_DONE;
|
return IO_DONE;
|
||||||
}
|
}
|
||||||
err = errno;
|
err = errno;
|
||||||
/* send can't really return 0, but EPIPE means the connection was
|
/* EPIPE means the connection was closed */
|
||||||
closed */
|
if (err == EPIPE) return IO_CLOSED;
|
||||||
if (put == 0 || err == EPIPE) return IO_CLOSED;
|
|
||||||
/* we call was interrupted, just try again */
|
/* we call was interrupted, just try again */
|
||||||
if (err == EINTR) continue;
|
if (err == EINTR) continue;
|
||||||
/* if failed fatal reason, report error */
|
/* 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;
|
if (*ps == SOCKET_INVALID) return IO_CLOSED;
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
long put = (long) sendto(*ps, data, count, 0, addr, len);
|
long put = (long) sendto(*ps, data, count, 0, addr, len);
|
||||||
if (put > 0) {
|
if (put >= 0) {
|
||||||
*sent = put;
|
*sent = put;
|
||||||
return IO_DONE;
|
return IO_DONE;
|
||||||
}
|
}
|
||||||
err = errno;
|
err = errno;
|
||||||
if (put == 0 || err == EPIPE) return IO_CLOSED;
|
if (err == EPIPE) return IO_CLOSED;
|
||||||
if (err == EINTR) continue;
|
if (err == EINTR) continue;
|
||||||
if (err != EAGAIN) return err;
|
if (err != EAGAIN) return err;
|
||||||
if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) 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;
|
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
|
* Put socket into blocking mode
|
||||||
\*-------------------------------------------------------------------------*/
|
\*-------------------------------------------------------------------------*/
|
||||||
@ -360,7 +420,7 @@ const char *socket_strerror(int err) {
|
|||||||
case ECONNABORTED: return "closed";
|
case ECONNABORTED: return "closed";
|
||||||
case ECONNRESET: return "closed";
|
case ECONNRESET: return "closed";
|
||||||
case ETIMEDOUT: return "timeout";
|
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...");
|
print("server: waiting for client connection...");
|
||||||
control = assert(server:accept());
|
control = assert(server:accept());
|
||||||
while 1 do
|
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));
|
assert(control:send(ack));
|
||||||
print(command);
|
print(command);
|
||||||
(load(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"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user