예제 #1
0
파일: client.py 프로젝트: dummey/CSE125
class Client(object):
    def __init__(self,
                 remote_port=8000,
                 remote_address="127.0.0.1",
                 local_port=9000,
                 local_address="127.0.0.1",
                 run_local=False,
                 logging=False,
                 callbacks={},
                 **kwargs):

        self.connection = Connection(ip=remote_address,
                                     port=remote_port,
                                     callbacks=callbacks,
                                     client_id=0)

        self.dataBuffer = []
        self.logging = logging
        self.callbacks = callbacks

    def send(self, tag, data):
        """Communicates the given data to the server"""
        self.connection.send(tag, dumps(data))

    def register(self, func, tag):
        """Decorator, must include a specific tag. Takes a function that will accept two arguments
        a tag, and the data itself"""
        self.callbacks[tag] = func
        return func

    def shutdown(self):
        self.connection.shutdown()
예제 #2
0
파일: client.py 프로젝트: dummey/CSE125
class Client(object):
    def __init__(self, remote_port=8000, remote_address="127.0.0.1",
                 local_port=9000, local_address="127.0.0.1", run_local=False,
                 logging=False, callbacks={}, **kwargs):
        
        self.connection = Connection(ip=remote_address, 
                                    port=remote_port, 
                                    callbacks=callbacks,
                                    client_id=0)
        
        self.dataBuffer = []
        self.logging = logging
        self.callbacks = callbacks
        
    

    def send(self, tag, data):
        """Communicates the given data to the server"""
        self.connection.send(tag, dumps(data))

    def register(self, func, tag):
        """Decorator, must include a specific tag. Takes a function that will accept two arguments
        a tag, and the data itself"""
        self.callbacks[tag] = func
        return func

    def shutdown(self):
        self.connection.shutdown()
예제 #3
0
class GameState():
    user_tile_type: TileState
    turn: TileState
    winner: TileState
    _state: List[TileState]
    _board_size: int
    _listener: Callable
    multi_palyer_connection: Connection = None

    def __init__(self,
                 board_size: int,
                 listener: Callable,
                 is_server: bool = None) -> None:
        self._board_size = board_size
        self._state = [TileState.EMPTY] * (board_size * board_size)
        self._listener = listener
        self.winner = None
        self.turn = TileState.X
        self.user_tile_type = TileState.X
        self.setup_multiplayer_connection(is_server)

    def setup_multiplayer_connection(self, is_server: bool = None):
        if is_server != None:
            self.multi_palyer_connection = Connection()
            if is_server:
                self.multi_palyer_connection.serve("localhost", 8080)
                self.multi_palyer_connection.wait_client_thread.join()
            else:
                self.multi_palyer_connection.connect("localhost", 8080)
                self.user_tile_type = TileState.O

            self.multi_palyer_connection.recive_listener = self.multiplayer_event

    def multiplayer_event(self, payload):
        if payload['packet'] == Packets.TILE_CHANGE:
            tile_type = payload['tile_type']
            x = payload['x']
            y = payload['y']

            self.set(x, y, tile_type, from_network=True)

    def new_game(self):
        self._state = [TileState.EMPTY] * (self._board_size * self._board_size)
        self.winner = None
        self._listener()

    def _index(self, x, y):
        return y * self._board_size + x

    def get(self, x: int, y: int):
        index = self._index(x, y)
        return self._state[index]

    def set(self, x: int, y: int, state: TileState, /, from_network=False):
예제 #4
0
    def setup_multiplayer_connection(self, is_server: bool = None):
        if is_server != None:
            self.multi_palyer_connection = Connection()
            if is_server:
                self.multi_palyer_connection.serve("localhost", 8080)
                self.multi_palyer_connection.wait_client_thread.join()
            else:
                self.multi_palyer_connection.connect("localhost", 8080)
                self.user_tile_type = TileState.O

            self.multi_palyer_connection.recive_listener = self.multiplayer_event
