def main(): global client host, port, path = parse_uri("coap://[::1]:5683/lights") try: tmp = socket.gethostbyname(host) host = tmp print "Host:", tmp except socket.gaierror: print("Exception") pass msg = Message() # msg.source = (host, port) # msg.destination = ('192.168.103.137', 5683) # msg.type = defines.Types['CON'] msg.payload = '{"message": "Hello"}' # msg.code = 2 # print msg.pretty_print() try: client = HelperClient(server=(host, port)) response = client.get(path) print response.pretty_print() response = client.post(path, msg.payload, timeout=10) print response.pretty_print() response = client.delete(path) print response.pretty_print() client.close() # client = CoAPclient(host, port, msg) except Exception as e: print "Exception: ", str(e) client.close()
def receive_datagram(self): """ Receive datagram from the UDP socket and invoke the callback function. """ logger.debug("Start receiver Thread") while not self.stopped.isSet(): self._socket.settimeout(0.1) try: datagram, addr = self._socket.recvfrom(1500) except socket.timeout: # pragma: no cover continue except Exception as e: # pragma: no cover if self._cb_ignore_read_exception is not None and isinstance(self._cb_ignore_read_exception, collections.Callable): if self._cb_ignore_read_exception(e, self): continue return else: # pragma: no cover if len(datagram) == 0: logger.debug("Exiting receiver Thread due to orderly shutdown on server end") return serializer = Serializer() try: host, port = addr except ValueError: host, port, tmp1, tmp2 = addr source = (host, port) message = serializer.deserialize(datagram, source) if isinstance(message, Response): logger.debug("receive_datagram - " + str(message)) transaction, send_ack = self._messageLayer.receive_response(message) if transaction is None: # pragma: no cover continue self._wait_for_retransmit_thread(transaction) if send_ack: self._send_ack(transaction) self._blockLayer.receive_response(transaction) if transaction.block_transfer: self._send_block_request(transaction) continue elif transaction is None: # pragma: no cover self._send_rst(transaction) return self._observeLayer.receive_response(transaction) if transaction.notification: # pragma: no cover ack = Message() ack.type = defines.Types['ACK'] ack = self._messageLayer.send_empty(transaction, transaction.response, ack) self.send_datagram(ack) self._callback(transaction.response) else: self._callback(transaction.response) elif isinstance(message, Message): self._messageLayer.receive_empty(message) logger.debug("Exiting receiver Thread due to request")
def _test_with_client_observe(self, message_list, callback): client = HelperClient(self.server_address) token = None last_mid = 0 for message, expected in message_list: if message is not None: token = message.token client.send_request(message, callback) received_message = self.queue.get() if expected is not None: last_mid = expected.mid if expected.type is not None: self.assertEqual(received_message.type, expected.type) if expected.mid is not None: self.assertEqual(received_message.mid, expected.mid) self.assertEqual(received_message.code, expected.code) if expected.source is not None: self.assertEqual(received_message.source, self.server_address) if expected.token is not None: self.assertEqual(received_message.token, expected.token) if expected.payload is not None: self.assertEqual(received_message.payload, expected.payload) if expected.options is not None: self.assertEqual(received_message.options, expected.options) message = Message() message.type = defines.Types["RST"] message.token = token message._mid = last_mid message.destination = self.server_address client.send_empty(message) client.stop()
def receive_datagram(self): """ Receive datagram from the UDP socket and invoke the callback function. """ logger.debug("Start receiver Thread") while not self.stopped.isSet(): self._socket.settimeout(0.1) try: datagram, addr = self._socket.recvfrom(1152) except socket.timeout: # pragma: no cover continue except Exception as e: # pragma: no cover if self._cb_ignore_read_exception is not None and callable(self._cb_ignore_read_exception): if self._cb_ignore_read_exception(e, self): continue return else: # pragma: no cover if len(datagram) == 0: logger.debug("Exiting receiver Thread due to orderly shutdown on server end") return serializer = Serializer() try: host, port = addr except ValueError: host, port, tmp1, tmp2 = addr source = (host, port) message = serializer.deserialize(datagram, source) if isinstance(message, Response): logger.debug("receive_datagram - " + str(message)) transaction, send_ack = self._messageLayer.receive_response(message) if transaction is None: # pragma: no cover continue self._wait_for_retransmit_thread(transaction) if send_ack: self._send_ack(transaction) self._blockLayer.receive_response(transaction) if transaction.block_transfer: self._send_block_request(transaction) continue elif transaction is None: # pragma: no cover self._send_rst(transaction) return self._observeLayer.receive_response(transaction) if transaction.notification: # pragma: no cover ack = Message() ack.type = defines.Types['ACK'] ack = self._messageLayer.send_empty(transaction, transaction.response, ack) self.send_datagram(ack) self._callback(transaction.response) else: self._callback(transaction.response) elif isinstance(message, Message): self._messageLayer.receive_empty(message) logger.debug("Exiting receiver Thread due to request")
def listen(self, timeout=10): """ Listen for incoming messages. Timeout is used to check if the server must be switched off. :param timeout: Socket Timeout in seconds """ self._socket.settimeout(float(timeout)) while not self.stopped.isSet(): try: data, client_address = self._socket.recvfrom(4096) if len(client_address) > 2: client_address = (client_address[0], client_address[1]) except socket.timeout: continue try: serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message rst.mid = self._messageLayer._current_mid self._messageLayer._current_mid += 1 % 65535 self.send_datagram(rst) continue logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug("message duplicated, transaction completed") if transaction.response is not None: self.send_datagram(transaction.response) return elif transaction.request.duplicated and not transaction.completed: logger.debug("message duplicated, transaction NOT completed") self._send_ack(transaction) return args = (transaction, ) t = threading.Thread(target=self.receive_request, args=args) t.start() # self.receive_datagram(data, client_address) elif isinstance(message, Response): logger.error("Received response from %s", message.source) else: # is Message transaction = self._messageLayer.receive_empty(message) if transaction is not None: with transaction: self._blockLayer.receive_empty(message, transaction) self._observeLayer.receive_empty(message, transaction) except RuntimeError: print "Exception with Executor" self._socket.close()
def receive_datagram(self): """ Receive datagram from the UDP socket and invoke the callback function. """ logger.debug("Start receiver Thread") while not self.stopped.isSet(): self._socket.settimeout(1) try: datagram, addr = self._socket.recvfrom(1152) except socket.timeout: # pragma: no cover continue except socket.error: # pragma: no cover return else: # pragma: no cover if len(datagram) == 0: logger.debug("orderly shutdown on server end") return serializer = Serializer() try: host, port = addr except ValueError: host, port, tmp1, tmp2 = addr source = (host, port) message = serializer.deserialize(datagram, source) if isinstance(message, Response): transaction, send_ack = self._messageLayer.receive_response( message) if transaction is None: # pragma: no cover continue if send_ack: self._send_ack(transaction) self._blockLayer.receive_response(transaction) if transaction.block_transfer: transaction = self._messageLayer.send_request( transaction.request) self.send_datagram(transaction.request) continue elif transaction is None: # pragma: no cover self._send_rst(transaction) return self._observeLayer.receive_response(transaction) if transaction.notification: # pragma: no cover ack = Message() ack.type = defines.Types['ACK'] ack = self._messageLayer.send_empty( transaction, transaction.response, ack) self.send_datagram(ack) self._callback(transaction.response) else: self._callback(transaction.response) elif isinstance(message, Message): self._messageLayer.receive_empty(message)
def end_observation(self, token): """ Remove an observation token from our records. :param token: the token for the observation """ dummy = Message() dummy.token = token dummy.destination = self._server self._observeLayer.remove_subscriber(dummy)
def receive_datagram(self, args): """ Handle messages coming from the udp socket. :param args: (data, client_address) """ data, client_address = args logging.debug("receiving datagram") try: host, port = client_address except ValueError: host, port, tmp1, tmp2 = client_address client_address = (host, port) serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = Types["RST"] rst.code = message rst.mid = message.mid self.send_datagram(rst) return logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): if not message.proxy_uri or message.uri_path != "coap2http": logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = Types["RST"] rst.code = Codes.BAD_REQUEST.number rst.mid = message.mid self.send_datagram(rst) return # Execute HTTP/HTTPS request http_response = CoAP_HTTP.execute_http_request(message.code, message.proxy_uri, message.payload) # HTTP response to CoAP response conversion coap_response = CoAP_HTTP.to_coap_response(http_response, message.code, client_address, message.mid) # Send datagram and return self.send_datagram(coap_response) return elif isinstance(message, Message): logger.error("Received message from %s", message.source) else: # is Response logger.error("Received response from %s", message.source)
def receive_datagram(self): """ Receive datagram from the UDP socket and invoke the callback function. """ logger.debug("Start receiver Thread") while not self.stopped.isSet(): try: xbee_message = self.xbee.read_data(timeout=0.1) except TimeoutException: continue except Exception as e: if self._cb_ignore_read_exception is not None and isinstance( self._cb_ignore_read_exception, collections.Callable): if self._cb_ignore_read_exception(e, self): continue return serializer = Serializer() message = serializer.deserialize(bytes(xbee_message.data), self._server) if isinstance(message, Response): logger.debug("receive_datagram - " + str(message)) transaction, send_ack = self._messageLayer.receive_response( message) if transaction is None: # pragma: no cover continue self._wait_for_retransmit_thread(transaction) if send_ack: self._send_ack(transaction) self._blockLayer.receive_response(transaction) if transaction.block_transfer: self._send_block_request(transaction) continue elif transaction is None: # pragma: no cover self._send_rst(transaction) return self._observeLayer.receive_response(transaction) if transaction.notification: # pragma: no cover ack = Message() ack.type = defines.Types['ACK'] ack = self._messageLayer.send_empty( transaction, transaction.response, ack) self.send_datagram(ack) self._callback(transaction.response) else: self._callback(transaction.response) elif isinstance(message, Message): self._messageLayer.receive_empty(message) logger.debug("Exiting receiver Thread due to request")
def _send_rst(self, transaction): # pragma: no cover """ Sends an RST message for the response. :param transaction: transaction that holds the response """ rst = Message() rst.type = defines.Types['RST'] if not transaction.response.acknowledged: rst = self._messageLayer.send_empty(transaction, transaction.response, rst) self.send_datagram(rst)
def _send_ack(self, transaction): """ Sends an ACK message for the response. :param transaction: transaction that holds the response """ ack = Message() ack.type = defines.Types['ACK'] if not transaction.response.acknowledged: ack = self._messageLayer.send_empty(transaction, transaction.response, ack) self.send_datagram(ack)
def _send_ack(self, transaction): """ Sends an ACK message for the request. :param transaction: the transaction that owns the request """ ack = Message() ack.type = defines.Types['ACK'] # TODO handle mutex on transaction if not transaction.request.acknowledged and transaction.request.type == defines.Types["CON"]: ack = self._messageLayer.send_empty(transaction, transaction.request, ack) self.send_datagram(ack)
def receive_datagram(self): logger.debug("Start receiver Thread") while not self.stopped.isSet(): self._socket.settimeout(1) try: datagram, addr = self._socket.recvfrom(1152) except socket.timeout: # pragma: no cover continue except socket.error: # pragma: no cover return else: # pragma: no cover if len(datagram) == 0: print 'orderly shutdown on server end' return serializer = Serializer() try: host, port = addr except ValueError: host, port, tmp1, tmp2 = addr source = (host, port) message = serializer.deserialize(datagram, source) if isinstance(message, Response): transaction, send_ack = self._messageLayer.receive_response(message) if transaction is None: # pragma: no cover continue if send_ack: self._send_ack(transaction) self._blockLayer.receive_response(transaction) if transaction.block_transfer: transaction = self._messageLayer.send_request(transaction.request) self.send_datagram(transaction.request) continue elif transaction is None: # pragma: no cover self._send_rst(transaction) return self._observeLayer.receive_response(transaction) if transaction.notification: # pragma: no cover ack = Message() ack.type = defines.Types['ACK'] ack = self._messageLayer.send_empty(transaction, transaction.response, ack) self.send_datagram(ack) self._callback(transaction.response) else: self._callback(transaction.response) elif isinstance(message, Message): self._messageLayer.receive_empty(message)
def _send_rst(self, transaction): # Handle separate """ Sends an RST message for the request. :param request: [request, sleep_time] or request """ rst = Message() rst.type = defines.Types['RST'] if not transaction.response.acknowledged: rst = self._messageLayer.send_empty(transaction, transaction.response, rst) self.send_datagram(rst)
def _send_ack(self, transaction): # Handle separate """ Sends an ACK message for the request. :param request: [request, sleep_time] or request """ ack = Message() ack.type = defines.Types['ACK'] if not transaction.request.acknowledged: ack = self._messageLayer.send_empty(transaction, transaction.request, ack) self.send_datagram(ack)
def handle_notification(self, response, client_callback): host, port = response.source key = hash(str(host) + str(port) + str(response.token)) self.relation[key] = (response, time.time(), client_callback) if response.type == defines.inv_types["CON"]: ack = Message.new_ack(response) self.send(ack)
def _send_ack(self, transaction): """ Sends an ACK message for the request. :param transaction: the transaction that owns the request """ ack = Message() ack.type = defines.Types['ACK'] with transaction: if not transaction.request.acknowledged and transaction.request.type == defines.Types[ "CON"]: ack = self._messageLayer.send_empty(transaction, transaction.request, ack) if ack.type is not None and ack.mid is not None: self.send_datagram(ack)
def cancel_observing(self, response, send_rst): host, port = response.source key = hash(str(host) + str(port) + str(response.token)) del self.relation[key] if send_rst: rst = Message.new_rst(response) self.send(rst)
def _test_modular(self, lst): serializer = Serializer() for t in lst: message, expected = t send_ack = False if message is not None: datagram = serializer.serialize(message) self.proto.datagramReceived(datagram, ("127.0.0.1", 5600)) else: send_ack = True datagram, source = self.tr.written.pop(0) host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, expected.type) if not send_ack: self.assertEqual(message.mid, expected.mid) self.assertEqual(message.code, expected.code) self.assertEqual(message.source, source) self.assertEqual(message.token, expected.token) self.assertEqual(message.payload, expected.payload) self.assertEqual(message.options, expected.options) if send_ack: message = Message.new_ack(message) datagram = serializer.serialize(message) self.proto.datagramReceived(datagram, ("127.0.0.1", 5600)) self.tr.written = []
def _test_separate(self, message, notification): serializer = Serializer() datagram = serializer.serialize(message) self.proto.datagramReceived(datagram, ("127.0.0.1", 5600)) datagram, source = self.tr.written[0] host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, defines.inv_types["ACK"]) self.assertEqual(message.code, None) self.assertEqual(message.mid, self.current_mid + 4) self.assertEqual(message.source, source) datagram, source = self.tr.written[1] host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, notification.type) self.assertEqual(message.code, notification.code) self.assertEqual(message.source, source) self.assertEqual(message.token, notification.token) self.assertEqual(message.payload, notification.payload) self.assertEqual(message.options, notification.options) self.tr.written = [] message = Message.new_ack(message) datagram = serializer.serialize(message) self.proto.datagramReceived(datagram, ("127.0.0.1", 5600)) self.tr.written = []
def _test_separate(self, message, notification): serializer = Serializer() datagram = serializer.serialize(message) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(datagram, self.server_address) datagram, source = sock.recvfrom(4096) host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, defines.inv_types["ACK"]) self.assertEqual(message.code, None) self.assertEqual(message.mid, self.current_mid - 1) self.assertEqual(message.source, source) datagram, source = sock.recvfrom(4096) host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, notification.type) self.assertEqual(message.code, notification.code) self.assertEqual(message.source, source) self.assertEqual(message.token, notification.token) self.assertEqual(message.payload, notification.payload) self.assertEqual(message.options, notification.options) message = Message.new_ack(message) datagram = serializer.serialize(message) sock.sendto(datagram, self.server_address) sock.close()
def to_coap_response(http_response, request_method, client_address, mid, token): coap_msg = Message() coap_msg.destination = client_address coap_msg.type = Types["ACK"] coap_msg.code = CoAP_HTTP.to_coap_code(http_response.status_code, request_method) coap_msg.mid = mid coap_msg.token = token if 'Content-Type' in http_response.headers: coap_msg.content_type = CoAP_HTTP.to_coap_content_type( http_response.headers['Content-Type'].split(";")[0]) else: coap_msg.content_type = 0 coap_msg.payload = http_response.content return coap_msg
def _test_modular(self, lst): serializer = Serializer() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for t in lst: message, expected = t send_ack = False if message is not None: datagram = serializer.serialize(message) sock.sendto(datagram, self.server_address) else: send_ack = True datagram, source = sock.recvfrom(4096) host, port = source message = serializer.deserialize(datagram, host, port) self.assertEqual(message.type, expected.type) if not send_ack: self.assertEqual(message.mid, expected.mid) self.assertEqual(message.code, expected.code) self.assertEqual(message.source, source) self.assertEqual(message.token, expected.token) self.assertEqual(message.payload, expected.payload) self.assertEqual(message.options, expected.options) if send_ack: message = Message.new_ack(message) datagram = serializer.serialize(message) sock.sendto(datagram, self.server_address) sock.close()
def to_coap_response(http_response, request_method, client_address, mid): coap_msg = Message() coap_msg.destination = client_address coap_msg.type = Types["ACK"] coap_msg.code = CoAP_HTTP.to_coap_code(http_response.status_code, request_method) coap_msg.mid = mid if 'Content-Type' in http_response.headers: coap_msg.content_type = CoAP_HTTP.to_coap_content_type(http_response.headers['Content-Type'].split(";")[0]) else: coap_msg.content_type = 0 coap_msg.payload = http_response.content return coap_msg
def handle_response(self, response): if response.type == defines.inv_types["CON"]: ack = Message.new_ack(response) self.send(ack) key_token = hash(str(self.server[0]) + str(self.server[1]) + str(response.token)) if key_token in self.sent_token.keys(): self.received_token[key_token] = response req, timestamp, callback, client_callback = self.sent_token[key_token] key = hash(str(self.server[0]) + str(self.server[1]) + str(req.mid)) self.received[key] = response callback(req.mid, client_callback)
def coap_encode(payload): message = Message() message.type = defines.Types['CON'] message.token = 4321 message.mid = 2 message.options = None message.payload = str(payload) serializer = Serializer() messagestring = serializer.serialize(message) return messagestring
def cancel_observing(self, response, send_rst): # pragma: no cover if send_rst: message = Message() message.destination = self.server message.code = defines.Codes.EMPTY.number message.type = defines.Types["RST"] message.token = response.token message.mid = response.mid self.protocol.send_message(message) self.stop()
def handle_request(self, request): """ Handles requests. :param request: the request :return: the response """ host, port = request.source key = hash(str(host) + str(port) + str(request.mid)) if key not in self._parent.received: if request.blockwise: # Blockwise last, request = self._parent.blockwise_transfer(request) if last: self._parent.received[key] = (request, time.time()) return request else: self._parent.received[key] = (request, time.time()) return request else: request, timestamp = self._parent.received.get(key) request.duplicated = True self._parent.received[key] = (request, timestamp) try: response, timestamp = self._parent.sent.get(key) except TypeError: response = None if isinstance(response, Response): return response elif request.acknowledged: ack = Message.new_ack(request) return ack elif request.rejected: rst = Message.new_rst(request) return rst else: # The server has not yet decided, whether to acknowledge or # reject the request. We know for sure that the server has # received the request though and can drop this duplicate here. return None
def _test_with_client_observe(self, message_list, callback): # pragma: no cover client = HelperClient(self.server_address) token = None last_mid = 0 for message, expected in message_list: if message is not None: token = message.token client.send_request(message, callback) received_message = self.queue.get() if expected is not None: last_mid = expected.mid if expected.type is not None: self.assertEqual(received_message.type, expected.type) if expected.mid is not None: self.assertEqual(received_message.mid, expected.mid) self.assertEqual(received_message.code, expected.code) if expected.source is not None: self.assertEqual(received_message.source, self.server_address) if expected.token is not None: self.assertEqual(received_message.token, expected.token) if expected.payload is not None: self.assertEqual(received_message.payload, expected.payload) if expected.options is not None: self.assertEqual(received_message.options, expected.options) message = Message() message.type = defines.Types["RST"] message.token = token message._mid = last_mid message.destination = self.server_address client.send_empty(message) client.stop()
def send_ack(self, request): # Handle separate """ Sends an ACK message for the request. :param request: [request] or request """ if isinstance(request, list): request = request[0] ack = Message.new_ack(request) host, port = request.source self._parent.send(ack, host, port) request.acknowledged = True
def datagramReceived(self, data, addr): """ Handler for received UDP datagram. :param data: the UDP datagram :param host: source host :param port: source port """ try: host, port = addr except ValueError: host, port, tmp1, tmp2 = addr log.msg("Datagram received from " + str(host) + ":" + str(port)) serializer = Serializer() message = serializer.deserialize(data, host, port) print "Message received from " + host + ":" + str(port) print "----------------------------------------" print message print "----------------------------------------" if isinstance(message, Request): log.msg("Received request") ret = self.request_layer.handle_request(message) if isinstance(ret, Request): response = self.request_layer.process(ret) else: response = ret self.schedule_retrasmission(message, response, None) log.msg("Send Response") self.send(response, host, port) elif isinstance(message, Response): log.err("Received response") rst = Message.new_rst(message) rst = self.message_layer.matcher_response(rst) log.msg("Send RST") self.send(rst, host, port) elif isinstance(message, tuple): message, error = message response = Response() response.destination = (host, port) response.code = defines.responses[error] response = self.reliability_response(message, response) response = self.message_layer.matcher_response(response) log.msg("Send Error") self.send(response, host, port) elif message is not None: # ACK or RST log.msg("Received ACK or RST") self.message_layer.handle_message(message)
def handle_response(self, response): if response.type == defines.inv_types["CON"]: ack = Message.new_ack(response) self.send(ack, self._endpoint) key_token = hash(str(self._endpoint[0]) + str(self._endpoint[1]) + str(response.token)) if key_token in self.sent_token.keys(): self.received_token[key_token] = response req = self.sent_token[key_token] key = hash(str(self._endpoint[0]) + str(self._endpoint[1]) + str(req.mid)) timer, counter = self.call_id[key] timer.cancel() self.received[key] = response self.condition.acquire() self._response = response self.condition.notify() self.condition.release()
def send_ack(self, list_request): """ Send an ack to the client. Used mostly with separate. :param list_request: the request to be acknowledge. :type list_request: [Request] or Request """ if isinstance(list_request, list): request = list_request[0] else: request = list_request del self.timer[request.mid] host, port = request.source ack = Message.new_ack(request) self.send(ack, host, port)
def send_ack(self, request): # Handle separate """ Sends an ACK message for the request. :param request: [request, sleep_time] or request """ if isinstance(request, list): if len(request) == 2: time.sleep(request[1]) request = request[0] ack = Message.new_ack(request) host, port = request.source if not request.acknowledged: self._parent.send(ack, host, port) request.acknowledged = True
def finish_request(self, args): """ Handler for received UDP datagram. :param args: (data, (client_ip, client_port) """ data, client_address = args host = client_address[0] port = client_address[1] # logging.log(logging.INFO, "Datagram received from " + str(host) + ":" + str(port)) serializer = Serializer() message = serializer.deserialize(data, host, port) # print "Message received from " + host + ":" + str(port) # print "----------------------------------------" # print message # print "----------------------------------------" if isinstance(message, Request): # log.msg("Received request") ret = self.request_layer.handle_request(message) if isinstance(ret, Request): response = self.request_layer.process(ret) else: response = ret self.schedule_retrasmission(message, response, None) # log.msg("Send Response") return response, host, port elif isinstance(message, Response): # log.err("Received response") rst = Message.new_rst(message) rst = self.message_layer.matcher_response(rst) # log.msg("Send RST") return rst, host, port elif isinstance(message, tuple): message, error = message response = Response() response.destination = (host, port) response.code = defines.responses[error] response = self.message_layer.reliability_response(message, response) response = self.message_layer.matcher_response(response) # log.msg("Send Error") return response, host, port elif message is not None: # ACK or RST # log.msg("Received ACK or RST") self.message_layer.handle_message(message) return None
def send_ack(self, list_request): """ Send an ack to the client. Used mostly with separate. :param list_request: the request to be acknowledge. :type list_request: [Request] or Request """ if isinstance(list_request, list): request = list_request[0] else: request = list_request key_timer = hash(str(request.source[0]) + str(request.source[1]) + str(request.mid)) if self.timer.get(key_timer) is not None: del self.timer[key_timer] host, port = request.source ack = Message.new_ack(request) self.send(ack, host, port)
def cancel_observing(self, response, send_rst): # pragma: no cover """ Delete observing on the remote server. :param response: the last received response :param send_rst: if explicitly send RST message :type send_rst: bool """ if send_rst: message = Message() message.destination = self.server message.code = defines.Codes.EMPTY.number message.type = defines.Types["RST"] message.token = response.token message.mid = response.mid self.protocol.send_message(message) self.stop()
def finish_request(self, request, client_address): host = client_address[0] port = client_address[1] data = request[0] self.socket = request[1] # log.msg("Datagram received from " + str(host) + ":" + str(port)) serializer = Serializer() message = serializer.deserialize(data, host, port) # print "Message received from " + host + ":" + str(port) # print "----------------------------------------" # print message # print "----------------------------------------" if isinstance(message, Request): # log.msg("Received request") ret = self.request_layer.handle_request(message) if isinstance(ret, Request): self.forward_request(ret) elif isinstance(message, Response): # log.err("Received response") rst = Message.new_rst(message) rst = self.message_layer.matcher_response(rst) # log.msg("Send RST") self.send(rst, host, port) elif isinstance(message, tuple): message, error = message response = Response() response.destination = (host, port) response.code = defines.responses[error] response = self.message_layer.reliability_response(message, response) response = self.message_layer.matcher_response(response) # log.msg("Send Error") self.send(response, host, port) elif message is not None: # ACK or RST # log.msg("Received ACK or RST") self.message_layer.handle_message(message)
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = struct.calcsize(fmt) s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid if token_length > 0: fmt = "%ss" % token_length s = struct.Struct(fmt) token_value = s.unpack_from(datagram[pos:])[0] message.token = token_value.decode("utf-8") else: message.token = None pos += token_length current_option = 0 values = datagram[pos:] length_packet = len(values) pos = 0 while pos < length_packet: next_byte = struct.unpack("B", values[pos].to_bytes(1, "big"))[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint num, option_length, pos = Serializer.read_option_value_len_from_byte(next_byte, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[current_option] except KeyError: (opt_critical, _, _) = defines.OptionRegistry.get_option_flags(current_option) if opt_critical: raise AttributeError("Critical option %s unknown" % current_option) else: # If the non-critical option is unknown # (vendor-specific, proprietary) - just skip it #log.err("unrecognized option %d" % current_option) pass else: if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos: pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b.to_bytes(1, "big"))[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos: pos + option_length] value = tmp else: value = values[pos: pos + option_length] option = Option() option.number = current_option option.value = Serializer.convert_to_raw(current_option, value, option_length) message.add_option(option) if option.number == defines.OptionRegistry.CONTENT_TYPE.number: message.payload_type = option.value finally: pos += option_length else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError("Packet length %s, pos %s" % (length_packet, pos)) message.payload = "" payload = values[pos:] try: if message.payload_type == defines.Content_types["application/octet-stream"]: message.payload = payload else: message.payload = payload.decode("utf-8") except AttributeError: message.payload = payload.decode("utf-8") pos += len(payload) return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number
def listen(self, timeout=10): """ Listen for incoming messages. Timeout is used to check if the server must be switched off. :param timeout: Socket Timeout in seconds """ self._socket.settimeout(float(timeout)) while not self.stopped.isSet(): try: data, client_address = self._socket.recvfrom(4096) if len(client_address) > 2: client_address = (client_address[0], client_address[1]) except socket.timeout: continue except Exception as e: if self._cb_ignore_listen_exception is not None and callable(self._cb_ignore_listen_exception): if self._cb_ignore_listen_exception(e, self): continue raise try: serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message rst.mid = self._messageLayer.fetch_mid() self.send_datagram(rst) continue logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug("message duplicated, transaction completed") if transaction.response is not None: self.send_datagram(transaction.response) continue elif transaction.request.duplicated and not transaction.completed: logger.debug("message duplicated, transaction NOT completed") self._send_ack(transaction) continue args = (transaction, ) t = threading.Thread(target=self.receive_request, args=args) t.start() # self.receive_datagram(data, client_address) elif isinstance(message, Response): logger.error("Received response from %s", message.source) else: # is Message transaction = self._messageLayer.receive_empty(message) if transaction is not None: with transaction: self._blockLayer.receive_empty(message, transaction) self._observeLayer.receive_empty(message, transaction) except Exception as e: logger.error("Exception received in listen") logger.exception(traceback.format_exc()) continue except RuntimeError: logger.exception("Exception with Executor") try: # Python does not close the OS FD on socket.close() # Ensure OS socket is closed with shutdown to prevent FD leak self._socket.shutdown(socket.SHUT_RDWR) except socket.error: pass self._socket.close()
def receive_datagram(self, args): """ Handle messages coming from the udp socket. :param args: (data, client_address) """ data, client_address = args logging.debug("receiving datagram") try: host, port = client_address except ValueError: host, port, tmp1, tmp2 = client_address client_address = (host, port) serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message self.send_datagram(rst) return logger.info("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug("message duplicated, transaction completed") transaction = self._observeLayer.send_response(transaction) transaction = self._blockLayer.send_response(transaction) transaction = self._messageLayer.send_response(transaction) self.send_datagram(transaction.response) return elif transaction.request.duplicated and not transaction.completed: logger.debug("message duplicated, transaction NOT completed") self._send_ack(transaction) return transaction.separate_timer = self._start_separate_timer( transaction) transaction = self._blockLayer.receive_request(transaction) if transaction.block_transfer: self._stop_separate_timer(transaction.separate_timer) transaction = self._messageLayer.send_response(transaction) self.send_datagram(transaction.response) return transaction = self._observeLayer.receive_request(transaction) """ call to the cache layer to check if there's a cached response for the request if not, call the forward layer """ if self._cacheLayer is not None: transaction = self._cacheLayer.receive_request(transaction) if transaction.cacheHit is False: logging.debug(transaction.request) transaction = self._forwardLayer.receive_request( transaction) logging.debug(transaction.response) transaction = self._observeLayer.send_response(transaction) transaction = self._blockLayer.send_response(transaction) transaction = self._cacheLayer.send_response(transaction) else: transaction = self._forwardLayer.receive_request(transaction) transaction = self._observeLayer.send_response(transaction) transaction = self._blockLayer.send_response(transaction) self._stop_separate_timer(transaction.separate_timer) transaction = self._messageLayer.send_response(transaction) if transaction.response is not None: if transaction.response.type == defines.Types["CON"]: self._start_retransmission(transaction, transaction.response) self.send_datagram(transaction.response) elif isinstance(message, Message): transaction = self._messageLayer.receive_empty(message) if transaction is not None: transaction = self._blockLayer.receive_empty( message, transaction) self._observeLayer.receive_empty(message, transaction) else: # is Response logger.error("Received response from %s", message.source)
def receive_datagram(self, args): """ Handle messages coming from the udp socket. :param args: (data, client_address) """ data, client_address = args logging.debug("receiving datagram") try: host, port = client_address except ValueError: host, port, tmp1, tmp2 = client_address client_address = (host, port) serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = Types["RST"] rst.code = message rst.mid = message.mid self.send_datagram(rst) return logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): if not message.proxy_uri or message.uri_path != "coap2http": logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = Types["RST"] rst.code = Codes.BAD_REQUEST.number rst.mid = message.mid self.send_datagram(rst) return # Execute HTTP/HTTPS request http_response = CoAP_HTTP.execute_http_request( message.code, message.proxy_uri, message.payload) # HTTP response to CoAP response conversion coap_response = CoAP_HTTP.to_coap_response(http_response, message.code, client_address, message.mid) # Send datagram and return self.send_datagram(coap_response) return elif isinstance(message, Message): logger.error("Received message from %s", message.source) else: # is Response logger.error("Received response from %s", message.source)
def listen(self, timeout=10): """ Listen for incoming messages. Timeout is used to check if the server must be switched off. :param timeout: Socket Timeout in seconds """ self._socket.settimeout(float(timeout)) empty = [] while not self.stopped.isSet(): try: data = None client_address = None readable, writable, exceptional = select.select(self._socketlist, empty, empty, timeout) for s in readable: data, client_address = s.recvfrom(4096) if len(client_address) > 2: client_address = (client_address[0], client_address[1]) print ("listen : received ", client_address) except socket.timeout: print (".") continue except Exception as e: if self._cb_ignore_listen_exception is not None and isinstance(self._cb_ignore_listen_exception, collections.Callable): if self._cb_ignore_listen_exception(e, self): continue raise try: serializer = Serializer() if data is not None: message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message rst.mid = self._messageLayer.fetch_mid() self.send_datagram(rst) continue logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug("message duplicated, transaction completed") if transaction.response is not None: self.send_datagram(transaction.response) continue elif transaction.request.duplicated and not transaction.completed: logger.debug("message duplicated, transaction NOT completed") self._send_ack(transaction) continue args = (transaction, ) t = threading.Thread(target=self.receive_request, args=args) t.start() # self.receive_datagram(data, client_address) elif isinstance(message, Response): logger.error("Received response from %s", message.source) else: # is Message transaction = self._messageLayer.receive_empty(message) if transaction is not None: with transaction: self._blockLayer.receive_empty(message, transaction) self._observeLayer.receive_empty(message, transaction) except RuntimeError: logger.exception("Exception with Executor") # close sockets for sock in self._socketlist: sock.close()
def deserialize(datagram, source): """ De-serialize a stream of byte to a message. :param datagram: the incoming udp message :param source: the source address and port (ip, port) :return: the message :rtype: Message """ try: fmt = "!BBH" pos = 4 length = len(datagram) while pos < length: fmt += "c" pos += 1 s = struct.Struct(fmt) values = s.unpack_from(datagram) first = values[0] code = values[1] mid = values[2] version = (first & 0xC0) >> 6 message_type = (first & 0x30) >> 4 token_length = (first & 0x0F) if Serializer.is_response(code): message = Response() message.code = code elif Serializer.is_request(code): message = Request() message.code = code else: message = Message() message.source = source message.destination = None message.version = version message.type = message_type message.mid = mid pos = 3 if token_length > 0: message.token = "".join(values[pos:pos + token_length]) else: message.token = None pos += token_length current_option = 0 length_packet = len(values) while pos < length_packet: next_byte = struct.unpack("B", values[pos])[0] pos += 1 if next_byte != int(defines.PAYLOAD_MARKER): # the first 4 bits of the byte represent the option delta # delta = self._reader.read(4).uint delta = (next_byte & 0xF0) >> 4 # the second 4 bits represent the option length # length = self._reader.read(4).uint length = (next_byte & 0x0F) num, pos = Serializer.read_option_value_from_nibble( delta, pos, values) option_length, pos = Serializer.read_option_value_from_nibble( length, pos, values) current_option += num # read option try: option_item = defines.OptionRegistry.LIST[ current_option] except KeyError: # log.err("unrecognized option") raise AttributeError if option_length == 0: value = None elif option_item.value_type == defines.INTEGER: tmp = values[pos:pos + option_length] value = 0 for b in tmp: value = (value << 8) | struct.unpack("B", b)[0] elif option_item.value_type == defines.OPAQUE: tmp = values[pos:pos + option_length] value = bytearray(tmp) else: tmp = values[pos:pos + option_length] value = "" for b in tmp: value += str(b) pos += option_length option = Option() option.number = current_option option.value = Serializer.convert_to_raw( current_option, value, option_length) message.add_option(option) else: if length_packet <= pos: # log.err("Payload Marker with no payload") raise AttributeError message.payload = "" payload = values[pos:] for b in payload: message.payload += str(b) pos += 1 return message except AttributeError: return defines.Codes.BAD_REQUEST.number except struct.error: return defines.Codes.BAD_REQUEST.number
def main(): # pragma: no cover ip = "192.168.1.21" port = defines.COAP_DEFAULT_PORT multicast = False server = CoAPServer(ip, port, multicast) server.notify('/basic') try: # server.listen() while not server.stopped.isSet(): data, client_address = server._socket.recvfrom(4096) try: serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): print("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message rst.mid = server._messageLayer.fetch_mid() server.send_datagram(rst) continue # print("receive_datagram " + str(message.payload)) database().insert_value('CoAP', datetime.datetime.now(), str(message.payload)) if isinstance(message, Request): transaction = server._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: print("message duplicated, transaction completed") if transaction.response is not None: server.send_datagram(transaction.response) continue elif transaction.request.duplicated and not transaction.completed: print("message duplicated, transaction NOT completed") server._send_ack(transaction) continue args = (transaction, ) t = threading.Thread(target=server.receive_request, args=args) t.start() # self.receive_datagram(data, client_address) elif isinstance(message, Response): print("Received response from %s", message.source) else: # is Message transaction = server._messageLayer.receive_empty(message) if transaction is not None: with transaction: server._blockLayer.receive_empty( message, transaction) server._observeLayer.receive_empty( message, transaction) except RuntimeError: print("Exception with Executor") server._socket.close() except KeyboardInterrupt: print("Server Shutdown") server.close() print("Exiting...")
def receive_datagram(self, args): """ Receive datagram from the udp socket. :rtype : Message """ data, client_address = args serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message self.send_datagram(rst) return logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug("message duplicated,transaction completed") transaction = self._observeLayer.send_response(transaction) transaction = self._blockLayer.send_response(transaction) transaction = self._messageLayer.send_response(transaction) self.send_datagram(transaction.response) return elif transaction.request.duplicated and not transaction.completed: logger.debug("message duplicated,transaction NOT completed") self._send_ack(transaction) return transaction.separate_timer = self._start_separate_timer( transaction) transaction = self._blockLayer.receive_request(transaction) if transaction.block_transfer: self._stop_separate_timer(transaction.separate_timer) transaction = self._messageLayer.send_response(transaction) self.send_datagram(transaction.response) return transaction = self._observeLayer.receive_request(transaction) transaction = self._forwardLayer.receive_request_reverse( transaction) transaction = self._observeLayer.send_response(transaction) transaction = self._blockLayer.send_response(transaction) self._stop_separate_timer(transaction.separate_timer) transaction = self._messageLayer.send_response(transaction) if transaction.response is not None: if transaction.response.type == defines.Types["CON"]: self._start_retrasmission(transaction, transaction.response) self.send_datagram(transaction.response) elif isinstance(message, Message): transaction = self._messageLayer.receive_empty(message) if transaction is not None: transaction = self._blockLayer.receive_empty( message, transaction) self._observeLayer.receive_empty(message, transaction) else: # pragma: no cover logger.error("Received response from %s", message.source)
def listen(self, timeout=10): """ Listen for incoming messages. Timeout is used to check if the server must be switched off. :param timeout: Socket Timeout in seconds """ self._socket.settimeout(float(timeout)) while not self.stopped.isSet(): try: data, client_address = self._socket.recvfrom(4096) if len(client_address) > 2: client_address = (client_address[0], client_address[1]) except socket.timeout: continue try: serializer = Serializer() message = serializer.deserialize(data, client_address) if isinstance(message, int): logger.error("receive_datagram - BAD REQUEST") rst = Message() rst.destination = client_address rst.type = defines.Types["RST"] rst.code = message rst.mid = self._messageLayer._current_mid self._messageLayer._current_mid += 1 % 65535 self.send_datagram(rst) continue logger.debug("receive_datagram - " + str(message)) if isinstance(message, Request): transaction = self._messageLayer.receive_request(message) if transaction.request.duplicated and transaction.completed: logger.debug( "message duplicated, transaction completed") if transaction.response is not None: self.send_datagram(transaction.response) continue elif transaction.request.duplicated and not transaction.completed: logger.debug( "message duplicated, transaction NOT completed") self._send_ack(transaction) continue args = (transaction, ) t = threading.Thread(target=self.receive_request, args=args) t.start() # self.receive_datagram(data, client_address) elif isinstance(message, Response): logger.error("Received response from %s", message.source) else: # is Message transaction = self._messageLayer.receive_empty(message) if transaction is not None: with transaction: self._blockLayer.receive_empty( message, transaction) self._observeLayer.receive_empty( message, transaction) except RuntimeError: print "Exception with Executor" self._socket.close()