Platforms to show: All Mac Windows Linux Cross-Platform
/Network/Raw Socket/Raw Socket for UDP Protocol
Required plugins for this example: MBS Network Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Network/Raw Socket/Raw Socket for UDP Protocol
This example is the version from Sun, 23th Sep 2017.
Project "Raw Socket for UDP Protocol.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
Class MainWindow Inherits Window
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control iMessage Inherits TextField
ControlInstance iMessage Inherits TextField
EventHandler Sub TextChange()
SendButton.Enabled = me.text.len > 0
End EventHandler
End Control
Control Label2 Inherits Label
ControlInstance Label2 Inherits Label
End Control
Control iIP Inherits TextField
ControlInstance iIP Inherits TextField
End Control
Control Label3 Inherits Label
ControlInstance Label3 Inherits Label
End Control
Control iPort Inherits TextField
ControlInstance iPort Inherits TextField
End Control
Control List Inherits Listbox
ControlInstance List Inherits Listbox
End Control
Control SendButton Inherits PushButton
ControlInstance SendButton Inherits PushButton
EventHandler Sub Action()
dim Flags as integer = 0
dim r as Integer
// port
dim port as integer = val(iPort.Text)
if port <= 0 or port >= 65535 then
break
MsgBox "Wrong port: "+iPort.Text
Return
end if
// dest address
' UDP protocol header:
'struct udp_header
'{
'u_int32_t source_address;
'u_int32_t dest_address;
'u_int8_t placeholder;
'u_int8_t protocol;
'u_int16_t udp_length;
'};
// IP Header
'struct iphdr {
'__u8 ihl:4,version:4;
'__u8 tos;
'__be16 tot_len;
'__be16 id;
'__be16 frag_off;
'__u8 ttl;
'__u8 protocol;
'__sum16 check;
'__be32 saddr;
'__be32 daddr;
'/*The options start here. */
'};
'struct udphdr
'{
'u_int16_t uh_sport; /* source port */
'u_int16_t uh_dport; /* destination port */
'u_int16_t uh_ulen; /* udp length */
'u_int16_t uh_sum; /* udp checksum */
'};
// message
dim m as string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // ConvertEncoding(iMessage.Text, encodings.UTF8)
dim data as MemoryBlock = m
// allocate memory
dim udph as new MemoryBlock(8)
dim iph as new MemoryBlock(20)
// convert IPv4 from text to numeric value
dim DestIP as Uint32 = RAWSocketMBS.inet_addr(iIP.Text)
dim SourceIP as Uint32 = RAWSocketMBS.inet_addr("127.0.0.1")
System.DebugLog "DestIP: &h"+hex(DestIP)
System.DebugLog "SourceIP: &h"+hex(SourceIP)
// create destination address for OS. This is for Mac! Windows and Linux have different structures
dim dest as new MemoryBlock(16)
#if TargetMacOS
dest.UInt8Value(0) = dest.size
dest.UInt8Value(1) = RAWSocketMBS.AddressFamilyINet
dest.UInt16Value(2) = RAWSocketMBS.htons(port)
dest.UInt32Value(4) = DestIP
#else
dest.UInt8Value(0) = RAWSocketMBS.AddressFamilyINet
dest.UInt16Value(2) = RAWSocketMBS.htons(port)
dest.UInt32Value(4) = DestIP
#endif
dim TotalLength as integer = (iph.size + data.size + udph.size)
// Fill in the IP Header
iph.UInt8Value(0) = &h45 // version (4) and Header length (5*4 bytes)
iph.UInt8Value(1) = 0 // tos
iph.UInt16Value(2) = TotalLength // total length
iph.UInt16Value(4) = RAWSocketMBS.htons(54321) // packet ID
iph.UInt16Value(6) = RAWSocketMBS.htons(0)
iph.UInt8Value(8) = 255
iph.UInt8Value(9) = RAWSocketMBS.ProtocolUDP // 17
iph.UInt16Value(10) = 0 // Set to 0 before calculating checksum
iph.UInt32Value(12) = SourceIP
iph.UInt32Value(16) = DestIP
// IP checksum
dim ipData as MemoryBlock = iph + udph + data
iph.UInt16Value(10) = RAWSocketMBS.CalcChecksum(ipData, ipData.size)
System.DebugLog "checksum ip: &h"+ hex(iph.UInt16Value(10))
// UDP header
udph.UInt16Value(0) = RAWSocketMBS.htons(port) // source port
udph.UInt16Value(2) = RAWSocketMBS.htons(port) // dest port
udph.UInt16Value(4) = RAWSocketMBS.htons(udph.size+data.size) // UDP header size + data size
udph.UInt16Value(6) = 0 // leave checksum 0 now, filled later by pseudo header
#if true then
// Checksum optional
// Now the UDP checksum using the pseudo header
dim psh as new MemoryBlock(12)
psh.UInt32Value(0) = SourceIP
psh.UInt32Value(4) = DestIP
psh.UInt8Value(8) = 0
psh.UInt8Value(9) = RAWSocketMBS.ProtocolUDP
psh.UInt16Value(10) = RAWSocketMBS.htons(udph.size + data.size)
dim pseudogram as MemoryBlock = psh + udph + data
udph.UInt16Value(6) = RAWSocketMBS.CalcChecksum(pseudogram, pseudogram.size)
System.DebugLog "checksum udp: &h"+ hex(udph.UInt16Value(6))
#endif
dim DataToSend as MemoryBlock = iph + udph + data
System.DebugLog "DataToSend: "+str(DataToSend.size)
// send
if dsock <> nil then
r = dsock.SendTo(DataToSend, DataToSend.size, Flags, dest, dest.size)
System.DebugLog "SendTo: "+str(r)+" "+str(dsock.Lasterror)
end if
iMessage.Text = ""
End EventHandler
End Control
EventHandler Sub Close()
ssock = nil
dsock = nil
End EventHandler
EventHandler Sub Open()
// this example must be run as root to be allowed to use truely RAW Socket
// Second, this app does not work. It does send, but we don't see results in the window.
ChecksumTest
// Create RAW Socket to send UDP ourselves
dsock = new RAWSocketMBS(RAWSocketMBS.AddressFamilyINet, RAWSocketMBS.SocketTypeRaw, RAWSocketMBS.ProtocolRaw)
// Create UDP socket to receive packets
ssock = new MyRawSocket(RAWSocketMBS.AddressFamilyINet, RAWSocketMBS.SocketTypeDatagram, RAWSocketMBS.ProtocolUDP)
if ssock.Lasterror <> 0 or ssock.Handle = -1 then
MsgBox "Failed to create normal UDP socket"+EndOfLine+EndOfLine+"Error "+str(ssock.Lasterror)
quit
end if
// to test receive, we bind to any address with given port
// convert IPv4 from text to numeric value
dim IP as Uint32 = 0 // all IPv4
// create destination address. This is for Mac! Windows and Linux have different structures
dim dest as new MemoryBlock(16)
#if TargetMacOS then
dest.UInt8Value(0) = dest.size
dest.UInt8Value(1) = RAWSocketMBS.AddressFamilyINet
dest.UInt16Value(2) = RAWSocketMBS.htons(12345)
dest.UInt32Value(4) = IP
#else
dest.UInt8Value(0) = RAWSocketMBS.AddressFamilyINet
dest.UInt16Value(2) = RAWSocketMBS.htons(12345)
dest.UInt32Value(4) = IP
#endif
if ssock.Bind(dest, dest.size) then
log "Bind OK"
else
log "Bind: "+str(ssock.Lasterror)
end if
Exception r as UnsupportedOperationException
MsgBox "Must be run as root!"+EndOfLine+EndOfLine+r.message
quit
End EventHandler
Shared Sub ChecksumTest()
// some test packet
dim s as string = decodehex("4500003c1c4640004006b1e6ac100a63ac100a0c")
dim m as MemoryBlock = s
dim checksum as integer = m.UInt16Value(10)
m.UInt16Value(10) = 0 // for calculation
dim calc as integer = RAWSocketMBS.CalcChecksum(m, m.size)
if checksum <> calc then
Break // plugin broken?
end if
End Sub
Sub log(s as string)
List.AddRow s
list.ScrollPosition = list.ScrollPosition + 1
End Sub
Property dsock As RAWSocketMBS
Property ssock As MyRawSocket
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
Class MyRawSocket Inherits RAWSocketMBS
EventHandler Sub DataAvailable()
log CurrentMethodName
// simply log what we read
if false then
// using ReadAll
dim m as MemoryBlock = me.ReadAll
dim s as string = DefineEncoding(m, encodings.UTF8)
log s
else
// using ReadDatagram
dim d as DatagramMBS = me.ReadDatagram
dim s as string = DefineEncoding(d.Data, encodings.UTF8)
log "Received: "+s
log "from "+d.Address+":"+str(d.Port)
end if
End EventHandler
EventHandler Sub Error()
log CurrentMethodName
End EventHandler
EventHandler Sub SendComplete()
log CurrentMethodName
End EventHandler
Sub log(s as string)
MainWindow.log s
End Sub
End Class
End Project
See also:
The items on this page are in the following plugins: MBS Network Plugin.