예제 #5
0
파일: client.py 프로젝트: dummey/CSE125
    def __init__(self,
                 remote_port=8000,
                 remote_address="127.0.0.1",
                 local_port=9000,
                 local_address="127.0.0.1",
                 run_local=False,
                 logging=False,
                 callbacks={},
                 **kwargs):

        self.connection = Connection(ip=remote_address,
                                     port=remote_port,
                                     callbacks=callbacks,
                                     client_id=0)

        self.dataBuffer = []
        self.logging = logging
        self.callbacks = callbacks
예제 #6
0
def main(character, config):
    renderer = Renderer(config['Renderer'])
    conn = Connection(config['Network'])
    proxy = MessageProxy(conn)
    input_mgr = InputManager()
    res_mgr = ResourceManager(config['Game'])
    audio_mgr = AudioManager(config['Sound'])

    client = Client(
        character, renderer, proxy, input_mgr, res_mgr, audio_mgr, config)

    client.start()
예제 #7
0
파일: client.py 프로젝트: dummey/CSE125
 def __init__(self, remote_port=8000, remote_address="127.0.0.1",
              local_port=9000, local_address="127.0.0.1", run_local=False,
              logging=False, callbacks={}, **kwargs):
     
     self.connection = Connection(ip=remote_address, 
                                 port=remote_port, 
                                 callbacks=callbacks,
                                 client_id=0)
     
     self.dataBuffer = []
     self.logging = logging
     self.callbacks = callbacks
예제 #8
0
    def login(self, character_name, password):
        # Connect
        self._conn = Connection()
        self._conn.connect()

        # Send login packet
        login_packet = OutgoingPacket()
        login_packet.add_u8(0x0A)
        login_packet.add_u8(0)
        login_packet.add_u8(0)
        login_packet.add_u16(0)
        login_packet.add_u8(0)
        login_packet.add_string(character_name)
        login_packet.add_string(password)
        self._conn.send_packet(login_packet)

        # Receive login response
        while True:
            packet = self._conn.recv_packet()
            if packet:
                break
            time.sleep(0.1)

        packet_type = packet.get_u8()
        if packet_type == 0x14:
            error_message = packet.get_string()
            print("login: could not login: \"{}\"".format(error_message))
            self._conn.close()
            self._conn = None
            return False

        elif packet_type == 0x0A:
            self._parse_login_packet(packet)
            return True

        else:
            print("login: unknown packet type: {}".format(packet_type))
            self._conn.close()
            self._conn = None
            return False
예제 #9
0
 def __init__(self,
              id,
              port,
              ids,
              ports,
              on_request,
              on_release,
              logger=None):
     """
     :param id: self id
     :param port: self port
     :param ids: ids of other processes
     :param ports: ports of other processes
     :param on_request: callback function
     :param on_release: callback function
     """
     self.__number_of_processes = len(ids)
     self.ids = ids
     self.on_request = on_request
     self.on_release = on_release
     self.logger = logger
     self.connection = Connection(id, port, ids, ports, self.on_response,
                                  logger)
