Skip to content
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

Tether API + mm support #2832

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion hal/network/lwip/nat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ int Nat64::natInput(const ip_addr_t* src, const ip_addr_t* dst, L4Protocol proto
uint16_t newMss = lwip_htons(outif->mtu - 40);
uint16_t oldMss = lwip_ntohs(*(uint16_t*)(o + 2));
*(uint16_t*)(o + 2) = newMss;
LOG(ERROR, "Adjusted MSS from %u to %u", (unsigned)oldMss, outif->mtu - 40);
LOG_DEBUG(ERROR, "Adjusted MSS from %u to %u", (unsigned)oldMss, outif->mtu - 40);
}
o += 4;
break;
Expand Down
23 changes: 14 additions & 9 deletions hal/network/lwip/ppp_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ constexpr const char* Client::stateNames_[];
const auto NCP_CLIENT_LCP_ECHO_INTERVAL_SECONDS_DEFAULT = 5;
const auto NCP_CLIENT_LCP_ECHO_INTERVAL_SECONDS_R510 = 240; // 4 minutes (4.25 minutes max)
const auto NCP_CLIENT_LCP_ECHO_MAX_FAILS_DEFAULT = 10;
const auto NCP_CLIENT_LCP_ECHO_MAX_FAILS_DEFAULT_SERVER = 2;
const auto NCP_CLIENT_LCP_ECHO_MAX_FAILS_R510 = 1;

