예제 #1
0
파일: kiser.py 프로젝트: skerit/kiflea
    def wget(self, data):
        
        data = decode_hybi(data)['payload']
        
        if data == None:
            return False
        
        # Check if there's a header in the data
        if data.find("--KOP:") > -1:
            
            if self.wComplete == -1:
                verbose("Previous data was incomplete, new data already arrived", 0, 3)
            
            # Start splicing the header from the body
            self.wLength = data.partition("--KOP:")[2]
            data =  self.wLength.partition(":POK--")[2]
            self.wLength = int(self.wLength.partition(":POK--")[0])
            
            # If the length of the data matches the specified length, return the data
            if len(data) == self.wLength:
                
                self.wComplete = None
                self.wLength = None

                debug(data)
                
                # Return the completed data
                return data
            else:
                verbose("Length does not match. Data is " + str(len(data)) + " while we wanted " + str(self.wLength), 0, 3)
                self.wComplete = -1
                self.wData = data
        else:
            verbose("Does not contain a KOP", 0, 3)
            # See if wData isn't none
            if self.wData:
                self.wData = self.wData + data
                
                if len(self.wData) == self.wLength:
                    print "\r\nCompleted!!"
                    self.wComplete = None
                    self.wLength = None
    
                    # Return the completed data
                    return self.wData
                else:
                    self.wComplete = -2
            else: # If it is, this data got to us before any head, and we won't be able to piece it together with anything
                if data:
                    verbose("Received stray data: " + data, 0, 3)
                else:
                    verbose("Closing connection of user " + self.uid, 0, 2)
                    self.closeClient()

        # Return false if this point has been reached
        return False
예제 #2
0
파일: kiser.py 프로젝트: skerit/kiflea
    def open_socket(self):
        try:
            # create an InterNET, STREAMing socket (aka TCP/IP) 
            self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            
            # allow quick restart and reuse of server socket 
            self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

            self.server.bind((self.host,self.port))
            self.server.listen(5)
        except socket.error, (value,message):
            if self.server:
                self.server.close()
            verbose("\r\nCould not open socket: " + message, 0, 0)
            sys.exit(1)
예제 #3
0
파일: kiser.py 프로젝트: skerit/kiflea
    def __init__(self, startsock, address, queue, queueIndex, serverQueue):
        threading.Thread.__init__(self)
        
        self.startsock = startsock
        self.address = address
        
        self.verbose        = False
        self.ssl_only       = False
        self.daemon         = False
        self.handler_id     = 1
        self.cert = os.path.abspath('')
        self.key = self.web = self.record = ''
        
        self.size = 65536
        self.queue = queue
        self.queueIndex = queueIndex
        self.serverQueue = serverQueue
        self.threads = []
        self.wData = None               # Store incomplete data here
        self.wComplete = None           # Data receive boolean
        self.wLength = None             # The expected length of the received data
        self.running = True             # While this is true, the thread runs
        self.initiated = False          # Has this user been initialized?
        self.uid = None
        global globUser
        global globtest
        
        """ Do something with a WebSockets client connection. """
        # Initialize per client settings
        self.send_parts = []
        self.recv_part  = None
        self.base64     = False
        self.rec        = None
        self.start_time = int(time.time()*1000)

        # handler process
        try:
            try:
                verbose("Begin handshake", 2, 4)
                self.client = self.do_handshake(self.startsock, self.address)
                verbose("Handshake finished", 2, 3)

            except self.EClose:
                _, exc, _ = sys.exc_info()
                # Connection was not a WebSockets connection
                if exc.args[0]:
                    self.msg("%s: %s" % (address[0], exc.args[0]))
            except Exception:
                _, exc, _ = sys.exc_info()
                self.msg("handler exception: %s" % str(exc))
                if self.verbose:
                    self.msg(traceback.format_exc())
        finally:
            if self.client and self.client != self.startsock:
                verbose("Closing client", 0, 3)
                self.client.close()
        
        verbose("Client init finished", 2, 4)
예제 #4
0
파일: kiser.py 프로젝트: skerit/kiflea
 def closeClient(self):
     
     if(self.uid):
         self.updateWorld({'action': 'logoff'})
     
     self.running = 0
     
     # Loop through all the subthreads and close (join) them
     for c in self.threads:
         c.join()
     
     # Delete our queue from the dictionary
     rwQ.acquireRead()
     try:
         rwQ.acquireWrite()
         try:
             # Add a new queue to the array for the new thread
             debug('Globqueue length before deleting: ' + str(len(globQueue)))
             del globQueue[self.queueIndex]
             debug('Globqueue length after deleting: ' + str(len(globQueue)))
         finally:
             rwQ.release()
     finally:
         rwQ.release()
         
     # Delete our user from the dictionary
     if(self.uid):
         rwU.acquireRead()
         try:
             rwU.acquireWrite()
             try:
                 del globUser[self.uid]
             finally:
                 rwU.release()
         finally:
             rwU.release()
         
     self.client.close()
     
     verbose("Client disconnected", 0, 5)