예제 #10
0
class API:
    """
    Actually it is not pure RPC class.
    At least normally RPC layer doesn't suppose incoming messages
    that aren't answers for our outgoing requests.
    It means that in our case we must have some callback for them anyway (or maybe futures).
    Moreover some of our requests don't suppose answer (e.g. 'release').
    Therefore I guess it would be strange to await every confirmation
    before sending next request during broadcast messaging.
    (Can consider current implementation of 'request' method as asynchronous remote calls :))

    Anyway from the outside calls of the functions from this class looks exactly like RPC
    because they return only after receiving response (if it's supposed to be there).
    """
    # constants
    __REQUEST = 0
    __RELEASE = 1
    __CONFIRM = 2
    __PING = 3
    # variables
    __lock = RLock()
    # we use this lock to achieve consistency inside some functions
    # where we suppose logic time to be the same during the whole execution of function
    clock = 0  # lamport clock
    __number_of_processes = 0  # exclude current
    __number_of_confirmations = 0
    __last_request_id = 0
    __last_confirmation_time = 0

    def on_response(self, response):
        message, sender, sender_time, request_id = response
        self.__lock.acquire()
        self.clock = max(self.clock, sender_time) + 1
        if message == self.__CONFIRM:
            if request_id != self.__last_request_id:
                # probably it's delayed confirmation for previous PING request
                # that finished with timeout
                # ignore it
                return
            self.__number_of_confirmations += 1
            self.__last_confirmation_time = self.clock
            self.__lock.release()
            return
        self.__lock.release()
        if message == self.__REQUEST:
            self.on_request(sender, sender_time, request_id)
        elif message == self.__RELEASE:
            self.on_release(sender, sender_time)
        elif message == self.__PING:
            self.confirm(sender, request_id)

    def __init__(self,
                 id,
                 port,
                 ids,
                 ports,
                 on_request,
                 on_release,
                 logger=None):
        """
        :param id: self id
        :param port: self port
        :param ids: ids of other processes
        :param ports: ports of other processes
        :param on_request: callback function
        :param on_release: callback function
        """
        self.__number_of_processes = len(ids)
        self.ids = ids
        self.on_request = on_request
        self.on_release = on_release
        self.logger = logger
        self.connection = Connection(id, port, ids, ports, self.on_response,
                                     logger)

    def current_time(self):
        """
        :return: current lamport clock time
        """
        return self.clock

    def request(self) -> int:
        """
        send broadcast request with intention to acquire mutex
        returns when all confirmations received or after timeout
        :return: -1 if timeout, otherwise time of the last confirmation
        """
        self.__lock.acquire()
        self.__number_of_confirmations = 0
        self.__last_confirmation_time = 0
        self.__last_request_id += 1
        for _id in self.ids:
            self.clock += 1
            self.connection.send(_id, self.__REQUEST, self.clock,
                                 self.__last_request_id)
        self.__lock.release()
        start = time()
        # await confirmations
        timeout = False
        while self.__number_of_confirmations != self.__number_of_processes:
            if time() - start >= 10 and not timeout:
                self.logger.error('await for confirmations more than 10s...')
                timeout = True
        return self.__last_confirmation_time

    def confirm(self, recipient_id, request_id):
        """
        send confirmation
        :param recipient_id: id of process which requires confirmation
        """
        self.__lock.acquire()
        self.clock += 1
        # self.logger.warn("pong to {} with id: {}".format(recipient_id, request_id))
        self.connection.send(recipient_id, self.__CONFIRM, self.clock,
                             request_id)
        self.__lock.release()

    def release(self):
        """
        send broadcast request to notify release of mutex
        :return logic time of event
        """
        self.__lock.acquire()
        try:
            for _id in self.ids:
                self.clock += 1
                self.connection.send(_id, self.__RELEASE, self.clock)
            return self.clock
        finally:
            self.__lock.release()

    def increment_clock(self):
        """
        actually it isn't remote call, just increment local clock
        :return logic time of event
        """
        self.__lock.acquire()
        try:
            self.clock += 1
            return self.clock
        finally:
            self.__lock.release()

    def ping_all(self, timeout=1):
        self.__number_of_confirmations = 0
        self.__last_confirmation_time = 0
        self.__last_request_id += 1
        for _id in self.ids:
            self.connection.send(_id, self.__PING, self.clock,
                                 self.__last_request_id)
        start = time()
        # await confirmations
        while self.__number_of_confirmations != self.__number_of_processes:
            if time() - start >= timeout:
                return False
        return True

    def tear_down(self):
        """
        release socket
        """
        self.connection.tear_down()
