Skip to content

Reorg code per request from orphan pr 69 #107

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion adafruit_esp32spi/adafruit_esp32spi.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
_START_SCAN_NETWORKS = const(0x36)
_GET_FW_VERSION_CMD = const(0x37)
_SEND_UDP_DATA_CMD = const(0x39)
_GET_REMOTE_DATA_CMD = const(0x3A)
_GET_TIME = const(0x3B)
_GET_IDX_BSSID_CMD = const(0x3C)
_GET_IDX_CHAN_CMD = const(0x3D)
Expand Down Expand Up @@ -316,7 +317,7 @@ def _send_command_get_response(
*,
reply_params=1,
sent_param_len_16=False,
recv_param_len_16=False
recv_param_len_16=False,
):
"""Send a high level SPI command, wait and return the response"""
self._send_command(cmd, params, param_len_16=sent_param_len_16)
Expand Down Expand Up @@ -896,6 +897,16 @@ def get_time(self):
)
raise RuntimeError("Must be connected to WiFi before obtaining NTP.")

def get_remote_data(self, socknum):
"""Obtain remote IP
:param int socknum: the socket number.
"""
self._socknum_ll[0][0] = socknum
resp = self._send_command_get_response(
_GET_REMOTE_DATA_CMD, self._socknum_ll, reply_params=2
)
return {"ip_addr": resp[0], "port": resp[1]}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return {"ip_addr": resp[0], "port": resp[1]}
return (resp[0], resp[1])


def set_certificate(self, client_certificate):
"""Sets client certificate. Must be called
BEFORE a network connection is established.
Expand Down
21 changes: 20 additions & 1 deletion adafruit_esp32spi/adafruit_esp32spi_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,23 @@ class socket:

# pylint: disable=too-many-arguments
def __init__(
self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None, socknum=None
self,
family=AF_INET,
type=SOCK_STREAM,
proto=0,
fileno=None,
socknum=None,
remote_ip=None,
remote_port=None,
Comment on lines +61 to +62
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
remote_ip=None,
remote_port=None,

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh that makes sense @tannewt! I will work on these changes as soon as I get a second and will test and push an update. Thank you again.

Copy link
Member

Choose a reason for hiding this comment

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

No rush and no problem! Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tannewt I have implemented the changes. I wanted ask specifically how you would like this tested. Here is the result in the REPL.
>>> socket.socket. close connect connected read readline recv send settimeout write socknum available getpeername

I obviously cant call socket.socket.getpeername() so if you have a quick test I can code up I will begin testing so that I know what you are looking for specifically. Any simple example will do thanks!

Copy link
Member

Choose a reason for hiding this comment

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

I'd imagine you need to create a socket and connect before calling it. The new requests library can work with CPython sockets so that's probably the best place to start.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tannewt I created an access point called cool and then I connected my iPhone to it. It successfully connected however when I call socket.socket.getpeername() i get TypeError: function takes 1 positional arguments but 0 were given as it should be returning the peer ip of 192.168.4.2 as that is the iPhone and the server is 192.168.4.2.

Any suggestions on how to better check the getpeername call?

Copy link
Member

Choose a reason for hiding this comment

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

You actually need to connect a TCP socket and then call .getpeername() on it. The error is because you are calling it on the class, not an instance, and therefore no self is passed.

Why are you adding this overall? It doesn't seem like you have a use for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great question @tannewt. Over a year ago when I did the original PR I had issues where I had the device set up as an Access Point and if I accidently logged in from multiple browsers on various machines it would crash.

This original PR was designed to check for that remote IP and if it was not 192.168.4.2 then don't connect. It was to add the ability to get this information if a developer wanted to implement functionality such as this.

I am ok with closing the PR however. Thoughts?

Copy link
Contributor Author

@mytechnotalent mytechnotalent Oct 14, 2020

Choose a reason for hiding this comment

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

This is what I tried to do originally as well. I can't seem to even create a socket object here.

>>> import adafruit_esp32spi.adafruit_esp32spi_socket as socket
>>> s = socket.socket()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lib/adafruit_esp32spi/adafruit_esp32spi_socket.py", line 62, in __init__
AttributeError: 'NoneType' object has no attribute 'get_socket'
>>> 

Copy link
Member

Choose a reason for hiding this comment

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

With the current ESP32-SPI implementation you need to call set_interface on the socket module: https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/master/adafruit_esp32spi/adafruit_esp32spi_socket.py#L24 I believe you pass it the ESP32SPI object.

I could see this PR being helpful but if no one is using it enough to test, then we could just close for now.

):
if family != AF_INET:
raise RuntimeError("Only AF_INET family supported")
if type != SOCK_STREAM:
raise RuntimeError("Only SOCK_STREAM type supported")
self._buffer = b""
self._socknum = socknum if socknum else _the_interface.get_socket()
self._remote_ip = remote_ip
self._remote_port = remote_port
Comment on lines +70 to +71
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
self._remote_ip = remote_ip
self._remote_port = remote_port

self.settimeout(0)

# pylint: enable=too-many-arguments
Expand Down Expand Up @@ -193,6 +202,16 @@ def socknum(self):
"""The socket number"""
return self._socknum

@property
def remote_ip(self):
"""The remote ip"""
return self._remote_ip

@property
def remote_port(self):
"""The remote port"""
return self._remote_port

Comment on lines +205 to +214
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
@property
def remote_ip(self):
"""The remote ip"""
return self._remote_ip
@property
def remote_port(self):
"""The remote port"""
return self._remote_port
def getpeername(self):
ip, port = _the_interface.get_remote_data(self._socknum)
# Parse so that ip is a string and port is an int
# Second bullet here: https://docs.python.org/3/library/socket.html#socket-families
return (ip, port)

def close(self):
"""Close the socket, after reading whatever remains"""
_the_interface.socket_close(self._socknum)
Expand Down
9 changes: 9 additions & 0 deletions adafruit_esp32spi/adafruit_esp32spi_wsgiserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ def finish_response(self, result):
print("closing")
self._client_sock.close()

def check_remote_ip(self):
"""
Functionality to control what IP is connecting to the server.
"""
socknum = self._client_sock.socknum
remote_ip = _the_interface.get_remote_data(socknum)
return _the_interface.pretty_ip(remote_ip)

def client_available(self):
"""
returns a client socket connection if available.
Expand Down Expand Up @@ -178,6 +186,7 @@ def _get_environ(self, client):
env["wsgi.multiprocess"] = False
env["wsgi.run_once"] = False

env["REMOTE_ADDR"] = self._client_sock.remote_ip
env["REQUEST_METHOD"] = method
env["SCRIPT_NAME"] = ""
env["SERVER_NAME"] = _the_interface.pretty_ip(_the_interface.ip_address)
Expand Down