namespace {
Expand Down Expand Up @@ -115,6 +116,10 @@ void Client::init() {
SPARK_ASSERT(pcb_);
if_.flags &= ~NETIF_FLAG_UP;

if (server_) {
if_.name[1] = 's'; // "ps" instead of "pp"
}

LOCK_TCPIP_CORE();
ipcp_ = std::make_unique<Ipcp>(pcb_);
SPARK_ASSERT(ipcp_);
Expand Down Expand Up @@ -154,6 +159,11 @@ void Client::init() {
pcb_->lcp_echos_pending = 0; // reset echo count
}

if (server_) {
pcb_->settings.lcp_echo_interval = NCP_CLIENT_LCP_ECHO_INTERVAL_SECONDS_DEFAULT;
pcb_->settings.lcp_echo_fails = NCP_CLIENT_LCP_ECHO_MAX_FAILS_DEFAULT_SERVER;
}

pppapi_set_notify_phase_callback(pcb_, &Client::notifyPhaseCb);

os_queue_create(&queue_, sizeof(QueueEvent), 5, nullptr);
Expand Down Expand Up @@ -219,7 +229,7 @@ int Client::prepareConnect() {
#if HAL_PLATFORM_PPP_SERVER
LOCK_TCPIP_CORE();
if (server_) {
ppp_set_silent(pcb_, 1);
ppp_set_silent(pcb_, 0);
ppp_set_auth(pcb_, PPPAUTHTYPE_ANY, "particle", "particle");
ppp_set_auth_required(pcb_, 0);
} else {
Expand Down Expand Up @@ -321,15 +331,10 @@ int Client::input(const uint8_t* data, size_t size) {
const size_t header = 19;
if (pppos->in_state == PDDATA && pppos->in_head->len >= header) {
const size_t len = pppos->in_head->len - header;
const char breakAndAt[] = "+++AT";
const char breakAndAtDial[] = "+++ATD";
if (len >= strlen(breakAndAtDial) && !strncmp(((const char*)pppos->in_head->payload) + header, breakAndAtDial, strlen(breakAndAtDial))) {
const char okResponse[] = "\r\nCONNECT\r\n";
output((const uint8_t*)okResponse, strlen(okResponse));
} else if (len >= strlen(breakAndAt) && !strncmp(((const char*)pppos->in_head->payload) + header, breakAndAt, strlen(breakAndAt))) {
const char breakSeq[] = "+++";
if (len >= strlen(breakSeq) && !strncmp(((const char*)pppos->in_head->payload) + header, breakSeq, strlen(breakSeq))) {
pppos_drop_packet(pppos);
const char okResponse[] = "\r\nOK\r\n";
output((const uint8_t*)okResponse, strlen(okResponse));
disconnect();
}
}
}
Expand Down
211 changes: 184 additions & 27 deletions hal/network/lwip/pppservernetif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ LOG_SOURCE_CATEGORY("net.pppserver");
#include "dnsproxy.h"
#include "thread_runner.h"
#include "nat.h"
#include "at_server.h"
#include "device_code.h"
#include "deviceid_hal.h"
#include "bytes2hexbuf.h"
#include "network/ncp/cellular/cellular_network_manager.h"
#include "network/ncp/cellular/cellular_ncp_client.h"
#include "network/ncp/cellular/ncp.h"


using namespace particle::net;

Expand Down Expand Up @@ -171,6 +179,161 @@ int PppServerNetif::start() {

g_natInstance = nat_.get();

AtServerConfig conf;
auto server = std::make_unique<AtServer>();
SPARK_ASSERT(server);
server_ = std::move(server);
conf.stream(serial_.get());
conf.streamTimeout(1000);
server_->init(conf);

server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "H", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CGMI", "Particle"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CGMM", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
char buf[64] = {};
get_device_usb_name(buf, sizeof(buf));
request->sendResponse(buf);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "E0", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto conf = request->server()->config();
conf.echoEnabled(false);
request->server()->init(conf);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "E", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto conf = request->server()->config();
conf.echoEnabled(true);
request->server()->init(conf);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::ONE_INT_ARG, "X", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::ONE_INT_ARG, "V", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::ONE_INT_ARG, "&C", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+GCAP", "+GCAP: +CGSM,+CLTE"));
// +CSCS=?
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CGMR", PP_STR(SYSTEM_VERSION_STRING)));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CGSN", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
uint8_t id[HAL_DEVICE_ID_SIZE] = {};
const auto n = hal_get_device_id(id, sizeof(id));
if (n != HAL_DEVICE_ID_SIZE) {
return SYSTEM_ERROR_UNKNOWN;
}
char deviceId[HAL_DEVICE_ID_SIZE * 2 + 1] = {};
bytes2hexbuf_lower_case(id, sizeof(id), deviceId);
request->sendResponse(deviceId);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CMEE", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "I", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
char buf[64] = {};
get_device_usb_name(buf, sizeof(buf));
request->sendResponse("%s %s", "Particle", buf);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::TEST, "+URAT", "+URAT: (0-9)")); // Pretend to support all
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+URAT", "+URAT: 3")); // Pretend to be LTE
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::TEST, "+CGDCONT", "+CGDCONT: (0-1),\"IP\",,,(0-2),(0-4),(0,1),(0,3),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1)"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CGDCONT", "+CGDCONT: 1,\"IP\",\"particle\",0,0"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CFUN", "+CFUN: 1,0")); // Full functionality
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CMER", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CGACT", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CGACT", "+CGACT: 1,1"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::TEST, "+CMER", "+CMER: (0-3),(0),(0),(0-2),(0,1)"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CPIN", "+CPIN: READY"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CCID", "+CCID: 00000000000000000000"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CIMI", "000000000000000"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CNUM", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "PARTICLE1", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "PARTICLE2", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "Z", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "+CSQ", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
const auto mgr = cellularNetworkManager();
CHECK_TRUE(mgr, SYSTEM_ERROR_UNKNOWN);
const auto client = mgr->ncpClient();
CHECK_TRUE(client, SYSTEM_ERROR_UNKNOWN);
CellularSignalQuality s;
CHECK(client->getSignalQuality(&s));
const auto strn = s.strength();
const auto qual = s.quality();
request->sendResponse("+CSQ: %d,%d", strn, qual);
return 0;
}, nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::TEST, "+IFC", "+IFC: (0-2)(0-2)"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+IFC", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto stream = (SerialStream*)data;
CHECK_TRUE(stream, SYSTEM_ERROR_INVALID_STATE);
if (stream->config() & SERIAL_FLOW_CONTROL_RTS_CTS) {
request->sendResponse("+IFC: 2,2");
} else {
request->sendResponse("+IFC: 0,0");
}
return 0;
}, serial_.get()));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+IFC", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto stream = (SerialStream*)data;
CHECK_TRUE(stream, SYSTEM_ERROR_INVALID_STATE);
int v[2] = {};
CHECK_TRUE(request->scanf("%d,%d", &v[0], &v[1]) == 2, SYSTEM_ERROR_INVALID_ARGUMENT);
if (v[0] == 2 || v[1] == 2) {
auto c = stream->config() | SERIAL_FLOW_CONTROL_RTS_CTS;
return stream->setConfig(c);
} else if (v[0] == 0 || v[1] == 0) {
auto c = stream->config() & (~SERIAL_FLOW_CONTROL_RTS_CTS);
return stream->setConfig(c);
}
return SYSTEM_ERROR_INVALID_ARGUMENT;
}, serial_.get()));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CGEREP", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CREG", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CGREG", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CEREG", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CREG", "+CREG: 2,1")); // Dummy
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CGREG", "+CGREG: 2,1")); // Dummy
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+CEREG", "+CEREG: 2,1")); // Dummy
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CRC", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+CCWA", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+COPS", nullptr));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+COPS", "+COPS: 0,0,\"Particle\""));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::TEST, "+IPR", "+IPR: (0,9600,19200,38400,57600,115200,230400,460800,921600),()"));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::READ, "+IPR", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto stream = (SerialStream*)data;
CHECK_TRUE(stream, SYSTEM_ERROR_INVALID_STATE);
request->sendResponse("+IPR: %u", stream->baudrate());
return 0;
}, serial_.get()));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WRITE, "+IPR", [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto stream = (SerialStream*)data;
CHECK_TRUE(stream, SYSTEM_ERROR_INVALID_STATE);
int v = 0;
CHECK_TRUE(request->scanf("%d", &v) == 1, SYSTEM_ERROR_INVALID_ARGUMENT);
CHECK_TRUE(v > 0, SYSTEM_ERROR_INVALID_ARGUMENT);
CHECK(stream->setBaudRate(v));
return 0;
}, serial_.get()));
auto connectRequest = [](AtServerRequest* request, AtServerCommandType type, const char* command, void* data) -> int {
auto client = (net::ppp::Client*)data;
request->sendResponse("CONNECT %u", ((SerialStream*)request->server()->config().stream())->baudrate());
request->setFinalResponse(AtServerRequest::CONNECT);
request->server()->suspend();
client->setOutputCallback([](const uint8_t* data, size_t size, void* ctx) -> int {
// LOG(INFO, "output %u", size);
auto c = (Stream*)ctx;
int r = c->writeAll((const char*)data, size, 1000);
if (!r) {
return size;
}
return r;
}, request->server()->config().stream());
client->connect();
client->notifyEvent(ppp::Client::EVENT_LOWER_UP);
return 0;
};
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::WILDCARD, "D*", connectRequest, &client_));
server_->addCommandHandler(AtServerCommandHandler(AtServerCommandType::EXEC, "D", connectRequest, &client_));