예제 #5
0
파일: kiser.py 프로젝트: skerit/kiflea
 def loadMaps(self, maps):
     """
     Load all the XML maps
     """
     
     verbose("Loading maps ...", 0, 3)
     
     for fileName in maps:
         verbose(fileName, 2, 4)
         globMaps[fileName] = Maps.Map(fileName, rootFolder)
     
     verbose("Finished loading maps", 0, 2)
예제 #6
0
파일: Maps.py 프로젝트: skerit/kiflea
    def __init__(self, filename, dir):
        self.name = filename    # The filename equals the mapname
        self.dir = dir          # Where we can find the file
        
        mapTree = ET.parse(dir + filename)  # Open and parse the XML file
        mapRoot = mapTree.getroot()         # Get the root element (<map>, in this case)

        # Get the attributes of the <map> element
        self.width = int(mapRoot.attrib['width'])
        self.height = int(mapRoot.attrib['height'])
        self.tileWidth = int(mapRoot.attrib['tilewidth'])
        self.tileHeight = int(mapRoot.attrib['tileheight'])
        
        # Find all <property> elements within <properties> of the root
        mapProperties = mapRoot.findall('properties/property')
        
        # For every property, store it
        for property in mapProperties:
            self.properties[property.attrib['name']] = property.attrib['value']
            
        # Find all the events, which are called objects in the XML
        mapEvents = mapRoot.findall('objectgroup/object')
        
        for event in mapEvents:
            beginX = int(math.floor(int(event.attrib['x']) / self.tileWidth))
            beginY = int(math.floor(int(event.attrib['y']) / self.tileHeight))
            endX = beginX + int(math.floor(int(event.attrib['width']) / self.tileWidth))
            endY = beginY + int(math.floor(int(event.attrib['height']) / self.tileHeight))
            
            eventProperties = {}
            
            if 'name' in event.attrib:
                eventName = event.attrib['name']
            else:
                eventName = 'unknown'
            
            try:
                eventAction = event.attrib['type']
                
                eventProperties['name'] = eventName
                eventProperties['action'] = eventAction
                
                for props in event.findall('properties/property'):
                    eventProperties[props.attrib['name']] = props.attrib['value']
            except KeyError:
                print "KeyError!"
                continue
            
            print "Storing events in tiles"
            
            countY = beginY
            while countY < endY:
                countX = beginX
                while countX < endX:
                    currentTile = ((countY + 1) * self.width) + countX + 1
                    
                    if currentTile not in self.events:
                        self.events[currentTile] = []
                    
                    # Store the event in the array of this tile
                    self.events[currentTile].append(eventProperties)
                    
                    countX += 1
                countY += 1

        # Find all the layers
        mapLayers = mapRoot.findall('layer')
        
        # Loop through every layer
        for layer in mapLayers:
            properties = {}     # We'll store all the layer properties in here
            layerData = []      # Bitwise decoded decodeData will be stored here
            i = 0               # Iterator counter used for bitwise decoding
            
            # Decode the text of the first <data> element and create an array out of it
            decodeData = [ord(c) for c in layer.find('data').text.decode('base64')]
            
            while i < len(decodeData):
                tempTile = decodeData[i] | decodeData[i + 1] << 8 | decodeData[i + 2] << 16 | decodeData[i + 3] << 24
                
                layerData.append(tempTile)      # Append it to the layerData array
                i += 4                          # Increase the iterator by four
                
            tempProps = layer.find('properties')
            
            if tempProps != None:
            
                tempProps = tempProps.findall('property')    
            
                for property in tempProps:
                    # Best to use the .get() than the .attrib[] one
                    properties[property.get('name')] = property.get('value')
                
                self.layers[layer.get('name')] = {
                    'data': layerData,
                    'name': layer.get('name'),
                    'width': layer.get('width'),
                    'height': layer.get('height'),
                    'opacity': layer.get('opacity'),
                    'properties': properties
                }
        
        # Find all the tilesets
        mapTilesets = mapRoot.findall('tileset')
        
        for tileset in mapTilesets:
            tileSetName = tileset.get('name')
            firstGid = int(tileset.get('firstgid'))
            tileWidth = int(tileset.get('tilewidth'))
            tileHeight = int(tileset.get('tileheight'))
            tileSource = tileset.find('image').get('source')
            
            verbose("Opening image for tileSetName '" + tileSetName + "'", 3, 4)

            # Open the image, calculate its width and such
            im = Image.open(self.dir + tileSource)
            
            tilesPerRow = math.floor(im.size[0] / tileWidth)
            tilesPerCol = math.floor(im.size[1] / tileHeight)
            totalTiles = int(tilesPerCol * tilesPerRow)
            
            self.tilesets[tileSetName] = {
                'name': tileSetName,
                'source': tileSource,
                'tileWidth': tileWidth,
                'tileHeight': tileHeight,
                'firstgid': firstGid,
                'total': totalTiles,
                'tpr': tilesPerRow,
                'tpc': tilesPerCol
            }
            
            verbose("Start looking for tileProperties", 3, 4)

            # Add the new tileSet to the tileProperties list
            self.tileProperties[tileSetName] = {}
            
            # Loop through every tile
            for tile in tileset.findall('tile'):
                
                # Create a temporary list for properties
                tempProperties = {}
                
                # calculate the ID of this tile
                tileGid = firstGid + int(tile.get('id'))
                
                for position, prop in enumerate(tile.findall('properties/property')):
                    
                    propertyName = prop.get('name')
                    propertyValue = prop.get('value')
                    
                    # We define nextframes in tiled according to their order in 
                    # THAT tileset. We don't use tilegids there because these 
                    # can change as new tilesets are added or removed.
                    if propertyName == 'nextframe':
                        tempProperties[propertyName] = int(propertyValue) + (firstGid - 1)
                    else:
                        tempProperties[propertyName] = propertyValue
            
                # Store all the properties of this tile in the tileProperties array
                self.tileProperties[tileSetName][tileGid] = tempProperties
        
        # Get all the walkable tiles
        # Calculate the total ammount of tiles
        totalTileAmmount = self.width * self.height
        
        # Loop through the layers
        for layer in self.layers:
            # Loop through every tile in this layer
            for position, tile in enumerate(self.layers[layer]['data']):
                
                # If the tilenumber is actually in the tileProperties
                if tile in self.tileProperties[self.getTileSetName(tile)]:
                    
                    # Store every property in the mapProperties list
                    # Make sure the position is defined in the list first
                    if position not in self.mapProperties:
                        self.mapProperties[position] = {}
                    
                    for property in self.tileProperties[self.getTileSetName(tile)][tile]:
                        
                        self.mapProperties[position][property] = self.tileProperties[self.getTileSetName(tile)][tile][property]
                    
                    # These 2 are deprecated!
                    # check if it has the "impenetrable" property
                    if 'impenetrable' in self.tileProperties[self.getTileSetName(tile)][tile]:
                        self.walkableTiles[position] = 0;
                    
                    if 'terrainSpeed' in self.tileProperties[self.getTileSetName(tile)][tile]:
                        if position not in self.eventTiles:
                            self.eventTiles[position] = {}
                        
                        self.eventTiles[position]['terrainSpeed'] = self.tileProperties[self.getTileSetName(tile)][tile]['terrainSpeed']
