mirror of
https://github.com/dschmenk/PLASMA.git
synced 2026-04-25 04:18:25 +00:00
Internet CHAT client/server
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
//
|
||||
// HTTP Daemon
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln, gotoxy
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef isugt, isuge, isult, isule
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
//
|
||||
// Net object
|
||||
//
|
||||
import inet
|
||||
word iNet
|
||||
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
|
||||
end
|
||||
|
||||
const VERSION = 3
|
||||
const txtline = $07D0
|
||||
const inbuf = $0200
|
||||
const instr = $01FF
|
||||
|
||||
byte[4] serverIP
|
||||
word port, timeout
|
||||
word update_list, update_len
|
||||
byte response
|
||||
byte hellopkt = $DA, $7E, VERSION, VERSION >> 8, $00, $00, $A2, 'H'
|
||||
byte[9] handle = ""
|
||||
byte chatpkt = $DA, $7E, VERSION, VERSION >> 8, $00, $01, $A2, 'C'
|
||||
byte[33] msg
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
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 toupper(c)
|
||||
if c >= 'a'
|
||||
c = c - $20
|
||||
fin
|
||||
return c
|
||||
end
|
||||
|
||||
def recvUDP(ipsrc, portsrc, data, len, param)
|
||||
byte t
|
||||
|
||||
response = data->7
|
||||
when response
|
||||
is 'C'
|
||||
putln
|
||||
if data->16
|
||||
^$32 = $3F // Inverse
|
||||
for t = 0 to data->8
|
||||
putc(toupper(^(data + t + 9)))
|
||||
next
|
||||
^$32 = $FF // Normal
|
||||
for t = data->8 to 7
|
||||
putc(' ')
|
||||
next
|
||||
puts(data + 16)
|
||||
else
|
||||
puts("Welcome, "); puts(data + 8)
|
||||
fin
|
||||
break
|
||||
is 'W'
|
||||
//puts("Connected to ")
|
||||
//puts(instr); putc('='); putip(@serverIP)
|
||||
break
|
||||
is 'U'
|
||||
update_list = data
|
||||
update_len = len
|
||||
break;
|
||||
is 'E'
|
||||
puts("Server error!"); putln
|
||||
wend
|
||||
end
|
||||
|
||||
def gotoxy(x, y)
|
||||
^$24 = x + ^$20
|
||||
return call($FB5B, y + ^$22, 0, 0, 0)
|
||||
end
|
||||
|
||||
def txtwin(left, top, width, height)
|
||||
if !width or !height
|
||||
left = 0
|
||||
top = 0
|
||||
width = 40
|
||||
height = 24
|
||||
fin
|
||||
^$20 = left
|
||||
^$21 = width
|
||||
^$22 = top
|
||||
^$23 = height + top
|
||||
return gotoxy(0, 0)
|
||||
end
|
||||
|
||||
def txtclr
|
||||
^$20 = 0
|
||||
^$21 = 40
|
||||
^$22 = 0
|
||||
^$23 = 24
|
||||
return call($FC58, $00, $00, $00, $00)
|
||||
end
|
||||
|
||||
def kbstr
|
||||
byte key, inlen
|
||||
|
||||
^$C010
|
||||
inlen = 0
|
||||
repeat
|
||||
^(txtline + inlen) = $DF
|
||||
key = ^$C000
|
||||
if key & $80
|
||||
^(txtline + inlen) = $A0
|
||||
^$C010
|
||||
if key == $88
|
||||
if inlen > 0
|
||||
inlen = inlen - 1
|
||||
fin
|
||||
elsif key == $9B
|
||||
while inlen
|
||||
^(txtline + inlen) = $A0
|
||||
inlen = inlen - 1
|
||||
loop
|
||||
elsif key >= $A0 and inlen < 39
|
||||
^(txtline + inlen) = key
|
||||
^(inbuf + inlen) = key & $7F
|
||||
inlen = inlen + 1
|
||||
fin
|
||||
fin
|
||||
iNet:serviceIP()
|
||||
until key == $8D
|
||||
^instr = inlen
|
||||
repeat
|
||||
^(txtline + inlen) = $A0
|
||||
inlen = inlen - 1
|
||||
until inlen == $FF
|
||||
return instr
|
||||
end
|
||||
if !iNet:initIP()
|
||||
return -1
|
||||
fin
|
||||
repeat
|
||||
puts("Enter chat server address\n")
|
||||
gets(':'+$80)
|
||||
if ^instr
|
||||
if iNet:resolveIP(instr, @serverIP)
|
||||
repeat
|
||||
puts("Enter chat handle (7 characters or less)\n")
|
||||
gets(':'+$80)
|
||||
until ^instr > 0 and ^instr < 8
|
||||
memcpy(@handle, instr, ^instr + 1)
|
||||
port = iNet:openUDP($6501, @recvUDP, 0)
|
||||
iNet:sendUDP(port, @serverIP, $6502, @hellopkt, 16)
|
||||
timeout = 1000
|
||||
while !response and timeout
|
||||
iNet:serviceIP()
|
||||
timeout = timeout - 1
|
||||
loop
|
||||
if response == 'W'
|
||||
txtclr()
|
||||
gotoxy(0, 22)
|
||||
puts("========================================")
|
||||
txtwin(0, 0, 40, 22)
|
||||
gotoxy(0, 0)
|
||||
repeat
|
||||
kbstr()
|
||||
if ^instr
|
||||
if ^instr > 31
|
||||
^instr = 31
|
||||
fin
|
||||
memcpy(@msg, instr, ^instr + 1)
|
||||
iNet:sendUDP(port, @serverIP, $6502, @chatpkt, 40)
|
||||
fin
|
||||
until ^instr == 0
|
||||
txtclr()
|
||||
elsif response == 'U'
|
||||
heaprelease(update_list + update_len) // Set top of heap to end of update list
|
||||
memcpy($0300, @serverIP, 4) // Pass serverIP to UPDATE
|
||||
*$0304 = $6502 // Pass server port to UPDATE
|
||||
*$0306 = update_list + 8 // Pass list pointer to UPDATE
|
||||
^instr = 0
|
||||
modexec("UPDATE")
|
||||
else
|
||||
puts("Welcome timed out."); putln
|
||||
fin
|
||||
else
|
||||
puts("Unable to resolve."); puts(instr); putln
|
||||
fin
|
||||
fin
|
||||
until not ^instr
|
||||
done
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<chat xmlns="updates">
|
||||
<file name="PLASMA.SYSTEM" type="0xFF" aux="0x2000" mask="0x0001"/>
|
||||
<file name="UTHERNET" type="0xFE" aux="0x1000" mask="0x0002"/>
|
||||
<file name="UTHERNET2" type="0xFE" aux="0x1000" mask="0x0004"/>
|
||||
<file name="ETHERIP" type="0xFE" aux="0x1000" mask="0x0008"/>
|
||||
<file name="INET" type="0xFE" aux="0x1000" mask="0x0010"/>
|
||||
<file name="DHCP" type="0xFE" aux="0x1000" mask="0x0020"/>
|
||||
<file name="UPDATE" type="0xFE" aux="0x1000" mask="0x0040"/>
|
||||
<file name="CHAT" type="0xFE" aux="0x1000" mask="0x0080"/>
|
||||
<file name="AUTORUN" type="0x06" aux="0x0000" mask="0x0100"/>
|
||||
<current level="3"/>
|
||||
<version level="1" updates="0x0000"/>
|
||||
<version level="2" updates="0x00C0"/>
|
||||
<version level="3" updates="0x01C0"/>
|
||||
</chat>
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/python
|
||||
import sys, struct, socket, select
|
||||
|
||||
server = ("localhost", 0x6502)
|
||||
myhandle = "Python"
|
||||
VERSION = 3
|
||||
|
||||
# SOCK_DGRAM is the socket type to use for UDP sockets
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.sendto(struct.pack('<HHHBc8p', 0x7EDA, VERSION, 1, 0xFF, 'H', myhandle), server)
|
||||
data, server = s.recvfrom(2048)
|
||||
magic, ver, seq, hw, res = struct.unpack_from('<HHHBc', data)
|
||||
if res == 'U':
|
||||
ulistofst = 8
|
||||
print "Update file list: (", len(data), " bytes)"
|
||||
while len(data) - ulistofst >= 20:
|
||||
filename, filetype, fileaux = struct.unpack_from('<17pBH', data, ulistofst)
|
||||
if filename == "": break
|
||||
print filename, filetype, fileaux
|
||||
ulistofst += 20
|
||||
elif res <> 'W':
|
||||
print "Server rejected HELLO"
|
||||
else:
|
||||
p = select.poll()
|
||||
p.register(s, select.POLLIN)
|
||||
p.register(sys.stdin, select.POLLIN)
|
||||
while 1:
|
||||
pollin = p.poll()
|
||||
if len(pollin) > 0:
|
||||
if pollin[0][0] == sys.stdin.fileno():
|
||||
instr = raw_input()
|
||||
if len(instr) == 0: break
|
||||
s.sendto(struct.pack('<HHHBc32p', 0x7EDA, VERSION, 1, 0xFF, 'C', instr), server)
|
||||
elif pollin[0][0] == s.fileno():
|
||||
data, server = s.recvfrom(2048)
|
||||
magic, ver, seq, hw, req = struct.unpack_from('<HHHBc', data)
|
||||
if req == 'C':
|
||||
handle, msg = struct.unpack_from('8p32p', data, 8)
|
||||
if msg:
|
||||
print handle, ": ", msg
|
||||
#elif handle <> myhandle:
|
||||
else:
|
||||
print "Welcome, ", handle
|
||||
s.close()
|
||||
@@ -0,0 +1 @@
|
||||
+CHAT
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+104
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/python
|
||||
# Apple II Chat server program
|
||||
import struct, socket, select, time
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
HOST = '' # Symbolic name meaning all available interfaces
|
||||
PORT = 0x6502 # Apple II Chat non-privileged port
|
||||
VERSION = 1
|
||||
client_list = {}
|
||||
chat_files = {}
|
||||
chat_vers = []
|
||||
|
||||
def client_add(address, port, handle):
|
||||
global client_list
|
||||
client_list[address] = (port, handle)
|
||||
|
||||
def broadcast(handle, msg):
|
||||
global client_list
|
||||
if msg:
|
||||
print handle, ": ", msg
|
||||
else:
|
||||
print "Welcome, ", handle
|
||||
bcastmsg = struct.pack('<HHHBc8p32p', 0x7EDA, VERSION, 0, 0xCA, 'C', handle, msg)
|
||||
for c in client_list:
|
||||
client = (c, client_list[c][0])
|
||||
s.sendto(bcastmsg, client)
|
||||
|
||||
def send_update(client, ver):
|
||||
updatemask = 0
|
||||
updatelist = []
|
||||
for i in xrange(ver, VERSION):
|
||||
updatemask |= chat_vers[i]
|
||||
for f in chat_files:
|
||||
if updatemask & chat_files[f][2]:
|
||||
updatelist.append(f)
|
||||
print "Update client version ", ver, " with:", updatelist
|
||||
pkthdr = struct.pack('<HHHBc', 0x7EDA, VERSION, 0, 0xCA, 'U')
|
||||
pktmsg = ""
|
||||
for f in updatelist:
|
||||
pktmsg += struct.pack('<17pBH', f, chat_files[f][0], chat_files[f][1])
|
||||
pktmsg += struct.pack('B', 0)
|
||||
s.sendto(pkthdr + pktmsg, client)
|
||||
#
|
||||
# Read version XML file
|
||||
#
|
||||
tree = ET.parse('chat-version.xml')
|
||||
root = tree.getroot()
|
||||
for chatfile in root.findall('{updates}file'):
|
||||
fname = chatfile.get('name')
|
||||
ftype = int(chatfile.get('type'), 0)
|
||||
faux = int(chatfile.get('aux'), 0)
|
||||
fmask = int(chatfile.get('mask'), 0)
|
||||
chat_files[fname] = (ftype, faux, fmask)
|
||||
for chatver in root.findall('{updates}version'):
|
||||
chat_vers.insert(int(chatver.get('level')), int(chatver.get('updates'), 0))
|
||||
chatver = root.find('{updates}current')
|
||||
VERSION = int(chatver.get('level'))
|
||||
print "CHAT server version:", VERSION
|
||||
#
|
||||
# Initialize UDP socket
|
||||
#
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind((HOST, PORT))
|
||||
p = select.poll()
|
||||
p.register(s.fileno(), select.POLLIN)
|
||||
#
|
||||
# Main server loop
|
||||
#
|
||||
while 1:
|
||||
if p.poll(1000):
|
||||
data, client = s.recvfrom(2048)
|
||||
address, port = client
|
||||
magic, ver, seq, hw, req = struct.unpack_from('<HHHBc', data)
|
||||
if req == 'H':
|
||||
handle, = struct.unpack_from('8p', data, 8)
|
||||
if ver <> VERSION:
|
||||
send_update(client, ver)
|
||||
else:
|
||||
client_add(address, port, handle)
|
||||
s.sendto(struct.pack('<HHHBc', magic, ver, seq, 0xCA, 'W'), client)
|
||||
broadcast(handle, "")
|
||||
elif req == 'C':
|
||||
try:
|
||||
msg, = struct.unpack_from('32p', data, 8)
|
||||
handle = client_list[address][1]
|
||||
broadcast(handle, msg)
|
||||
except:
|
||||
s.sendto(struct.pack('<HHHBc', 0x7EDA, VERSION, 0, 0xCA, 'E'), client)
|
||||
elif req == 'F':
|
||||
try:
|
||||
filename, fileblock = struct.unpack_from('<17pH', data, 8)
|
||||
f = open('clientfiles/'+filename, 'r')
|
||||
f.seek(fileblock * 1024)
|
||||
msg = f.read(1024)
|
||||
f.close()
|
||||
s.sendto(struct.pack('<HHHBc', 0x7EDA, VERSION, seq, 0xCA, 'F') + msg, client)
|
||||
except:
|
||||
s.sendto(struct.pack('<HHHBc', 0x7EDA, VERSION, seq, 0xCA, 'E'), client)
|
||||
else:
|
||||
print "Unknown request: " + req
|
||||
else:
|
||||
pass
|
||||
s.close()
|
||||
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
.SUFFIXES =
|
||||
AFLAGS = -o $@
|
||||
CHAT = CHAT\#FE1000
|
||||
UPDATE = UPDATE\#FE1000
|
||||
PLASM = ../plasm
|
||||
#
|
||||
# Image filetypes for Virtual ][
|
||||
#
|
||||
PLATYPE = .\$$ED
|
||||
BINTYPE = .BIN
|
||||
SYSTYPE = .SYS
|
||||
TXTTYPE = .TXT
|
||||
#
|
||||
# Image filetypes for CiderPress
|
||||
#
|
||||
#RELTYPE = \#FE1000
|
||||
#INTERPTYPE = \#050000
|
||||
#BINTYPE = \#060000
|
||||
#SYSTYPE = \#FF2000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(UPDATE) $(CHAT)
|
||||
|
||||
clean:
|
||||
-rm *FE1000 *FF2000
|
||||
-rm *.o *~ *.a
|
||||
|
||||
$(UPDATE): update.pla $(PLASM)
|
||||
./$(PLASM) -AM < update.pla > update.a
|
||||
acme --setpc 4094 -o $(UPDATE) update.a
|
||||
cp $(UPDATE) chatserver/clientfiles/UPDATE
|
||||
|
||||
$(CHAT): chat.pla $(PLASM)
|
||||
./$(PLASM) -AM < chat.pla > chat.a
|
||||
acme --setpc 4094 -o $(CHAT) chat.a
|
||||
cp $(CHAT) chatserver/clientfiles/CHAT
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
//
|
||||
// HTTP Daemon
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef isugt, isuge, isult, isule
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
//
|
||||
// Net object
|
||||
//
|
||||
import inet
|
||||
word iNet
|
||||
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
|
||||
end
|
||||
|
||||
const VERSION = 1
|
||||
|
||||
byte[4] serverIP
|
||||
word serverPort
|
||||
word updateList
|
||||
word portUDP, timeout
|
||||
byte response
|
||||
byte perr
|
||||
byte dlFile = "DOWNLOAD"
|
||||
byte dlRef
|
||||
byte rdreqpkt = $DA, $7E, VERSION, VERSION >> 8, $00, $00, $A2, 'F'
|
||||
byte[17] filename = ""
|
||||
word fileblock
|
||||
word xferlen
|
||||
|
||||
asm reboot
|
||||
BIT $C082 ; ENABLE ROM
|
||||
DEC $03F4 ; INVALIDATE POWER-UP BYTE
|
||||
JMP ($FFFC) ; RESET
|
||||
end
|
||||
//
|
||||
// ProDOS routines
|
||||
//
|
||||
def getpfx(path)
|
||||
byte params[3]
|
||||
|
||||
^path = 0
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = syscall($C7, @params)
|
||||
return path
|
||||
end
|
||||
def setpfx(path)
|
||||
byte params[3]
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = syscall($C6, @params)
|
||||
return path
|
||||
end
|
||||
def open(path, buff)
|
||||
byte params[6]
|
||||
|
||||
params.0 = 3
|
||||
params:1 = path
|
||||
params:3 = buff
|
||||
params.5 = 0
|
||||
perr = syscall($C8, @params)
|
||||
return params.5
|
||||
end
|
||||
def close(refnum)
|
||||
byte params[2]
|
||||
|
||||
params.0 = 1
|
||||
params.1 = refnum
|
||||
perr = syscall($CC, @params)
|
||||
return perr
|
||||
end
|
||||
def read(refnum, buff, len)
|
||||
byte params[8]
|
||||
|
||||
params.0 = 4
|
||||
params.1 = refnum
|
||||
params:2 = buff
|
||||
params:4 = len
|
||||
params:6 = 0
|
||||
perr = syscall($CA, @params)
|
||||
return params:6
|
||||
end
|
||||
def write(refnum, buff, len)
|
||||
byte params[8]
|
||||
|
||||
params.0 = 4
|
||||
params.1 = refnum
|
||||
params:2 = buff
|
||||
params:4 = len
|
||||
params:6 = 0
|
||||
perr = syscall($CB, @params)
|
||||
return params:6
|
||||
end
|
||||
def create(path, access, type, aux)
|
||||
byte params[12]
|
||||
|
||||
params.0 = 7
|
||||
params:1 = path
|
||||
params.3 = access
|
||||
params.4 = type
|
||||
params:5 = aux
|
||||
params.7 = $1
|
||||
params:8 = 0
|
||||
params:10 = 0
|
||||
perr = syscall($C0, @params)
|
||||
return perr
|
||||
end
|
||||
def destroy(path)
|
||||
byte params[3]
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
perr = syscall($C1, @params)
|
||||
return perr
|
||||
end
|
||||
def rename(path, newpath)
|
||||
byte params[5]
|
||||
|
||||
params.0 = 2
|
||||
params:1 = path
|
||||
params:3 = newpath
|
||||
perr = syscall($C2, @params)
|
||||
return perr
|
||||
end
|
||||
//
|
||||
// Restart
|
||||
//
|
||||
def restart
|
||||
puts("Press any key to reboot...")
|
||||
getc()
|
||||
reboot()
|
||||
end
|
||||
//
|
||||
// Error
|
||||
//
|
||||
def dl_error(errstr)
|
||||
puts("Update Error: "); puts(errstr); putln
|
||||
restart()
|
||||
end
|
||||
//
|
||||
// Receive UDP packet
|
||||
//
|
||||
def recvUDP(ipsrc, portsrc, data, len, param)
|
||||
when data->7
|
||||
is 'F'
|
||||
if data=>4 == rdreqpkt:4 // Sequence numbers match
|
||||
xferlen = len - 8
|
||||
if xferlen > 0
|
||||
if write(dlRef, data + 8, xferlen) <> xferlen or perr
|
||||
dl_error("Write download file")
|
||||
fin
|
||||
fin
|
||||
response = 'F'
|
||||
fin
|
||||
break
|
||||
is 'E'
|
||||
dl_error("Server error")
|
||||
break
|
||||
otherwise
|
||||
dl_error("Unexpected packet")
|
||||
wend
|
||||
end
|
||||
//
|
||||
// Main update loop
|
||||
//
|
||||
memcpy(@serverIP, $0300, 4) // Passed in IP
|
||||
serverPort = *$0304 // Passed in port
|
||||
updateList = *$0306 // Passed in update list
|
||||
portUDP = iNet:openUDP($6500, @recvUDP, 0)
|
||||
while ^updateList
|
||||
puts("Updating: "); puts(updateList)
|
||||
destroy(@dlFile)
|
||||
if create(@dlFile, $C3, updateList->17, updateList=>18)
|
||||
dl_error("Unable to create download file")
|
||||
fin
|
||||
dlRef = open(@dlFile, $0800) // Use system io_buffer
|
||||
if not dlRef
|
||||
dl_error("Unable to open download file")
|
||||
fin
|
||||
rdreqpkt:4 = 2 // Init sequence number
|
||||
memcpy(@filename, updateList, 17)
|
||||
fileblock = 0
|
||||
repeat
|
||||
iNet:sendUDP(portUDP, @serverIP, serverPort, @rdreqpkt, 27)
|
||||
timeout = 1000
|
||||
response = 0
|
||||
while not response and timeout
|
||||
iNet:serviceIP()
|
||||
timeout = timeout - 1
|
||||
loop
|
||||
if not response
|
||||
dl_error("No response from server")
|
||||
fin
|
||||
putc('.')
|
||||
fileblock = fileblock + 1
|
||||
rdreqpkt:4 = rdreqpkt:4 + 1 // Increment sequence
|
||||
until xferlen <> 1024
|
||||
close(dlRef)
|
||||
destroy(updateList)
|
||||
rename(@dlFile, updateList)
|
||||
if perr
|
||||
dl_error("Rename download file")
|
||||
fin
|
||||
updateList = updateList + 20
|
||||
putln
|
||||
loop
|
||||
iNet:closeUDP(portUDP)
|
||||
puts("Update complete.\n")
|
||||
restart()
|
||||
done
|
||||
+13
-2
@@ -1,6 +1,14 @@
|
||||
//
|
||||
// Original Uthernet ethernet card based on Cirrus Logic cs8900a
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef isugt, isuge, isult, isule
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
byte MACHID
|
||||
end
|
||||
//
|
||||
// Include dependency on S/W IP stack
|
||||
//
|
||||
import etherip
|
||||
@@ -25,7 +33,7 @@ const AUTO_INC = $8000
|
||||
//
|
||||
// Uthernet register addresses
|
||||
//
|
||||
byte[] slot // Init time only
|
||||
byte[] slot // Init time only
|
||||
byte rxdata_lo, rxdata_hi
|
||||
byte txcmd
|
||||
byte txlen
|
||||
@@ -213,7 +221,7 @@ end
|
||||
//
|
||||
// Identify Uthernet card and initialize
|
||||
//
|
||||
for slot = $F0 downto $90 step $10
|
||||
for slot = $90 to $F0 step $10
|
||||
if (peekiow(slot+TXCMD) & $CC3F) == $09
|
||||
pokeiow(slot+PREG_INDEX, 0)
|
||||
if peekiow(slot+PREG_DATA) == $630E
|
||||
@@ -238,6 +246,9 @@ for slot = $F0 downto $90 step $10
|
||||
//
|
||||
// Install etherip driver
|
||||
//
|
||||
puts("Found Uthernet I in slot #")
|
||||
putc('0' + ((slot - $80) >> 4))
|
||||
putln
|
||||
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
|
||||
return modkeep
|
||||
fin
|
||||
|
||||
+96
-97
@@ -104,8 +104,10 @@ const WIZ_RXMEM3 = $7800
|
||||
//
|
||||
// Wiznet indirect registers
|
||||
//
|
||||
byte regidx, regdata
|
||||
word slot, saveidx
|
||||
byte slot
|
||||
word saveidx
|
||||
byte regidx
|
||||
byte regdata
|
||||
//
|
||||
// Wiznet MAC address
|
||||
//
|
||||
@@ -720,108 +722,99 @@ def wizServiceIP
|
||||
if ir
|
||||
wiz = @wizChannel
|
||||
for i = 0 to 3
|
||||
when ir & (1 << i)
|
||||
is 1
|
||||
is 2
|
||||
is 4
|
||||
is 8
|
||||
wizregs = wiz=>channel_regs
|
||||
wizdata = wiz=>channel_rxmem
|
||||
sir = peekreg(wizregs + WIZ_SnIR)
|
||||
when wiz->channel_proto
|
||||
is WIZ_PROTO_UDP
|
||||
if sir & $04
|
||||
//
|
||||
// Receive UDP packet
|
||||
//
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
if rxwr + rxlen >= WIZ_RXSIZE
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(rxpkt,swab(rxpkt=>4),rxpkt+8,rxlen-8,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
fin
|
||||
break
|
||||
is WIZ_PROTO_TCP
|
||||
if sir & $01
|
||||
//
|
||||
// Connect TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_LISTEN
|
||||
peekregs(wiz=>channel_regs + WIZ_SnDIPR, @wiz=>channel_remip, IP4ADR_SIZE)
|
||||
wiz=>channel_remport = peekregw(wiz=>channel_regs + WIZ_SnDPORT)
|
||||
is TCP_STATE_CONNECT
|
||||
wiz->channel_state = TCP_STATE_OPEN
|
||||
wend
|
||||
if ir & (1 << i)
|
||||
wizregs = wiz=>channel_regs
|
||||
wizdata = wiz=>channel_rxmem
|
||||
sir = peekreg(wizregs + WIZ_SnIR)
|
||||
pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR
|
||||
when wiz->channel_proto
|
||||
is WIZ_PROTO_UDP
|
||||
if sir & $04
|
||||
//
|
||||
// Receive UDP packet
|
||||
//
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
if rxwr + rxlen >= WIZ_RXSIZE
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
if sir & $04
|
||||
//
|
||||
// Receive TCP packet
|
||||
//
|
||||
if wiz->channel_state == TCP_STATE_OPEN
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
if rxwr + rxlen > WIZ_RXSIZE
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,rxpkt,rxlen,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(rxpkt,swab(rxpkt=>4),rxpkt+8,rxlen-8,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
fin
|
||||
break
|
||||
is WIZ_PROTO_TCP
|
||||
if sir & $01
|
||||
//
|
||||
// Connect TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_LISTEN
|
||||
peekregs(wiz=>channel_regs + WIZ_SnDIPR, @wiz=>channel_remip, IP4ADR_SIZE)
|
||||
wiz=>channel_remport = peekregw(wiz=>channel_regs + WIZ_SnDPORT)
|
||||
is TCP_STATE_CONNECT
|
||||
wiz->channel_state = TCP_STATE_OPEN
|
||||
wend
|
||||
fin
|
||||
if sir & $04
|
||||
//
|
||||
// Receive TCP packet
|
||||
//
|
||||
if wiz->channel_state == TCP_STATE_OPEN
|
||||
rxlen = peekregw(wizregs + WIZ_SnRSR)
|
||||
rxrr = peekregw(wizregs + WIZ_SnRXRD)
|
||||
rxwr = rxrr & WIZ_RXMASK
|
||||
rxpkt = heapalloc(rxlen)
|
||||
if rxwr + rxlen > WIZ_RXSIZE
|
||||
splitlen = WIZ_RXSIZE - rxwr
|
||||
peekregs(wizdata + rxwr, rxpkt, splitlen)
|
||||
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
|
||||
else
|
||||
peekregs(wizdata + rxwr, rxpkt, rxlen)
|
||||
fin
|
||||
fin
|
||||
if sir & $02
|
||||
//
|
||||
// Close TCP socket
|
||||
//
|
||||
if wiz->channel_state == TCP_STATE_OPEN // Notify callback w/ len = 0
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,0,wiz=>channel_lclport,0,wiz=>channel_recv_parm)
|
||||
fin
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
pokeregw(wizregs + WIZ_SnRXRD, rxrr + rxlen)
|
||||
pokereg(wizregs + WIZ_SnCR, $40) // RECV
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,rxpkt,rxlen,wiz=>channel_recv_parm)
|
||||
heaprelease(rxpkt)
|
||||
fin
|
||||
if sir & $08
|
||||
//
|
||||
// Timeout on TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_OPEN
|
||||
wiz->channel_state = TCP_STATE_CLOSING
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
break
|
||||
is TCP_STATE_CONNECT
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
is TCP_STATE_CLOSING
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
wend
|
||||
fin
|
||||
if sir & $02
|
||||
//
|
||||
// Close TCP socket
|
||||
//
|
||||
if wiz->channel_state == TCP_STATE_OPEN // Notify callback w/ len = 0
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,0,wiz=>channel_lclport,0,wiz=>channel_recv_parm)
|
||||
fin
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
fin
|
||||
if sir & $08
|
||||
//
|
||||
// Timeout on TCP socket
|
||||
//
|
||||
when wiz->channel_state
|
||||
is TCP_STATE_OPEN
|
||||
wiz->channel_state = TCP_STATE_CLOSING
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
break
|
||||
is TCP_STATE_CONNECT
|
||||
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
|
||||
is TCP_STATE_CLOSING
|
||||
wiz->channel_state = TCP_STATE_CLOSED
|
||||
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
|
||||
wend
|
||||
fin
|
||||
wend
|
||||
pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR
|
||||
ir = ir ^ (1 << i)
|
||||
wend
|
||||
fin
|
||||
wiz = wiz + t_channel
|
||||
next
|
||||
//
|
||||
// Clear IR
|
||||
//
|
||||
pokereg(WIZ_IR, ir)
|
||||
fin
|
||||
end
|
||||
//
|
||||
@@ -884,6 +877,12 @@ for slot = $90 to $F0 step $10
|
||||
pokeregw(WIZ_RTR, 5000) // Timeout period to 500ms
|
||||
pokereg(WIZ_RMSR, $55) // 2K Rx memory/channel
|
||||
pokereg(WIZ_TMSR, $55) // 2K Tx memory/channel
|
||||
//
|
||||
// Print settings
|
||||
//
|
||||
puts("Found Uthernet II in slot #")
|
||||
putc('0' + ((slot - $80) >> 4))
|
||||
putln
|
||||
//
|
||||
// Fill channel structure
|
||||
//
|
||||
|
||||
+1
-1
@@ -977,7 +977,7 @@ def create(path, access, type, aux)
|
||||
return perr
|
||||
end
|
||||
def destroy(path)
|
||||
byte params[12]
|
||||
byte params[3]
|
||||
|
||||
params.0 = 1
|
||||
params:1 = path
|
||||
|
||||
Reference in New Issue
Block a user