Exemplo n.º 1
0
	def __handle_find_by_type_req(self, op, pdu):
		if len(pdu) < 7:
			return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, startHandle, endHandle, uuid, value = \
			att_pdu.parse_find_by_type_req(pdu)

		if startHandle == 0 or startHandle > endHandle:
			return att_pdu.new_error_resp(op, startHandle,
				att.ECODE_INVALID_HANDLE)

		respCount = 0
		resp = bytearray([att.OP_FIND_BY_TYPE_RESP])
		for handle in self._handles[startHandle:endHandle+1]:
			if handle._uuid != uuid:
				continue
			if handle._read() != value:
				continue
			if len(resp) + 4 > self._socket.sendMTU:
				break
			resp += handle._get_handle_as_bytearray()
			resp += handle._owner._get_end_group_handle()._get_handle_as_bytearray()
			respCount += 1

		if respCount == 0:
			return att_pdu.new_error_resp(op, startHandle, \
				att.ECODE_ATTR_NOT_FOUND)
		else:
			return resp
Exemplo n.º 2
0
	def __handle_find_info_req(self, op, pdu):
		if len(pdu) != 5:
			return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, startHandle, endHandle = att_pdu.parse_find_info_req(pdu)

		if startHandle == 0 or startHandle > endHandle:
			return att_pdu.new_error_resp(op, startHandle,
				att.ECODE_INVALID_HANDLE)

		respCount = 0
		resp = bytearray([att.OP_FIND_INFO_RESP])
		respFmt = None
		for handle in self._handles[startHandle:endHandle+1]:
			if respFmt is None:
				respFmt = len(handle._uuid)
				resp.append(1 if respFmt == 2 else 2)
			if len(handle._uuid) != respFmt:
				break
			if len(resp) + 2 + respFmt > self._socket.sendMTU:
				break
			resp += handle._get_handle_as_bytearray()
			resp += handle._uuid.raw[::-1]
			respCount += 1

		if respCount == 0:
			return att_pdu.new_error_resp(op, startHandle, \
				att.ECODE_ATTR_NOT_FOUND)
		else:
			return resp
Exemplo n.º 3
0
	def __recv_single(self):
		"""Read and handle a single packet"""

		if self._stream:
			# Stream mode
			n = self._sock.recv(1)
			if n == "":
				raise RuntimeError("socket connection broken")
			received = 0
			n = ord(n)
			if n == 0:
				return
			pdu = bytearray()
			while received < n:
				chunk = self._sock.recv(n - received)
				if chunk == "":
					raise RuntimeError("socket connection broken")
				received += len(chunk)
				pdu += bytearray(ord(x) for x in chunk)
		else:
			# Seqpacket mode
			pdu = self._sock.recv()
			if pdu == "":
				raise RuntimeError("socket connection broken")
			pdu = bytearray(ord(x) for x in pdu)

		op = pdu[0]
		if op == att.OP_MTU_REQ:
			resp = bytearray(3)
			resp[0] = att.OP_MTU_RESP
			resp[1] = self._recv_mtu & 0xFF
			resp[2] = (self._recv_mtu >> 8) & 0xFF
			self._send(resp)

		elif (att.isRequest(op) or op == att.OP_WRITE_CMD
			or op == att.OP_SIGNED_WRITE_CMD or op == att.OP_HANDLE_CNF):

			if self._server is not None:
				resp = self._server._handle_packet(pdu)
				if resp is not None:
					self._send(resp)
			elif att.isRequest(op):
				warnings.warn("server not supported")
				resp = att_pdu.new_error_resp(op, 0, att.ECODE_REQ_NOT_SUPP)
				self._send(resp)

		elif (att.isResponse(op)
			or (op == att.OP_ERROR and len(pdu) >= 2 and att.isRequest(pdu[1]))
			or op == att.OP_HANDLE_NOTIFY or op == att.OP_HANDLE_IND):

			if self._client is not None:
				resp = self._client._handle_packet(pdu)
				if resp is not None:
					self._send(resp)

		else:
			warnings.warn("unknown opcode: " + str(op))
Exemplo n.º 4
0
	def __handle_read_by_group_req(self, op, pdu):
		if len(pdu) != 7 and len(pdu) != 21:
			return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, startHandle, endHandle, uuid = \
			att_pdu.parse_read_by_group_req(pdu)

		if startHandle == 0 or startHandle > endHandle:
			return att_pdu.new_error_resp(op, startHandle,
				att.ECODE_INVALID_HANDLE)

		respCount = 0
		resp = bytearray([att.OP_READ_BY_GROUP_RESP, 0]) # 0 is placeholder
		valLen = None
		for handle in self._handles[startHandle:endHandle+1]:
			if handle._uuid != uuid:
				continue

			valRead = handle._read()
			if valRead is None:
				return att_pdu.new_error_resp(op, startHandle,
					att.ECODE_READ_NOT_PERM)

			assert isinstance(valRead, bytearray)
			if not valLen:
				assert len(valRead) <= 0xFF - 4
				valLen = len(valRead)
				resp[1] = valLen + 4
			if valLen != len(valRead):
				break
			if len(resp) + 4 + valLen > self._socket.sendMTU:
				break
			resp += handle._get_handle_as_bytearray()
			resp += handle._owner._get_end_group_handle()._get_handle_as_bytearray()
			resp += valRead
			respCount += 1

		if respCount == 0:
			return att_pdu.new_error_resp(op, startHandle,
				att.ECODE_ATTR_NOT_FOUND)
		else:
			return resp
