23
23
24
24
from scapy .error import Scapy_Exception
25
25
from 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
27
29
from scapy .contrib .isotp .isotp_soft_socket import TimeoutScheduler
28
30
from scapy .data import MTU
29
31
from scapy .utils import EDecimal
30
32
from scapy .automaton import ObjectPipe , select_objects
31
33
32
34
from scapy .supersocket import SuperSocket , SimpleSocket
33
35
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
-
75
36
log_coap_sock = logging .getLogger ("scapy.contrib.coap_socket" )
76
37
77
38
@@ -85,7 +46,7 @@ class CoAPSocket(SuperSocket):
85
46
>>> with CoAPSocket("127.0.0.1", 1234) as coap_client:
86
47
>>> req = CoAPSocket.make_coap_req_packet(
87
48
>>> 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)
89
50
>>> # Careful, this will block until the coap_client receives something
90
51
>>> res = coap_client.recv()
91
52
@@ -172,12 +133,24 @@ def recv(self, x=MTU, **kwargs):
172
133
def close (self ):
173
134
# type: () -> None
174
135
if not self .closed :
175
- self .impl .close ()
176
136
self .closed = True
137
+ self .impl .close ()
177
138
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 )
181
154
182
155
@staticmethod
183
156
def make_coap_req_packet (method = GET , uri = "" , options = None , payload = b"" ):
@@ -630,8 +603,10 @@ def _on_pkt_recv(self, pkt, sa_ll):
630
603
else :
631
604
self ._handle_rcv_request (pkt , sa_ll )
632
605
else :
633
- # Response, check pending requests
606
+ # Response, check pending requests and process internally
634
607
self ._handle_request_response (pkt , sa_ll )
608
+ # Then give the response to the user.
609
+ self .rx_queue .send ((pkt .build (), pkt .time ))
635
610
636
611
def _post (self ):
637
612
# type: () -> dict
@@ -805,8 +780,6 @@ def _handle_request_response(self, pkt, sa_ll):
805
780
index [0 ], index [1 ],
806
781
coap_codes [pkt .code ])
807
782
del self .pending_requests [index ]
808
- # Piggybacked message, give it to the user
809
- self .rx_queue .send ((pkt .build (), pkt .time ))
810
783
elif pkt .type == ACK and pkt .code == EMPTY_MESSAGE :
811
784
log_coap_sock .debug (
812
785
"Server sent an empty ack, request will be fulfilled later: "
@@ -824,14 +797,10 @@ def _handle_request_response(self, pkt, sa_ll):
824
797
response = CoAPSocketImpl .empty_ack_params ()
825
798
response ["msg_id" ] = pkt .msg_id
826
799
self ._sock_send (sa_ll , CoAP (** response ))
827
-
828
- # Give the packet to the user
829
- self .rx_queue .send ((pkt .build (), pkt .time ))
830
800
else :
831
- log_coap_sock .info ("Not handled message, giving to user : "
801
+ log_coap_sock .info ("Not handled message: "
832
802
"type=%s; code=%s;" ,
833
803
pkt .type , coap_codes [pkt .code ])
834
- self .rx_queue .send ((pkt .build (), pkt .time ))
835
804
836
805
def _sock_send (self , address , pl ):
837
806
# type: (tuple[str, int], Packet) -> None
0 commit comments