diff --git a/features/netsocket/NetworkInterface.h b/features/netsocket/NetworkInterface.h index a1c4e77aa7..1fc05cb0c5 100644 --- a/features/netsocket/NetworkInterface.h +++ b/features/netsocket/NetworkInterface.h @@ -36,6 +36,7 @@ class WiFiInterface; class MeshInterface; class CellularInterface; class EMACInterface; +class PPPInterface; /** Common interface that is shared between network devices. * @@ -338,6 +339,14 @@ public: return 0; } + /** Return pointer to a PPPInterface. + * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. + */ + virtual PPPInterface *pppInterface() + { + return 0; + } + /** Return pointer to a CellularInterface. * @return Pointer to requested interface type or NULL if this class doesn't implement the interface. * @deprecated CellularBase migrated to CellularInterface - use cellularInterface() diff --git a/features/netsocket/OnboardNetworkStack.h b/features/netsocket/OnboardNetworkStack.h index 17e634b562..f68a6518de 100644 --- a/features/netsocket/OnboardNetworkStack.h +++ b/features/netsocket/OnboardNetworkStack.h @@ -22,6 +22,7 @@ #include "NetworkStack.h" #include "EMAC.h" #include "L3IP.h" +#include "PPP.h" /** * mbed OS API for onboard IP stack abstraction @@ -165,11 +166,21 @@ public: return NSAPI_ERROR_OK; }; + virtual nsapi_error_t add_ppp_interface(PPP &ppp, bool default_if, Interface **interface_out) + { + return NSAPI_ERROR_UNSUPPORTED; + }; + virtual nsapi_error_t remove_l3ip_interface(Interface **interface_out) { return NSAPI_ERROR_OK; }; + virtual nsapi_error_t remove_ppp_interface(Interface **interface_out) + { + return NSAPI_ERROR_UNSUPPORTED; + }; + virtual void set_default_interface(OnboardNetworkStack::Interface *interface) { } diff --git a/features/netsocket/PPP.h b/features/netsocket/PPP.h new file mode 100644 index 0000000000..ce53e43201 --- /dev/null +++ b/features/netsocket/PPP.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PPP_H_ +#define PPP_H_ + +#include +#include "Callback.h" +#include "FileHandle.h" +#include "NetStackMemoryManager.h" + +class PPP { +public: + + /** Return the default on-board PPP + * + * Returns the default on-board PPP - this will be target-specific, and + * may not be available on all targets. + */ + static PPP &get_default_instance(); + + virtual ~PPP() {}; + + /** + * Callback to be registered with PPP interface and to be called for received packets + * + * @param buf Received data + */ + //typedef void (*ppp_link_input_fn)(void *data, net_stack_mem_buf_t *buf); + typedef mbed::Callback ppp_link_input_cb_t; + + /** + * Callback to be registered with PPP interface and to be called for link status changes + * + * @param up Link status + */ + //typedef void (*ppp_link_state_change_fn)(void *data, bool up); + typedef mbed::Callback ppp_link_state_change_cb_t; + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() = 0; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the cellular device. + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const = 0; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of characters to copy + */ + virtual void get_ifname(char *name, uint8_t size) const = 0; + + /** + * Sends the packet over the link + * + * That cannot be called from an interrupt context. + * + * @param buf Packet to be sent + * @return True if the packet was sent, false otherwise + */ + virtual bool link_out(net_stack_mem_buf_t *buf, nsapi_ip_stack_t ip_stack) = 0; + + /** + * Initializes the PPP + * + * @return True on success, False in case of an error. + */ + virtual bool power_up() = 0; + + /** + * Deinitializes the PPP + * + */ + virtual void power_down() = 0; + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(ppp_link_input_cb_t input_cb) = 0; + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(ppp_link_state_change_cb_t state_cb) = 0; + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(NetStackMemoryManager &mem_mngr) = 0; + + /** Sets file stream used to communicate with modem + * + * @param stream Pointer to file handle + */ + virtual void set_stream(mbed::FileHandle *stream) = 0; + + /** Sets IP protocol versions of IP stack + * + * @param ip_stack IP protocol version + */ + virtual void set_ip_stack(nsapi_ip_stack_t ip_stack) = 0; + + /** Sets user name and password for PPP protocol + * + * @param uname User name + * @param password Password + */ + virtual void set_credentials(const char *uname, const char *password) = 0; + + /** Gets local IP address + * + * @param version IP address version + * @return IP address + */ + virtual const nsapi_addr_t *get_ip_address(nsapi_version_t version) = 0; + + /** Get the local network mask. + * + * @return Local network mask or null if no network mask has been received. + */ + virtual const nsapi_addr_t *get_netmask() = 0; + + /** Get the local gateway. + * + * @return Local gateway or null if no network mask has been received. + */ + virtual const nsapi_addr_t *get_gateway() = 0; + + /** Gets DNS server address + * + * @param index Server index + */ + virtual const nsapi_addr_t *get_dns_server(uint8_t index) = 0; +}; + +#endif /* PPP_H_ */ diff --git a/features/netsocket/PPPInterface.cpp b/features/netsocket/PPPInterface.cpp new file mode 100644 index 0000000000..69d93f5577 --- /dev/null +++ b/features/netsocket/PPPInterface.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PPPInterface.h" + +using namespace mbed; + +/* Interface implementation */ +PPPInterface::PPPInterface(PPP &ppp, OnboardNetworkStack &stack) : + _ppp(ppp), + _stack(stack), + _interface(NULL), + _blocking(true), + _ip_address(), + _netmask(), + _gateway(), + _stream(NULL), + _ip_stack(DEFAULT_STACK), + _uname(NULL), + _password(NULL) +{ +} + +PPPInterface::~PPPInterface() +{ + _stack.remove_ppp_interface(&_interface); +} + +nsapi_error_t PPPInterface::set_network(const char *ip_address, const char *netmask, const char *gateway) +{ + strncpy(_ip_address, ip_address ? ip_address : "", sizeof(_ip_address)); + _ip_address[sizeof(_ip_address) - 1] = '\0'; + strncpy(_netmask, netmask ? netmask : "", sizeof(_netmask)); + _netmask[sizeof(_netmask) - 1] = '\0'; + strncpy(_gateway, gateway ? gateway : "", sizeof(_gateway)); + _gateway[sizeof(_gateway) - 1] = '\0'; + + return NSAPI_ERROR_OK; +} + +nsapi_error_t PPPInterface::connect() +{ + _ppp.set_stream(_stream); + _ppp.set_ip_stack(_ip_stack); + _ppp.set_credentials(_uname, _password); + + if (!_interface) { + nsapi_error_t err = _stack.add_ppp_interface(_ppp, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + } + + return _interface->bringup(false, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + _ip_stack, + _blocking); +} + +nsapi_error_t PPPInterface::disconnect() +{ + if (_interface) { + return _interface->bringdown(); + } + return NSAPI_ERROR_OK; +} + +const char *PPPInterface::get_ip_address() +{ + if (_interface && _interface->get_ip_address(_ip_address, sizeof(_ip_address))) { + return _ip_address; + } + + return NULL; +} + +const char *PPPInterface::get_netmask() +{ + if (_interface && _interface->get_netmask(_netmask, sizeof(_netmask))) { + return _netmask; + } + + return 0; +} + +const char *PPPInterface::get_gateway() +{ + if (_interface && _interface->get_gateway(_gateway, sizeof(_gateway))) { + return _gateway; + } + + return 0; +} + +char *PPPInterface::get_interface_name(char *interface_name) +{ + if (_interface) { + return _interface->get_interface_name(interface_name); + } + + return NULL; +} + +void PPPInterface::set_as_default() +{ + if (_interface) { + _stack.set_default_interface(_interface); + } +} + +void PPPInterface::set_stream(mbed::FileHandle *stream) +{ + _stream = stream; +} + +void PPPInterface::set_ip_stack(nsapi_ip_stack_t ip_stack) +{ + + _ip_stack = ip_stack; +} + +void PPPInterface::set_credentials(const char *uname, const char *password) +{ + _uname = uname; + _password = password; +} + +NetworkStack *PPPInterface::get_stack() +{ + return &_stack; +} + +void PPPInterface::attach( + mbed::Callback status_cb) +{ + _connection_status_cb = status_cb; + if (_interface) { + _interface->attach(status_cb); + } +} + +nsapi_connection_status_t PPPInterface::get_connection_status() const +{ + if (_interface) { + return _interface->get_connection_status(); + } else { + return NSAPI_STATUS_DISCONNECTED; + } +} + +nsapi_error_t PPPInterface::set_blocking(bool blocking) +{ + _blocking = blocking; + return NSAPI_ERROR_OK; +} + diff --git a/features/netsocket/PPPInterface.h b/features/netsocket/PPPInterface.h new file mode 100644 index 0000000000..33f550eb42 --- /dev/null +++ b/features/netsocket/PPPInterface.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PPP_INTERFACE_H +#define PPP_INTERFACE_H + +#include "nsapi.h" +#include "OnboardNetworkStack.h" +#include "NetworkInterface.h" +#include "PPP.h" + + +/** PPPInterface class + * Implementation of the NetworkInterface for an PPP-service + * + * This class provides the necessary glue logic to create a NetworkInterface + * based on an PPP and an OnboardNetworkStack. + * + */ +class PPPInterface : public virtual NetworkInterface { +public: + /** Create an PPP-based network interface. + * + * The default arguments obtain the default PPP, which will be target- + * dependent (and the target may have some JSON option to choose which + * is the default, if there are multiple). The default stack is configured + * by JSON option nsapi.default-stack. + * + * Due to inability to return errors from the constructor, no real + * work is done until the first call to connect(). + * + * @param ppp Reference to PPP to use + * @param stack Reference to onboard-network stack to use + */ + PPPInterface(PPP &ppp = PPP::get_default_instance(), + OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); + virtual ~PPPInterface(); + + /** Set a static IP address + * + * Configures this network interface to use a static IP address. + * Implicitly disables DHCP, which can be enabled in set_dhcp. + * Requires that the network is disconnected. + * + * @param ip_address Null-terminated representation of the local IP address + * @param netmask Null-terminated representation of the local network mask + * @param gateway Null-terminated representation of the local gateway + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t set_network(const char *ip_address, const char *netmask, const char *gateway); + + /** Start the interface + * @return 0 on success, negative on failure + */ + virtual nsapi_error_t connect(); + + /** Stop the interface + * @return 0 on success, negative on failure + */ + virtual nsapi_error_t disconnect(); + + /** Get the local IP address + * + * @return Null-terminated representation of the local IP address + * or null if no IP address has been received + */ + virtual const char *get_ip_address(); + + /** Get the local network mask + * + * @return Null-terminated representation of the local network mask + * or null if no network mask has been received + */ + virtual const char *get_netmask(); + + /** Get the local gateways + * + * @return Null-terminated representation of the local gateway + * or null if no network mask has been received + */ + virtual const char *get_gateway(); + + /** Get the network interface name + * + * @return Null-terminated representation of the network interface name + * or null if interface not exists + */ + virtual char *get_interface_name(char *interface_name); + + /** Set the network interface as default one + */ + virtual void set_as_default(); + + /** Register callback for status reporting + * + * @param status_cb The callback for status changes + */ + virtual void attach(mbed::Callback status_cb); + + /** Get the connection status + * + * @return The connection status according to nsapi_connection_status_t + */ + virtual nsapi_connection_status_t get_connection_status() const; + + /** Set blocking status of connect() which by default should be blocking + * + * @param blocking true if connect is blocking + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t set_blocking(bool blocking); + + /** Sets file stream used to communicate with modem + * + * @param stream Pointer to file handle + */ + virtual void set_stream(mbed::FileHandle *stream); + + /** Sets IP protocol versions of IP stack + * + * @param ip_stack IP protocol version + */ + virtual void set_ip_stack(nsapi_ip_stack_t ip_stack); + + /** Sets user name and password for PPP protocol + * + * @param uname User name + * @param password Password + */ + virtual void set_credentials(const char *uname, const char *password); + + /** Provide access to the PPP + * + * This should be used with care - normally the network stack would + * control the PPP, so manipulating the PPP while the stack + * is also using it (ie after connect) will likely cause problems. + * + * @return Reference to the PPP in use + */ + PPP &getppp() const + { + return _ppp; + } + + virtual PPPInterface *pppInterface() + { + return this; + } + +protected: + /** Provide access to the underlying stack + * + * @return The underlying network stack + */ + virtual NetworkStack *get_stack(); + + PPP &_ppp; + OnboardNetworkStack &_stack; + OnboardNetworkStack::Interface *_interface; + bool _blocking; + char _ip_address[NSAPI_IPv6_SIZE]; + char _netmask[NSAPI_IPv4_SIZE]; + char _gateway[NSAPI_IPv4_SIZE]; + mbed::Callback _connection_status_cb; + + mbed::FileHandle *_stream; + nsapi_ip_stack_t _ip_stack; + const char *_uname; + const char *_password; + +}; + +#endif