Skip to content

Follow-up: Added CoAP socket #4334#5000

Closed
polybassa wants to merge 19 commits into
secdev:masterfrom
polybassa:coap_sockets
Closed

Follow-up: Added CoAP socket #4334#5000
polybassa wants to merge 19 commits into
secdev:masterfrom
polybassa:coap_sockets

Conversation

@polybassa
Copy link
Copy Markdown
Contributor

Description

This PR implements a CoAP socket, pretty similar on how ISOTPSoftSocket works.
I implemented the basic message exchange, mostly based on the RFC-7252.

  • Congestion control
  • Retransmission mechanism
  • Separate responses
  • Message duplication detection

Known-limitations

  • No POST and DELETE methods
  • No DTLS
  • No discovery via multicast/broadcast, although you can still bind to one of these interfaces
  • No observer
  • The SR/SR1 functions cannot handle separate responses.

General comments

It has a dependency for from scapy.contrib.isotp.isotp_soft_socket import TimeoutScheduler, I found nice how this is implemented, so I just used it, I didn't want to copy/paste again.

Also I added some unit tests for the basic cases.

Quick usage

Client example:
    >>> with CoAPSocket("127.0.0.1", 1234) as coap_client:
    >>>     req = CoAPSocket.make_coap_req_packet(method=GET, uri="endpoint-uri", payload=b"")
    >>>     coap_client.send("127.0.0.1", 5683, req)
    >>>     res = coap_client.recv() # Careful, this will block until the coap_client receives something

Server without specifying resources:
    >>> with CoAPSocket("127.0.0.1", 5683) as coap_server:
    >>>     while True:
    >>>         pkg = coap_server.recv()
    >>>         handle_package(pkg)

Server with custom resources:
    >>> class DummyResource(CoAPResource):
    >>>     def get(self, payload, options, token, sa_ll):
    >>>         return {"type": ACK, "code": CONTENT_205, "options": [(CONTENT_FORMAT, CF_TEXT_PLAIN)], "payload": b'dummy response'}
    >>>
    >>> class DelayedResource(CoAPResource):
    >>>     def __init__(self, url):
    >>>         CoAPResource.__init__(self, url=url)
    >>>         self.delayed_tokens = []
    >>>
    >>>     def delayed_message(self):
    >>>         token, address = self.delayed_tokens.pop(0)
    >>>         pkt = CoAPSocket.make_delayed_resp_packet(token, [(CONTENT_FORMAT, CF_TEXT_PLAIN)], b"delayed payload")
    >>>         self._send_separate_response(pkt, address)
    >>>
    >>>     def get(self, payload, options, token, sa_ll):
    >>>         # We know that this can take a while, so we return an empty ACK now and wait for whatever resource to be available.
    >>>         TimeoutScheduler.schedule(1, self.delayed_message)
    >>>         self.delayed_tokens.append((token, sa_ll))
    >>>         return CoAPSocket.empty_ack_params()
    >>>
    >>> # Doesn't matter if it starts with "/dummy" or "dummy", but it is an error if it is in the end
    >>> lst_resources = [DummyResource("dummy"), DelayedResource("/delayed")].
    >>> with CoAPSocket("127.0.0.1", 5683, lst_resources=lst_resources) as coap_socket:
    >>>     while True:
    >>>         pkg = coap_socket.recv()
    >>>         # You can handle the packages inside your resources, here will only be the "unhandled" ones.

This follow-up reintegrates master and adds additional unit tests

eHonnef and others added 18 commits March 24, 2024 15:45
Fixing response payload

Some docstring and bug fixes.

Finished CoAP server logic implementation

Added client interaction

Client/Server done.

Added delayed response handling

Fixing small problems

Unit tests

Documentation
- Moved the defines/enumerators to coap.py
- Changed the send() function to match the SuperSocket declaration
- Updated unit tests
- Implemented coap.answers function
- Fixed some types
- Remove unnecessary override
- Changed sr and sr1 functions signatures.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- Changed return type hint for `__enter__` method to `Self`.
- Updated imports to include `Self` from `scapy.compat`.

Remove `setup.py` in favor of `pyproject.toml` configuration

- Deleted `setup.py` as its functionality is now handled by `pyproject.toml`.
- Updated `pyproject.toml` to explicitly include `readme`.

Reorganize imports and improve code formatting in `scapy/sendrecv.py`

- Optimized import order for better readability.
- Adjusted code indentation and removed unnecessary blank lines for consistency.
- Updated `pyproject.toml` to include `readme` as a dynamic attribute.

Add `setup.py` and reorganize imports in `scapy/sendrecv.py`

- Introduced `setup.py` for setuptools support.
- Refactored and reordered imports in `scapy/sendrecv.py` to improve readability and maintainability.
- Minor improvements and consistency changes to `scapy/sendrecv.py`.

Handle missing edge keys gracefully in graph component

Fix hashret of DoIP

Add version field for DoIP and DoIP sockets

Update .gitlab-ci.yml file

fix Build

Disable open LDAP

Dissecto DIFFs

update documentation

use python scm way to generate versions

fix spellcheck

testing new versioning

Fix the newest codespell update (secdev#4400)

fix spellcheck

Disable debug message

fix flake

Remove log message

remove diffs between github and dissecto
fixes

improve thread safety by replacing instance lock with class-level lock tracking

add return type annotation to `__del__` method in graph module

replace instance lock initialization with defaultdict for thread safety
… packet metadata during serialization

The new regression tests protect against breaking older pickle payloads by ensuring legacy tuple-state unpickling still works.
They also lock in current behavior for the new state format by checking full metadata and comments fidelity after pickle roundtrip.
This gives coverage for both backward compatibility and current serialization behavior in one place: test/regression.uts.
@polybassa polybassa mentioned this pull request May 24, 2026
@polybassa
Copy link
Copy Markdown
Contributor Author

@gpotter2 How should I proceed with the trailer check for "old" commits?

AI-Assisted: no
@polybassa
Copy link
Copy Markdown
Contributor Author

this branch has a dirty history.

@polybassa polybassa closed this May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants