Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- UDP = {
- Server = {
- Create = function (Port)
- local Socket = IO.CreateUDPStream(Port)
- if Socket then
- local Server = setmetatable(
- {
- Socket = Socket,
- RecvPackets = {},
- SendPackets = {},
- SendID = {},
- PacketID = {},
- PacketType = {},
- Ping = {},
- PingRequest = {},
- }, UDP.ServerMT
- )
- return Server
- end
- end,
- CreatePacketType = function (Name, Function)
- -- So we create a function that reads packets of certain type ID
- assert(type(ID) == "number", "CreatePacketType must contain a id identifier")
- assert(type(Function) == "function", "CreatePacketType must contain a function")
- local PacketID = #self.PacketType + 1
- self.PacketID[Name] = PacketID
- self.PacketType[PacketID] = Function
- -- Function = self.PacketType[self.PacketID[ type name of the packet ]]
- -- Function = self.PacketType[ type id of the packet]
- end,
- packetType = function (Name, IP, Port)
- -- Let's that this client has a packet type ID for the type name of this packet, but the rest of the clients have different type IDs
- if IP and Port then
- local Address = IP..":"..Port
- if self.SendID[Address] then
- return self.SendID[Address][Name]
- end
- end
- -- Otherwise we send an already known type
- return self.PacketID[Name]
- end,
- newPacketIDToIP = function (IP, Port)
- local Address = IP..":"..Port
- if not self.SendPackets[Address] then
- self.SendPackets[Address] = {}
- end
- local Packet = {}
- local PacketPrevID = #self.SendPackets[Address]
- local PacketID = PacketPrevID + 1
- if PacketID >= 65536 then
- PacketID = 0
- end
- Packet.ID = PacketID
- Packet.Prev = PacketPrevID
- self.SendPackets[Address][PacketID] = Packet
- return Packet, PacketID
- end,
- newPacketFromIP = function (IP, Port, ID)
- local Address = IP..":"..Port
- if not self.RecvPackets[Address] then
- self.RecvPackets[Address] = {Current = Packet.ID}
- end
- local Packet = {ID = ID}
- local PacketPrevID = Packet.ID - 1
- if PacketPrevID < 0 then
- PacketPrevID = 65535
- end
- Packet.Prev = PacketPrevID
- self.RecvPackets[Address][Packet.ID] = Packet
- if self.RecvPackets[Address].Current == Packet.Prev then
- self.RecvPackets[Address].Current = Packet.ID
- end
- return Packet, Packet.ID
- end,
- NewPacket = function (Name, IP, Port, Data)
- -- We create a packet for
- local Type = self:packetType(Name, IP, Port)
- if Type then
- local Stream = IO.CreateBankStream()
- if Stream then
- if Data and string.len(Data) > 32 then
- IO.WriteString(Stream, Data)
- IO.SeekStream(Stream, 0)
- end
- local Packet = self:newPacketIDToIP(IP, Port)
- Packet.Type = Type
- Packet.Stream = Stream
- Packet.IP = IP
- Packet.Port = Port
- Packet.Retries = 0
- Packet.SendLast = 0
- return Packet
- end
- end
- end,
- NewPacketFrom = function (Type, ID, IP, Port, Data)
- local Stream = IO.CreateBankStream()
- if Stream then
- if Data then
- IO.WriteString(Stream, Data)
- end
- local Packet = self:newPacketFromIP(IP, Port, ID)
- Packet.Type = Type
- Packet.Stream = Stream
- Packet.IP = IP
- Packet.Port = Port
- return Packet
- end
- end,
- Delete = {
- -- Different functions to delete already read/sent packets
- RecvPacket = function (Packet)
- local Address = Packet.IP..":"..Port
- if self.RecvPackets[Address] then
- self.RecvPackets[Address][Packet.ID] = nil
- if table.empty(self.RecvPackets[Address]) then
- self.RecvPackets[Address] = nil
- end
- end
- end,
- SendPacket = function (Packet)
- local Address = Packet.IP..":"..Port
- if self.SendPackets[Address] then
- self.SendPackets[Address][Packet.ID] = nil
- if table.empty(self.SendPackets[Address]) then
- self.SendPackets[Address] = nil
- end
- end
- end,
- RecvPacketID = function (IP, Port, PacketID)
- local Address = IP..":"..Port
- if self.RecvPackets[Address] then
- self.RecvPackets[Address][PacketID] = nil
- if table.empty(self.RecvPackets[Address]) then
- self.RecvPackets[Address] = nil
- end
- end
- end,
- SendPacketID = function (IP, Port, PacketID)
- local Address = IP..":"..Port
- if self.SendPackets[Address] then
- self.SendPackets[Address][PacketID] = nil
- if table.empty(self.SendPackets[Address]) then
- self.SendPackets[Address] = nil
- end
- end
- end,
- },
- NextPacket = function ()
- -- Gets the next packet from the queue
- for Address, Packets in pairs(self.RecvPackets) do
- for ID, Packet in pairs(Packets) do
- if Packets.Current >= Packet.ID then
- return Packet
- end
- end
- end
- end,
- ReceivePackets = function ()
- while IO.RecvUDPMsg(self.Socket) do
- -- Reads messages from the UDP socket
- local MsgSize = IO.ReadAvail(self.Socket)
- local MsgIP = IO.UDPMsgIP(self.Socket)
- local MsgPort = IO.UDPMsgPort(self.Socket)
- if MsgSize >= 1 then
- MsgSize = MsgSize - 1
- local MsgType = IO.ReadByte(self.Socket)
- if MsgType == 0 then
- -- DELETE PACKET
- if MsgSize >= 2 then
- local PacketID = IO.ReadShort(self.Socket)
- self.Delete.SendPacketID(self, IP, Port, PacketID)
- end
- elseif MsgType == 1 then
- -- RECEIVED PACKET
- if MsgSize >= 2 then
- local PacketType = IO.ReadShort(self.Socket)
- local PacketID = IO.ReadShort(self.Socket)
- MsgSize = MsgSize - 4
- local PacketDatagram = IO.ReadString(self.Socket, MsgSize)
- if string.len(PacketDatagram) > 0 then
- self:NewPacketFrom(PacketType, PacketID, MsgIP, MsgPort, PacketDatagram)
- IO.WriteByte(self.Socket, 0)
- IO.WriteShort(self.Socket, PacketID)
- IO.SendUDPMsg(self.Socket, MsgIP, MsgPort)
- end
- end
- end
- end
- end
- local NextPacket = self:NextPacket()
- while NextPacket do
- -- As long as we can read packets, we have to parse them with our already known functions
- local PacketProtocol = self.PacketType[NextPacket.Type]
- if PacketProtocol then
- PacketProtocol(NextPacket)
- end
- self.Delete.RecvPacket(self, NextPacket)
- NextPacket = self:NextPacket()
- end
- end,
- SendPackets = function ()
- -- We re-send the packets that haven't been received
- for Address, Packets in pairs(self.SendPackets) do
- for PacketID, Packet in pairs(Packets) do
- if os.clock() - Packet.SendLast >= 0.125 then
- Packet.Retries = Packet.Retries + 1
- Packet.SendLast = Packet.SendLast + 1
- local Datagram = IO.ReadString(Packet.Stream, IO.StreamSize(Packet.Stream))
- IO.SeekStream(Packet.Stream, 0)
- IO.WriteString(self.Socket, Datagram)
- IO.SendUDPMsg(self.Socket, Packet.IP, Packet.Port)
- if Packet.Retries >= 16 then
- -- If this packet failed to send 16 times during 2 seconds, it is cancelled
- self.Delete.SendPacket(self, Packet)
- end
- end
- end
- end
- end,
- Update = function ()
- -- Update function, so we just need to call this instead of two
- self:SendPackets()
- self:ReceivePackets()
- end,
- }
- }
- UDP.ServerMT = {__index = UDP.Server, __type = "udp server"}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement