mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-01-10 06:30:41 +00:00
Internet CHAT client/server
This commit is contained in:
parent
9a5d238910
commit
d6f3b5c475
233
src/chatsrc/chat.pla
Normal file
233
src/chatsrc/chat.pla
Normal file
@ -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
|
16
src/chatsrc/chatserver/chat-version.xml
Normal file
16
src/chatsrc/chatserver/chat-version.xml
Normal file
@ -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>
|
44
src/chatsrc/chatserver/client.py
Executable file
44
src/chatsrc/chatserver/client.py
Executable file
@ -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()
|
1
src/chatsrc/chatserver/clientfiles/AUTORUN
Normal file
1
src/chatsrc/chatserver/clientfiles/AUTORUN
Normal file
@ -0,0 +1 @@
|
||||
+CHAT
|
BIN
src/chatsrc/chatserver/clientfiles/CHAT
Normal file
BIN
src/chatsrc/chatserver/clientfiles/CHAT
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/DHCP
Normal file
BIN
src/chatsrc/chatserver/clientfiles/DHCP
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/ETHERIP
Normal file
BIN
src/chatsrc/chatserver/clientfiles/ETHERIP
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/INET
Normal file
BIN
src/chatsrc/chatserver/clientfiles/INET
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/PLASMA.SYSTEM
Normal file
BIN
src/chatsrc/chatserver/clientfiles/PLASMA.SYSTEM
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/UPDATE
Normal file
BIN
src/chatsrc/chatserver/clientfiles/UPDATE
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/UTHERNET
Normal file
BIN
src/chatsrc/chatserver/clientfiles/UTHERNET
Normal file
Binary file not shown.
BIN
src/chatsrc/chatserver/clientfiles/UTHERNET2
Normal file
BIN
src/chatsrc/chatserver/clientfiles/UTHERNET2
Normal file
Binary file not shown.
104
src/chatsrc/chatserver/server.py
Executable file
104
src/chatsrc/chatserver/server.py
Executable file
@ -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()
|
||||
|
37
src/chatsrc/makefile
Executable file
37
src/chatsrc/makefile
Executable file
@ -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
|
||||
|
231
src/chatsrc/update.pla
Normal file
231
src/chatsrc/update.pla
Normal file
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user