예제 #11
0
class Protocol():
    def __init__(self, client):
        self._client = client
        self._conn = None

    def connected(self):
        return self._conn != None

    def login(self, character_name, password):
        # Connect
        self._conn = Connection()
        self._conn.connect()

        # Send login packet
        login_packet = OutgoingPacket()
        login_packet.add_u8(0x0A)
        login_packet.add_u8(0)
        login_packet.add_u8(0)
        login_packet.add_u16(0)
        login_packet.add_u8(0)
        login_packet.add_string(character_name)
        login_packet.add_string(password)
        self._conn.send_packet(login_packet)

        # Receive login response
        while True:
            packet = self._conn.recv_packet()
            if packet:
                break
            time.sleep(0.1)

        packet_type = packet.get_u8()
        if packet_type == 0x14:
            error_message = packet.get_string()
            print("login: could not login: \"{}\"".format(error_message))
            self._conn.close()
            self._conn = None
            return False

        elif packet_type == 0x0A:
            self._parse_login_packet(packet)
            return True

        else:
            print("login: unknown packet type: {}".format(packet_type))
            self._conn.close()
            self._conn = None
            return False

    def logout(self):
        # Gracefully logout
        logout_packet = OutgoingPacket()
        logout_packet.add_u8(0x14)
        self._conn.send_packet(logout_packet)

        # Just wait for the socket to close by the server
        try:
            while True:
                handle_packet()
        except:
            self._conn = None

    def disconnect(self):
        # Just close the socket
        self._conn.close()
        self._conn = None

    def move(self, direction):
        packet = OutgoingPacket()
        packet.add_u8(0x65 + direction)
        self._conn.send_packet(packet)

    def handle_packet(self):
        packet = self._conn.recv_packet()
        if not packet:
            return False

        packet_type = packet.get_u8()
        #print("parse_packet: skipping unknown packet type: 0x{:02x}".format(packet_type))
        return True

    # Helpers

    def _parse_position(self, packet):
        x = packet.get_u16()
        y = packet.get_u16()
        z = packet.get_u8()
        return x, y, z

    def _parse_item(self, packet):
        item_type_id = packet.get_u16()
        # TODO(simon): parse count if stackable & parse subtype if multitype
        return Item(item_type_id)

    def _parse_creature(self, packet):
        creature_type = packet.get_u16()
        if creature_type == 0x0061:
            # New creature
            packet.get_u32()  # creature ids to remove
            creature_id = packet.get_u32()
            creature_name = packet.get_string()

        elif creature_type == 0x0062:
            # TODO(simon): Handle known creature
            raise Exception()

        else:
            print("Unknown creature_type: {}".format(creature_type))
            raise Exception()

        # Skip health, direction, outfit, 0xDC00 ?? and speed
        packet.skip(11)

        return Creature(creature_id, creature_name)

    def _parse_tile(self, packet):
        tile = Tile()
        tile.ground = self._parse_item(packet)

        for stackpos in range(10):
            if packet.peek_u16() >= 0xFF00:
                packet.get_u16()
                return tile

            elif packet.peek_u16() == 0x0061 or packet.peek_u16() == 0x0062:
                tile.creatures.append(self._parse_creature(packet))

            else:
                tile.items.append(self._parse_item(packet))

        raise Exception()

    def _parse_login_packet(self, packet):
        self._client.player_id = packet.get_u32()

        packet.skip(2)

        tmp = packet.get_u8()
        if tmp != 0x64:
            print("Expected full map (0x64) but got: {}".format(tmp))
            raise Exception()

        self._client.player_position = self._parse_position(packet)
        x, y, z = self._client.player_position
        for x_ in range(x - 9, x + 9):
            for y_ in range(y - 7, y + 7):
                self._client.tiles[(x_, y_)] = self._parse_tile(packet)
예제 #12
0
'''
The main entrance of the program
'''
import time

from logger import Logger
from network import Connection
from sonic import UltraSonic

SONIC = UltraSonic()
LOGGER = Logger()
CONNECTION = Connection()


def main(working_time):
    '''
    main function to SmartBin to work
    :param working_time:
    :return: status
    '''
    while working_time > 0:
        command, dist = 'measure', SONIC.middle_value()
        LOGGER.write(command, dist)
        # logger.write(CONNECTION.send_data(dist))
        time.sleep(10)
        working_time -= 10


if __name__ == '__main__':
    main(40)