SPARK_ASSERT(os_thread_create(&thread_, "pppserver", OS_THREAD_PRIORITY_NETWORK, &PppServerNetif::loop, this, OS_THREAD_STACK_SIZE_DEFAULT_HIGH) == 0);
return 0;
}
Expand All @@ -181,21 +344,28 @@ if_t PppServerNetif::interface() {

void PppServerNetif::loop(void* arg) {
PppServerNetif* self = static_cast<PppServerNetif*>(arg);
unsigned int timeout = 1000;
while(!self->exit_) {
auto ev = self->serial_->waitEvent(SerialStream::READABLE | PPP_SERVER_NETIF_EVENT_EXIT, timeout);
auto ev = self->serial_->waitEvent(PPP_SERVER_NETIF_EVENT_EXIT, 0);
if (ev & PPP_SERVER_NETIF_EVENT_EXIT) {
//break;
break;
}
if (!self->server_->suspended()) {
self->server_->process();
} else {
auto ev = self->serial_->waitEvent(SerialStream::READABLE | PPP_SERVER_NETIF_EVENT_EXIT, 1000);
if (ev & PPP_SERVER_NETIF_EVENT_EXIT) {
break;
}

if (ev & SerialStream::READABLE) {
char tmp[256] = {};
while (self->serial_->availForRead() > 0) {
int sz = self->serial_->read(tmp, sizeof(tmp));
// LOG(INFO, "input %d", sz);
auto r = self->client_.input((const uint8_t*)tmp, sz);
(void)r;
// LOG(INFO, "input result = %d", r);
if (ev & SerialStream::READABLE) {
char tmp[256] = {};
while (self->serial_->availForRead() > 0) {
int sz = self->serial_->read(tmp, sizeof(tmp));
// LOG(INFO, "input %d", sz);
auto r = self->client_.input((const uint8_t*)tmp, sz);
(void)r;
// LOG(INFO, "input result = %d", r);
}
}
}
}
Expand All @@ -206,24 +376,11 @@ void PppServerNetif::loop(void* arg) {
}

int PppServerNetif::up() {
LOG(INFO, "up");
CHECK(start());
client_.setOutputCallback([](const uint8_t* data, size_t size, void* ctx) -> int {
// LOG(INFO, "output %u", size);
auto c = (PppServerNetif*)ctx;
int r = c->serial_->writeAll((const char*)data, size, 1000);
if (!r) {
return size;
}
return r;
}, this);
client_.connect();
client_.notifyEvent(ppp::Client::EVENT_LOWER_UP);
return SYSTEM_ERROR_NONE;
}

int PppServerNetif::down() {
LOG(INFO, "down");
if (dnsRunner_) {
dnsRunner_->destroy();
}
Expand All @@ -236,7 +393,6 @@ int PppServerNetif::down() {
}

int PppServerNetif::powerUp() {
LOG(INFO, "powerUp");
// FIXME: As long as the interface is initialized,
// it must have been powered up as of right now.
// The system network manager transit the interface to powering up,
Expand All @@ -246,7 +402,6 @@ int PppServerNetif::powerUp() {
}

int PppServerNetif::powerDown() {
LOG(INFO, "powerDown");
int ret = down();
// FIXME: This don't really power off the module.
// Notify the system network manager that the module is powered down
Expand Down Expand Up @@ -302,7 +457,6 @@ void PppServerNetif::pppEventHandlerCb(particle::net::ppp::Client* c, uint64_t e
}

void PppServerNetif::pppEventHandler(uint64_t ev, int data) {
LOG(INFO, "ppp event %llx %d", ev, data);
if (ev == particle::net::ppp::Client::EVENT_UP) {
unsigned mtu = client_.getIf()->mtu;
LOG(TRACE, "Negotiated MTU: %u", mtu);
Expand All @@ -320,6 +474,9 @@ void PppServerNetif::pppEventHandler(uint64_t ev, int data) {
dns_->destroy();
}
nat_->disable(interface());
// Drop back into AT mode
client_.notifyEvent(ppp::Client::EVENT_LOWER_DOWN);
server_->resume();
} else if (ev == particle::net::ppp::Client::EVENT_CONNECTING) {
} else if (ev == particle::net::ppp::Client::EVENT_ERROR) {
LOG(ERROR, "PPP error event data=%d", data);
Expand Down
3 changes: 3 additions & 0 deletions hal/network/lwip/pppservernetif.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <lwip/pbuf.h>
#include "ppp_client.h"
#include "serial_stream.h"
#include "at_server.h"

#ifdef __cplusplus

Expand Down Expand Up @@ -102,6 +103,8 @@ class PppServerNetif : public BaseNetif {
std::unique_ptr<::particle::ThreadRunner> dnsRunner_;
std::unique_ptr<particle::net::nat::Nat64> nat_;
if_req_ppp_server_uart_settings settings_;
std::unique_ptr<AtServer> server_;

};

} } // namespace particle::net
Expand Down
Loading