Skip to content

Add proto to sockets #8752

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Dec 29, 2023
Merged

Add proto to sockets #8752

merged 24 commits into from
Dec 29, 2023

Conversation

carson-coder
Copy link

Add #8750

@carson-coder
Copy link
Author

espressif port is tested but I couldn't test the raspberry pi because I don't have a device to test it

@carson-coder
Copy link
Author

looks like raspberrypi_pico and some other builds failed so I will try to fix that

Copy link

@jepler jepler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit adds some files that should probably not have been added (os, os.path, etc) with many thousands of lines of content. Please rebase this branch so that these files are not added to our history. If that's beyond your git skills, I can help you figure out how.

The rest looks plausible, based on my small understanding of networking.

//| """Create a new socket
//|
//| :param ~int family: AF_INET or AF_INET6
//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
//| :param ~int proto: Int
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should probably also add some "proto" named constants to the socketpool object, such as IPPROTO_IP and IPPROTO_ICMP. It might also make sense to state that this value is only used for SOCK_RAW.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I can work on this tomorrow.

@carson-coder
Copy link
Author

Could you help me with git rebase @jepler

@dhalbert
Copy link
Collaborator

dhalbert commented Dec 27, 2023

Do you have `adafruit/circuitpython as a remote, e.g.:

$ git remote -v
adafruit	https://github.com/adafruit/circuitpython.git (fetch)
adafruit	https://github.com/adafruit/circuitpython.git (push)
origin	https://github.com/dhalbert/circuitpython.git (fetch)
origin	https://github.com/dhalbert/circuitpython.git (push)

It might be called upstream instead. If not add it as a remote.
So, to rebase:

$ git fetch adafruit
$ git rebase adafruit/main

There may well be conflicts that you have to resolve.

@carson-coder
Copy link
Author

$ git fetch adafruit
$ git rebase adafruit/main

Could I do adafruit/8.2.x because I am adding this on the 8.2.x branch

@carson-coder
Copy link
Author

I think I did it

@dhalbert
Copy link
Collaborator

ould I do adafruit/8.2.x because I am adding this on the 8.2.x branch

fer sure, and I guess you did

@carson-coder
Copy link
Author

Yep

@jepler
Copy link

jepler commented Dec 27, 2023

Looks like pre-commit wants a few more changes. Other than that, this looks good to me (but i didn't test)

@dhalbert
Copy link
Collaborator

What kind of network testing do you want to do with this? Can you write a ping?

//| """Create a new socket
//|
//| :param ~int family: AF_INET or AF_INET6
//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
//| :param ~int proto: IPPROTO_TCP or IPPROTO_IP. Only works with SOCK_RAW
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I manually passed the value of proto = 1 for ICMP and it works to allow me to create a manual ICMP packet with a raw socket (I've tested it). Unfortunately, it doesn't look like IPPROTO_ICMP = 1 is defined anywhere, in the existing code base.

@300bps
Copy link

300bps commented Dec 29, 2023

I've been testing the Raspberry Pi Pico version of this build (some comments were in the associated issue). The results are:

  1. These code changes in this build SUCCESSFULLY allow me to create a raw ICMP (ping) socket by passing proto=1. Previously, this was not supported.
    import socketpool
    import wifi

    IP_HEADER_PROTOCOL_ICMP = 1
    sp = socketpool.SocketPool(wifi.radio)
    sp.socket(family=socketpool.AF_INET, type=socketpool.SOCK_RAW, proto=IP_HEADER_PROTOCOL_ICMP)
  1. I've manually created ICMP ping (echo) raw packets and SUCCESSFULLY sent them and received ping responses from a number of sites: (1.1.1.1, 8.8.8.8, 1.0.0.1, and 8.8.4.4, along with my local router). I've tested it by continuously pinging once per second for several hours at a time. I've also run faster rapid-fire pings for shorter intervals successfully.
  2. I checked the circuitpython codebase and didn't find an IPPROTO_ICMP = 1 or SOCKETPOOL_IPPROTO_ICMP = 1 that could be passed as a symbolic constant for the 'proto' parameter in the 'socket' call. This isn't necessary for the changes to be usable and functional. If this were desired to be added, the locations could be found by searching 'IPPROTO_IP' or 'IPPROTO_TCP'.
  3. The only unexpected behavior that I've observed is: if I attempt to open 2 or more ICMP raw sockets, the last one opened functions correctly and the earlier ones repeatedly time out. I don't see a direct cause of that in the changes in this pull request, and think it seems most likely to be a consequence or limitation of the lower-level 'lwip' networking code.
  4. All-in-all the changes in this PR do enable the ability to use raw sockets to build ICMP and other raw messages and it brings CP more in-line with regular python socket functionality. I recommend adopting it into the main for new CP9 builds.

Kudos @carson-coder for enabling this functionality.

@300bps
Copy link

300bps commented Dec 29, 2023

What kind of network testing do you want to do with this? Can you write a ping?

@dhalbert I did successfully do this with the .uf2 from this PR for the RPi Pico and it works well. See my previous comment above for more detailed results. Thanks!

@anecdata
Copy link
Member

I think socketpool.SocketPool.IPPROTO_ICMP could be added:

>>> help(socketpool.SocketPool)
object <class 'SocketPool'> is of type type
  socket -- <function>
  getaddrinfo -- <function>
  gaierror -- <class 'gaierror'>
  AF_INET -- 2
  AF_INET6 -- 10
  SOCK_STREAM -- 1
  SOCK_DGRAM -- 2
  SOCK_RAW -- 3
  TCP_NODELAY -- 1
  IPPROTO_TCP -- 6
  IPPROTO_IP -- 0
  IP_MULTICAST_TTL -- 5
  EAI_NONAME -- -2

@carson-coder
Copy link
Author

For constantant for the proto parm I just use the Two that already exist

@carson-coder
Copy link
Author

Should I add every IPPROTO_* constant. And what would I do for the socketpool.socket() docstring because listing every constant isn't viable because there are a lot

@dhalbert
Copy link
Collaborator

You could add only the ones that are actually implemented by Espressif or RP2040 wifi. And yes, add each one, with a docstring underneath. as class constants.

@carson-coder
Copy link
Author

I just added each one and in the docstring for socket I said that proto can be IPPROTO_TCP, IPPROTO_IP or any other IPPROTO_ constant. and I added each constant in the class doc string. you can look at the next commit.

Comment on lines 86 to 109
//| IPPROTO_AH: int
//| IPPROTO_DSTOPTS: int
//| IPPROTO_EGP: int
//| IPPROTO_ESP: int
//| IPPROTO_FRAGMENT: int
//| IPPROTO_GRE: int
//| IPPROTO_HOPOPTS: int
//| IPPROTO_ICMP: int
//| IPPROTO_ICMPV6: int
//| IPPROTO_IDP: int
//| IPPROTO_IGMP: int
//| IPPROTO_IPIP: int
//| IPPROTO_IPV6: int
//| IPPROTO_MPTCP: int
//| IPPROTO_NONE: int
//| IPPROTO_PIM: int
//| IPPROTO_PUP: int
//| IPPROTO_RAW: int
//| IPPROTO_ROUTING: int
//| IPPROTO_RSVP: int
//| IPPROTO_SCTP: int
//| IPPROTO_TP: int
//| IPPROTO_UDP: int
//| IPPROTO_UDPLITE: int
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding them here does not make them available in Python You need to add them around line 221 in this file. But there are too many to add, and most will not be used. Just add a few of the common ones, including ICMP.

For instance, MicroPython defines these common ones:
https://github.com/micropython/micropython/blob/9feb0689eeaca5ce88aedcc680f997a3b4d0221c/extmod/modsocket.c#L640

Copy link

@300bps 300bps Dec 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IPPROTO_ICMP=1 and IPPROTO_RAW=255 are the 2 that'd I'd suggest explicitly adding to those that are already implemented in CP.

@carson-coder
Copy link
Author

CPython's socket doesn't define IPPROTO_IPV4 but the micropython file that was linked did so I am not going to define it because it is not in python

@carson-coder carson-coder requested a review from jepler December 29, 2023 16:55
Copy link

@jepler jepler left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's good to merge if the CI comes up green. Thanks for taking care of all the details here!

@carson-coder
Copy link
Author

Np

@jepler jepler dismissed dhalbert’s stale review December 29, 2023 21:00

this was completed

@jepler jepler merged commit 5c3361b into adafruit:8.2.x Dec 29, 2023
@carson-coder carson-coder deleted the add-proto-to-sockets branch December 29, 2023 21:03
@jepler jepler mentioned this pull request Dec 29, 2023
@300bps
Copy link

300bps commented Dec 29, 2023

Nice work!

@dhalbert GitHub newbie question here, but it looks like this was merged into a branch (8.2.x). How does it get into main so that it will be available in the CP9.0 codebase? Are there periodic merges from older branches or does it have to be manually done?

@dhalbert
Copy link
Collaborator

That was done here: #8769 by @jepler.

@300bps
Copy link

300bps commented Dec 30, 2023

That was done here: #8769 by @jepler.

Awesome! Thanks for the 411.

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.

5 participants