diff --git a/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp index 61a78dcfc6..adbb7f157c 100644 --- a/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp +++ b/UNITTESTS/features/netsocket/InternetSocket/test_InternetSocket.cpp @@ -24,10 +24,14 @@ extern std::list eventFlagsStubNextRetval; // InternetSocket is an abstract class, so we have to test it via its child. class stubInternetSocket : public InternetSocket { protected: - nsapi_error_t return_value = 0; + nsapi_error_t return_value; public: + stubInternetSocket() { + return_value = 0; + } virtual nsapi_error_t connect(const SocketAddress &address) { + _remote_peer = address; return return_value; } virtual nsapi_size_or_error_t send(const void *data, nsapi_size_t size) @@ -227,3 +231,25 @@ TEST_F(TestInternetSocket, sigio) socket->close(); // Trigger event; EXPECT_EQ(callback_is_called, true); } + +TEST_F(TestInternetSocket, getpeername) +{ + SocketAddress peer; + SocketAddress zero; + + stack.return_value = NSAPI_ERROR_OK; + + EXPECT_EQ(socket->getpeername(&peer), NSAPI_ERROR_NO_SOCKET); + + socket->open((NetworkStack *)&stack); + socket->connect(zero); + + EXPECT_EQ(socket->getpeername(&peer), NSAPI_ERROR_NO_CONNECTION); + + const nsapi_addr_t saddr = {NSAPI_IPv4, {192, 168, 0, 1} }; + const SocketAddress remote(saddr, 1024); + socket->connect(remote); + + EXPECT_EQ(socket->getpeername(&peer), NSAPI_ERROR_OK); + EXPECT_EQ(remote, peer); +} diff --git a/UNITTESTS/stubs/NetworkStack_stub.h b/UNITTESTS/stubs/NetworkStack_stub.h index 43eda21ee9..080a07a2b9 100644 --- a/UNITTESTS/stubs/NetworkStack_stub.h +++ b/UNITTESTS/stubs/NetworkStack_stub.h @@ -24,7 +24,12 @@ class NetworkStackstub : public NetworkStack { public: std::list return_values; - nsapi_error_t return_value = 0; + nsapi_error_t return_value; + + NetworkStackstub() { + return_value = 0; + } + virtual const char *get_ip_address() { return "127.0.0.1"; diff --git a/features/netsocket/InternetSocket.cpp b/features/netsocket/InternetSocket.cpp index a114b6bbf9..5d24f3b1c4 100644 --- a/features/netsocket/InternetSocket.cpp +++ b/features/netsocket/InternetSocket.cpp @@ -214,3 +214,15 @@ void InternetSocket::attach(Callback callback) { sigio(callback); } + +nsapi_error_t InternetSocket::getpeername(SocketAddress *address) +{ + if (!_socket) { + return NSAPI_ERROR_NO_SOCKET; + } + if (!_remote_peer) { + return NSAPI_ERROR_NO_CONNECTION; + } + *address = _remote_peer; + return NSAPI_ERROR_OK; +} diff --git a/features/netsocket/InternetSocket.h b/features/netsocket/InternetSocket.h index b4681cb596..168a10c21e 100644 --- a/features/netsocket/InternetSocket.h +++ b/features/netsocket/InternetSocket.h @@ -117,6 +117,10 @@ public: */ virtual void sigio(mbed::Callback func); + /** @copydoc Socket::getpeername + */ + virtual nsapi_error_t getpeername(SocketAddress *address); + /** Register a callback on state change of the socket. * * @see Socket::sigio diff --git a/features/netsocket/Socket.h b/features/netsocket/Socket.h index f917575ab3..a9f4c0788e 100644 --- a/features/netsocket/Socket.h +++ b/features/netsocket/Socket.h @@ -254,6 +254,17 @@ public: * @return NSAPI_ERROR_OK on success, negative error code on failure */ virtual nsapi_error_t listen(int backlog = 1) = 0; + + /** Get the remote-end peer associated with this socket. + * + * Copy the remote peer address to a SocketAddress structure pointed by + * address parameter. Socket must be connected to have a peer address + * associated. + * + * @param address Pointer to SocketAddress structure. + * @return NSAPI_ERROR_OK on success, negative error code on failure. + */ + virtual nsapi_error_t getpeername(SocketAddress *address) = 0; }; diff --git a/features/netsocket/TLSSocketWrapper.cpp b/features/netsocket/TLSSocketWrapper.cpp index 4aa207fe3e..ef080adc9c 100644 --- a/features/netsocket/TLSSocketWrapper.cpp +++ b/features/netsocket/TLSSocketWrapper.cpp @@ -577,4 +577,12 @@ nsapi_error_t TLSSocketWrapper::listen(int) return NSAPI_ERROR_UNSUPPORTED; } +nsapi_error_t TLSSocketWrapper::getpeername(SocketAddress *address) +{ + if (!_handshake_completed) { + return NSAPI_ERROR_NO_CONNECTION; + } + return _transport->getpeername(address); +} + #endif /* MBEDTLS_SSL_CLI_C */ diff --git a/features/netsocket/TLSSocketWrapper.h b/features/netsocket/TLSSocketWrapper.h index 4accb3c28e..60b86c9676 100644 --- a/features/netsocket/TLSSocketWrapper.h +++ b/features/netsocket/TLSSocketWrapper.h @@ -132,6 +132,7 @@ public: virtual nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen); virtual Socket *accept(nsapi_error_t *error = NULL); virtual nsapi_error_t listen(int backlog = 1); + virtual nsapi_error_t getpeername(SocketAddress *address); #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(DOXYGEN) /** Get own certificate directly from Mbed TLS