1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-01-22 18:15:59 +00:00
Files
PLASMA/src/libsrc/inet.pla
2016-03-13 12:41:27 -07:00

247 lines
4.7 KiB
Plaintext

include "inc/cmdsys.plh"
//
// Net object
//
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
word setDNS
word resolveIP
word setCallback
word setParam
end
//
// DNS message
//
struc t_dnshdr
word dnsID
word dnsCode
word dnsQdCount
word dnsAnCount
word dnsNsCount
word dnsArCount
end
//
// External interface to net class. Must be first.
//
export byte[t_inet] iNet
//
// List of loadable network device drivers
//
byte netDrivers = "UTHERNET2"
byte = "UTHERNET"
byte = ""
word driver = @netDrivers
//
// DNS address (default to Google DNS)
//
byte[4] dns = 8,8,8,8
const DNS_QUERY = 1
const DNS_ANSWER = 2
byte stateDNS
def iNetSetDNS(ipptr)
return memcpy(@dns, ipptr, 4)
end
def putln
return putc($0D)
end
def putb(hexb)
return call($FDDA, hexb, 0, 0, 0)
end
def puth(hex)
return call($F941, hex >> 8, hex, 0, 0)
end
def puti(i)
if i < 0; putc('-'); i = -i; fin
if i < 10
putc(i + '0')
else
puti(i / 10)
putc(i % 10 + '0')
fin
end
def putip(ipptr)
byte i
for i = 0 to 2
puti(ipptr->[i]); putc('.')
next
return puti(ipptr->[i])
end
def dumpbytes(buf, len)
word i
for i = 0 to len - 1
putb(buf->[i])
if i & 7 == 7
putln
else
putc(' ')
fin
next
end
def parseIP(ipstr, ipaddr)
byte i
word endstr
endstr = ipstr + ^ipstr
for i = 0 to 3
ipstr = ipstr + 1
while ^ipstr >= '0' and ^ipstr <= '9' and ipstr <= endstr
ipaddr->[i] = ipaddr->[i] * 10 + ^ipstr - '0'
ipstr = ipstr + 1
loop
if ^ipstr <> '.' and ipstr < endstr
return 0
fin
next
return i == 3
end
def parseDomain(domstr, msgptr)
byte i, l
l = 0
for i = 1 to ^domstr
if domstr->[i] == '.'
msgptr->[l] = i - l - 1
l = i
else
msgptr->[i] = domstr->[i]
fin
next
msgptr->[l] = i - l - 1
msgptr = msgptr + i
^msgptr = 0 // Terminate label list
return msgptr + 1
end
def recvDNS(remip, remport, pkt, len, ipaddr)
byte q, r
word resptr
if pkt=>dnsID == $BEEF
q = pkt->dnsQdCount.1
r = pkt->dnsAnCount.1 + pkt->dnsNsCount.1 + pkt->dnsArCount.1
resptr = pkt + t_dnshdr
while q
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
//putln; dumpbytes(resptr, 4); putln
resptr = resptr + 4
q = q - 1
loop
while r
//dumpbytes(resptr, 40); putln
if ^resptr & $C0 == $C0
resptr = resptr + 2
else
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
fin
if resptr->1 == 1 and resptr->3 == 1 and resptr->9 == 4
ipaddr=>0 = resptr=>10
ipaddr=>2 = resptr=>12
fin
//putln; dumpbytes(resptr, 10); putc(':'); putln
resptr = resptr + 8
//dumpbytes(resptr + 2, ^(resptr + 1))
resptr = resptr + 2 + ^(resptr + 1); putln
r = r - 1
loop
fin
stateDNS = DNS_ANSWER
end
def iNetResolve(namestr, ipaddr)
word dnspkt, msgptr, msglen
word portDNS, timeout
ipaddr=>0 = 0
ipaddr=>2 = 0
if not parseIP(namestr, ipaddr)
//
// Query Domain Name Server for address
//
dnspkt = heapmark // Use heap as working DNS query packet
msgptr = dnspkt
msgptr=>dnsID = $BEEF
msgptr=>dnsCode = $0001 // RD (Recursion Desired)
msgptr=>dnsQdCount = $0100 // BE count = 1
msgptr=>dnsAnCount = 0
msgptr=>dnsNsCount = 0
msgptr=>dnsArCount = 0
msgptr = parseDomain(namestr, msgptr + t_dnshdr)
msgptr=>0 = $0100 // BE TYPE = Address
msgptr=>2 = $0100 // BE CLASS = INternet
msglen = msgptr - dnspkt + 4
heapalloc(msglen)
//
// Prepare to receive DNS answer from server
//
portDNS = iNet:openUDP(3999, @recvDNS, ipaddr)
//
// Service IP
//
stateDNS = DNS_QUERY
iNet:sendUDP(portDNS, @dns, 53, dnspkt, msglen)
for timeout = 1 to 1000
iNet:serviceIP()
if stateDNS == DNS_ANSWER
break
fin
next
iNet:closeUDP(portDNS)
heaprelease(dnspkt)
fin
return ipaddr=>0 <> 0 or ipaddr=>2 <> 0
end
export def iNetInit
//
// Look for net hardware
//
while ^driver
//puts(driver);putln
if modexec(driver) >= 0
break
fin
driver = driver + ^driver + 1
loop
if !^driver
return 0
fin
//
// Get an IP address
//
modexec("DHCP")
iNet:resolveIP = @iNetResolve
return @iNet
end
//
// Fill iNet class
//
iNet:initIP = @iNetInit
iNet:setDNS = @iNetSetDNS
done