<s> """<STR_LIT>""" <EOL> __author__ = "<STR_LIT>" <EOL> __url__ = u'<STR_LIT>' <EOL> __copyright__ = "<STR_LIT>" <EOL> __credits__ = [ <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> ] <EOL> __license__ = '<STR_LIT>' <EOL> import logging <EOL> import select <EOL> import socket <EOL> import time <EOL> import sys <EOL> __import__ ( '<STR_LIT>' ) <EOL> from x84 import cmdline <EOL> from x84 . db import DBHandler <EOL> from x84 . terminal import get_terminals , kill_session , find_tty <EOL> from x84 . fail2ban import get_fail2ban_function <EOL> def main ( ) : <EOL> """<STR_LIT>""" <EOL> import x84 . bbs . ini <EOL> x84 . bbs . ini . init ( * cmdline . parse_args ( ) ) <EOL> from x84 . bbs import get_ini <EOL> from x84 . bbs . ini import CFG <EOL> if sys . maxunicode == <NUM_LIT> : <EOL> import warnings <EOL> warnings . warn ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> servers = get_servers ( CFG ) <EOL> if ( CFG . has_section ( '<STR_LIT>' ) and <EOL> ( not CFG . has_option ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> or CFG . getboolean ( '<STR_LIT>' , '<STR_LIT>' ) ) ) : <EOL> from x84 import webserve <EOL> webserve . main ( ) <EOL> if get_ini ( section = '<STR_LIT>' , key = '<STR_LIT>' ) : <EOL> from x84 import msgpoll <EOL> msgpoll . main ( ) <EOL> try : <EOL> _loop ( servers ) <EOL> except KeyboardInterrupt : <EOL> for server in servers : <EOL> for thread in server . threads [ : ] : <EOL> if not thread . stopped : <EOL> thread . stopped = True <EOL> server . threads . remove ( thread ) <EOL> for key , client in server . clients . items ( ) [ : ] : <EOL> kill_session ( client , '<STR_LIT>' ) <EOL> del server . clients [ key ] <EOL> return <NUM_LIT:0> <EOL> def get_servers ( CFG ) : <EOL> """<STR_LIT>""" <EOL> servers = [ ] <EOL> if ( CFG . has_section ( '<STR_LIT>' ) and <EOL> ( not CFG . has_option ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> or CFG . getboolean ( '<STR_LIT>' , '<STR_LIT>' ) ) ) : <EOL> from x84 . telnet import TelnetServer <EOL> servers . append ( TelnetServer ( config = CFG ) ) <EOL> if ( CFG . has_section ( '<STR_LIT>' ) and <EOL> not CFG . has_option ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> or CFG . getboolean ( '<STR_LIT>' , '<STR_LIT>' ) ) : <EOL> from x84 . ssh import SshServer <EOL> servers . append ( SshServer ( config = CFG ) ) <EOL> if ( CFG . has_section ( '<STR_LIT>' ) and <EOL> ( not CFG . has_option ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> or CFG . getboolean ( '<STR_LIT>' , '<STR_LIT>' ) ) ) : <EOL> from x84 . rlogin import RLoginServer <EOL> servers . append ( RLoginServer ( config = CFG ) ) <EOL> return servers <EOL> def find_server ( servers , fd ) : <EOL> """<STR_LIT>""" <EOL> for server in servers : <EOL> if fd == server . server_socket . fileno ( ) : <EOL> return server <EOL> def accept ( log , server , check_ban ) : <EOL> """<STR_LIT>""" <EOL> if None in ( server . client_factory , server . connect_factory ) : <EOL> raise NotImplementedError ( <EOL> "<STR_LIT>" <EOL> . format ( server = server ) ) <EOL> client_factory_kwargs = server . client_factory_kwargs <EOL> if callable ( server . client_factory_kwargs ) : <EOL> client_factory_kwargs = server . client_factory_kwargs ( server ) <EOL> connect_factory_kwargs = server . connect_factory_kwargs <EOL> if callable ( server . connect_factory_kwargs ) : <EOL> connect_factory_kwargs = server . connect_factory_kwargs ( server ) <EOL> try : <EOL> sock , address_pair = server . server_socket . accept ( ) <EOL> if server . client_count ( ) > server . MAX_CONNECTIONS : <EOL> try : <EOL> sock . shutdown ( socket . SHUT_RDWR ) <EOL> except socket . error : <EOL> pass <EOL> sock . close ( ) <EOL> log . error ( '<STR_LIT>' <EOL> . format ( addr = address_pair [ <NUM_LIT:0> ] ) ) <EOL> return <EOL> if check_ban ( address_pair [ <NUM_LIT:0> ] ) is False : <EOL> log . debug ( '<STR_LIT>' . format ( addr = address_pair [ <NUM_LIT:0> ] ) ) <EOL> try : <EOL> sock . shutdown ( socket . SHUT_RDWR ) <EOL> except socket . error : <EOL> pass <EOL> sock . close ( ) <EOL> return <EOL> client = server . client_factory ( sock , address_pair , <EOL> ** client_factory_kwargs ) <EOL> server . clients [ client . sock . fileno ( ) ] = client <EOL> thread = server . connect_factory ( client , ** connect_factory_kwargs ) <EOL> log . info ( '<STR_LIT>' <EOL> '<STR_LIT>' . format ( client = client , thread = thread ) ) <EOL> server . threads . append ( thread ) <EOL> thread . start ( ) <EOL> except socket . error as err : <EOL> log . error ( '<STR_LIT>' . format ( * err ) ) <EOL> def get_session_output_fds ( servers ) : <EOL> """<STR_LIT>""" <EOL> session_fds = [ ] <EOL> for server in servers : <EOL> for client in server . clients . values ( ) : <EOL> tty = find_tty ( client ) <EOL> if tty is not None : <EOL> session_fds . append ( tty . master_read . fileno ( ) ) <EOL> return session_fds <EOL> def client_recv ( servers , ready_fds , log ) : <EOL> """<STR_LIT>""" <EOL> from x84 . bbs . exception import Disconnected <EOL> for server in servers : <EOL> for client in server . clients_ready ( ready_fds ) : <EOL> try : <EOL> client . socket_recv ( ) <EOL> except Disconnected as err : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( client = client , err = err ) ) <EOL> kill_session ( client , '<STR_LIT>' . format ( err = err ) ) <EOL> def client_send ( terminals , log ) : <EOL> """<STR_LIT>""" <EOL> from x84 . bbs . exception import Disconnected <EOL> for _ , tty in terminals : <EOL> if tty . client . send_ready ( ) : <EOL> try : <EOL> tty . client . send ( ) <EOL> except Disconnected as err : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( client = tty . client , err = err ) ) <EOL> kill_session ( tty . client , '<STR_LIT>' . format ( err = err ) ) <EOL> def session_send ( terminals ) : <EOL> """<STR_LIT>""" <EOL> for _ , tty in terminals : <EOL> if tty . client . input_ready ( ) : <EOL> try : <EOL> tty . master_write . send ( ( '<STR_LIT:input>' , tty . client . get_input ( ) ) ) <EOL> except IOError : <EOL> kill_session ( tty . client , '<STR_LIT>' ) <EOL> elif tty . timeout and tty . client . idle ( ) > tty . timeout : <EOL> kill_session ( tty . client , '<STR_LIT>' ) <EOL> def handle_lock ( locks , tty , event , data , tap_events , log ) : <EOL> """<STR_LIT>""" <EOL> method , stale = data <EOL> if method == '<STR_LIT>' : <EOL> if event in locks : <EOL> holder = locks [ event ] [ <NUM_LIT:1> ] <EOL> for _sid , _ in get_terminals ( ) : <EOL> if _sid == holder and _sid != tty . sid : <EOL> log . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( tty = tty , event = event , holder = holder ) ) <EOL> break <EOL> elif _sid == holder and _sid == tty . sid : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( tty = tty , event = event ) ) <EOL> else : <EOL> log . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( tty = tty , event = event , holder = holder ) ) <EOL> del locks [ event ] <EOL> if event not in locks : <EOL> locks [ event ] = ( time . time ( ) , tty . sid ) <EOL> tty . master_write . send ( ( event , True , ) ) <EOL> if tap_events : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( tty = tty , event = event ) ) <EOL> else : <EOL> holder = locks [ event ] [ <NUM_LIT:1> ] <EOL> elapsed = time . time ( ) - locks [ event ] [ <NUM_LIT:0> ] <EOL> if ( stale is not None and elapsed > stale ) : <EOL> locks [ event ] = ( time . time ( ) , tty . sid ) <EOL> log . warn ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( tty = tty , event = event , holder = holder , <EOL> elapsed = elapsed , stale = stale ) ) <EOL> tty . master_write . send ( ( event , True , ) ) <EOL> else : <EOL> log . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( tty = tty , event = event , holder = holder , <EOL> elapsed = elapsed , stale = stale ) ) <EOL> tty . master_write . send ( ( event , False , ) ) <EOL> elif method == '<STR_LIT>' : <EOL> if event not in locks : <EOL> log . error ( '<STR_LIT>' <EOL> '<STR_LIT>' . format ( tty = tty , event = event ) ) <EOL> else : <EOL> del locks [ event ] <EOL> if tap_events : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( tty = tty , event = event ) ) <EOL> def session_recv ( locks , terminals , log , tap_events ) : <EOL> """<STR_LIT>""" <EOL> for sid , tty in terminals : <EOL> while tty . master_read . poll ( ) : <EOL> try : <EOL> event , data = tty . master_read . recv ( ) <EOL> except ( EOFError , IOError ) as err : <EOL> log . exception ( '<STR_LIT>' . format ( err ) ) <EOL> kill_session ( tty . client , '<STR_LIT>' . format ( err ) ) <EOL> break <EOL> except TypeError as err : <EOL> log . exception ( '<STR_LIT>' . format ( err ) ) <EOL> break <EOL> if event == '<STR_LIT>' : <EOL> kill_session ( tty . client , '<STR_LIT>' ) <EOL> break <EOL> elif event == '<STR_LIT>' : <EOL> data . msg = ( '<STR_LIT>' <EOL> . format ( data = data , tty = tty ) ) <EOL> log . handle ( data ) <EOL> elif event == '<STR_LIT>' : <EOL> tty . client . send_unicode ( ucs = data [ <NUM_LIT:0> ] , encoding = data [ <NUM_LIT:1> ] ) <EOL> elif event == '<STR_LIT>' : <EOL> for _sid , _tty in terminals : <EOL> if data [ <NUM_LIT:0> ] == _sid : <EOL> kill_session ( <EOL> tty . client , '<STR_LIT>' . format ( sid ) ) <EOL> break <EOL> elif event == '<STR_LIT>' : <EOL> if tap_events : <EOL> log . debug ( '<STR_LIT>' . format ( data ) ) <EOL> tgt_sid , send_event , send_val = data [ <NUM_LIT:0> ] , data [ <NUM_LIT:1> ] , data [ <NUM_LIT:2> : ] <EOL> for _sid , _tty in terminals : <EOL> if tgt_sid == _sid : <EOL> _tty . master_write . send ( ( send_event , send_val ) ) <EOL> break <EOL> elif event == '<STR_LIT>' : <EOL> if tap_events : <EOL> log . debug ( '<STR_LIT>' . format ( data = data ) ) <EOL> for _sid , _tty in terminals : <EOL> if sid != _sid : <EOL> _tty . master_write . send ( ( event , data , ) ) <EOL> elif event == '<STR_LIT>' : <EOL> if tap_events : <EOL> log . debug ( '<STR_LIT>' <EOL> . format ( tty = tty , data = data ) ) <EOL> tty . timeout = data <EOL> elif event . startswith ( '<STR_LIT>' ) : <EOL> DBHandler ( tty . master_write , event , data ) . start ( ) <EOL> elif event . startswith ( '<STR_LIT>' ) : <EOL> handle_lock ( locks , tty , event , data , tap_events , log ) <EOL> else : <EOL> log . error ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> . format ( tty = tty , event = event , data = data ) ) <EOL> def _loop ( servers ) : <EOL> """<STR_LIT>""" <EOL> from x84 . bbs . ini import CFG <EOL> SELECT_POLL = <NUM_LIT> <EOL> WIN32 = sys . platform . lower ( ) . startswith ( '<STR_LIT:win32>' ) <EOL> session_fds = set ( ) <EOL> log = logging . getLogger ( '<STR_LIT>' ) <EOL> if not len ( servers ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> tap_events = CFG . getboolean ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> check_ban = get_fail2ban_function ( ) <EOL> locks = dict ( ) <EOL> while True : <EOL> for server in servers : <EOL> for key , client in server . clients . items ( ) [ : ] : <EOL> if not client . is_active ( ) : <EOL> kill_session ( client , '<STR_LIT>' ) <EOL> del server . clients [ key ] <EOL> for thread in [ _thread for _thread in server . threads <EOL> if _thread . stopped ] [ : ] : <EOL> server . threads . remove ( thread ) <EOL> check_r = list ( ) <EOL> for server in servers : <EOL> check_r . append ( server . server_socket . fileno ( ) ) <EOL> check_r . extend ( server . client_fds ( ) ) <EOL> if not WIN32 : <EOL> session_fds = get_session_output_fds ( servers ) <EOL> check_r . extend ( session_fds ) <EOL> try : <EOL> ready_r , _ , _ = select . select ( check_r , [ ] , [ ] , SELECT_POLL ) <EOL> except select . error as err : <EOL> log . debug ( '<STR_LIT>' . format ( err ) ) <EOL> continue <EOL> for fd in ready_r : <EOL> server = find_server ( servers , fd ) <EOL> if server is not None : <EOL> accept ( log , server , check_ban ) <EOL> client_recv ( servers , ready_r , log ) <EOL> terms = get_terminals ( ) <EOL> if WIN32 or set ( session_fds ) & set ( ready_r ) : <EOL> try : <EOL> session_recv ( locks , terms , log , tap_events ) <EOL> except IOError as err : <EOL> log . warn ( err ) <EOL> client_send ( terms , log ) <EOL> session_send ( terms ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> exit ( main ( ) ) </s>
