Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local ffi = require("ffi")
- local socket_wrapper = require("socket_wrapper")
- local print = print
- local tostring = tostring
- local tonumber = tonumber
- local strsub = string.sub
- local setmetatable = setmetatable
- local function isnil(object)
- if object then
- return strsub(tostring(object), -4) == "NULL"
- end
- return true
- end
- ffi.cdef [[
- void free (void* ptr);
- void *malloc(size_t size);
- ]]
- ffi.free = ffi.C.free
- ffi.alloc = ffi.C.malloc
- module("bnet")
- BNET_MAX_CLIENTS = 32
- function Shl(A, B)
- if A and B then
- return A * (2 ^ B)
- end
- end
- function CountHostIPs(Host)
- local Addresses, AdressType, AddressLength = socket_wrapper.gethostbyname_(Host)
- if isnil(Addresses) or AddressLength ~= 4 then
- return 0
- end
- local Count = 0
- while not isnil(Addresses[Count]) do
- Count = Count + 1
- end
- return Count
- end
- function IntIP(IP)
- local InetADDR = socket_wrapper.inet_addr_(IP)
- local HTONL = socket_wrapper.htonl_(InetADDR)
- return HTONL
- end
- --[[
- function StringIP(IP)
- return socket_wrapper.inet_ntoa_(socket_wrapper.htonl_(IP))
- end
- ]]
- function ReadAvail(Stream)
- local Size = ffi.new("int", 0)
- if Stream.UDP then
- if Stream.Socket == stream_wrapper.INVALID_SOCKET then
- return 0
- end
- if socket_wrapper.ioctl_(Stream.Socket, stream_wrapper.FIONREAD, Size) then
- return 0
- end
- return tonumber(Size) or 0
- elseif Stream.TCP then
- return Stream:Size()
- end
- return 0
- end
- TUDPStream = {
- Timeout = 0,
- Socket = 0,
- LocalIP = 0,
- LocalPort = 0,
- MessageIP = 0,
- MessagePort = 0,
- RecvSize = 0,
- SendSize = 0,
- UDP = true
- }
- UDP = {__index = TUDPStream}
- function TUDPStream:Read(Buffer, Size)
- local Temp
- if Size > self.RecvSize then
- Size = self.RecvSize
- end
- if Size > 0 then
- ffi.copy(Buffer, self.RecvBuffer, Size)
- if Size < self.RecvSize then
- Temp = ffi.alloc(self.RecvBuffer, Size)
- ffi.copy(Temp, self.RecvBuffer + Size, self.RecvSize - Size)
- ffi.free(self.RecvBuffer)
- self.RecvBuffer = Temp
- self.RecvSize = self.RecvSize - Size
- else
- ffi.free(self.RecvBuffer)
- self.RecvSize = 0
- end
- end
- return Size
- end
- function TUDPStream:Write(Buffer, Size)
- if Size <= 0 then
- return 0
- end
- local Temp = ffi.alloc(self.SendSize + Size)
- if self.SendSize > 0 then
- ffi.copy(Temp, self.SendBuffer, self.SendSize)
- ffi.copy(Temp + self.sendSize, Buffer, Size)
- ffi.free(self.SendBuffer)
- self.SendBuffer = Temp
- self.SendSize = self.SendSize + Size
- else
- ffi.copy(Temp, Buffer, Size)
- self.SendBuffer = Temp
- self.SendSize = Size
- end
- end
- function TUDPStream:Size()
- return self.RecvSize
- end
- function TUDPStream:Eof()
- if self.Socket == socket_wrapper.INVALID_SOCKET then
- return - 1
- end
- return self.RecvSize == 0
- end
- function TUDPStream:Close()
- if self.Socket ~= socket_wrapper.INVALID_SOCKET then
- socket_wrapper.shutdown_(self.Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(self.Socket)
- self.Socket = INVALID_SOCKET
- end
- end
- function CreateUDPStream(Port)
- local Socket = socket_wrapper.socket_(socket_wrapper.AF_INET, socket_wrapper.SOCK_DRAGM, 0)
- if Socket == socket_wrapper.INVALID_SOCKET then
- return nil
- end
- if socket_wrapper.bind_(Socket, socket_wrapper.AF_INET, Port) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local Address = ffi.new("struct sockaddr_in")
- local Addr = ffi.cast("struct sockaddr *", Address)
- local SizePtr = ffi.new("int[1]")
- SizePtr[0] = ffi.sizeof(Address)
- if socket_wrapper.getsockname_(Socket, Addr, NameLen) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local IP = socket_wrapper.inet_ntoa_(Address.sin_addr)
- local Port = socket_wrapper.ntohs(Address.sin_port)
- local Stream = setmetatable({
- Socket = Socket,
- LocalIP = ffi.string(IP),
- LocalPort = Port
- }, UDP)
- return Stream
- end
- function CloseUDPStream(Stream)
- return Stream and Stream:Close()
- end
- function RecvUDPMsg(Stream)
- if not Stream or Stream.Socket == socket_wrapper.INVALID_SOCKET then
- return false
- end
- if socket_wrapper.select_(1, Stream.Socket, 0, nil, 0, nil, self.Timeout) ~= 1 then
- return false
- end
- local Size = ffi.new("int", 0)
- if socket_wrapper.ioctl_(Stream.Socket, socket_wrapper.FIONREAD, Size) == socket_wrapper.SOCKET_ERROR then
- return false
- end
- if Size <= 0 then
- return false
- end
- if Stream.RecvSize > 0 then
- local Temp = ffi.alloc(Stream.RecvSize + Size)
- ffi.copy(Temp, Stream.RecvBuffer, Stream.RecvSize)
- ffi.free(Stream.RecvBuffer)
- Stream.RecvBuffer = Temp
- else
- Stream.RecvBuffer = ffi.alloc(Size)
- end
- local MessageIP = ffi.new("int", 0)
- local MessagePort = ffi.new("int", 0)
- local Result = socket_wrapper.recvfrom_(Stream.Socket, Stream.RecvBuffer + Stream.RecvSize, Size, 0, MessageIP, MessagePort)
- if Result == socket_wrapper.SOCKET_ERROR or Result == 0 then
- return nil
- else
- Stream.MessageIP = MessageIP
- Stream.MessagePort = MessagePort
- Stream.RecvSize = Stream.RecvSize + Result
- return MessageIP
- end
- end
- function SendUDPMsg(Stream, IP, Port)
- if not Stream or Stream.Socket == socket_wrapper.INVALID_SOCKET or Stream.SendSize == 0 then
- return nil
- end
- if socket_wrapper.select_(0, nil, 1, Stream.Socket, 0, nil, 0) ~= 1 then
- return nil
- end
- if not Port or Port == 0 then
- Port = Stream.LocalPort
- end
- local Result = socket_wrapper.sendto_(Stream.Socket, Stream.SendBuffer, Stream.SendSize, 0, IP, Port)
- if Result == socket_wrapper.SOCKET_ERROR or Result == 0 then
- return nil
- end
- if Result == Stream.SendSize then
- ffi.free(Stream.SendBuffer)
- Stream.SendSize = 0
- else
- local Temp = ffi.alloc(Stream.SendSize - Result)
- ffi.copy(Temp, Stream.SendBuffer + Result, Stream.SendSize - Result)
- ffi.free(Stream.SendBuffer)
- Stream.SendBuffer = Temp
- end
- end
- function UDPMsgIP(Stream)
- return Stream and Stream.MessageIP
- end
- function UDPMsgPort(Stream)
- return Stream and Stream.MessagePort
- end
- function UDPStreamIP(Stream)
- return (Stream and Stream.Socket ~= socket_wrapper.INVALID_SOCKET) and Stream.LocalIP
- end
- function UDPStreamPort(Stream)
- return (Stream and Stream.Socket ~= socket_wrapper.INVALID_SOCKET) and Stream.LocalPort
- end
- function UDPTimeouts(Recv)
- if Recv >= 0 then
- TUDPStream.Timeout = Recv
- end
- end
- TTCPStream = {
- Timeouts = {
- [0] = 10000,
- [1] = 0
- },
- Socket = 0,
- LocalIP = 0,
- LocalPort = 0,
- TCP = true
- }
- TCP = {__index = TTCPStream}
- function TTCPStream:Connected()
- if self.Socket == socket_wrapper.INVALID_SOCKET then
- return false
- end
- if socket_wrapper.select_(1, self.Socket, 0, nil, 0, nil, 0) ~= 1 or ReadAvail(self) ~= 0 then
- return true
- end
- self:Close()
- return false
- end
- function TTCPStream:Read(Buffer, Size)
- if self.Socket == socket_wrapper.INVALID_SOCKET then
- return 0
- end
- if socket_wrapper.select_(1, self.Socket, 0, nil, 0, nil, self.Timeouts[0]) ~= 1 then
- return 0
- end
- local Result = socket_wrapper.recv_(self.Socket, self.Buffer, Size)
- if Result == socket_wrapper.SOCKET_ERROR then
- return 0
- end
- return Result
- end
- function TTCPStream:Write(Buffer, Size)
- if self.Socket == socket_wrapper.INVALID_SOCKET then
- return 0
- end
- if socket_wrapper.select_(1, nil, 1, self.Socket, 0, nil, 0) ~= 1 then
- return 0
- end
- local Result = socket_wrapper.send_(self.Socket, self.Buffer, Size, 0)
- if Result == socket_wrapper.SOCKET_ERROR then
- return 0
- end
- return Result
- end
- function TTCPStream:Size()
- local Size = ffi.new("int[1]")
- if socket_wrapper.ioctl_(self.Socket, FIONREAD, Size) == socket_wrapper.SOCKET_ERROR then
- return 0
- end
- return Size[0]
- end
- function TTCPStream:Eof()
- if self.Socket == socket_wrapper.INVALID_SOCKET then
- return -1
- end
- local Result = socket_wrapper.select_(1, self.Socket, 0, nil, 0, nil, self.Timeouts[0])
- if Result == socket_wrapper.SOCKET_ERROR then
- self:Close()
- return -1
- elseif Result == 1 then
- if self:Size() == 0 then
- return -1
- end
- return 0
- end
- return 1
- end
- function TTCPStream:Close()
- if self.Socket ~= socket_wrapper.INVALID_SOCKET then
- socket_wrapper.shutdown_(self.Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(self.Socket)
- self.Socket = socket_wrapper.INVALID_SOCKET
- end
- end
- function TCPStreamConnected(Stream)
- return Stream:Connected()
- end
- function OpenTCPStream(Server, ServerPort, LocalPort)
- if not LocalPort then
- LocalPort = 0
- end
- local ServerIP = socket_wrapper.inet_addr_(Server)
- local PAddress
- if ServerIP == socket_wrapper.INADDR_NONE then
- local Addresses, AddressType, AddressLength = socket_wrapper.gethostbyname_(Server)
- if not Addresses or AddressLength ~= 4 then
- return nil
- end
- if not Addresses[0] then
- return nil
- end
- PAddress = Addresses[0]
- local ShlA = Shl(PAddress[3], 24)
- local ShlB = Shl(PAddress[2], 16)
- local ShlC = Shl(PAddress[1], 8)
- ServerIP = ShlA or ShlB or ShlC or PAddress[0]
- end
- local Socket = socket_wrapper.socket_(socket_wrapper.AF_INET, socket_wrapper.SOCK_STREAM, 0)
- if Socket == socket_wrapper.INVALID_SOCKET then
- return nil
- end
- if socket_wrapper.bind_(Socket, socket_wrapper.AF_INET, LocalPort) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local SAddress = ffi.new("struct sockaddr_in")
- local Addr = ffi.cast("struct sockaddr *", SAddress)
- local SizePtr = ffi.new("int[1]")
- SizePtr[0] = ffi.sizeof(SAddress)
- if socket_wrapper.getsockname_(Socket, SAddress, NameLen) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local IP = socket_wrapper.ntohl_(SAddress.sin_addr.s_addr)
- local Port = socket_wrapper.ntohs_(SAddress.sin_port)
- local Stream = setmetatable({
- Socket = Socket,
- LocalIP = ffi.string(IP),
- LocalPort = Port
- }, TCP)
- if socket_wrapper.connect_(Socket, ServerIP, socket_wrapper.AF_INET, 4, ServerPort) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- return Stream
- end
- function CloseTCPStream(Stream)
- return Stream and Stream:Close()
- end
- function CreateTCPServer(Port)
- if not Port then
- Port = 0
- end
- local Socket = socket_wrapper.socket_(socket_wrapper.AF_INET, socket_wrapper.SOCK_STREAM, 0)
- if Socket == socket_wrapper.INVALID_SOCKET then
- return nil
- end
- if socket_wrapper.bind_(Socket, socket_wrapper.AF_INET, Port) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local SAddress = ffi.new("struct sockaddr_in")
- local Addr = ffi.cast("struct sockaddr *", SAddress)
- local SizePtr = ffi.new("int[1]")
- SizePtr[0] = ffi.sizeof(SAddress)
- if socket_wrapper.getsockname_(Socket, Addr, SizePtr) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- local IP = socket_wrapper.inet_ntoa_(SAddress.sin_addr)
- local Port = socket_wrapper.ntohs_(SAddress.sin_port)
- local Stream = setmetatable({
- Socket = Socket,
- LocalIP = ffi.string(IP),
- LocalPort = Port
- }, TCP)
- if socket_wrapper.listen_(Socket, BNET_MAX_CLIENTS) == socket_wrapper.SOCKET_ERROR then
- socket_wrapper.shutdown_(Socket, socket_wrapper.SD_BOTH)
- socket_wrapper.closesocket_(Socket)
- return nil
- end
- return Stream
- end
- function AcceptTCPStream(Stream)
- if not Stream or Stream.Socket == socket_wrapper.INVALID_SOCKET then
- return nil
- end
- local Read = ffi.new("int[1]", Stream.Socket)
- if socket_wrapper.select_(1, Read, 0, nil, 0, nil, TTCPStream.Timeouts[1]) ~= 1 then
- return nil
- end
- local Address = ffi.new("struct sockaddr_in")
- local Addr = ffi.cast("struct sockaddr *", Address)
- local SizePtr = ffi.new("int[1]")
- SizePtr[0] = ffi.sizeof(Address)
- local Result = socket_wrapper.accept_(Stream.Socket, Addr, SizePtr)
- if Result == socket_wrapper.SOCKET_ERROR then
- return nil
- end
- local IP = socket_wrapper.inet_ntoa_(Address.sin_addr)
- local Port = socket_wrapper.ntohs_(Address.sin_port)
- local Client = setmetatable({
- Socket = Result,
- LocalIP = ffi.string(IP),
- LocalPort = Port
- }, TCP)
- return Client
- end
- function TCPStreamIP(Stream)
- return Stream and Stream.LocalIP
- end
- function TCPStreamPort(Stream)
- return Stream and Stream.LocalPort
- end
- function TCPTimeouts(Read, Accept)
- if Read < 0 then Read = 0 end
- if Accept < 0 then Accept = 0 end
- TTCPStream.Timeouts[0] = Read
- TTCPStream.Timeouts[1] = Accept
- end
- us = CreateTCPServer(0)
- print("New server (TCP) port: "..TCPStreamPort(us))
- while true do
- local cl = AcceptTCPStream(us)
- if cl then
- print("new client")
- print("IP: "..TCPStreamIP(cl))
- print("Port: "..TCPStreamPort(cl))
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment