2 # -*- coding: utf-8 -*-
4 # Copyright (c) 2018-2021 Niklas Ekström
16 logging.basicConfig(format = '%(levelname)s, %(asctime)s, %(name)s, line %(lineno)d: %(message)s')
17 logger = logging.getLogger(__name__)
18 logger.setLevel(logging.INFO)
21 idx = sys.argv.index('-conf-file')
22 CONFIG_FILE_PATH = sys.argv[idx + 1]
23 except (ValueError, IndexError):
24 CONFIG_FILE_PATH = 'a314/files_pi/a314fs.conf'
26 SHARED_DIRECTORY = 'data/a314shared'
27 METAFILE_EXTENSION = ':a314'
29 with open(CONFIG_FILE_PATH, encoding='utf-8') as f:
33 SHARED_DIRECTORY = dev['path']
37 MSG_DEREGISTER_REQ = 3
38 MSG_DEREGISTER_RES = 4
44 MSG_CONNECT_RESPONSE = 10
51 while len(header) < 9:
52 data = drv.recv(9 - len(header))
54 logger.error('Connection to a314d was closed, terminating.')
57 (plen, stream_id, ptype) = struct.unpack('=IIB', header)
59 while len(payload) < plen:
60 data = drv.recv(plen - len(payload))
62 logger.error('Connection to a314d was closed, terminating.')
65 return (stream_id, ptype, payload)
67 def send_register_req(name):
68 m = struct.pack('=IIB', len(name), 0, MSG_REGISTER_REQ) + name
71 def send_read_mem_req(address, length):
72 m = struct.pack('=IIBII', 8, 0, MSG_READ_MEM_REQ, address, length)
75 def read_mem(address, length):
76 send_read_mem_req(address, length)
77 stream_id, ptype, payload = wait_for_msg()
78 if ptype != MSG_READ_MEM_RES:
79 logger.error('Expected MSG_READ_MEM_RES but got %s. Shutting down.', ptype)
83 def send_write_mem_req(address, data):
84 m = struct.pack('=IIBI', 4 + len(data), 0, MSG_WRITE_MEM_REQ, address) + data
87 def write_mem(address, data):
88 send_write_mem_req(address, data)
89 stream_id, ptype, payload = wait_for_msg()
90 if ptype != MSG_WRITE_MEM_RES:
91 logger.error('Expected MSG_WRITE_MEM_RES but got %s. Shutting down.', ptype)
94 def send_connect_response(stream_id, result):
95 m = struct.pack('=IIBB', 1, stream_id, MSG_CONNECT_RESPONSE, result)
98 def send_data(stream_id, data):
99 m = struct.pack('=IIB', len(data), stream_id, MSG_DATA) + data
102 def send_eos(stream_id):
103 m = struct.pack('=IIB', 0, stream_id, MSG_EOS)
106 def send_reset(stream_id):
107 m = struct.pack('=IIB', 0, stream_id, MSG_RESET)
115 ACTION_CURRENT_VOLUME = 7
116 ACTION_LOCATE_OBJECT = 8
117 ACTION_RENAME_DISK = 9
118 ACTION_WRITE = ord('W')
119 ACTION_READ = ord('R')
120 ACTION_FREE_LOCK = 15
121 ACTION_DELETE_OBJECT = 16
122 ACTION_RENAME_OBJECT = 17
123 ACTION_MORE_CACHE = 18
125 ACTION_WAIT_CHAR = 20
126 ACTION_SET_PROTECT = 21
127 ACTION_CREATE_DIR = 22
128 ACTION_EXAMINE_OBJECT = 23
129 ACTION_EXAMINE_NEXT = 24
130 ACTION_DISK_INFO = 25
133 ACTION_SET_COMMENT = 28
137 ACTION_DISK_TYPE = 32
138 ACTION_DISK_CHANGE = 33
140 ACTION_SAME_LOCK = 40
141 ACTION_SCREEN_MODE = 994
142 ACTION_READ_RETURN = 1001
143 ACTION_WRITE_RETURN = 1002
144 ACTION_FINDUPDATE = 1004
145 ACTION_FINDINPUT = 1005
146 ACTION_FINDOUTPUT = 1006
149 ACTION_TRUNCATE = 1022
150 ACTION_WRITE_PROTECT = 1023
151 ACTION_EXAMINE_FH = 1034
152 ACTION_UNSUPPORTED = 65535
154 ERROR_NO_FREE_STORE = 103
155 ERROR_TASK_TABLE_FULL = 105
156 ERROR_LINE_TOO_LONG = 120
157 ERROR_FILE_NOT_OBJECT = 121
158 ERROR_INVALID_RESIDENT_LIBRARY = 122
159 ERROR_NO_DEFAULT_DIR = 201
160 ERROR_OBJECT_IN_USE = 202
161 ERROR_OBJECT_EXISTS = 203
162 ERROR_DIR_NOT_FOUND = 204
163 ERROR_OBJECT_NOT_FOUND = 205
164 ERROR_BAD_STREAM_NAME = 206
165 ERROR_OBJECT_TOO_LARGE = 207
166 ERROR_ACTION_NOT_KNOWN = 209
167 ERROR_INVALID_COMPONENT_NAME = 210
168 ERROR_INVALID_LOCK = 211
169 ERROR_OBJECT_WRONG_TYPE = 212
170 ERROR_DISK_NOT_VALIDATED = 213
171 ERROR_DISK_WRITE_PROTECTED = 214
172 ERROR_RENAME_ACROSS_DEVICES = 215
173 ERROR_DIRECTORY_NOT_EMPTY = 216
174 ERROR_TOO_MANY_LEVELS = 217
175 ERROR_DEVICE_NOT_MOUNTED = 218
176 ERROR_SEEK_ERROR = 219
177 ERROR_COMMENT_TOO_BIG = 220
178 ERROR_DISK_FULL = 221
179 ERROR_DELETE_PROTECTED = 222
180 ERROR_WRITE_PROTECTED = 223
181 ERROR_READ_PROTECTED = 224
182 ERROR_NOT_A_DOS_DISK = 225
184 ERROR_NO_MORE_ENTRIES = 232
193 MODE_OLDFILE = 1005 # Open existing file read/write positioned at beginning of file.
194 MODE_NEWFILE = 1006 # Open freshly created file (delete old file) read/write, exclusive lock.
195 MODE_READWRITE = 1004 # Open old file w/shared lock, creates file if doesn't exist.
197 OFFSET_BEGINNING = -1 # Relative to Begining Of File.
198 OFFSET_CURRENT = 0 # Relative to Current file position.
199 OFFSET_END = 1 # relative to End Of File.
203 ST_SOFTLINK = 3 # looks like dir, but may point to a file!
204 ST_LINKDIR = 4 # hard link to dir
205 ST_FILE = -3 # must be negative for FIB!
206 ST_LINKFILE = -4 # hard link to file
209 current_stream_id = 0
211 class ObjectLock(object):
212 def __init__(self, key, mode, path):
225 next_key = 1 if next_key == 0x7fffffff else (next_key + 1)
230 def find_path(key, name):
233 vol = name[:i].lower()
234 if vol == '' or vol == 'pi0' or vol == 'pidisk':
257 p = '.' if len(cp) == 0 else '/'.join(cp)
258 entries = os.listdir(p)
261 if comp.lower() == e.lower():
273 def read_metadata(path):
277 if not os.path.isfile(path + METAFILE_EXTENSION):
278 return (protection, comment)
281 f = open(path + METAFILE_EXTENSION, 'r')
285 protection = int(line[1:].strip())
289 comment = line[1:].strip()[:79]
291 except FileNotFoundError:
293 return (protection, comment)
295 def write_metadata(path, protection=None, comment=None):
296 p, c = read_metadata(path)
298 if protection == None:
303 if (p, c) == (protection, comment):
307 f = open(path + METAFILE_EXTENSION, 'w')
308 f.write('p' + str(protection) + '\n')
309 f.write('c' + comment + '\n')
311 except FileNotFoundError as e:
312 logger.warning('Failed to write metadata for file %s: %s', path, e)
316 def process_locate_object(key, mode, name):
317 logger.debug('ACTION_LOCATE_OBJECT, key: %s, mode: %s, name: %s', key, mode, name)
319 cp = find_path(key, name)
321 if cp is None or not (len(cp) == 0 or os.path.exists('/'.join(cp))):
322 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
324 # TODO: Must check if there is already a lock for this path,
325 # and if so, if the locks are compatible.
328 locks[key] = ObjectLock(key, mode, cp)
329 return struct.pack('>HHI', 1, 0, key)
331 def process_free_lock(key):
332 logger.debug('ACTION_FREE_LOCK, key: %s', key)
335 return struct.pack('>HH', 1, 0)
337 def process_copy_dir(prev_key):
338 logger.debug('ACTION_COPY_DIR, prev_key: %s', prev_key)
341 locks[key] = ObjectLock(key, ol.mode, ol.path)
342 return struct.pack('>HHI', 1, 0, key)
344 def process_parent(prev_key):
345 logger.debug('ACTION_PARENT, prev_key: %s', prev_key)
347 if len(ol.path) == 0:
351 locks[key] = ObjectLock(key, SHARED_LOCK, ol.path[:-1])
352 return struct.pack('>HHI', 1, 0, key)
354 def mtime_to_dmt(mtime):
356 days = mtime // 86400
357 left = mtime - days * 86400
359 secs = left - mins * 60
361 days -= 2922 # Days between 1970-01-01 and 1978-01-01
362 days = max(0, days) # If days are before Amiga epoc
363 return (days, mins, ticks)
365 def process_examine_object(key):
366 logger.debug('ACTION_EXAMINE_OBJECT, key: %s', key)
369 if len(ol.path) == 0:
374 path = '/'.join(ol.path)
376 days, mins, ticks = mtime_to_dmt(os.path.getmtime(path))
377 protection, comment = read_metadata(path)
379 if os.path.isfile(path):
380 size = os.path.getsize(path)
385 ol.entry_it = os.scandir(path)
387 size = min(size, 2 ** 31 - 1)
388 fn = (chr(len(fn)) + fn).encode('latin-1', 'ignore')
389 comment = (chr(len(comment)) + comment).encode('latin-1', 'ignore')
390 return struct.pack('>HHHhIIIII', 1, 0, 666, type_, size, protection, days, mins, ticks) + fn + comment
392 def process_examine_next(key, disk_key):
393 logger.debug('ACTION_EXAMINE_NEXT, key: %s, disk_key: %s', key, disk_key)
396 if len(ol.path) == 0:
399 path = '/'.join(ol.path)
401 if not os.path.isdir(path):
402 return struct.pack('>HH', 0, ERROR_OBJECT_WRONG_TYPE)
406 entry = next(ol.entry_it, None)
407 while entry and entry.name.endswith(METAFILE_EXTENSION):
408 entry = next(ol.entry_it, None)
411 return struct.pack('>HH', 0, ERROR_NO_MORE_ENTRIES)
414 path = ('/'.join(ol.path + (fn,)))
416 days, mins, ticks = mtime_to_dmt(entry.stat().st_mtime)
417 protection, comment = read_metadata(path)
419 if os.path.isfile(path):
420 size = os.path.getsize(path)
426 size = min(size, 2 ** 31 - 1)
427 fn = (chr(len(fn)) + fn).encode('latin-1', 'ignore')
428 comment = (chr(len(comment)) + comment).encode('latin-1', 'ignore')
429 return struct.pack('>HHHhIIIII', 1, 0, disk_key, type_, size, protection, days, mins, ticks) + fn + comment
431 def process_examine_fh(arg1):
432 logger.debug('ACTION_EXAMINE_FH, arg1: %s', arg1)
434 fn = open_file_handles[arg1].f.name
435 path = os.path.realpath(fn)
436 days, mins, ticks = mtime_to_dmt(os.path.getmtime(path))
437 protection, comment = read_metadata(path)
439 if os.path.isfile(path):
440 size = os.path.getsize(path)
446 size = min(size, 2 ** 31 - 1)
447 fn = (chr(len(fn)) + fn).encode('latin-1', 'ignore')
448 comment = (chr(len(comment)) + comment).encode('latin-1', 'ignore')
449 return struct.pack('>HHHhIIIII', 1, 0, 666, type_, size, protection, days, mins, ticks) + fn + comment
454 open_file_handles = {}
459 next_fp = 1 if next_fp == 0x7fffffff else next_fp + 1
460 while fp in open_file_handles:
464 class OpenFileHandle(object):
465 def __init__(self, fp, f, p):
470 def process_findxxx(mode, key, name):
471 if mode == ACTION_FINDINPUT:
472 logger.debug('ACTION_FINDINPUT, key: %s, name: %s', key, name)
473 elif mode == ACTION_FINDOUTPUT:
474 logger.debug('ACTION_FINDOUTPUT, key: %s, name: %s', key, name)
475 elif mode == ACTION_FINDUPDATE:
476 logger.debug('ACTION_FINDUPDATE, key: %s, name: %s', key, name)
478 cp = find_path(key, name)
480 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
483 if len(cp) == 0 or os.path.isdir(path):
484 return struct.pack('>HH', 0, ERROR_OBJECT_WRONG_TYPE)
486 # TODO: Must check if there already exists a non-compatible lock for this path.
488 # TODO: This must be handled better. Especially error reporting.
490 protection, _ = read_metadata(path)
492 if mode == MODE_OLDFILE:
493 f = open(path, 'r+b')
494 elif mode == MODE_READWRITE:
495 f = open(path, 'r+b')
497 protection = protection & 0b11101111
498 write_metadata(path, protection=protection)
499 elif mode == MODE_NEWFILE:
501 return struct.pack('>HH', 0, ERROR_DELETE_PROTECTED)
502 elif protection & 0x4:
503 return struct.pack('>HH', 0, ERROR_WRITE_PROTECTED)
504 f = open(path, 'w+b')
506 protection = protection & 0b11101111
507 write_metadata(path, protection=protection)
509 if mode == MODE_READWRITE:
511 f = open(path, 'w+b')
513 protection = protection & 0b11101111
514 write_metadata(path, protection=protection)
516 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
518 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
521 ofh = OpenFileHandle(fp, f, protection)
522 open_file_handles[fp] = ofh
524 return struct.pack('>HHI', 1, 0, fp)
526 def process_read(arg1, address, length):
527 logger.debug('ACTION_READ, arg1: %s, address: %s, length: %s', arg1, address, length)
528 protection = open_file_handles[arg1].p
530 return struct.pack('>HH', 0, ERROR_READ_PROTECTED)
531 f = open_file_handles[arg1].f
532 data = f.read(length)
534 write_mem(address, data)
535 return struct.pack('>HHI', 1, 0, len(data))
537 def process_write(arg1, address, length):
538 logger.debug('ACTION_WRITE, arg1: %s, address: %s, length: %s', arg1, address, length)
539 protection = open_file_handles[arg1].p
541 return struct.pack('>HH', 0, ERROR_WRITE_PROTECTED)
542 data = read_mem(address, length)
543 f = open_file_handles[arg1].f
548 return struct.pack('>HH', 0, ERROR_DISK_FULL)
549 return struct.pack('>HHI', 1, 0, length)
551 def process_seek(arg1, new_pos, mode):
552 logger.debug('ACTION_SEEK, arg1: %s, new_pos: %s, mode: %s', arg1, new_pos, mode)
554 f = open_file_handles[arg1].f
558 if mode == OFFSET_CURRENT:
560 elif mode == OFFSET_END:
563 f.seek(new_pos, from_what)
565 return struct.pack('>HHi', 1, 0, old_pos)
567 def process_end(arg1):
568 logger.debug('ACTION_END, arg1: %s', arg1)
570 if arg1 in open_file_handles:
571 f = open_file_handles.pop(arg1).f
574 return struct.pack('>HH', 1, 0)
576 def process_delete_object(key, name):
577 logger.debug('ACTION_DELETE_OBJECT, key: %s, name: %s', key, name)
579 cp = find_path(key, name)
580 if cp is None or len(cp) == 0:
581 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
584 is_dir = os.path.isdir(path)
586 protection, _ = read_metadata(path)
588 return struct.pack('>HH', 0, ERROR_DELETE_PROTECTED)
595 if os.path.isfile(path + METAFILE_EXTENSION):
596 os.remove(path + METAFILE_EXTENSION)
599 return struct.pack('>HH', 0, ERROR_DIRECTORY_NOT_EMPTY)
601 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
603 return struct.pack('>HH', 1, 0)
605 def process_rename_object(key, name, target_dir, new_name):
606 logger.debug('ACTION_RENAME_OBJECT, key: %s, name: %s, target_dir: %s, new_name: %s', key, name, target_dir, new_name)
608 cp1 = find_path(key, name)
609 if cp1 is None or len(cp1) == 0:
610 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
612 from_path = '/'.join(cp1)
613 if not os.path.exists(from_path):
614 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
616 cp2 = find_path(target_dir, new_name)
617 if cp2 is None or len(cp2) == 0:
618 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
620 to_path = '/'.join(cp2)
622 if from_path == to_path:
623 return struct.pack('>HH', 1, 0)
625 if os.path.exists(to_path):
626 return struct.pack('>HH', 0, ERROR_OBJECT_EXISTS)
629 os.rename(from_path, to_path)
630 if os.path.isfile(from_path + METAFILE_EXTENSION):
631 os.rename(from_path + METAFILE_EXTENSION, to_path + METAFILE_EXTENSION)
633 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
635 return struct.pack('>HH', 1, 0)
637 def process_create_dir(key, name):
638 logger.debug('ACTION_CREATE_DIR, key: %s, name: %s', key, name)
640 cp = find_path(key, name)
641 if cp is None or len(cp) == 0:
642 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
648 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
651 locks[key] = ObjectLock(key, SHARED_LOCK, cp)
652 return struct.pack('>HHI', 1, 0, key)
654 def process_set_protect(key, name, mask):
655 logger.debug('ACTION_SET_PROTECT, key: %s, name: %s, mask: %s', key, name, mask)
657 cp = find_path(key, name)
658 if cp is None or len(cp) == 0:
659 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
662 if write_metadata(path, protection=mask):
663 return struct.pack('>HH', 1, 0)
665 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
667 def process_set_comment(key, name, comment):
668 logger.debug('ACTION_SET_COMMENT, key: %s, name: %s, comment: %s', key, name, comment)
670 if len(comment) > 79:
671 return struct.pack('>HH', 0, ERROR_COMMENT_TOO_BIG)
673 cp = find_path(key, name)
674 if cp is None or len(cp) == 0:
675 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
678 if write_metadata(path, comment=comment):
679 return struct.pack('>HH', 1, 0)
681 return struct.pack('>HH', 0, ERROR_OBJECT_NOT_FOUND)
683 def process_same_lock(key1, key2):
684 logger.debug('ACTION_SAME_LOCK, key1: %s key2: %s', key1, key2)
686 if not (key1 in locks and key2 in locks):
687 return struct.pack('>HH', 0, LOCK_DIFFERENT)
688 elif locks[key1].path == locks[key2].path:
689 return struct.pack('>HH', 1, LOCK_SAME)
691 return struct.pack('>HH', 0, LOCK_SAME_VOLUME)
693 def process_request(req):
694 #logger.debug('len(req): %s, req: %s', len(req), list(req))
696 (rtype,) = struct.unpack('>H', req[:2])
698 if rtype == ACTION_LOCATE_OBJECT:
699 key, mode, nlen = struct.unpack('>IHB', req[2:9])
700 name = req[9:9+nlen].decode('latin-1')
701 return process_locate_object(key, mode, name)
702 elif rtype == ACTION_FREE_LOCK:
703 (key,) = struct.unpack('>I', req[2:6])
704 return process_free_lock(key)
705 elif rtype == ACTION_COPY_DIR:
706 (key,) = struct.unpack('>I', req[2:6])
707 return process_copy_dir(key)
708 elif rtype == ACTION_PARENT:
709 (key,) = struct.unpack('>I', req[2:6])
710 return process_parent(key)
711 elif rtype == ACTION_EXAMINE_OBJECT:
712 (key,) = struct.unpack('>I', req[2:6])
713 return process_examine_object(key)
714 elif rtype == ACTION_EXAMINE_NEXT:
715 key, disk_key = struct.unpack('>IH', req[2:8])
716 return process_examine_next(key, disk_key)
717 elif rtype == ACTION_EXAMINE_FH:
718 (arg1,) = struct.unpack('>I', req[2:6])
719 return process_examine_fh(arg1)
720 elif rtype == ACTION_FINDINPUT or rtype == ACTION_FINDOUTPUT or rtype == ACTION_FINDUPDATE:
721 key, nlen = struct.unpack('>IB', req[2:7])
722 name = req[7:7+nlen].decode('latin-1')
723 return process_findxxx(rtype, key, name)
724 elif rtype == ACTION_READ:
725 arg1, address, length = struct.unpack('>III', req[2:14])
726 return process_read(arg1, address, length)
727 elif rtype == ACTION_WRITE:
728 arg1, address, length = struct.unpack('>III', req[2:14])
729 return process_write(arg1, address, length)
730 elif rtype == ACTION_SEEK:
731 arg1, new_pos, mode = struct.unpack('>Iii', req[2:14])
732 return process_seek(arg1, new_pos, mode)
733 elif rtype == ACTION_END:
734 (arg1,) = struct.unpack('>I', req[2:6])
735 return process_end(arg1)
736 elif rtype == ACTION_DELETE_OBJECT:
737 key, nlen = struct.unpack('>IB', req[2:7])
738 name = req[7:7+nlen].decode('latin-1')
739 return process_delete_object(key, name)
740 elif rtype == ACTION_RENAME_OBJECT:
741 key, target_dir, nlen, nnlen = struct.unpack('>IIBB', req[2:12])
742 name = req[12:12+nlen].decode('latin-1')
743 new_name = req[12+nlen:12+nlen+nnlen].decode('latin-1')
744 return process_rename_object(key, name, target_dir, new_name)
745 elif rtype == ACTION_CREATE_DIR:
746 key, nlen = struct.unpack('>IB', req[2:7])
747 name = req[7:7+nlen].decode('latin-1')
748 return process_create_dir(key, name)
749 elif rtype == ACTION_SET_PROTECT:
750 key, mask, nlen = struct.unpack('>IIB', req[2:11])
751 name = req[11:11+nlen].decode('latin-1')
752 return process_set_protect(key, name, mask)
753 elif rtype == ACTION_SET_COMMENT:
754 key, nlen, clen = struct.unpack('>IBB', req[2:8])
755 name = req[8:8+nlen].decode('latin-1')
756 comment = req[8+nlen:8+nlen+clen].decode('latin-1')
757 return process_set_comment(key, name, comment)
758 elif rtype == ACTION_SAME_LOCK:
759 key1, key2 = struct.unpack('>II', req[2:10])
760 return process_same_lock(key1, key2)
761 elif rtype == ACTION_UNSUPPORTED:
762 (dp_Type,) = struct.unpack('>H', req[2:4])
763 logger.warning('Unsupported action %d (Amiga/a314fs)', dp_Type)
764 return struct.pack('>HH', 0, ERROR_ACTION_NOT_KNOWN)
766 logger.warning('Unsupported action %d (a314d/a314fs)', rtype)
767 return struct.pack('>HH', 0, ERROR_ACTION_NOT_KNOWN)
772 idx = sys.argv.index('-ondemand')
777 fd = int(sys.argv[idx + 1])
778 drv = socket.socket(fileno=fd)
780 drv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
781 drv.connect(('localhost', 7110))
783 send_register_req(b'a314fs')
784 stream_id, ptype, payload = wait_for_msg()
786 logger.error('Unable to register service a314fs, shutting down')
791 os.chdir(SHARED_DIRECTORY)
792 logger.info('a314fs is running, shared directory: %s', SHARED_DIRECTORY)
795 stream_id, ptype, payload = wait_for_msg()
797 if ptype == MSG_CONNECT:
798 if payload == b'a314fs':
799 if current_stream_id is not None:
800 send_reset(current_stream_id)
801 current_stream_id = stream_id
802 send_connect_response(stream_id, 0)
804 send_connect_response(stream_id, 3)
805 elif ptype == MSG_DATA:
806 address, length = struct.unpack('>II', payload)
807 #logger.debug('address: %s, length: %s', address, length)
808 req = read_mem(address + 2, length - 2)
809 res = process_request(req)
810 write_mem(address + 2, res)
811 #write_mem(address, b'\xff\xff')
812 send_data(stream_id, b'\xff\xff')
813 elif ptype == MSG_EOS:
814 if stream_id == current_stream_id:
815 logger.debug('Got EOS, stream closed')
817 current_stream_id = None
818 elif ptype == MSG_RESET:
819 if stream_id == current_stream_id:
820 logger.debug('Got RESET, stream closed')
821 current_stream_id = None