Exemplo n.º 5
0
	def __handle_read_req(self, op, pdu):
		if len(pdu) < 3:
			return  att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, handleNo = att_pdu.parse_read_req(pdu)

		if not self.__is_valid_handle(handleNo):
			return att_pdu.new_error_resp(op, handleNo,
				att.ECODE_INVALID_HANDLE)

		if self._handles[handleNo]._read_callback:
			try:
				value = self._handles[handleNo]._read_callback()
				resp = bytearray([att.OP_READ_RESP])
				resp += value
				return resp
			except int, ecode:
				return att_pdu.new_error_resp(op, handleNo, ecode)
			except ServerError:
				return att_pdu.new_error_resp(op, handleNo,
					att.ECODE_UNLIKELY)
Exemplo n.º 6
0
	def __handle_write_cmd_req(self, op, pdu):
		if len(pdu) < 3:
			return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, handleNo, value = att_pdu.parse_write(pdu)

		if not self.__is_valid_handle(handleNo):
			if op == att.OP_WRITE_REQ:
				return att_pdu.new_error_resp(op, handleNo,
					att.ECODE_INVALID_HANDLE)
			else:
				return None

		if self._handles[handleNo]._write_callback:
			try:
				self._handles[handleNo]._write_callback(value)
				return bytearray([att.OP_WRITE_RESP])
			except int, ecode:
				return att_pdu.new_error_resp(op, handleNo, ecode)
			except ServerError:
				return att_pdu.new_error_resp(op, handleNo,
					att.ECODE_UNLIKELY)
Exemplo n.º 7
0
	def _handle_packet(self, pdu):
		op = pdu[0]
		if op == att.OP_FIND_INFO_REQ:
			return self.__handle_find_info_req(op, pdu)
		elif op == att.OP_FIND_BY_TYPE_REQ:
			return self.__handle_find_by_type_req(op, pdu)
		elif op == att.OP_READ_BY_TYPE_REQ:
			return self.__handle_read_by_type_req(op, pdu)
		elif op == att.OP_READ_BY_GROUP_REQ:
			return self.__handle_read_by_group_req(op, pdu)
		elif op == att.OP_READ_REQ:
			return self.__handle_read_req(op, pdu)
		elif op == att.OP_WRITE_REQ or op == att.OP_WRITE_CMD:
			return self.__handle_write_cmd_req(op, pdu)
		elif op == att.OP_HANDLE_CNF:
			self.__handle_confirm(op, pdu)
			return None
		else:
			return att_pdu.new_error_resp(op, 0, att.ECODE_REQ_NOT_SUPP)
Exemplo n.º 8
0
	def _handle_packet(self, pdu):
		op = pdu[0]
		if (att.isResponse(op) or (op == att.OP_ERROR
			and self._currentRequest and self._currentResponse is None
			and pdu[1] == self._currentRequest[0])):

			self._currentResponse = pdu
			self._responseEvent.set()
			return None

		if op == att.OP_HANDLE_NOTIFY or op == att.OP_HANDLE_IND:
			if len(pdu) < 3:
				return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

			_, handleNo, value = att_pdu.parse_notify_indicate(pdu)

			if handleNo not in self._valHandles:
				if op == att.OP_HANDLE_NOTIFY:
					warnings.warn("notification on unknown handle")
				else:
					warnings.warn("indication on unknown handle")
				return None

			charac = self._valHandles[handleNo]
			if charac._subscribeCallback is not None:
				try:
					charac._subscribeCallback(value)
				except ClientError, err:
					warnings.warn(err)
			else:
				warnings.warn("unsolicited notification or indication")

			if op == att.OP_HANDLE_IND:
				return bytearray([att.OP_HANDLE_CNF])
			else:
				return None
Exemplo n.º 9
0
			return att_pdu.new_error_resp(op, handleNo,
				att.ECODE_INVALID_HANDLE)

		if self._handles[handleNo]._read_callback:
			try:
				value = self._handles[handleNo]._read_callback()
				resp = bytearray([att.OP_READ_RESP])
				resp += value
				return resp
			except int, ecode:
				return att_pdu.new_error_resp(op, handleNo, ecode)
			except ServerError:
				return att_pdu.new_error_resp(op, handleNo,
					att.ECODE_UNLIKELY)
		else:
			return att_pdu.new_error_resp(op, 0,
				att.ECODE_READ_NOT_PERM)

	def __handle_write_cmd_req(self, op, pdu):
		if len(pdu) < 3:
			return att_pdu.new_error_resp(op, 0, att.ECODE_INVALID_PDU)

		_, handleNo, value = att_pdu.parse_write(pdu)

		if not self.__is_valid_handle(handleNo):
			if op == att.OP_WRITE_REQ:
				return att_pdu.new_error_resp(op, handleNo,
					att.ECODE_INVALID_HANDLE)
			else:
				return None

		if self._handles[handleNo]._write_callback: