diff -ur v8/sock_ut.py v9/sock_ut.py --- v8/sock_ut.py 2021-07-16 10:25:21.000000000 +0900 +++ v9/sock_ut.py 2021-07-17 01:34:19.000000000 +0900 @@ -7,6 +7,7 @@ import empty import thr +import cmd_ut import dbg can_read = lambda sc, tmout=0: select.select( [ sc ], [], [], tmout )[ 0 ] == [ sc ] @@ -15,6 +16,106 @@ cut_tail = lambda s, cut: s[ : -len( cut ) ] if s.endswith( cut ) else s +def fio_new( get_b1_, put_b_, get_b_=None ): + + to_s = lambda bt: bt.decode( 'utf-8' ) + to_b = lambda s: s.encode( 'utf-8' ) + + def get_b1( f ): + b1 = get_b1_( f ) + return b1 if b1 else b'' + + get_s1 = lambda f : to_s( get_b1( f ) ) + + def get_b_line( f ): + b = b'' + while True: + b1 = get_b1( f ) + if not b1: + break + b += b1 + if b1 == b'\n': + break + return b + + get_s_line = lambda f: to_s( get_b_line( f ) ) + + def get_b( f ): + if get_b_: + return get_b_( f ) + + b = b'' + while not b or can_read( f ): + b1 = get_b1( f ) + if not b1: + break + b += b1 + return b + + get_s = lambda f: to_s( get_b( f ) ) + + def get_b_all( f ): + b = b'' + while not b or can_read( f ): + b_ = get_b( f ) + if not b_: + break + b += b_ + return b + + get_s_all = lambda f: to_s( get_b_all( f ) ) + + + def put_b( f, b ): + try: + put_b_( f, b ) + except: + return False + if hasattr( f, 'flush' ): + f.flush() + return True + + put_s = lambda f, s: put_b( f, to_b( s ) ) + + + def get_func( use_b, use_all ): + if use_b: + return get_b_all if use_all else get_b + return get_s_all if use_all else get_s + + def put_func( use_b ): + return put_b if use_b else put_s + + + return empty.new( locals() ) + + +def get_std_b( f ): + return f.buffer if hasattr( f, 'buffer' ) else f + +stdin_b = get_std_b( sys.stdin ) +stdout_b = get_std_b( sys.stdout ) +std_fio = fio_new( lambda f: f.read( 1 ), lambda f, b: f.write( b ) ) + + +def proc_new( cmd ): + proc = cmd_ut.proc_new( cmd, stdin=cmd_ut.PIPE, stdout=cmd_ut.PIPE ) + + stdin = proc.get_stdin() + stdout = proc.get_stdout() + + get_b1 = lambda f: f.read( 1 ) + put_b = lambda f, b: f.write( b ) if f else 0 + + fio = fio_new( get_b1, put_b ) + + def stop(): + proc.kill() + proc.wait() + + return empty.new( locals() ) + + def port_conn( port, host='localhost' ): cs = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) try: @@ -23,52 +124,33 @@ return None return cs -def send_bt( sc, bt ): - try: - sc.sendall( bt ) - except: - return False - return True - -def recv_bt( sc, bufmax=16*1024 ): - bt = sc.recv( bufmax ) - return bt - -def recv_bt_all( sc ): - buf = b'' - while not buf or can_read( sc ): - bt = recv_bt( sc ) - if not bt: - break - buf += bt - return buf +bufmax = 16 * 1024 +sc_fio = fio_new( lambda f: f.recv( 1 ), lambda f, b: f.sendall( b ), lambda f: f.recv( bufmax ) ) def send_str( sc, s ): s = add_tail( s, '\n' ) - bt = s.encode( 'utf-8' ) - return send_bt( sc, bt ) + return sc_fio.put_s( sc, s ) -def recv_str( sc, bufmax=16*1024 ): - bt = recv_bt( sc, bufmax + 1 ) # '\n' - s = bt.decode( 'utf-8' ) +def recv_str_line( sc ): + s = sc_fio.get_s_line( sc ) return cut_tail( s, '\n' ) def recv_str_all( sc ): - bt = recv_bt_all( sc ) - s = bt.decode( 'utf-8' ) + s = sc_fio.get_s_all( sc ) return cut_tail( s, '\n' ) def pipe_loop( sc_from, sc_to ): while True: - bt = recv_bt( sc_from ) - if not bt: + b = sc_fio.get_b( sc_from ) + if not b: break - if not send_bt( sc_to, bt ): + if not sc_fio.put_b( sc_to, b ): break # srv=name,port=xxx,host=xxx # srv=name,id=xxx,port=xxx,host=xxx # srv=name,id=xxx +# get_srvs # kill=name # kill_base_srv # name @@ -150,7 +232,7 @@ pipe_loop( sc, sc2 ) def base_th( port, sc, ev_quit ): - s = recv_str( sc ) + s = recv_str_line( sc ) if not s: sc.close() return @@ -169,6 +251,10 @@ q = srvs.get( name ) q.put( 'kill' ) + elif s == 'get_srvs': + r = '\n'.join( srvs.keys() ) + send_str( sc, r ) + elif s == 'kill_base_srv': ev_quit.set() send_str( sc, 'next' ) @@ -214,7 +300,7 @@ return ss def accept_recv_ping( ss ): - s = recv_str( ss ) + s = recv_str_line( ss ) if not s: return None @@ -244,7 +330,7 @@ if not send_str( cs, s ): cs.close() return None - s = recv_str( cs, bufmax=2 ) + s = recv_str_line( cs ) if s != 'ok': cs.close() return None @@ -266,20 +352,42 @@ thr.ths.start( th ) ss.close() -def srv_func_new( cb ): +def srv_func_new( cb, use_b=False, use_all=False ): + send = send_ = sc_fio.put_func( use_b ) + recv = recv_ = sc_fio.get_func( use_b, use_all ) + if not use_b: + send = lambda f, s: send_( f, add_tail( s, '\n' ) ) + recv = lambda f: cut_tail( recv_( f ), '\n' ) def func( sc ): while True: - s = recv_str( sc ) + s = recv( sc ) if not s: break r = cb( s ) - if not send_str( sc, r ): + if not r: + break + if not send( sc, r ): break sc.close() return empty.new( locals() ) +def srv_loop_cmd( host, port, name, cmd ): + + def th_func( sc ): + proc = proc_new( cmd ) + + def cb( b ): + proc.fio.put_b( proc.stdin, b ) + return proc.fio.get_b_line( proc.stdout ) + + srv_func = srv_func_new( cb, use_b=True, use_all=True ) + srv_func.func( sc ) + proc.stop() + + srv_loop( port, name, th_func, host ) + def connect( port, name, host='localhost' ): cs = port_conn( port, host ) if not cs: @@ -289,12 +397,21 @@ cs.close() return None - s = recv_str( cs, bufmax=2 ) + s = recv_str_line( cs ) if s != 'ok': cs.close() return None return cs +def get_srvs( host, port ): + cs = port_conn( port, host ) + if not cs: + return + send_str( cs, 'get_srvs' ) + r = recv_str_all( cs ) + cs.close() + return r.split( '\n' ) + def kill_srv( port, name, host='loaclhost' ): cs = port_conn( port, host ) if not cs: @@ -310,7 +427,7 @@ return dbg.out( 'kill_base_srv' ) send_str( cs, 'kill_base_srv' ) - r = recv_str( cs ) + r = recv_str_line( cs ) cs.close() cs = port_conn( port, host ) # for accept loop @@ -323,8 +440,11 @@ 'base [ port=13579 ]', 'srv [ host=localhost ][ port=13579 ] upper', 'srv [ host=localhost ][ port=13579 ] eval', + 'srv [ host=localhost ][ port=13579 ] srv_name cmd arg ...', 'cli [ host=localhost ][ port=13579 ] upper word word word ...', 'cli [ host=localhost ][ port=13579 ] eval word word word ...', + 'cli [ host=localhost ][ port=13579 ] srv_name', + 'srvs [ host=localhost ][ port=13579 ]', 'kill_base [ host=localhost ][ port=13579 ]', 'kill [ host=localhost ][ port=13579 ] srv_name ( srv_name is upper, eval or ... )' ] @@ -345,7 +465,7 @@ for i in range( len( argv ) ): if argv[ i ].startswith( k ): return argv.pop( i )[ len( k ) : ] - return dv + return dv host = popk( 'host=', 'localhost' ) port = int( popk( 'port=', '13579' ) ) @@ -358,27 +478,55 @@ cmd = pop() if cmd == 'base': base_srv( port ) - elif cmd == 'srv': + elif cmd == 'srv': name = pop() if name in names: cb = names.get( name ) srv_func = srv_func_new( cb ) srv_loop( port, name, srv_func.func, host ) - elif cmd == 'cli': + else: + cmd = ' '.join( argv ) + srv_loop_cmd( host, port, name, cmd ) + elif cmd == 'cli': + lst = get_srvs( host, port ) name = pop() + if name not in lst: + return + + sc = connect( port, name, host ) + if not sc: + return + if name in names: - sc = connect( port, name, host ) - if not sc: - return while len( argv ) > 0: w = pop() if not send_str( sc, w ): break - r = recv_str( sc ) + r = recv_str_line( sc ) if not r: break dbg.out( '{} --> {}'.format( w, r ) ) - sc.close() + else: + while True: + b = std_fio.get_b_line( stdin_b ) + if not b: + break + + if not sc_fio.put_b( sc, b ): + break + + b = sc_fio.get_b_all( sc ) + if not b: + break + + if not std_fio.put_b( stdout_b, b ): + break + sc.close() + + elif cmd == 'srvs': + lst = get_srvs( host, port ) + dbg.out( '\n'.join( lst ) ) + elif cmd == 'kill': name = pop() kill_srv( port, name, host )