예제 #7
0
파일: kiser.py 프로젝트: skerit/kiflea
def decode_hybi(buf, base64=False):
    """ Decode HyBi style WebSocket packets.
        Returns:
        {'fin' : 0_or_1,
        'opcode' : number,
        'mask' : 32_bit_number,
        'hlen' : header_bytes_number,
        'length' : payload_bytes_number,
        'payload' : decoded_buffer,
        'left' : bytes_left_number,
        'close_code' : number,
        'close_reason' : string}
        """

    f = {'fin' : 0,
         'opcode' : 0,
         'mask' : 0,
         'hlen' : 2,
         'length' : 0,
         'payload' : None,
         'left' : 0,
         'close_code' : None,
         'close_reason' : None}

    blen = len(buf)
    f['left'] = blen

    if blen < f['hlen']:
        return f # Incomplete frame header

    b1, b2 = struct.unpack_from(">BB", buf)
    f['opcode'] = b1 & 0x0f
    f['fin'] = (b1 & 0x80) >> 7
    has_mask = (b2 & 0x80) >> 7

    f['length'] = b2 & 0x7f

    if f['length'] == 126:
        f['hlen'] = 4
        if blen < f['hlen']:
            return f # Incomplete frame header
        (f['length'],) = struct.unpack_from('>xxH', buf)
    elif f['length'] == 127:
        f['hlen'] = 10
        if blen < f['hlen']:
            return f # Incomplete frame header
        (f['length'],) = struct.unpack_from('>xxQ', buf)

    full_len = f['hlen'] + has_mask * 4 + f['length']

    if blen < full_len: # Incomplete frame
        return f # Incomplete frame header

    # Number of bytes that are part of the next frame(s)
    f['left'] = blen - full_len

    # Process 1 frame
    if has_mask:
        # unmask payload
        f['mask'] = buf[f['hlen']:f['hlen']+4]
        b = c = s2b('')
        if f['length'] >= 4:
            mask = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'),
                    offset=f['hlen'], count=1)
            data = numpy.frombuffer(buf, dtype=numpy.dtype('<u4'),
                    offset=f['hlen'] + 4, count=int(f['length'] / 4))
            #b = numpy.bitwise_xor(data, mask).data
            b = numpy.bitwise_xor(data, mask).tostring()

        if f['length'] % 4:
            #print("Partial unmask")
            mask = numpy.frombuffer(buf, dtype=numpy.dtype('B'),
                    offset=f['hlen'], count=(f['length'] % 4))
            data = numpy.frombuffer(buf, dtype=numpy.dtype('B'),
                    offset=full_len - (f['length'] % 4),
                    count=(f['length'] % 4))
            c = numpy.bitwise_xor(data, mask).tostring()
        f['payload'] = b + c
    else:
        verbose("Unmasked frame: %s" % repr(buf), 0, 2)
        #f['payload'] = buf[(f['hlen'] + has_mask * 4):full_len]
        print buf[1:len(buf)-1]
        f['payload'] = buf[1:len(buf)-1]

    if base64 and f['opcode'] in [1, 2]:
        try:
            f['payload'] = b64decode(f['payload'])
        except:
            print("Exception while b64decoding buffer: %s" %
                    repr(buf))
            raise

    if f['opcode'] == 0x08:
        if f['length'] >= 2:
            f['close_code'] = struct.unpack_from(">H", f['payload'])
        if f['length'] > 3:
            f['close_reason'] = f['payload'][2:]

    return f
