Welcome to the PtokaX Wiki!
This wiki is devoted to let users share information on the great hubsoft PtokaX. However, it is not limited to PtokaX, it is destined to share and discuss information on different parts of the LUA programming language, but the site is NOT intended to be a replacement for the primary LUA Board aka the PtokaX Portal, nor the secondary LUA Board or the PtokaX resources.
If you’re not familiar with wikis then in short: they are user-contributed sites: pages can be edited by (almost) anyone. As such, there is always kind of up-to-date and (hopefully) proper content. They are better than forums, since relevant pieces of information are on the same page. Do not hesitate to share your knowledge, and we all hope you can learn and teach a lot here! — bastya_elvtars
Trace: » The Operating System Library in Lua 5.1.x » Overview of the PtokaX API2 » Using the string library in LUA » Metatables and metamethods » Setting up PtokaX » main » how_to_register » File manipulation » Using SVN » The PtokaX WSA library
The PtokaX WSA library
This library is obsolete, use luasocket instead.
About
PtokaX WSA lib is a lua extension. You can only use it with Ptokax dchub. However if someone need it for another build of lua i'll maybe consider compileing for that build also. The lib purpose is to provide ptokax lua scripts with a tcp client. To allow simple operations like downloading a version file from a web server to check for script updates, or maybe you want a +whois on your hub. Or maybe you just need to look up hostnames, convert ip addresses to and from dotted format (usefull for ip-ranges). Thesae things are now posible to script in ptokax. In the downloaded package, there is the pxwsa.dll and some sample lua scripts.
Copyright & License
Copyright
px_console.exe→ Copyright © 2005 Morten Larsen, aka bluebear.pxwsa.dll→ Copyright © 2005 Morten Larsen, aka bluebear.- manual and sample scripts → Copyright © 2005 Morten Larsen, aka bluebear.
- Lua → Copyright © 1994-2004 Tecgraf, PUC-Rio.
- PtokaX DC Hub → Copyright © 2002-2003 Ptaczek, Frontline3k and aMutex.
- PtokaX DC Hub → Copyright © 2004-2005 Ptaczek and PPK.
License
This license applies to all version of pxwsa.dll, as well as the sample lua scripts and this document.
pxwsa.dll, sample scripts and its documentation is provided as-is, without warranty of any kind, and you're using it at your own risk. I can not be held liable to any party for direct, indirect, special, incidental, or consequential damages arising out of the use of this package and its documentation. I have no obligation to provide maintenance, support, updates, enhancements, or modifications.
You may:
- use pxwsa.dll and sample scripts for whatever non-profit/non-commercial project.
- redistribute original packages downloaded from http://www.thewildplace.dk, without prior permission from me
If you redistribute pxwsa you must credit me and link to my homepage, and you must always have the newest versions available, and not just older versions. And if you discontinue to redistribute the packages, you must clearly state on the page holding the pxwsa.dll package, that you do not keep updates anymore. And advise users to check for newest version on any site that has it's pxwsa archive fully updated. Or you can redirect you discontinued page to http://www.thewildplace.dk/
You may not use pxwsa.dll in any kind of commercial or profit based environment (including religious organizations and educational institutions such as schools and universities) without prior permission from me. If you need such premission, you must find a way to contact me. The best way for that is via email or my site.
System requirements
You must have PtokaX DC Hub >= 0.3.3.21 in order to make the library work. You should put it to the sripts\lib folder. If there is no such folder, create one.
The API
Loading the library
Before you can use the lib you must load it:
libinit = loadlib("pxwsa.dll", "_libinit") libinit()
Common functions
These functions are independent of the socket type you are planning to use.
WSA.Version()
Returns a string containing the PxWSA.dll version.
WSA.Init()
The function initilaizes WS2_32.DLL. You must call this before calling any other function in the pxwsa.dll lib. Usually this can be done in Main()
Function returns 2 nil if there are no errors. Else it returns an error code and an error string.
Usage
errorCode, errorStr = WSA.Init() if errorCode then -- Could not init else -- Init was a success end
WSA.Dispose()
The WSA.Dispose() function terminates use of the WS2_32.DLL. You must call this function when you don't want the usage of sockets any more. Usually this can be done in OnExit(). Usage and return values are the same as in WSA.Init.
Is it supposed to deallocate everything?
WSA.NewSocket([socketType [, LingerOpt]])
Creates a new socket.
Function returns 3 variables; 2x error and socket. If there are no errors, the error variables will be returned as nil, and the socket variable will be the socket ID. If there is an error, it will return an errorcode and a string, and the socket variable will be nil.
Socket ID is used for connecting, sending, receiving and disconnecting. Socket IDs allow you to use multiple sockets, each haveing a unique handle.
Arguments
SocketType: Specifies the socket type: TCP or UDP. Enter0for TCP, any non-zero value for UDP.LingerOpt:
Not coded yet and can not be used
In version 0.0.2 you could only use TCP sockets. Now you can use both TCP and UDP. This changes the WSA.NewSocket function: you now need to specify which protocol you want to use. To ensure backwards compatibility, and not make older scripts broken with this change, the function is overloaded. Meaning you can call it with more than one combination of arguments; without arguments you will get a tcp socket, with one argument you will select the protocol, with 2 arguments you specify the socket type, and the linger option.
Usage
errorCode, errorStr, sock = WSA.NewSocket(0) -- TCP Socket if errorCode then -- Could not get a new socket.. else -- New socket was a success end
WSA.Close(socketID)
Closes/disconnects an existing socket, you can not use the socket any longer, therefore you will have to create a new one, as WSA.Close causes the socket handle to become deallocated so that the application can no longer reference or use the socket in any manner. In next version you can expect, settings for how to close the socket (Gracefully or Abortive). This will be done when allocateing a new socket with the WSA.NewSocket() function.
The function returns 2 variables. If there were no errors 2 nil is returned, else an error code and a string.
Arguments
* socketID: must be an existant socket created with WSA.NewSocket.
Usage
errorCode, errorStr = WSA.Close(sock) if errorCode then -- Some error else -- Socket deallocated :) end end
DNS/IP-related functions
These functions are utilities that make your life easier whaen it comes to hostname lookup or DNS management.
WSA.IPtoDEC(IP)
Converts an IPv4 address to decimal format (i. e. if IP is a.b.c.d then it returns a*16777216+b*65536+c*256+d). Returns nil on failure.
WSA.DECtoIP(DEC)
Converts DEC (an integer number) to an IPv4 address. Returns nil on failure.
WSA.GetHostByName(hostname)
Returns the IP address for a hostname by using a DNS lookup. Ex.: WSA.GetHostByName(“localhost”) returns 127.0.0.1. Returns nil on failure.
WSA.GetHostByAddr()
Gets the hostname belonging to an IP address by doing a reverse DNS lookup. Returns nil on failure.
Synchronous socket functions
These sockets are easier to use in a script, but at the cost of blocking anything else in the hub until the socket operation is finished, so for this time users cannot search/initiate downloads/chat, so it is generally worth the time to use asynchronous sockets (see below) instead.
WSA.Connect(socketID, addr, port)
The WSA.Connect() function establishes a connection using a specified (and existant) socket.
The function returns 2 variables. If there were no errors, 2 nil is returned otherwise it returns an errorcode and string.
Arguments:
socketID: an existant socket created with WSA.NewSocketaddr: remote IP/hostnameport: remote port
Usage
errorCode, errorStr = WSA.Connect(sock, "google.com", 80) if errorCode then -- Could not connect else -- We're connected :) end
WSA.Send(socketID, stringDataToSend)
Sends data to a connected socket (see WSA.Connect above.) It sends raw data, so you gotta have a good knowledge on the protocol you are trying to use. Returns 3 variables. If there were no errors, 2 nil is returned, otherwise it an errorcode and a string. The third variable returns amount of bytes sent and nil on error.
Notes
This function can only be used when you created socketID for TCP communications.
Arguments
stringDataToSend: a string value that is sent to the remote host's specified port
Usage
sData = "I want to transmit this text over a socket" errorCode, errorStr, bytesSent = WSA.Send(sock, sData) if errorCode then -- Send faild else -- Send completed :) end
WSA.SendTo(socketID, stringDataToSend, addr, port)
Sends data to a specific destination. Returns 3 variables. If there were no errors, 2 nil is returned otherwise it a errorcode and string. The third variable returns amount of bytes sent and nil on error.
Notes
This is normally used for UDP protocol only. Since UDP is a stateless protocol, the actual state of a socket is unknown. Therefore if you want to send data to a host listening on an UDP port (e. g. DNS query or NETBIOS-DGM service) you have to re-specify the hostname/IP and the port, as the UDP socket is not handled as connected, even if a WSA.Connect has been previously done. For UDP, it is still good to call WSA.Connect in order to determine whether the communication is possible at all, i. e. to 'test' the connection.
For TCP, the last 2 arguments are ignored, but it's mandatory that the socket is connected, therefore this function becomes the same as WSA.Send.
Arguments
- socketID: see the above notes
- stringDataToSend: see
WSA.Send - addr: must be specified, but used by UDP only, remote IP/hostname
- port: must be specified, but used by UDP only, remote port
Usage
sdata = "I want to transmit this text over a socket" errorCode, errorStr, bytesSent = WSA.SendTo(sock, sdata, "192.168.1.54", 1024) if errorCode then -- Send was an failure else -- Send completed :) end
WSA.Receive(socketID)
Receives data from a connected socket. Returns 4 variables, if there were no errors nil is returned to the error variables and the data to the data variable. If there was errors, the error variables will return the errorcode and string, and the data variable will return nil.
Notes
For connectionless sockets, data is extracted from the first enqueued datagram (message) from the destination address specified by the WSA.BeginConnect (see below) / WSA.Connect function. If the datagram or message is larger than the buffer (32K) specified in the pxwsa C code, the buffer is filled with the first part of the datagram, and WSA.BeginReceive (see below) / WSA.Receive generates the error 10040. For unreliable protocols (UDP) the excess data is lost; for reliable protocols (TCP), the data is retained by the service provider until it is successfully read by calling WSA.BeginReceive (see below) / WSA.Receive multiple times. This can easily be achieved by using a while loop (see below).
Arguments
- socketID: an existant socket created with
WSA.NewSocketand (if TCP) connected to withWSA.Connect
Usage
This is one way of usage:
-- by bluebear errorCode, errorStr, sdata, bytesRead = WSA.Receive(sock) if errorCode then -- Receive was an failure if errorCode == 0 then -- the connection has been gracefully closed by remotehost. else -- Receive done - but there can still be data on the socket -- you need to read. end end
A Complete Example
This is something that gives a better understanding of the functions described above.
ghost="www.thewildplace.dk" gport=80 gprot=0 -- 0 for TCP, 1 for UDP (mostly it's TCP) gfile="/lua/wsa/index.html" Msg="" -- an internal 'receive buffer' _,_,sock=WSA.NewSocket(gprot) -- creating a socket, according to what we have above errorCode,errorString=WSA.Connect(sock,ghost,gport) if errorCode then -- connection failed WSA.Close(sock) return 1 end -- if we cannot connect, no bothering -- HTTP-specific commend sending CMD="GET "..gfile.." HTTP/1.1\r\nHost: "..ghost.."\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"..string.char(13,10) WSA.SendTo(sock,CMD,ghost,gport) -- universal for tcp and udp -- do until receiving finishes or there is too big data (futile for UDP, that's why there is a gprot) while errorCode==nil or (gprot==0 and errorCode==10040) do errorCode, errorStr, sdata, bytesRead = WSA.Receive(sock) -- starting to receive now Msg=Msg..sdata -- merge the received data into the internal recv buffer end WSA.Close(sock) -- Msg should be used NOW.
Asynchronous socket functions
Allows you to create async calls from your lua script. They work different than the blocking socket methods. An event (luascript function) will be fired when there is for example data ready on a socket. They do not block the code, when something happens, then you are 'ringed back', so you do not have to 'hold on the phone'.
WSA.BeginConnect(socketID, addr, port)
Begins to asynchronously connect a socket to a remote endpoint..
Arguments
- socketID: an existant socket created with
WSA.NewSocket - addr: remote IP/hostname
- port: remote port
If the connection succeeds or fails, it fires the following function:
OnWsaConnected ( errorCode, errorStr, socket )
If there are no errors, the error variables will be returned as nil.
Usage
OnWsaConnected = function ( errorCode, errorStr, socket ) if errorCode then -- Could not connect else -- We're connected :) end end WSA.BeginConnect(socket, "localhost", 411) -- we connect to an *existant* socket.
WSA.BeginSend(socketID,data)
The WSA.BeginSend() begins to asynchronously transmit data on a connected socket..
Arguments
- socketID: an existant socket created with
WSA.NewSocketand connected with - data: a string value that is sent to the remote host's specified port
OnWsaSendComplete ( errorCode, errorStr, socket, bytesSent )
If there are no errors, the error variables will be returned as nil. And socket, bytesSent will be returned with their respective values. If there is errors only error and socket variables will return useful data. bytesSent will be returned as nil.
Usage
OnWsaSendComplete = function ( errorCode, errorStr, socket, bytesSent ) if errorCode then -- Sending failed else -- Sent end return 0 end data = "Transmit this string" WSA.BeginSend(socket, data)
WSA.BeginReceive(soketID)
Begins to asynchronously receive data from a connected socket.
Notes:
For connectionless sockets, data is extracted from the first enqueued datagram (message) from the destination address specified by the WSA.BeginConnect() / WSA.Connect() function.
For connectionless sockets, data is extracted from the first enqueued datagram (message) from the destination address specified by the WSA.BeginConnect function. If the datagram or message is larger than the buffer (32K) specified in the pxwsa C code, the buffer is filled with the first part of the datagram, and WSA.BeginReceive generates the error 10040. For unreliable protocols (UDP) the excess data is lost; for reliable protocols (TCP), the data is retained by the service provider until it is successfully read by returning 0.
Arguments
- socketID: an existant socket created with
WSA.NewSocket
OnWsaDataArrival ( errorCode, errorStr, socket, sData, bytesRead )
If there are no errors, the error variables will be returned as nil. And socket, sdata, length will be returned with their respective values. If there is errors only error and socket variables will return usefull data, sdata and length will be returned as nil.
Important
Your function must return 0 or 1. If you return 1 (or just any number > 0) the socket will continue to asynchronously receive data. If you return ''0' the socket will not continue receiving data.
OnWsaDataArrival = function ( errorCode, errorStr, socket, sdata, bytesRead ) local retVal = 0 if errorCode then -- Receive was an failure if errorCode == 0 then -- the connection has been gracefully closed by remotehost. -- You should call the close method now else -- Error while reading data from socket. end else -- Receive done - but there can still be data on the socket you need to read. retVal = 1 end return retVal end WSA.BeginReceive(socket)
A Complete Example
Many things above sound mysterious, so maybe this example will help you.
ghost="www.thewildplace.dk" gport=80 gprot=0 -- 0 for TCP, 1 for UDP (mostly it's TCP) gfile="/lua/wsa/index.html" function OnWsaConnected ( errorCode, errorStr, sock ) -- connection attempt to host finished if errorCode then -- connection failed WSA.Close(sock) else -- we are connected. local CMD="GET "..gfile.." HTTP/1.1\r\nHost: "..ghost.."\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"..string.char(13,10) WSA.BeginSend(sock,CMD) -- Sending a request end end function OnWsaSendComplete ( errorCode, errorStr, sock, bytesSent ) -- send attempt finished if errorCode then -- Sending failed WSA.Close(sock) else -- Sent WSA.BeginReceive(sock) -- let's wait for response to request end end function OnWsaDataArrival ( errorCode, errorStr, sock, sdata, bytesRead ) -- response -- proper response orjust partial data if not errorCode or (errorCode==10040 and prot==0) then DataRecv=DataRecv..sdata -- merging to the receive buffer return 1 -- telling the thread to continue to receive else -- do something to the data, as you will not get more. :-) DataRecv="" -- empty the internal 'receive buffer' return 0 -- tell the lib not to try any longer end end -- empty string, works as the receive buffer -- it must be global, as if itis created as local OnWsaDataArrival -- it is flushed every time a new data arrives DataRecv="" _,_,sock=WSA.NewSocket(gprot) -- creating a socket, according to what we have above WSA.BeginConnect(sock,ghost,gport) -- try a connection to host
This is all about the WSA lib now, hope we could make you understand it. If not, feel free to initiate some inline discussion as described here.
bluebear & bastya_elvtars
You are here: About the Wiki » scriptinghelp » The PtokaX WSA library