2323
2424from scapy .error import Scapy_Exception
2525from scapy .packet import Packet
26- from scapy .contrib .coap import CoAP , coap_options , coap_codes
26+ from scapy .contrib .coap import CoAP , coap_options , coap_codes , EMPTY_MESSAGE , GET , \
27+ POST , PUT , DELETE , COAP_REQ_CODES , CONTENT_205 , NOT_FOUND_404 , NOT_ALLOWED_405 , \
28+ CF_TEXT_PLAIN , CF_APP_LINK_FORMAT , PAYMARK , URI_PATH , CONTENT_FORMAT , CON , NON , ACK
2729from scapy .contrib .isotp .isotp_soft_socket import TimeoutScheduler
2830from scapy .data import MTU
2931from scapy .utils import EDecimal
3032from scapy .automaton import ObjectPipe , select_objects
3133
3234from scapy .supersocket import SuperSocket , SimpleSocket
3335
34- """
35- CoAP message request codes (RFC 7252 @ section-5.8.1)
36- """
37- EMPTY_MESSAGE = 0
38- GET = 1
39- POST = 2
40- PUT = 3
41- DELETE = 4
42- COAP_REQ_CODES = [GET , POST , PUT , DELETE ]
43- """
44- CoAP message response codes (RFC 7252 @ section-12.1.2)
45- Also, from scapy.contrib.coap.coap_codes
46- """
47- EMPTY_ACK = EMPTY_MESSAGE
48- CONTENT_205 = 69
49- NOT_FOUND_404 = 132
50- NOT_ALLOWED_405 = 133
51- NOT_IMPLEMENTED_501 = 161
52- """
53- CoAP content type (RFC 7252 @ section-12.3)
54- """
55- CF_TEXT_PLAIN = b"\x00 "
56- CF_APP_LINK_FORMAT = b"\x28 "
57- CF_APP_XML = b"\x29 "
58- CF_APP_OCTET_STREAM = b"\x2A "
59- CF_APP_EXI = b"\x2F "
60- CF_APP_JSON = b"\x32 "
61- """
62- CoAP options (RFC 7252 @ section-5.10)
63- """
64- PAYMARK = b"\xff "
65- URI_PATH = 11
66- CONTENT_FORMAT = 12
67- """
68- CoAP message type
69- """
70- CON = 0
71- NON = 1
72- ACK = 2
73- RST = 3
74-
7536log_coap_sock = logging .getLogger ("scapy.contrib.coap_socket" )
7637
7738
@@ -85,7 +46,7 @@ class CoAPSocket(SuperSocket):
8546 >>> with CoAPSocket("127.0.0.1", 1234) as coap_client:
8647 >>> req = CoAPSocket.make_coap_req_packet(
8748 >>> method=GET, uri="endpoint-uri", payload=b"")
88- >>> coap_client.send("127.0.0 .1", 5683, req)
49+ >>> coap_client.send(IP(dst="192.168.1 .1") / UDP(dport=1234) / req)
8950 >>> # Careful, this will block until the coap_client receives something
9051 >>> res = coap_client.recv()
9152
@@ -172,12 +133,24 @@ def recv(self, x=MTU, **kwargs):
172133 def close (self ):
173134 # type: () -> None
174135 if not self .closed :
175- self .impl .close ()
176136 self .closed = True
137+ self .impl .close ()
177138
178- def send (self , ip , port , x ):
179- # type: (str, int, CoAP) -> None
180- self .impl .send (ip , port , x )
139+ def send (self , x ):
140+ # type: (Packet) -> int
141+ """
142+ Send the packet using this socket.
143+ Should be a CoAP packet with IP and UDP data.
144+
145+ Example:
146+ >>> IP(dst="192.168.1.1") / UDP(dport=1234) / CoAP()
147+ >>> IP(dst="192.168.1.1") / UDP(dport=1234) / CoAPSocket.make_coap_req_packet()
148+
149+ :param x: Concatenated packet with IP / UDP / CoAP
150+ :return: The length of x, which is the amount of bytes sent
151+ """
152+ self .impl .send (x .dst , x .dport , x [CoAP ])
153+ return len (x )
181154
182155 @staticmethod
183156 def make_coap_req_packet (method = GET , uri = "" , options = None , payload = b"" ):
@@ -630,8 +603,10 @@ def _on_pkt_recv(self, pkt, sa_ll):
630603 else :
631604 self ._handle_rcv_request (pkt , sa_ll )
632605 else :
633- # Response, check pending requests
606+ # Response, check pending requests and process internally
634607 self ._handle_request_response (pkt , sa_ll )
608+ # Then give the response to the user.
609+ self .rx_queue .send ((pkt .build (), pkt .time ))
635610
636611 def _post (self ):
637612 # type: () -> dict
@@ -805,8 +780,6 @@ def _handle_request_response(self, pkt, sa_ll):
805780 index [0 ], index [1 ],
806781 coap_codes [pkt .code ])
807782 del self .pending_requests [index ]
808- # Piggybacked message, give it to the user
809- self .rx_queue .send ((pkt .build (), pkt .time ))
810783 elif pkt .type == ACK and pkt .code == EMPTY_MESSAGE :
811784 log_coap_sock .debug (
812785 "Server sent an empty ack, request will be fulfilled later: "
@@ -824,14 +797,10 @@ def _handle_request_response(self, pkt, sa_ll):
824797 response = CoAPSocketImpl .empty_ack_params ()
825798 response ["msg_id" ] = pkt .msg_id
826799 self ._sock_send (sa_ll , CoAP (** response ))
827-
828- # Give the packet to the user
829- self .rx_queue .send ((pkt .build (), pkt .time ))
830800 else :
831- log_coap_sock .info ("Not handled message, giving to user : "
801+ log_coap_sock .info ("Not handled message: "
832802 "type=%s; code=%s;" ,
833803 pkt .type , coap_codes [pkt .code ])
834- self .rx_queue .send ((pkt .build (), pkt .time ))
835804
836805 def _sock_send (self , address , pl ):
837806 # type: (tuple[str, int], Packet) -> None
0 commit comments