예제 #8
0
파일: kiser.py 프로젝트: skerit/kiflea
 def __init__(self, serverQueue):
     threading.Thread.__init__(self)
     self.serverQueue = serverQueue
     self.running = True
     global globUser
     verbose('EventHandler has started', 0, 1)
예제 #9
0
파일: kiser.py 프로젝트: skerit/kiflea
 def run(self):
     queue = self.queue
     error = 0           # Error counter for this thread
     
     while self.running:
         
         # Receive data
         data = self.wget(self.client.recv(self.size))
         
         # If data equals false after running through wget,
         # close the client and skip the rest of the code (by continuing)
         if data == False:
             self.closeClient()
             continue
         
         try:
             # Try to parse the JSON data
             data = json.loads(data)
         except ValueError:
             verbose('This is not a JSON object: "' + data + '" -- end data;', 0, 2)
             error += 1
             data = None
             if error > 50:
                 verbose("This thread is being shut down: 50 errors", 0, 2)
                 running = 0
         
         # Only continue if there actually is data
         if data:
             # Initiate the user if it hasn't happened yet
             if self.initiated == False:
                 if data['action'] == 'logon':
                     verbose('Initializing user: '******'username'], 0, 3)
                     self.loginUser(data)
             else:
                 # Here we decide what to do with the information received
                 try:
                     
                     for case in switch(data['action']):
                         
                         # Timesync: sync the time between client and server
                         if case('timesync'):
                             t = datetime.datetime.now()
                             self.queue.put({'action': 'timesync', 'time': int(time.time()*1000)})
                             del t
                             break
                         
                         # Quit: start closing the connection
                         if case('quit'):
                             verbose("User " + self.uid + " is quitting", 0, 2)
                             self.closeClient()
                             break
                         
                         # Move: The player has moved
                         # {"action":"move","added":1316437492646,"x":34,"y":17,"moveRequested":1316437492646} <-- old
                         # {"action":"move","timeRequested":1316437492646,"x":34,"y":17, "targetid": "U1"} <-- new
                         if case('move'):
                             
                             # Target ID should not be used, could be spoofed.
                             data['uid'] = self.uid
                             
                             isWalkable = globMaps[globUser[self.uid]['map']].isTileWalkable(int(data['x']), int(data['y']))
                             
                             if isWalkable == True:
                                 del globUser[self.uid]['path'][0]
                                 globUser[self.uid]['path'].append(data)
                                 globUser[self.uid]['position']['x'] = int(data['x'])
                                 globUser[self.uid]['position']['y'] = int(data['y'])
                             
                             data['walkable'] = isWalkable
                             data['terrainSpeed'] = globMaps[globUser[self.uid]['map']].getTerrainSpeed(int(data['x']), int(data['y']))
                             
                             # Send the data to everyone
                             self.updateWorld(data)
                             
                             # Update the globuser var if it's walkable
                             if isWalkable:
                                 globUser[self.uid]['x'] = int(data['x'])
                                 globUser[self.uid]['y'] = int(data['y'])
                             
                             break
                         
                         # Iniuser: The client does not know a specific user, send him the required data
                         if case('iniuser'):
                             data = globUser[data['who']]
                             data['action'] = 'initiation'
                             self.queue.put(data)
                             break
                         
                         # Unknown command received
                         if case():
                             verbose("Unknown command received from " + self.uid, 0, 2)
                             # No need to break here, it'll stop anyway
     
                 except KeyError:
                     # Key is not present
                     verbose("No action key found, ignoring", 0, 3)
                     pass
