Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement some bsdsocket functions #204

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions amitools/vamos/lib/BsdSocketLibrary.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
from amitools.vamos.libcore.impl import LibImpl
from amitools.vamos.machine.regs import REG_D0, REG_D1, REG_D2, REG_A0, REG_A1, REG_A2, REG_A3

import select
import socket as s
from amitools.vamos.astructs.astructdef import AmigaStructDef, AmigaClassDef
from amitools.vamos.astructs.astruct import AmigaStruct
from amitools.vamos.astructs.string import CSTR
from amitools.vamos.astructs.pointer import APTR_VOID
from amitools.vamos.astructs.scalar import LONG, UBYTE, UWORD, ULONG

class BsdSocketLibrary(LibImpl):

def setup_lib(self, ctx, base_addr):
self.alloc = ctx.alloc
self.cnt = 0
# track opened sockets
self.socks = {}
# get host by name
self.hostByName = None

def finish_lib(self, ctx):
self.cnt = None

def open_lib(self, ctx, open_cnt):
self.cnt = open_cnt

def close_lib(self, ctx, open_cnt):
if self.hostByName != None:
self.hostByName.free()
self.hostByName = None
self.cnt = open_cnt

def get_version(self):
return 4

def get_cnt(self):
return self.cnt

def putSock(self, sock):
n = 0
while True:
if not n in self.socks:
self.socks[n] = sock
return n
n = n + 1

def socket(self, ctx):
# domain = ctx.cpu.r_reg(REG_D0)
t = ctx.cpu.r_reg(REG_D1)
if t == 1:
t = s.SOCK_STREAM
elif t == 2:
t = s.SOCK_DGRAM
else:
t = s.SOCK_RAW
# protocol = ctx.cpu.r_reg(REG_D2)
sock = s.socket(s.AF_INET, t)
if sock != None:
return self.putSock(sock)
return 0

def CloseSocket(self, ctx):
n = ctx.cpu.r_reg(REG_D0)
if n in self.socks:
sock = self.socks[n]
sock.close()
del self.socks[n]

def gethostbyname(self, ctx):
name_ptr = ctx.cpu.r_reg(REG_A0)
name = ctx.mem.r_cstr(name_ptr)
h = s.gethostbyname(name)
if h != None:
ip = 0
for x in h.split("."):
ip = ip << 8
ip += int(x)
# print(name, h, ip)

if self.hostByName == None:
self.hostByName = HostEntClass.alloc(self.alloc)

self.hostByName.h_name.set(name_ptr)
self.hostByName.h_aliases.set(0)
self.hostByName.h_addrtype.set(0)
self.hostByName.h_length.set(1)
self.hostByName.h_addr_list.set(self.hostByName._addr + 20)
self.hostByName.h_addr.set(self.hostByName._addr + 24)
self.hostByName.h_addr_val.set(ip)
return self.hostByName._addr

return 0

def bind(self, ctx):
sockn = ctx.cpu.r_reg(REG_D0)
if not sockn in self.socks:
return -1

soalen = ctx.cpu.r_reg(REG_D1)
if soalen < 8:
return -2;

soar = ctx.cpu.r_reg(REG_A0)
soa = SockAddrClass(ctx.mem, soar)

# no bind necessary
if soa.sin_port.get() == 0:
return 0

sock = self.socks[sockn]
ip = soa.sin_addr.get()
s = self.ip2s(ip)
if sock.bind((s, soa.sin_port.get())) == None:
return -3

return 0

def connect(self, ctx):
n = ctx.cpu.r_reg(REG_D0)
if not n in self.socks:
return -1

soalen = ctx.cpu.r_reg(REG_D1)
if soalen < 8:
return -2;

soar = ctx.cpu.r_reg(REG_A0)
soa = SockAddrClass(ctx.mem, soar)

# port necessary
if soa.sin_port.get() == 0:
return -3

sock = self.socks[n]
ip = soa.sin_addr.get()
s = self.ip2s(ip)
# print("connect to:", ip, s, soa.sin_port.get())
sock.connect((s, soa.sin_port.get()))
return 0

def ip2s(self, ip):
return str((ip >> 24) & 0xff) + "." + str((ip >> 16) & 0xff) + "." + str((ip >> 8) & 0xff) + "." + str(ip & 0xff)

def send(self, ctx):
n = ctx.cpu.r_reg(REG_D0)
if not n in self.socks:
return -1

buf_ptr = ctx.cpu.r_reg(REG_A0)
size = ctx.cpu.r_reg(REG_D1)
flags = ctx.cpu.r_reg(REG_D2)
data = ctx.mem.r_block(buf_ptr, size)

sock = self.socks[n]
return sock.send(data, flags)

def recv(self, ctx):
n = ctx.cpu.r_reg(REG_D0)
if not n in self.socks:
return -1

buf_ptr = ctx.cpu.r_reg(REG_A0)
size = ctx.cpu.r_reg(REG_D1)
flags = ctx.cpu.r_reg(REG_D2)

sock = self.socks[n]
read = sock.recv(size, flags)
sz = len(read)
ctx.mem.w_block(buf_ptr, read)
return sz

def listFromFdSet(self, mem, addr, sz):
fdset = ULongULongClass(mem, addr)
l = fdset.l0.get() + (fdset.l1.get() << 32)
r = []
for i in range (0, sz):
if l & (1 << i) != 0 and i in self.socks:
r.append(self.socks[i])
return r

def markFdSet(self, mem, lst, addr, sz):
if addr != 0:
s = set(lst)
fdset = ULongULongClass(mem, addr)
l = 0
for i in range (0, sz):
if i in self.socks and self.socks[i] in s:
l = l | (1 << i)
#print("set ULongULong", l)
fdset.l0.set(l)
fdset.l1.set(l >> 32)

def WaitSelect(self, ctx):
sz = ctx.cpu.r_reg(REG_D0)
rfds = ctx.cpu.r_reg(REG_A0)
wfds = ctx.cpu.r_reg(REG_A1)
xfds = ctx.cpu.r_reg(REG_A2)
timevalp = ctx.cpu.r_reg(REG_A3)
signals = ctx.cpu.r_reg(REG_D1)

# clear signals
if signals != 0:
sig = ULongULongStruct(ctx.mem, signals)
sig.l0.set(0)

rlist, wlist, xlist = [], [], []
if rfds != 0:
rlist = self.listFromFdSet(ctx.mem, rfds, sz)
if wfds != 0:
wlist = self.listFromFdSet(ctx.mem, wfds, sz)
if xfds != 0:
xlist = self.listFromFdSet(ctx.mem, xfds, sz)

r, w, x = None, None, None
if timevalp != 0:
timeval = ULongULongClass(ctx.mem, timevalp)
timeout = timeval.l0.get() + timeval.l1.get() * 1e-6
#print("WaitSelect timeout", timeout, rlist, wlist, xlist)
r,w,x = select.select(rlist, wlist, xlist, timeout)
else:
#print("WaitSelect no timeout", rlist, wlist, xlist)
r,w,x = select.select(rlist, wlist, xlist)

self.markFdSet(ctx.mem, r, rfds, sz)
self.markFdSet(ctx.mem, w, wfds, sz)
self.markFdSet(ctx.mem, x, xfds, sz)

@AmigaStructDef
class ULongULongStruct(AmigaStruct):
_format = [
(ULONG, "l0"),
(UBYTE, "l1"),
]

@AmigaClassDef
class ULongULongClass(ULongULongStruct):
pass

@AmigaStructDef
class SockAddrStruct(AmigaStruct):
_format = [
(UBYTE, "sin_len"),
(UBYTE, "sin_family"),
(UWORD, "sin_port"),
(ULONG, "sin_addr"),
(ULONG, "sin_zero0"),
(ULONG, "sin_zero1"),
]

@AmigaClassDef
class SockAddrClass(SockAddrStruct):
pass

@AmigaStructDef
class HostEntStruct(AmigaStruct):
_format = [
(CSTR, "h_name"),
(APTR_VOID, "h_aliases"),
(LONG, "h_addrtype"),
(LONG, "h_length"),
(APTR_VOID, "h_addr_list"),
# internal
(LONG, "h_addr"),
(LONG, "h_addr_val"),
]

@AmigaClassDef
class HostEntClass(HostEntStruct):
pass

2 changes: 2 additions & 0 deletions amitools/vamos/lib/LibList.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .UtilityLibrary import UtilityLibrary
from .VamosTestLibrary import VamosTestLibrary
from .VamosTestDevice import VamosTestDevice
from .BsdSocketLibrary import BsdSocketLibrary

vamos_libs = {
"dos.library": DosLibrary,
Expand All @@ -26,6 +27,7 @@
"mathtrans.library": MathTransLibrary,
"timer.device": TimerDevice,
"utility.library": UtilityLibrary,
"bsdsocket.library": BsdSocketLibrary,
"vamostest.library": VamosTestLibrary,
"vamostestdev.device": VamosTestDevice,
}
1 change: 1 addition & 0 deletions amitools/vamos/libmgr/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def setup(self):
odg_base,
)
self.lib_mgr.add_ctx("exec.library", self.exec_ctx)
self.lib_mgr.add_ctx("bsdsocket.library", self.exec_ctx)
self.lib_mgr.add_ctx("dos.library", self.dos_ctx)
# add all vamos libs
for name in vamos_libs:
Expand Down
Loading