mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-03-21 17:44:21 -05:00
Refactoring library and example. Renaming ISP => PPP
This commit is contained in:
parent
b7f5288d4c
commit
c41d99562a
10
README.md
10
README.md
|
|
@ -448,19 +448,19 @@ Name | Return type | Description
|
|||
`deactivate()` | - | Deactivates the library, resetting the serial mode to GPIO. Calling `shutdown()` first is recommended, but the adapter will put itself in sleep mode after 3 seconds anyway.
|
||||
`shutdown()` | **bool** | Gracefully shuts down the adapter, closing all connections. After some time, the state will be changed to `SHUTDOWN`, and only then it's safe to call `deactivate()`.
|
||||
`call(phoneNumber)` | **bool** | Initiates a P2P connection with a `phoneNumber`. After some time, the state will be `CALL_ESTABLISHED` (or `ACTIVE_SESSION` if the connection fails or ends). In REON/libmobile the phone number can be a number assigned by the relay server, or a 12-digit IPv4 address (for example, `"127000000001"` would be `127.0.0.1`).
|
||||
`callISP(password, loginId)` | **bool** | Calls the ISP number registered in the adapter configuration, or a default number if the adapter hasn't been configured. Then, performs a login operation using the provided `password` and `loginId`. After some time, the state will be `ISP_ACTIVE`. If `loginId` is empty and the adapter has been configured, it will use the one stored in the configuration. Both parameters are null-terminated strings (max `32` characters).
|
||||
`callISP(password, loginId)` | **bool** | Calls the ISP number registered in the adapter configuration, or a default number if the adapter hasn't been configured. Then, performs a login operation using the provided `password` and `loginId`. After some time, the state will be `PPP_ACTIVE`. If `loginId` is empty and the adapter has been configured, it will use the one stored in the configuration. Both parameters are null-terminated strings (max `32` characters).
|
||||
`dnsQuery(domainName, result)` | **bool** | Looks up the IPv4 address for a `domainName` (a null-terminated string, max `253` characters). The `result` is a pointer to a `LinkMobile::DNSQuery` struct that will be filled with the result. When the request is completed, the `completed` field will be `true`. If an IP address was found, the `success` field will be `true` and the `ipv4` field can be read as a 4-byte address.
|
||||
`openConnection(ip, port, type, result)` | **bool** | Opens a TCP/UDP (`type`) connection at the given `ip` (4-byte address) on the given `port`. The `result` is a pointer to a `LinkMobile::OpenConn` struct that will be filled with the result. When the request is completed, the `completed` field will be `true`. If the connection was successful, the `success` field will be `true` and the `connectionId` field can be used when calling the `transfer(...)` method. Only `2` connections can be opened at the same time.
|
||||
`closeConnection(connectionId, type, result)` | **bool** | Closes an active TCP/UDP (`type`) connection. The `result` is a pointer to a `LinkMobile::CloseConn` struct that will be filled with the result. When the request is completed, the `completed` field will be `true`. If the connection was closed correctly, the `success` field will be `true`.
|
||||
`transfer(dataToSend, result, [connectionId])` | **bool** | Requests a data transfer (up to `254` bytes) and responds the received data. The transfer can be done with the other node in a P2P connection, or with any open TCP/UDP connection if an ISP session is active. In the case of a TCP/UDP connection, the `connectionId` must be provided. The `result` is a pointer to a `LinkMobile::DataTransfer` struct that will be filled with the received data. It can also point to `dataToSend` to reuse the struct. When the request is completed, the `completed` field will be `true`. If the transfer was successful, the `success` field will be `true`. If not, you can assume that the connection was closed.
|
||||
`transfer(dataToSend, result, [connectionId])` | **bool** | Requests a data transfer (up to `254` bytes) and responds the received data. The transfer can be done with the other node in a P2P connection, or with any open TCP/UDP connection if a PPP session is active. In the case of a TCP/UDP connection, the `connectionId` must be provided. The `result` is a pointer to a `LinkMobile::DataTransfer` struct that will be filled with the received data. It can also point to `dataToSend` to reuse the struct. When the request is completed, the `completed` field will be `true`. If the transfer was successful, the `success` field will be `true`. If not, you can assume that the connection was closed.
|
||||
`waitFor(asyncRequest)` | **bool** | Waits for `asyncRequest` to be completed. Returns `true` if the request was completed && successful, and the adapter session is still alive. Otherwise, it returns `false`. The `asyncRequest` is a pointer to a `LinkMobile::DNSQuery`, `LinkMobile::OpenConn`, `LinkMobile::CloseConn`, or `LinkMobile::DataTransfer`.
|
||||
`hangUp()` | **bool** | Hangs up the current P2P or ISP call. Closes all connections.
|
||||
`hangUp()` | **bool** | Hangs up the current P2P or PPP call. Closes all connections.
|
||||
`readConfiguration(configurationData)` | **bool** | Retrieves the adapter configuration, and puts it in the `configurationData` struct. If the adapter has an active session, the data is already loaded, so it's instantaneous.
|
||||
`getState()` | **LinkMobile::State** | Returns the current state (one of `LinkMobile::State::NEEDS_RESET`, `LinkMobile::State::PINGING`, `LinkMobile::State::WAITING_TO_START`, `LinkMobile::State::STARTING_SESSION`, `LinkMobile::State::ACTIVATING_SIO32`, `LinkMobile::State::WAITING_32BIT_SWITCH`, `LinkMobile::State::READING_CONFIGURATION`, `LinkMobile::State::SESSION_ACTIVE`, `LinkMobile::State::CALL_REQUESTED`, `LinkMobile::State::CALLING`, `LinkMobile::State::CALL_ESTABLISHED`, `LinkMobile::State::ISP_CALL_REQUESTED`, `LinkMobile::State::ISP_CALLING`, `LinkMobile::State::ISP_LOGIN`, `LinkMobile::State::ISP_ACTIVE`, `LinkMobile::State::SHUTDOWN_REQUESTED`, `LinkMobile::State::ENDING_SESSION`, `LinkMobile::State::WAITING_8BIT_SWITCH`, or `LinkMobile::State::SHUTDOWN`).
|
||||
`getState()` | **LinkMobile::State** | Returns the current state (one of `LinkMobile::State::NEEDS_RESET`, `LinkMobile::State::PINGING`, `LinkMobile::State::WAITING_TO_START`, `LinkMobile::State::STARTING_SESSION`, `LinkMobile::State::ACTIVATING_SIO32`, `LinkMobile::State::WAITING_32BIT_SWITCH`, `LinkMobile::State::READING_CONFIGURATION`, `LinkMobile::State::SESSION_ACTIVE`, `LinkMobile::State::CALL_REQUESTED`, `LinkMobile::State::CALLING`, `LinkMobile::State::CALL_ESTABLISHED`, `LinkMobile::State::ISP_CALL_REQUESTED`, `LinkMobile::State::ISP_CALLING`, `LinkMobile::State::PPP_LOGIN`, `LinkMobile::State::PPP_ACTIVE`, `LinkMobile::State::SHUTDOWN_REQUESTED`, `LinkMobile::State::ENDING_SESSION`, `LinkMobile::State::WAITING_8BIT_SWITCH`, or `LinkMobile::State::SHUTDOWN`).
|
||||
`getRole()` | **LinkMobile::Role** | Returns the current role in the P2P connection (one of `LinkMobile::Role::NO_P2P_CONNECTION`, `LinkMobile::Role::CALLER`, or `LinkMobile::Role::RECEIVER`).
|
||||
`isConfigurationValid()` | **int** | Returns whether the adapter has been configured or not. Returns `1` = yes, `0` = no, `-1` = unknown (no session active).
|
||||
`isConnectedP2P()` | **bool** | Returns `true` if a P2P call is established (the state is `CALL_ESTABLISHED`).
|
||||
`isConnectedISP()` | **bool** | Returns `true` if an ISP call is active (the state is `ISP_ACTIVE`).
|
||||
`isConnectedPPP()` | **bool** | Returns `true` if a PPP session is active (the state is `PPP_ACTIVE`).
|
||||
`isSessionActive()` | **bool** | Returns `true` if the session is active.
|
||||
`canShutdown()` | **bool** | Returns `true` if there's an active session and there's no previous shutdown requests.
|
||||
`getDataSize()` | **LinkSPI::DataSize** | Returns the current operation mode (`LinkSPI::DataSize`).
|
||||
|
|
|
|||
|
|
@ -3,42 +3,27 @@
|
|||
// (0) Include the header
|
||||
#include "../../../lib/LinkMobile.hpp"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <tonc.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "../../_lib/interrupt.h"
|
||||
|
||||
void transfer(LinkMobile::DataTransfer& dataTransfer, std::string text);
|
||||
std::string readConfiguration();
|
||||
std::string getNumberInput();
|
||||
std::string getPasswordInput();
|
||||
std::string getDomainInput();
|
||||
std::string getTextInput(std::string& field,
|
||||
u32 maxChars,
|
||||
std::string inputName,
|
||||
std::string defaultValue,
|
||||
std::string defaultValueName);
|
||||
std::string getInput(std::string& field,
|
||||
u32 maxChars,
|
||||
std::string inputName,
|
||||
std::vector<std::vector<std::string>> rows,
|
||||
std::vector<std::vector<std::string>> altRows,
|
||||
std::string defaultValue,
|
||||
std::string defaultValueName,
|
||||
std::string altName);
|
||||
std::string getStateString(LinkMobile::State state);
|
||||
std::string getErrorString(LinkMobile::Error error);
|
||||
std::string getErrorTypeString(LinkMobile::Error::Type errorType);
|
||||
std::string getResultString(LinkMobile::CommandResult cmdResult);
|
||||
void log(std::string text);
|
||||
std::string toStr(char* chars, int size);
|
||||
void wait(u32 verticalLines);
|
||||
bool didPress(u16 key, bool& pressed);
|
||||
void waitForA();
|
||||
// One transfer for every N frames
|
||||
constexpr static int TRANSFER_FREQUENCY = 30;
|
||||
|
||||
bool isConnected = false;
|
||||
LinkMobile::DataTransfer dataTransfer;
|
||||
LinkMobile::DataTransfer lastCompletedTransfer;
|
||||
LinkMobile::DNSQuery dnsQuery;
|
||||
bool waitingDNS = false;
|
||||
std::string outgoingData = "";
|
||||
u32 counter = 0;
|
||||
u32 frameCounter = 0;
|
||||
std::string output = "";
|
||||
bool hasError = false;
|
||||
u16 keys = 0;
|
||||
|
||||
template <typename I>
|
||||
[[nodiscard]] std::string toHex(I w, size_t hex_len = sizeof(I) << 1);
|
||||
bool left = false, right = false, up = false, down = false;
|
||||
bool a = false, b = false, l = false, r = false;
|
||||
bool start = false, select = false;
|
||||
|
|
@ -57,12 +42,10 @@ int main() {
|
|||
init();
|
||||
|
||||
start:
|
||||
// Options
|
||||
log("LinkMobile_demo (v7.0.0)\n\n"
|
||||
"Press A to start");
|
||||
log("LinkMobile_demo (v7.0.0)\n\nPress A to start");
|
||||
waitForA();
|
||||
|
||||
// (1) Create a LinkWireless instance
|
||||
// (1) Create a LinkMobile instance
|
||||
linkMobile = new LinkMobile();
|
||||
|
||||
// (2) Add the required interrupt service routines
|
||||
|
|
@ -77,178 +60,25 @@ start:
|
|||
// (3) Initialize the library
|
||||
linkMobile->activate();
|
||||
|
||||
bool isConnected = false;
|
||||
LinkMobile::DataTransfer dataTransfer;
|
||||
LinkMobile::DataTransfer lastCompletedTransfer;
|
||||
LinkMobile::DNSQuery dnsQuery;
|
||||
bool waitingDNS = false;
|
||||
std::string outgoingData = "";
|
||||
u32 counter = 0;
|
||||
u32 frameCounter = 0;
|
||||
|
||||
while (true) {
|
||||
// (one transfer for every N frames)
|
||||
constexpr static int TRANSFER_FREQUENCY = 30;
|
||||
keys = ~REG_KEYS & KEY_ANY;
|
||||
hasError = linkMobile->getError().type != LinkMobile::Error::Type::NONE;
|
||||
output = "State = " + getStateString(linkMobile->getState()) + "\n";
|
||||
|
||||
u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
|
||||
std::string output = "";
|
||||
bool shouldWaitForA = false;
|
||||
output += "State = " + getStateString(linkMobile->getState()) + "\n";
|
||||
|
||||
auto error = linkMobile->getError();
|
||||
bool hasError = error.type != LinkMobile::Error::NONE;
|
||||
if (hasError) {
|
||||
output += getErrorString(error);
|
||||
output += "\n (SELECT = stop)";
|
||||
} else if (linkMobile->getState() == LinkMobile::State::SESSION_ACTIVE) {
|
||||
output += "\nL = Read configuration";
|
||||
output += "\nR = Call someone";
|
||||
output += "\nSTART = Call the ISP";
|
||||
output += "\n\n (A = ok)\n (SELECT = stop)";
|
||||
} else {
|
||||
if (linkMobile->isConnectedP2P()) {
|
||||
output += "\n (A = send)";
|
||||
output += "\n (L = hang up)";
|
||||
} else if (linkMobile->isConnectedISP()) {
|
||||
output += "\n (A = DNS query)";
|
||||
output += "\n (L = hang up)";
|
||||
}
|
||||
output += "\n (SELECT = stop)";
|
||||
}
|
||||
printMenu();
|
||||
|
||||
if (linkMobile->isConnectedP2P()) {
|
||||
if (!isConnected) {
|
||||
isConnected = true;
|
||||
outgoingData = linkMobile->getRole() == LinkMobile::Role::CALLER
|
||||
? "caller!!!"
|
||||
: "receiver!!!";
|
||||
transfer(dataTransfer, outgoingData);
|
||||
}
|
||||
if (dataTransfer.completed) {
|
||||
if (dataTransfer.size > 0)
|
||||
lastCompletedTransfer = dataTransfer;
|
||||
dataTransfer.completed = false;
|
||||
}
|
||||
|
||||
if (keys & KEY_A) {
|
||||
counter++;
|
||||
outgoingData =
|
||||
(linkMobile->getRole() == LinkMobile::Role::CALLER ? "caller: "
|
||||
: "receiver: ") +
|
||||
std::to_string(counter);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
if (frameCounter >= TRANSFER_FREQUENCY) {
|
||||
frameCounter = 0;
|
||||
transfer(dataTransfer, outgoingData);
|
||||
}
|
||||
|
||||
if (lastCompletedTransfer.completed) {
|
||||
char received[LINK_MOBILE_MAX_USER_TRANSFER_LENGTH];
|
||||
for (u32 i = 0; i < lastCompletedTransfer.size; i++)
|
||||
received[i] = lastCompletedTransfer.data[i];
|
||||
received[lastCompletedTransfer.size] = '\0';
|
||||
output += "\n\n>> " + std::string(outgoingData);
|
||||
output += "\n<< " + std::string(received);
|
||||
}
|
||||
} else if (linkMobile->isConnectedISP()) {
|
||||
if (!isConnected)
|
||||
isConnected = true;
|
||||
|
||||
if (waitingDNS && dnsQuery.completed) {
|
||||
waitingDNS = false;
|
||||
log("DNS Response:\n " + std::to_string(dnsQuery.ipv4[0]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[1]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[2]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[3]) + "\n\n" +
|
||||
(dnsQuery.success ? "OK!\nLet's connect to it on TCP 80!"
|
||||
: "DNS query failed!"));
|
||||
waitForA();
|
||||
|
||||
// (9) Open connections
|
||||
log("Connecting...");
|
||||
LinkMobile::OpenConn openConn;
|
||||
linkMobile->openConnection(dnsQuery.ipv4, 80,
|
||||
LinkMobile::ConnectionType::TCP, &openConn);
|
||||
|
||||
while (linkMobile->isConnectedISP() && !openConn.completed)
|
||||
VBlankIntrWait();
|
||||
if (!linkMobile->isConnectedISP())
|
||||
continue;
|
||||
|
||||
if (openConn.success) {
|
||||
LinkMobile::DataTransfer http;
|
||||
std::string request = std::string("GET / HTTP/1.1\r\nHost: ") +
|
||||
selectedDomain + "\r\n\r\n";
|
||||
for (u32 i = 0; i < request.size(); i++)
|
||||
http.data[i] = request[i];
|
||||
http.size = request.size();
|
||||
linkMobile->transfer(http, &http, openConn.connectionId);
|
||||
log("Connected! (" + std::to_string(openConn.connectionId) +
|
||||
") Requesting /");
|
||||
|
||||
while (linkMobile->isConnectedISP() && !http.completed)
|
||||
VBlankIntrWait();
|
||||
if (!linkMobile->isConnectedISP())
|
||||
continue;
|
||||
|
||||
if (http.success) {
|
||||
u32 retry = 1;
|
||||
while (http.size == 0) {
|
||||
log("Re-transfering... " + std::to_string(retry));
|
||||
LinkMobile::DataTransfer retryy =
|
||||
LinkMobile::DataTransfer{.data = {}, .size = 0};
|
||||
for (u32 i = 0; i < request.size(); i++)
|
||||
retryy.data[i] = request[i];
|
||||
retryy.size = request.size();
|
||||
linkMobile->transfer(retryy, &http, openConn.connectionId);
|
||||
while (linkMobile->isConnectedISP() && !http.completed)
|
||||
VBlankIntrWait();
|
||||
if (!linkMobile->isConnectedISP())
|
||||
break;
|
||||
if (!http.success)
|
||||
break;
|
||||
retry++;
|
||||
}
|
||||
if (!linkMobile->isConnectedISP())
|
||||
continue;
|
||||
if (!http.success) {
|
||||
log("HTTP failed!");
|
||||
waitForA();
|
||||
continue;
|
||||
}
|
||||
|
||||
log("Internet on GBA! yay\n\n" + std::string((char*)http.data));
|
||||
waitForA();
|
||||
} else {
|
||||
log("HTTP request failed!");
|
||||
waitForA();
|
||||
}
|
||||
} else {
|
||||
log("Connection to \"" + selectedDomain + "\" failed!");
|
||||
waitForA();
|
||||
}
|
||||
}
|
||||
|
||||
output += waitingDNS ? "\n\nWaiting DNS..." : "";
|
||||
} else {
|
||||
if (isConnected) {
|
||||
isConnected = false;
|
||||
dataTransfer = {};
|
||||
lastCompletedTransfer = {};
|
||||
dnsQuery = {};
|
||||
waitingDNS = false;
|
||||
counter = 0;
|
||||
frameCounter = 0;
|
||||
outgoingData = "";
|
||||
}
|
||||
handleP2P();
|
||||
} else if (linkMobile->isConnectedPPP()) {
|
||||
handlePPP();
|
||||
} else if (isConnected) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
// SELECT = stop
|
||||
if (didPress(KEY_SELECT, select)) {
|
||||
bool didShutdown = linkMobile->getState() == LinkMobile::State::SHUTDOWN;
|
||||
|
||||
if (hasError || didShutdown) {
|
||||
linkMobile->deactivate();
|
||||
interrupt_disable(INTR_VBLANK);
|
||||
|
|
@ -264,7 +94,7 @@ start:
|
|||
|
||||
goto start;
|
||||
} else if (linkMobile->canShutdown()) {
|
||||
// (11) Turn off the adapter
|
||||
// (12) Turn off the adapter
|
||||
linkMobile->shutdown();
|
||||
}
|
||||
}
|
||||
|
|
@ -273,8 +103,8 @@ start:
|
|||
case LinkMobile::State::SESSION_ACTIVE: {
|
||||
// L = Read Configuration
|
||||
if (didPress(KEY_L, l)) {
|
||||
output = readConfiguration();
|
||||
shouldWaitForA = true;
|
||||
readConfiguration();
|
||||
waitForA();
|
||||
}
|
||||
|
||||
// R = Call someone
|
||||
|
|
@ -304,7 +134,7 @@ start:
|
|||
}
|
||||
break;
|
||||
}
|
||||
case LinkMobile::State::ISP_ACTIVE: {
|
||||
case LinkMobile::State::PPP_ACTIVE: {
|
||||
// A = DNS query
|
||||
if (didPress(KEY_A, a) && !waitingDNS) {
|
||||
std::string domain = getDomainInput();
|
||||
|
|
@ -327,29 +157,140 @@ start:
|
|||
|
||||
VBlankIntrWait();
|
||||
log(output);
|
||||
if (shouldWaitForA)
|
||||
waitForA();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void transfer(LinkMobile::DataTransfer& dataTransfer, std::string text) {
|
||||
// (5) Send/receive data
|
||||
for (u32 i = 0; i < text.size(); i++)
|
||||
dataTransfer.data[i] = text[i];
|
||||
dataTransfer.data[text.size()] = '\0';
|
||||
dataTransfer.size = text.size() + 1;
|
||||
linkMobile->transfer(dataTransfer, &dataTransfer);
|
||||
void handleP2P() {
|
||||
if (!isConnected) {
|
||||
// First transfer
|
||||
isConnected = true;
|
||||
outgoingData = linkMobile->getRole() == LinkMobile::Role::CALLER
|
||||
? "caller!!!"
|
||||
: "receiver!!!";
|
||||
transfer(dataTransfer, outgoingData, 0xff, true);
|
||||
}
|
||||
|
||||
if (dataTransfer.completed) {
|
||||
// Save a copy of last received data
|
||||
if (dataTransfer.size > 0)
|
||||
lastCompletedTransfer = dataTransfer;
|
||||
dataTransfer.completed = false;
|
||||
}
|
||||
|
||||
if (keys & KEY_A) {
|
||||
// `A` increments the counter
|
||||
counter++;
|
||||
outgoingData =
|
||||
(linkMobile->getRole() == LinkMobile::Role::CALLER ? "caller: "
|
||||
: "receiver: ") +
|
||||
std::to_string(counter);
|
||||
}
|
||||
|
||||
frameCounter++;
|
||||
if (frameCounter >= TRANSFER_FREQUENCY) {
|
||||
// Transfer every N frames
|
||||
frameCounter = 0;
|
||||
transfer(dataTransfer, outgoingData, 0xff, true);
|
||||
}
|
||||
|
||||
if (lastCompletedTransfer.completed) {
|
||||
// Show received data
|
||||
output += "\n\n>> " + std::string(outgoingData);
|
||||
output += "\n<< " + std::string((char*)lastCompletedTransfer.data);
|
||||
// (LinkMobile zero-pads an extra byte, so this is safe)
|
||||
}
|
||||
}
|
||||
|
||||
std::string readConfiguration() {
|
||||
void handlePPP() {
|
||||
if (!isConnected)
|
||||
isConnected = true;
|
||||
|
||||
if (waitingDNS && dnsQuery.completed) {
|
||||
waitingDNS = false;
|
||||
log("DNS Response:\n " + std::to_string(dnsQuery.ipv4[0]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[1]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[2]) + "." +
|
||||
std::to_string(dnsQuery.ipv4[3]) + "\n\n" +
|
||||
(dnsQuery.success ? "OK!\nLet's connect to it on TCP 80!"
|
||||
: "DNS query failed!"));
|
||||
waitForA();
|
||||
if (!dnsQuery.success)
|
||||
return;
|
||||
|
||||
// (9) Open connections
|
||||
log("Connecting...");
|
||||
LinkMobile::OpenConn openConn;
|
||||
linkMobile->openConnection(dnsQuery.ipv4, 80,
|
||||
LinkMobile::ConnectionType::TCP, &openConn);
|
||||
if (!linkMobile->waitFor(&openConn)) {
|
||||
log("Connection failed!");
|
||||
waitForA();
|
||||
return;
|
||||
}
|
||||
|
||||
// HTTP request
|
||||
|
||||
LinkMobile::DataTransfer http;
|
||||
std::string request =
|
||||
std::string("GET / HTTP/1.1\r\nHost: ") + selectedDomain + "\r\n\r\n";
|
||||
std::string output = "";
|
||||
u32 chunk = 1;
|
||||
u32 retry = 1;
|
||||
do {
|
||||
log("Downloading... (" + std::to_string(chunk) + ", " +
|
||||
std::to_string(retry) + ")\n (hold START = close conn)\n\n" + output);
|
||||
|
||||
if (didPress(KEY_START, start)) {
|
||||
log("Closing...");
|
||||
LinkMobile::CloseConn closeConn;
|
||||
linkMobile->closeConnection(
|
||||
openConn.connectionId, LinkMobile::ConnectionType::TCP, &closeConn);
|
||||
linkMobile->waitFor(&closeConn);
|
||||
return;
|
||||
}
|
||||
|
||||
transfer(http, request, openConn.connectionId);
|
||||
if (!linkMobile->waitFor(&http)) {
|
||||
log("Connection closed:\n " + std::to_string(chunk) + " packets!\n\n" +
|
||||
output);
|
||||
waitForA();
|
||||
return;
|
||||
}
|
||||
|
||||
if (http.size > 0) {
|
||||
chunk++;
|
||||
output += std::string((char*)http.data);
|
||||
// (LinkMobile zero-pads an extra byte, so this is safe)
|
||||
}
|
||||
|
||||
http = {};
|
||||
request = "";
|
||||
retry++;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
output += waitingDNS ? "\n\nWaiting DNS..." : "";
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
isConnected = false;
|
||||
dataTransfer = {};
|
||||
lastCompletedTransfer = {};
|
||||
dnsQuery = {};
|
||||
waitingDNS = false;
|
||||
counter = 0;
|
||||
frameCounter = 0;
|
||||
outgoingData = "";
|
||||
}
|
||||
|
||||
void readConfiguration() {
|
||||
LinkMobile::ConfigurationData data;
|
||||
if (!linkMobile->readConfiguration(data))
|
||||
return "Read failed :(";
|
||||
log("Read failed :(");
|
||||
|
||||
return (
|
||||
"Magic:\n " + toStr(data.magic, 2) + ", $" +
|
||||
log("Magic:\n " + toStr(data.magic, 2) + ", $" +
|
||||
toHex(data.registrationState) + "\nPrimary DNS:\n " +
|
||||
std::to_string(data.primaryDNS[0]) + "." +
|
||||
std::to_string(data.primaryDNS[1]) + "." +
|
||||
|
|
@ -368,6 +309,42 @@ std::string readConfiguration() {
|
|||
: "SIO8"));
|
||||
}
|
||||
|
||||
void printMenu() {
|
||||
auto error = linkMobile->getError();
|
||||
|
||||
if (hasError) {
|
||||
output += getErrorString(error);
|
||||
output += "\n (SELECT = stop)";
|
||||
} else if (linkMobile->getState() == LinkMobile::State::SESSION_ACTIVE) {
|
||||
output += "\nL = Read configuration";
|
||||
output += "\nR = Call someone";
|
||||
output += "\nSTART = Call the ISP";
|
||||
output += "\n\n (A = ok)\n (SELECT = stop)";
|
||||
} else {
|
||||
if (linkMobile->isConnectedP2P()) {
|
||||
output += "\n (A = send)";
|
||||
output += "\n (L = hang up)";
|
||||
} else if (linkMobile->isConnectedPPP()) {
|
||||
output += "\n (A = DNS query)";
|
||||
output += "\n (L = hang up)";
|
||||
}
|
||||
output += "\n (SELECT = stop)";
|
||||
}
|
||||
}
|
||||
|
||||
void transfer(LinkMobile::DataTransfer& dataTransfer,
|
||||
std::string text,
|
||||
u8 connectionId,
|
||||
bool addNullTerminator) {
|
||||
// (5) Send/receive data
|
||||
for (u32 i = 0; i < text.size(); i++)
|
||||
dataTransfer.data[i] = text[i];
|
||||
if (addNullTerminator)
|
||||
dataTransfer.data[text.size()] = '\0';
|
||||
dataTransfer.size = text.size() + addNullTerminator;
|
||||
linkMobile->transfer(dataTransfer, &dataTransfer, connectionId);
|
||||
}
|
||||
|
||||
std::string getNumberInput() {
|
||||
std::vector<std::vector<std::string>> rows;
|
||||
rows.push_back({"1", "2", "3"});
|
||||
|
|
@ -377,24 +354,25 @@ std::string getNumberInput() {
|
|||
std::vector<std::vector<std::string>> altRows;
|
||||
|
||||
return getInput(selectedNumber, LINK_MOBILE_MAX_PHONE_NUMBER_LENGTH,
|
||||
"a number", rows, altRows, "127000000001", "localhost", "");
|
||||
"a number", rows, altRows, {{"localhost", "127000000001"}},
|
||||
"");
|
||||
}
|
||||
|
||||
std::string getPasswordInput() {
|
||||
return getTextInput(selectedPassword, LINK_MOBILE_MAX_PASSWORD_LENGTH,
|
||||
"your password", "pass123", "pass123");
|
||||
"your password", {{"pass123", "pass123"}});
|
||||
}
|
||||
|
||||
std::string getDomainInput() {
|
||||
return getTextInput(selectedDomain, LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH,
|
||||
"a domain name", "something.com", "something.com");
|
||||
return getTextInput(
|
||||
selectedDomain, LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH, "a domain name",
|
||||
{{"something.com", "something.com"}, {"localhost", "localhost"}});
|
||||
}
|
||||
|
||||
std::string getTextInput(std::string& field,
|
||||
u32 maxChars,
|
||||
std::string inputName,
|
||||
std::string defaultValue,
|
||||
std::string defaultValueName) {
|
||||
std::vector<DefaultValue> defaultValues) {
|
||||
std::vector<std::vector<std::string>> rows;
|
||||
rows.push_back({"a", "b", "c", "d", "e"});
|
||||
rows.push_back({"f", "g", "h", "i", "j"});
|
||||
|
|
@ -415,8 +393,8 @@ std::string getTextInput(std::string& field,
|
|||
altRows.push_back({"5", "6", "7", "8", "9"});
|
||||
altRows.push_back({"0", ".", "#", "/", "?"});
|
||||
|
||||
return getInput(field, maxChars, inputName, rows, altRows, defaultValue,
|
||||
defaultValueName, "caps lock");
|
||||
return getInput(field, maxChars, inputName, rows, altRows, defaultValues,
|
||||
"caps lock");
|
||||
}
|
||||
|
||||
std::string getInput(std::string& field,
|
||||
|
|
@ -424,13 +402,13 @@ std::string getInput(std::string& field,
|
|||
std::string inputName,
|
||||
std::vector<std::vector<std::string>> rows,
|
||||
std::vector<std::vector<std::string>> altRows,
|
||||
std::string defaultValue,
|
||||
std::string defaultValueName,
|
||||
std::vector<DefaultValue> defaultValues,
|
||||
std::string altName) {
|
||||
VBlankIntrWait();
|
||||
|
||||
int selectedX = 0;
|
||||
int selectedY = 0;
|
||||
int selectedDefaultValue = 0;
|
||||
bool altActive = false;
|
||||
|
||||
while (true) {
|
||||
|
|
@ -469,8 +447,10 @@ std::string getInput(std::string& field,
|
|||
if (field.size() < maxChars)
|
||||
field += renderRows[selectedY][selectedX];
|
||||
}
|
||||
if (didPress(KEY_SELECT, select))
|
||||
field = defaultValue;
|
||||
if (didPress(KEY_SELECT, select)) {
|
||||
field = defaultValues[selectedDefaultValue].value;
|
||||
selectedDefaultValue = (selectedDefaultValue + 1) % defaultValues.size();
|
||||
}
|
||||
if (didPress(KEY_START, start))
|
||||
return field;
|
||||
if (altName != "" && didPress(KEY_L, l))
|
||||
|
|
@ -486,7 +466,8 @@ std::string getInput(std::string& field,
|
|||
output += "\n";
|
||||
}
|
||||
|
||||
output += "\n (B = back)\n (A = select)\n (SELECT = " + defaultValueName +
|
||||
output += "\n (B = back)\n (A = select)\n (SELECT = " +
|
||||
defaultValues[selectedDefaultValue].name +
|
||||
")\n (START = confirm)";
|
||||
|
||||
if (altName != "")
|
||||
|
|
@ -525,10 +506,10 @@ std::string getStateString(LinkMobile::State state) {
|
|||
return "ISP_CALL_REQUESTED";
|
||||
case LinkMobile::State::ISP_CALLING:
|
||||
return "ISP_CALLING";
|
||||
case LinkMobile::State::ISP_LOGIN:
|
||||
return "ISP_LOGIN";
|
||||
case LinkMobile::State::ISP_ACTIVE:
|
||||
return "ISP_ACTIVE";
|
||||
case LinkMobile::State::PPP_LOGIN:
|
||||
return "PPP_LOGIN";
|
||||
case LinkMobile::State::PPP_ACTIVE:
|
||||
return "PPP_ACTIVE";
|
||||
case LinkMobile::State::SHUTDOWN_REQUESTED:
|
||||
return "SHUTDOWN_REQUESTED";
|
||||
case LinkMobile::State::ENDING_SESSION:
|
||||
|
|
@ -558,8 +539,8 @@ std::string getErrorTypeString(LinkMobile::Error::Type errorType) {
|
|||
switch (errorType) {
|
||||
case LinkMobile::Error::Type::ADAPTER_NOT_CONNECTED:
|
||||
return "ADAPTER_NOT_CONNECTED";
|
||||
case LinkMobile::Error::Type::ISP_LOGIN_FAILED:
|
||||
return "ISP_LOGIN_FAILED";
|
||||
case LinkMobile::Error::Type::PPP_LOGIN_FAILED:
|
||||
return "PPP_LOGIN_FAILED";
|
||||
case LinkMobile::Error::Type::COMMAND_FAILED:
|
||||
return "COMMAND_FAILED";
|
||||
case LinkMobile::Error::Type::WEIRD_RESPONSE:
|
||||
|
|
@ -604,6 +585,8 @@ std::string lastLoggedText = "";
|
|||
void log(std::string text) {
|
||||
if (text == lastLoggedText)
|
||||
return;
|
||||
if (linkMobile != nullptr)
|
||||
VBlankIntrWait();
|
||||
tte_erase_screen();
|
||||
tte_write("#{P:0,0}");
|
||||
tte_write(text.c_str());
|
||||
|
|
@ -655,5 +638,3 @@ template <typename I>
|
|||
rc[i] = digits[(w >> j) & 0x0f];
|
||||
return rc;
|
||||
}
|
||||
|
||||
// TODO: Implement TCP/UDP sockets test functions
|
||||
|
|
|
|||
54
examples/LinkMobile_demo/src/main.h
Normal file
54
examples/LinkMobile_demo/src/main.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include "../../../lib/LinkMobile.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct DefaultValue {
|
||||
std::string name;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
void handleP2P();
|
||||
void handlePPP();
|
||||
void cleanup();
|
||||
void readConfiguration();
|
||||
|
||||
void printMenu();
|
||||
void transfer(LinkMobile::DataTransfer& dataTransfer,
|
||||
std::string text,
|
||||
unsigned char connectionId,
|
||||
bool addNullTerminator = false);
|
||||
|
||||
std::string getNumberInput();
|
||||
std::string getPasswordInput();
|
||||
std::string getDomainInput();
|
||||
std::string getTextInput(std::string& field,
|
||||
unsigned int maxChars,
|
||||
std::string inputName,
|
||||
std::vector<DefaultValue> defaultValues);
|
||||
std::string getInput(std::string& field,
|
||||
unsigned int maxChars,
|
||||
std::string inputName,
|
||||
std::vector<std::vector<std::string>> rows,
|
||||
std::vector<std::vector<std::string>> altRows,
|
||||
std::vector<DefaultValue> defaultValues,
|
||||
std::string altName);
|
||||
|
||||
std::string getStateString(LinkMobile::State state);
|
||||
std::string getErrorString(LinkMobile::Error error);
|
||||
std::string getErrorTypeString(LinkMobile::Error::Type errorType);
|
||||
std::string getResultString(LinkMobile::CommandResult cmdResult);
|
||||
|
||||
void log(std::string text);
|
||||
std::string toStr(char* chars, int size);
|
||||
void wait(unsigned int verticalLines);
|
||||
bool didPress(unsigned short key, bool& pressed);
|
||||
void waitForA();
|
||||
|
||||
template <typename I>
|
||||
[[nodiscard]] std::string toHex(I w, size_t hex_len = sizeof(I) << 1);
|
||||
|
||||
#endif // MAIN_H
|
||||
|
|
@ -38,15 +38,16 @@
|
|||
// - 9) Open connections:
|
||||
// auto type = LinkMobile::ConnectionType::TCP;
|
||||
// LinkMobile::OpenConn openConn;
|
||||
// linkMobile->openConnection(dnsQuery.ipv4, type, openConn);
|
||||
// linkMobile->openConnection(dnsQuery.ipv4, connType, &openConn);
|
||||
// // (do something until `openConn.completed` is `true`)
|
||||
// // (use `openConn.connectionId` as last argument of `transfer(...)`)
|
||||
// - 10) Close connections:
|
||||
// auto type = LinkMobile::ConnectionType::TCP;
|
||||
// LinkMobile::CloseConn closeConn;
|
||||
// linkMobile->closeConnection(openConn.connectionId, type, closeConn);
|
||||
// // (do something until `openConn.completed` is `true`)
|
||||
// - 11) Turn off the adapter:
|
||||
// linkMobile->closeConnection(openConn.connectionId, type, &closeConn);
|
||||
// // (do something until `closeConn.completed` is `true`)
|
||||
// - 11) Synchronously wait for an action to be completed:
|
||||
// linkMobile->waitFor(&dnsQuery);
|
||||
// - 12) Turn off the adapter:
|
||||
// linkMobile->shutdown();
|
||||
// --------------------------------------------------------------------------
|
||||
// (*) libtonc's interrupt handler sometimes ignores interrupts due to a bug.
|
||||
|
|
@ -149,25 +150,25 @@ class LinkMobile {
|
|||
|
||||
public:
|
||||
enum State {
|
||||
NEEDS_RESET,
|
||||
PINGING,
|
||||
WAITING_TO_START,
|
||||
STARTING_SESSION,
|
||||
ACTIVATING_SIO32,
|
||||
WAITING_32BIT_SWITCH,
|
||||
READING_CONFIGURATION,
|
||||
SESSION_ACTIVE,
|
||||
CALL_REQUESTED,
|
||||
CALLING,
|
||||
CALL_ESTABLISHED,
|
||||
ISP_CALL_REQUESTED,
|
||||
ISP_CALLING,
|
||||
ISP_LOGIN,
|
||||
ISP_ACTIVE,
|
||||
SHUTDOWN_REQUESTED,
|
||||
ENDING_SESSION,
|
||||
WAITING_8BIT_SWITCH,
|
||||
SHUTDOWN
|
||||
NEEDS_RESET = 0,
|
||||
PINGING = 1,
|
||||
WAITING_TO_START = 2,
|
||||
STARTING_SESSION = 3,
|
||||
ACTIVATING_SIO32 = 4,
|
||||
WAITING_32BIT_SWITCH = 5,
|
||||
READING_CONFIGURATION = 6,
|
||||
SESSION_ACTIVE = 7,
|
||||
CALL_REQUESTED = 8,
|
||||
CALLING = 9,
|
||||
CALL_ESTABLISHED = 10,
|
||||
ISP_CALL_REQUESTED = 11,
|
||||
ISP_CALLING = 12,
|
||||
PPP_LOGIN = 13,
|
||||
PPP_ACTIVE = 14,
|
||||
SHUTDOWN_REQUESTED = 15,
|
||||
ENDING_SESSION = 16,
|
||||
WAITING_8BIT_SWITCH = 17,
|
||||
SHUTDOWN = 18
|
||||
};
|
||||
|
||||
enum Role { NO_P2P_CONNECTION, CALLER, RECEIVER };
|
||||
|
|
@ -200,27 +201,20 @@ class LinkMobile {
|
|||
};
|
||||
|
||||
struct DNSQuery : public AsyncRequest {
|
||||
volatile bool completed = false;
|
||||
bool success = false;
|
||||
u8 ipv4[4] = {};
|
||||
};
|
||||
|
||||
enum ConnectionType { TCP, UDP };
|
||||
|
||||
struct OpenConn : public AsyncRequest {
|
||||
volatile bool completed = false;
|
||||
bool success = false;
|
||||
u8 connectionId = 0;
|
||||
};
|
||||
|
||||
struct CloseConn : public AsyncRequest {
|
||||
volatile bool completed = false;
|
||||
bool success = false;
|
||||
};
|
||||
|
||||
struct DataTransfer : public AsyncRequest {
|
||||
volatile bool completed = false;
|
||||
bool success = false;
|
||||
u8 data[LINK_MOBILE_MAX_USER_TRANSFER_LENGTH] = {};
|
||||
u8 size = 0;
|
||||
};
|
||||
|
|
@ -242,7 +236,7 @@ class LinkMobile {
|
|||
enum Type {
|
||||
NONE,
|
||||
ADAPTER_NOT_CONNECTED,
|
||||
ISP_LOGIN_FAILED,
|
||||
PPP_LOGIN_FAILED,
|
||||
COMMAND_FAILED,
|
||||
WEIRD_RESPONSE,
|
||||
TIMEOUT,
|
||||
|
|
@ -349,7 +343,7 @@ class LinkMobile {
|
|||
* @brief Calls the ISP number registered in the adapter configuration, or a
|
||||
* default number if the adapter hasn't been configured. Then, performs a
|
||||
* login operation using the provided REON `password` and `loginId`. After
|
||||
* some time, the state will be `ISP_ACTIVE`. If `loginId` is empty and the
|
||||
* some time, the state will be `PPP_ACTIVE`. If `loginId` is empty and the
|
||||
* adapter has been configured, it will use the one stored in the
|
||||
* configuration.
|
||||
* @param password The password, as a null-terminated string (max `32`
|
||||
|
|
@ -363,7 +357,7 @@ class LinkMobile {
|
|||
if (state != SESSION_ACTIVE || userRequests.isFull())
|
||||
return false;
|
||||
|
||||
auto request = UserRequest{.type = UserRequest::Type::ISP_LOGIN};
|
||||
auto request = UserRequest{.type = UserRequest::Type::PPP_LOGIN};
|
||||
copyString(request.password, password, LINK_MOBILE_MAX_PASSWORD_LENGTH);
|
||||
|
||||
if (std::strlen(loginId) > 0)
|
||||
|
|
@ -387,11 +381,14 @@ class LinkMobile {
|
|||
* `completed` field will be `true`. If an IP address was found, the `success`
|
||||
* field will be `true` and the `ipv4` field can be read as a 4-byte address.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active ISP session or available request slots.
|
||||
* active PPP session or available request slots.
|
||||
*/
|
||||
bool dnsQuery(const char* domainName, DNSQuery* result) {
|
||||
if (state != ISP_ACTIVE || userRequests.isFull())
|
||||
if (state != PPP_ACTIVE || userRequests.isFull()) {
|
||||
result->success = false;
|
||||
result->completed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
result->completed = false;
|
||||
result->success = false;
|
||||
|
|
@ -425,14 +422,17 @@ class LinkMobile {
|
|||
* connection was closed.
|
||||
* \warning Only `2` connections can be opened at the same time.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active ISP session, no available request slots.
|
||||
* active PPP session, no available request slots.
|
||||
*/
|
||||
bool openConnection(const u8* ip,
|
||||
u16 port,
|
||||
ConnectionType type,
|
||||
OpenConn* result) {
|
||||
if (state != ISP_ACTIVE || userRequests.isFull())
|
||||
if (state != PPP_ACTIVE || userRequests.isFull()) {
|
||||
result->success = false;
|
||||
result->completed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
result->completed = false;
|
||||
result->success = false;
|
||||
|
|
@ -458,13 +458,16 @@ class LinkMobile {
|
|||
* `completed` field will be `true`. If the connection was closed correctly,
|
||||
* the `success` field will be `true`.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active ISP session, no available request slots.
|
||||
* active PPP session, no available request slots.
|
||||
*/
|
||||
bool closeConnection(u8 connectionId,
|
||||
ConnectionType type,
|
||||
CloseConn* result) {
|
||||
if (state != ISP_ACTIVE || userRequests.isFull())
|
||||
if (state != PPP_ACTIVE || userRequests.isFull()) {
|
||||
result->success = false;
|
||||
result->completed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
result->completed = false;
|
||||
result->success = false;
|
||||
|
|
@ -482,7 +485,7 @@ class LinkMobile {
|
|||
/**
|
||||
* @brief Requests a data transfer and responds the received data. The
|
||||
* transfer can be done with the other node in a P2P connection, or with any
|
||||
* open TCP/UDP connection if an ISP session is active. In the case of a
|
||||
* open TCP/UDP connection if a PPP session is active. In the case of a
|
||||
* TCP/UDP connection, the `connectionId` must be provided.
|
||||
* @param dataToSend The data to send, up to 254 bytes.
|
||||
* @param result A pointer to a `LinkMobile::DataTransfer` struct that
|
||||
|
|
@ -496,9 +499,12 @@ class LinkMobile {
|
|||
bool transfer(DataTransfer dataToSend,
|
||||
DataTransfer* result,
|
||||
u8 connectionId = 0xff) {
|
||||
if ((state != CALL_ESTABLISHED && state != ISP_ACTIVE) ||
|
||||
userRequests.isFull())
|
||||
if ((state != CALL_ESTABLISHED && state != PPP_ACTIVE) ||
|
||||
userRequests.isFull()) {
|
||||
result->success = false;
|
||||
result->completed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
result->completed = false;
|
||||
result->success = false;
|
||||
|
|
@ -521,20 +527,21 @@ class LinkMobile {
|
|||
* `LinkMobile::OpenConn`, `LinkMobile::CloseConn`, or
|
||||
* `LinkMobile::DataTransfer`.
|
||||
*/
|
||||
bool waitForCompletion(AsyncRequest* asyncRequest) {
|
||||
bool waitFor(AsyncRequest* asyncRequest) {
|
||||
while (isSessionActive() && !asyncRequest->completed)
|
||||
Link::_IntrWait(1, Link::_IRQ_SERIAL | Link::_IRQ_VBLANK);
|
||||
|
||||
return isSessionActive() && asyncRequest->completed &&
|
||||
asyncRequest->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hangs up the current P2P or ISP call. Closes all connections.
|
||||
* @brief Hangs up the current P2P or PPP call. Closes all connections.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active call or available request slots.
|
||||
*/
|
||||
bool hangUp() {
|
||||
if ((state != CALL_ESTABLISHED && state != ISP_ACTIVE) ||
|
||||
if ((state != CALL_ESTABLISHED && state != PPP_ACTIVE) ||
|
||||
userRequests.isFull())
|
||||
return false;
|
||||
|
||||
|
|
@ -588,10 +595,10 @@ class LinkMobile {
|
|||
[[nodiscard]] bool isConnectedP2P() { return state == CALL_ESTABLISHED; }
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if an ISP call is active (the state is
|
||||
* `ISP_ACTIVE`).
|
||||
* @brief Returns `true` if a PPP session is active (the state is
|
||||
* `PPP_ACTIVE`).
|
||||
*/
|
||||
[[nodiscard]] bool isConnectedISP() { return state == ISP_ACTIVE; }
|
||||
[[nodiscard]] bool isConnectedPPP() { return state == PPP_ACTIVE; }
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if the session is active.
|
||||
|
|
@ -716,7 +723,7 @@ class LinkMobile {
|
|||
struct UserRequest {
|
||||
enum Type {
|
||||
CALL,
|
||||
ISP_LOGIN,
|
||||
PPP_LOGIN,
|
||||
DNS_QUERY,
|
||||
OPEN_CONNECTION,
|
||||
CLOSE_CONNECTION,
|
||||
|
|
@ -933,7 +940,7 @@ class LinkMobile {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case UserRequest::Type::ISP_LOGIN: {
|
||||
case UserRequest::Type::PPP_LOGIN: {
|
||||
if (state != SESSION_ACTIVE && state != ISP_CALL_REQUESTED &&
|
||||
state != ISP_CALLING) {
|
||||
popRequest();
|
||||
|
|
@ -951,7 +958,7 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case UserRequest::Type::DNS_QUERY: {
|
||||
if (state != ISP_ACTIVE) {
|
||||
if (state != PPP_ACTIVE) {
|
||||
popRequest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -963,7 +970,7 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case UserRequest::Type::OPEN_CONNECTION: {
|
||||
if (state != ISP_ACTIVE) {
|
||||
if (state != PPP_ACTIVE) {
|
||||
popRequest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -978,7 +985,7 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case UserRequest::Type::CLOSE_CONNECTION: {
|
||||
if (state != ISP_ACTIVE) {
|
||||
if (state != PPP_ACTIVE) {
|
||||
popRequest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -993,7 +1000,7 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case UserRequest::Type::TRANSFER: {
|
||||
if (state != CALL_ESTABLISHED && state != ISP_ACTIVE) {
|
||||
if (state != CALL_ESTABLISHED && state != PPP_ACTIVE) {
|
||||
popRequest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1006,7 +1013,7 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case UserRequest::Type::HANG_UP: {
|
||||
if (state != CALL_ESTABLISHED && state != ISP_ACTIVE) {
|
||||
if (state != CALL_ESTABLISHED && state != PPP_ACTIVE) {
|
||||
popRequest();
|
||||
return;
|
||||
}
|
||||
|
|
@ -1207,11 +1214,11 @@ class LinkMobile {
|
|||
if (userRequests.isEmpty())
|
||||
return abort(Error::Type::WTF);
|
||||
auto request = userRequests.peekRef();
|
||||
if (request->type != UserRequest::ISP_LOGIN)
|
||||
if (request->type != UserRequest::PPP_LOGIN)
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
setState(ISP_LOGIN);
|
||||
setState(PPP_LOGIN);
|
||||
cmdISPLogin(request->loginId, request->password);
|
||||
} else {
|
||||
// (ISP call failed)
|
||||
|
|
@ -1221,16 +1228,16 @@ class LinkMobile {
|
|||
|
||||
break;
|
||||
}
|
||||
case ISP_LOGIN: {
|
||||
case PPP_LOGIN: {
|
||||
if (!asyncCommand.respondsTo(COMMAND_ISP_LOGIN))
|
||||
return;
|
||||
if (asyncCommand.result != CommandResult::SUCCESS)
|
||||
return abort(Error::Type::ISP_LOGIN_FAILED);
|
||||
return abort(Error::Type::PPP_LOGIN_FAILED);
|
||||
|
||||
setState(ISP_ACTIVE);
|
||||
setState(PPP_ACTIVE);
|
||||
break;
|
||||
}
|
||||
case ISP_ACTIVE: {
|
||||
case PPP_ACTIVE: {
|
||||
if (asyncCommand.respondsTo(COMMAND_HANG_UP_TELEPHONE)) {
|
||||
setState(SESSION_ACTIVE);
|
||||
return;
|
||||
|
|
@ -1477,13 +1484,16 @@ class LinkMobile {
|
|||
u8 commandId = asyncCommand.relatedCommandId();
|
||||
return asyncCommand.direction == AsyncCommand::Direction::SENDING ||
|
||||
(commandId != COMMAND_WAIT_FOR_TELEPHONE_CALL &&
|
||||
commandId != COMMAND_DIAL_TELEPHONE &&
|
||||
commandId != COMMAND_DNS_QUERY &&
|
||||
commandId != COMMAND_OPEN_TCP_CONNECTION &&
|
||||
commandId != COMMAND_CLOSE_TCP_CONNECTION &&
|
||||
commandId != COMMAND_OPEN_UDP_CONNECTION &&
|
||||
commandId != COMMAND_CLOSE_UDP_CONNECTION &&
|
||||
commandId != COMMAND_TRANSFER_DATA);
|
||||
commandId != COMMAND_DIAL_TELEPHONE && !isAsyncRequest(commandId));
|
||||
}
|
||||
|
||||
bool isAsyncRequest(u8 commandId) {
|
||||
return commandId == COMMAND_DNS_QUERY ||
|
||||
commandId == COMMAND_OPEN_TCP_CONNECTION ||
|
||||
commandId == COMMAND_CLOSE_TCP_CONNECTION ||
|
||||
commandId == COMMAND_OPEN_UDP_CONNECTION ||
|
||||
commandId == COMMAND_CLOSE_UDP_CONNECTION ||
|
||||
commandId == COMMAND_TRANSFER_DATA;
|
||||
}
|
||||
|
||||
void addData(u8 value, bool start = false) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user