예제 #10
0
파일: kiser.py 프로젝트: skerit/kiflea
    def start_server(self):
        """
        Daemonize if requested. Listen for for connections. Run
        do_handshake() method for each connection. If the connection
        is a WebSockets client then call new_client() method (which must
        be overridden) for each new client connection.
        """
        
        # Start loading all the maps
        self.loadMaps(loadMaps)
        
        # Create an event handler
        e = EventHandler(serverQueue)
        
        # Start it
        e.start()
        
        # And thread it
        self.threads.append(e)
        
        lsock = self.socket(self.host, self.port)

        while True:
            try:
                try:
                    self.client = None
                    startsock = None
                    pid = err = 0

                    try:
                        # Wait for connection
                        ready = select.select([lsock], [], [], 1)[0]
                        
                        # Did we receive anything?
                        if lsock in ready:
                            # Yes, store the data here
                            startsock, address = lsock.accept()
                        else:
                            # No, continue to the next itteration
                            continue
                            
                    except Exception:
                        _, exc, _ = sys.exc_info()
                        if hasattr(exc, 'errno'):
                            err = exc.errno
                        elif hasattr(exc, 'args'):
                            err = exc.args[0]
                        else:
                            err = exc[0]
                        if err == errno.EINTR:
                            self.vmsg("Ignoring interrupted syscall")
                            continue
                        else:
                            raise
                    
                    verbose("Incoming connection: " + str(address), 0, 3)
                    
                    # Thread it!
                    rwQ.acquireRead()
                    try:
                        rwQ.acquireWrite()
                        try:
                            # Add a new queue to the array for the new thread
                            globQueue.append(Queue.Queue())
                        finally:
                            rwQ.release()
                    finally:
                        rwQ.release()
                    
                    # Get the index of this new queue in the array
                    globQueueIndex = len(globQueue) - 1
                    
                    # Create a new client
                    c = Client(startsock, address, globQueue[globQueueIndex], globQueueIndex, serverQueue)
                    
                    verbose("New thread started. Queueindex: " + str(globQueueIndex), 2, 3)
                    
                    # Start it
                    c.start()
                    
                    # And thread it
                    self.threads.append(c)

                except KeyboardInterrupt:
                    _, exc, _ = sys.exc_info()
                    print("In KeyboardInterrupt")
                    pass
                except SystemExit:
                    _, exc, _ = sys.exc_info()
                    print("In SystemExit")
                    break
                except Exception:
                    _, exc, _ = sys.exc_info()
                    self.msg("handler exception: %s" % str(exc))
                    verbose(traceback.format_exc(), 0, 1)
                        
            except Exception:
                _, exc, _ = sys.exc_info()
                self.msg("handler exception: %s" % str(exc))
                verbose(traceback.format_exc(), 0, 1)
        
        verbose("\r\nServer is shutting down", 0, 1)
        
        # Loop through all the threads and close (join) them
        for c in self.threads:
            verbose("Closing thread", 2, 2)
            c.join()
예제 #11
0
파일: kiser.py 프로젝트: skerit/kiflea
 def vmsg(self, msg):
     """ Same as msg() but only if verbose. """
     verbose(msg, 0, 1)
예제 #12
0
파일: kiser.py 프로젝트: skerit/kiflea
 def msg(self, msg):
     """ Output message with handler_id prefix. """
     verbose(msg, 0, 1)