コード例 #1
0
    def connect(self, host, port, stream_id):
        if self.state != self.READY:
            raise RuntimeError("PRUDP socket may only be used once")

        logger.info("Connecting to %s:%i:%i", host, port, stream_id)
        self.state = self.CONNECTING

        self.remote_port = stream_id

        self.local_port = 0xF
        if self.transport_type == self.settings.TRANSPORT_WEBSOCKET:
            self.local_port = 0x1F

        if not self.sock.connect(host, port):
            logger.error("Socket connection failed")
            self.state = self.DISCONNECTED
            return False

        self.timeout_event = scheduler.add_timeout(self.handle_silence_timeout,
                                                   self.silence_timeout)
        self.socket_event = scheduler.add_socket(self.handle_recv, self.sock)

        syn_packet = PRUDPPacket(TYPE_SYN, FLAG_NEED_ACK)
        syn_packet.signature = bytes(self.packet_encoder.signature_size())
        self.send_packet(syn_packet)
        if not self.wait_ack(syn_packet):
            logger.error("SYN handshake failed")
            return False

        self.local_session_id = random.randint(0, 0xFF)
        if self.transport_type == self.settings.TRANSPORT_UDP:
            self.source_signature = secrets.token_bytes(
                self.packet_encoder.signature_size())
        else:
            self.source_signature = hmac.HMAC(
                self.signature_key,
                self.signature_key + self.target_signature).digest()

        connect_packet = PRUDPPacket(TYPE_CONNECT,
                                     FLAG_RELIABLE | FLAG_NEED_ACK)
        connect_packet.signature = self.source_signature
        connect_packet.payload = self.build_connection_request()

        self.send_packet(connect_packet)
        if not self.wait_ack(connect_packet):
            logger.error("CONNECT handshake failed")
            return False

        self.packet_id_in += 1

        self.ping_event = scheduler.add_timeout(self.handle_ping,
                                                self.ping_timeout, True)

        logger.info("PRUDP connection OK")
        self.state = self.CONNECTED
        return True
コード例 #2
0
	def send(self, station, message, delay=1, limit=0):
		ack_id = next(self.ack_id) & 0xFFFFFFFF
		message.payload += struct.pack(">I", ack_id)
		
		handle = ResendMessage(station, message, ack_id, limit)
		self.messages[ack_id] = handle
		self.transport.send(station, message)
		handle.timeout = scheduler.add_timeout(self.handle_timeout, delay, True, handle)
		
		self.wait_ack(message)
コード例 #3
0
	def send_packet(self, packet):
		packet.packet_id = next(self.packet_id_out)

		logger.debug("(%i) Sending packet: %s", self.session_id, packet)
		
		if packet.flags & FLAG_NEED_ACK:
			event = scheduler.add_timeout(self.handle_ack_timeout, self.resend_timeout, param=(packet, 0))
			self.ack_events[packet.packet_id] = event
		
		self.send_packet_raw(packet)
コード例 #4
0
	def handle_ack_timeout(self, param):
		packet, counter = param
		if counter < 3:
			logger.debug("(%i) Resending packet: %s", self.session_id, packet)
			self.send_packet_raw(packet)
			
			event = scheduler.add_timeout(self.handle_ack_timeout, self.resend_timeout, param=(packet, counter+1))
			self.ack_events[packet.packet_id] = event
		else:
			logger.error("Packet timed out")
			self.state = self.DISCONNECTED
			del self.ack_events[packet.packet_id]
			self.remove_events()
コード例 #5
0
    def send(self, station, message, interval=.5, limit=10):
        self.ack_id = (self.ack_id + 1) & 0xFFFFFFFF
        if self.ack_id == 0:
            self.ack_id += 1

        message.payload += struct.pack(">I", self.ack_id)

        resend = ResendingMessage(station, message, self.ack_id, limit)
        resend.event = scheduler.add_timeout(self.handle_timeout, interval,
                                             True, resend)

        self.packets[self.ack_id] = resend

        self.transport.send(station, message)
コード例 #6
0
    def accept(self, stream_id):
        if self.state != self.READY:
            raise RuntimeError("PRUDP socket may only be used once")

        self.state = self.ACCEPTING

        self.local_port = stream_id

        self.timeout_event = scheduler.add_timeout(self.handle_silence_timeout,
                                                   self.silence_timeout)
        self.socket_event = scheduler.add_socket(self.handle_recv, self.sock)

        next(self.packet_id_out)

        while self.state == self.ACCEPTING:
            scheduler.update()
        return self.state == self.CONNECTED
コード例 #7
0
	def handle_timeout(self, param):
		packet, counter = param
		
		key = (packet.type, packet.stream_id, packet.packet_id)
		
		if counter < self.resend_limit:
			logger.debug("Resending packet: %s" %packet)
			self.sock.send(self.packet_encoder.encode(packet))
			
			event = scheduler.add_timeout(self.handle_timeout, self.resend_timeout, param=(packet, counter+1))
			block = self.ack_events[key][1]
			
			self.ack_events[key] = (event, block)
		
		else:
			logger.error("Packet timed out: %s" %packet)
			del self.ack_events[key]
			self.failure()
コード例 #8
0
    def connect(self, info):
        target_ip = info.public_station.address.address.host
        my_ip = self.backend.public_station["address"]

        target = info.public_station
        if target_ip == my_ip:
            target = info.local_station

        rvcid = target.rvcid
        if rvcid == self.session.rvcid:
            self.results[rvcid] = self.RESULT_OK
        else:
            self.results[rvcid] = self.RESULT_NONE

            self.timeouts[rvcid] = scheduler.add_timeout(
                self.handle_timeout, 8, False, rvcid)

            self.pending_nat.append(rvcid)
            self.nat_mgr.start_nat_traversal(target.to_station_url())
コード例 #9
0
	def send(self, packet, block=False):
		if not packet.flags & FLAG_ACK:
			packet.packet_id = self.sequence_mgr.assign(packet)
			packet.payload = self.message_encoder.encode(packet)
		
		logger.debug("Sending packet: %s", packet)
		self.sock.send(self.packet_encoder.encode(packet))
		
		if packet.flags & FLAG_RELIABLE or packet.type == TYPE_SYN:
			if packet.flags & FLAG_NEED_ACK:
				key = (packet.type, packet.stream_id, packet.packet_id)
				event = scheduler.add_timeout(self.handle_timeout, self.resend_timeout, param=(packet, 0))
				self.ack_events[key] = (event, block)
				
				if block:
					while key in self.ack_events:
						scheduler.update()
						
					if key in self.ack_packets:
						return self.ack_packets.pop(key)
コード例 #10
0
    def send(self, data, delay=0.5):
        limit = (self.transport.size_limit() & ~7) - 0x18
        fragments = (len(data) - 1) // limit

        for i in range(fragments):
            flags = 1
            if i == fragments - 1:  #Last fragment
                flags |= 2
            chunk = data[i * limit:(i + 1) * limit]

            payload = struct.pack(">HHIIIQ", flags, len(chunk), 0,
                                  self.packet_id_out, self.packet_id_in,
                                  self.early_packets) + chunk

            message = ReliableMessage(payload, self.packet_id_out, delay)
            message.timeout = scheduler.add_timeout(self.handle_timeout, delay,
                                                    True, message)
            self.messages[self.packet_id_out] = message

            self.send_raw(payload)

            self.packet_id_out += 1
コード例 #11
0
 def start_ping(self):
     self.ping_event = scheduler.add_timeout(self.handle_ping,
                                             self.ping_timeout, True)
コード例 #12
0
 def handle_station_joined(self, station):
     self.keep_alive_send[station.index] = \
      scheduler.add_timeout(self.send, 1, True, station)
コード例 #13
0
ファイル: prudp.py プロジェクト: netux/DiscordAndU
    def connect(self, host, port, payload=b""):
        if self.state != self.DISCONNECTED:
            raise RuntimeError("Socket was not disconnected")

        logger.info("Connecting to %s:%i", host, port)
        self.state = self.CONNECTING

        self.encryption.set_key(self.DEFAULT_KEY)
        self.secure_key = b""

        self.server_signature = b""
        self.client_signature = b""
        self.connect_response = b""

        self.packets = []
        self.packet_queue = {}
        self.fragment_buffer = b""
        self.packet_id_out = itertools.count()
        self.packet_id_in = 1
        self.session_id = 0

        self.packet_encoder.reset()
        if self.transport_type == self.settings.TRANSPORT_UDP:
            self.s = socket.Socket(socket.TYPE_UDP)
        elif self.transport_type == self.settings.TRANSPORT_TCP:
            self.s = socket.Socket(socket.TYPE_TCP)
        else:
            self.s = websocket.WebSocket()

        if not self.s.connect(host, port):
            logger.error("Socket connection failed")
            self.state = self.DISCONNECTED
            return False

        self.ack_events = {}
        self.ping_event = None
        self.timeout_event = scheduler.add_timeout(self.handle_silence_timeout,
                                                   self.silence_timeout)
        self.socket_event = scheduler.add_socket(self.handle_recv, self.s)

        self.send_packet(self.syn_packet)
        if not self.wait_ack(self.syn_packet):
            logger.error("PRUDP connection failed")
            return False

        self.session_id = random.randint(0, 0xFF)
        if self.transport_type == self.settings.TRANSPORT_UDP:
            self.client_signature = bytes([
                random.randint(0, 0xFF)
                for i in range(self.packet_encoder.signature_size())
            ])
        else:
            self.client_signature = hmac.HMAC(
                self.signature_key,
                self.signature_key + self.server_signature).digest()
        self.connect_packet.signature = self.client_signature
        self.connect_packet.payload = payload

        self.send_packet(self.connect_packet)
        if not self.wait_ack(self.connect_packet):
            logger.error("PRUDP connection failed")
            return False

        self.ping_event = scheduler.add_timeout(self.handle_ping,
                                                self.ping_timeout, True)

        logger.info("PRUDP connection OK")
        self.state = self.CONNECTED
        return True