mirror of
https://github.com/afska/gba-link-connection.git
synced 2026-04-25 16:23:41 -05:00
Implementing DNS query
This commit is contained in:
parent
f74504bb3e
commit
f994270ee0
|
|
@ -437,6 +437,8 @@ You can also change these compile-time constants:
|
|||
- On fatal errors, the library will transition to a `NEEDS_RESET` state. In that case, you can call `getError()` to know more details on what happened, and then `activate()` to restart.
|
||||
- When calling `deactivate()`, the adapter automatically turns itself off after `3` seconds of inactivity. However, to gracefully turn it off, it's recommended to call `shutdown()` first, wait until the state is `SHUTDOWN`, and then `deactivate()`.
|
||||
|
||||
// TODO: Add ISP methods
|
||||
|
||||
Name | Return type | Description
|
||||
--- | --- | ---
|
||||
`isActive()` | **bool** | Returns whether the library is active or not.
|
||||
|
|
@ -444,7 +446,9 @@ 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`).
|
||||
`transfer(dataToSend, receivedData)` | **bool** | Requests a data transfer (up to `254` bytes) within a P2P connection and responds the received data. The `receivedData` is a pointer to a `LinkWireless::DataTransfer` struct that will be filled with data. It can point to `dataToSend`. When the transfer is completed, the `completed` field will be `true`.
|
||||
`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).
|
||||
`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.
|
||||
`transfer(dataToSend, result)` | **bool** | Requests a data transfer (up to `254` bytes) within a P2P connection and responds the received data. 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 transfer is completed, the `completed` field will be `true`.
|
||||
`hangUp()` | **bool** | Hangs up the current P2P or ISP 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`).
|
||||
|
|
|
|||
|
|
@ -13,6 +13,12 @@ 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,
|
||||
|
|
@ -38,6 +44,7 @@ bool a = false, b = false, l = false, r = false;
|
|||
bool start = false, select = false;
|
||||
std::string selectedNumber = "";
|
||||
std::string selectedPassword = "";
|
||||
std::string selectedDomain = "";
|
||||
|
||||
LinkMobile* linkMobile = NULL;
|
||||
|
||||
|
|
@ -73,6 +80,8 @@ start:
|
|||
bool isConnected = false;
|
||||
LinkMobile::DataTransfer dataTransfer;
|
||||
LinkMobile::DataTransfer lastCompletedTransfer;
|
||||
LinkMobile::DNSQuery dnsQuery;
|
||||
bool waitingDNS = false;
|
||||
std::string outgoingData = "";
|
||||
u32 counter = 0;
|
||||
u32 frameCounter = 0;
|
||||
|
|
@ -83,7 +92,6 @@ start:
|
|||
|
||||
u16 keys = ~REG_KEYS & KEY_ANY;
|
||||
|
||||
// Menu
|
||||
std::string output = "";
|
||||
bool shouldWaitForA = false;
|
||||
output += "State = " + getStateString(linkMobile->getState()) + "\n";
|
||||
|
|
@ -97,12 +105,13 @@ start:
|
|||
output += "\nL = Read Configuration";
|
||||
output += "\nR = Call someone";
|
||||
output += "\nSTART = Call the ISP";
|
||||
output += "\n (A = ok)\n (SELECT = stop)";
|
||||
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 (LEFT = DNS query)";
|
||||
output += "\n (L = hang up)";
|
||||
}
|
||||
output += "\n (SELECT = stop)";
|
||||
|
|
@ -116,25 +125,26 @@ start:
|
|||
: "receiver!!!";
|
||||
transfer(dataTransfer, outgoingData);
|
||||
}
|
||||
|
||||
if (dataTransfer.completed) {
|
||||
if (dataTransfer.size > 0)
|
||||
lastCompletedTransfer = dataTransfer;
|
||||
|
||||
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);
|
||||
}
|
||||
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++)
|
||||
|
|
@ -143,11 +153,28 @@ start:
|
|||
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 ? "Success!" : "Failure!"));
|
||||
waitForA();
|
||||
}
|
||||
|
||||
output += waitingDNS ? "\n\nWaiting DNS..." : "";
|
||||
} else {
|
||||
if (isConnected) {
|
||||
isConnected = false;
|
||||
dataTransfer = {};
|
||||
lastCompletedTransfer = {};
|
||||
dnsQuery = {};
|
||||
waitingDNS = false;
|
||||
counter = 0;
|
||||
frameCounter = 0;
|
||||
outgoingData = "";
|
||||
|
|
@ -198,13 +225,30 @@ start:
|
|||
if (didPress(KEY_START, start)) {
|
||||
std::string password = getPasswordInput();
|
||||
if (password != "") {
|
||||
// (7) Connect to the internet
|
||||
linkMobile->callISP(password.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LinkMobile::State::CALL_ESTABLISHED:
|
||||
case LinkMobile::State::CALL_ESTABLISHED: {
|
||||
// L = hang up
|
||||
if (didPress(KEY_L, l)) {
|
||||
// (6) Hang up
|
||||
linkMobile->hangUp();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LinkMobile::State::ISP_ACTIVE: {
|
||||
// LEFT = DNS query
|
||||
if (didPress(KEY_LEFT, left)) {
|
||||
std::string domain = getDomainInput();
|
||||
if (domain != "") {
|
||||
// (8) Run DNS queries
|
||||
linkMobile->dnsQuery(domain.c_str(), &dnsQuery);
|
||||
waitingDNS = true;
|
||||
}
|
||||
}
|
||||
// L = hang up
|
||||
if (didPress(KEY_L, l)) {
|
||||
// (6) Hang up
|
||||
|
|
@ -272,6 +316,20 @@ std::string getNumberInput() {
|
|||
}
|
||||
|
||||
std::string getPasswordInput() {
|
||||
return getTextInput(selectedPassword, LINK_MOBILE_MAX_PASSWORD_LENGTH,
|
||||
"your password", "pass123", "pass123");
|
||||
}
|
||||
|
||||
std::string getDomainInput() {
|
||||
return getTextInput(selectedDomain, LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH,
|
||||
"a domain name", "something.com", "something.com");
|
||||
}
|
||||
|
||||
std::string getTextInput(std::string& field,
|
||||
u32 maxChars,
|
||||
std::string inputName,
|
||||
std::string defaultValue,
|
||||
std::string defaultValueName) {
|
||||
std::vector<std::vector<std::string>> rows;
|
||||
rows.push_back({"a", "b", "c", "d", "e"});
|
||||
rows.push_back({"f", "g", "h", "i", "j"});
|
||||
|
|
@ -280,7 +338,7 @@ std::string getPasswordInput() {
|
|||
rows.push_back({"u", "v", "w", "x", "y"});
|
||||
rows.push_back({"z", "1", "2", "3", "4"});
|
||||
rows.push_back({"5", "6", "7", "8", "9"});
|
||||
rows.push_back({"0", "!", "?", "#", "*"});
|
||||
rows.push_back({"0", ".", "#", "/", "?"});
|
||||
|
||||
std::vector<std::vector<std::string>> altRows;
|
||||
altRows.push_back({"A", "B", "C", "D", "E"});
|
||||
|
|
@ -290,11 +348,10 @@ std::string getPasswordInput() {
|
|||
altRows.push_back({"U", "V", "W", "X", "Y"});
|
||||
altRows.push_back({"Z", "1", "2", "3", "4"});
|
||||
altRows.push_back({"5", "6", "7", "8", "9"});
|
||||
altRows.push_back({"0", "!", "?", "#", "*"});
|
||||
altRows.push_back({"0", ".", "#", "/", "?"});
|
||||
|
||||
return getInput(selectedPassword, LINK_MOBILE_MAX_PASSWORD_LENGTH,
|
||||
"your password", rows, altRows, "pass123", "pass123",
|
||||
"caps lock");
|
||||
return getInput(field, maxChars, inputName, rows, altRows, defaultValue,
|
||||
defaultValueName, "caps lock");
|
||||
}
|
||||
|
||||
std::string getInput(std::string& field,
|
||||
|
|
@ -429,7 +486,7 @@ std::string getErrorString(LinkMobile::Error error) {
|
|||
toHex(error.cmdId) +
|
||||
"\n CmdResult: " + getResultString(error.cmdResult) +
|
||||
"\n CmdErrorCode: " + std::to_string(error.cmdErrorCode) +
|
||||
"\n ReqType: " + std::to_string(error.reqType) + "\n\n";
|
||||
"\n ReqType: " + std::to_string(error.reqType) + "\n";
|
||||
}
|
||||
|
||||
std::string getErrorTypeString(LinkMobile::Error::Type errorType) {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
# define EXPORT_API __declspec(dllexport)
|
||||
# else
|
||||
# define EXPORT_API __attribute__((visibility("default")))
|
||||
// TODO: Is this one below needed in MinGW?
|
||||
// Is this one below needed in MinGW?
|
||||
//# define EXPORT_API __attribute__((dllexport))
|
||||
# endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,15 @@
|
|||
// // (use `dataTransfer` as the received data)
|
||||
// - 6) Hang up:
|
||||
// linkMobile->hangUp();
|
||||
// - 7) Connect to the internet:
|
||||
// linkMobile->callISP("REON password");
|
||||
// - 8) Run DNS queries:
|
||||
// LinkMobile::DNSQuery dnsQuery;
|
||||
// linkMobile->dnsQuery("something.com", &dnsQuery);
|
||||
// // (do something until `dnsQuery.completed` is `true`)
|
||||
// // (use `dnsQuery.success` and `dnsQuery.ipv4`)
|
||||
// - 7) Turn off the adapter:
|
||||
// linkMobile->shutdown();
|
||||
// TODO: DOCUMENT ISP METHODS
|
||||
// --------------------------------------------------------------------------
|
||||
// (*) libtonc's interrupt handler sometimes ignores interrupts due to a bug.
|
||||
// That causes packet loss. You REALLY want to use libugba's instead.
|
||||
|
|
@ -58,6 +64,7 @@ static volatile char LINK_MOBILE_VERSION[] = "LinkMobile/v7.0.0";
|
|||
#define LINK_MOBILE_MAX_PHONE_NUMBER_LENGTH 32
|
||||
#define LINK_MOBILE_MAX_LOGIN_ID_LENGTH 32
|
||||
#define LINK_MOBILE_MAX_PASSWORD_LENGTH 32
|
||||
#define LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH 253
|
||||
#define LINK_MOBILE_COMMAND_TRANSFER_BUFFER \
|
||||
(LINK_MOBILE_MAX_COMMAND_TRANSFER_LENGTH + 4)
|
||||
#define LINK_MOBILE_DEFAULT_TIMEOUT (60 * 3)
|
||||
|
|
@ -214,6 +221,12 @@ class LinkMobile {
|
|||
bool completed = false;
|
||||
};
|
||||
|
||||
struct DNSQuery {
|
||||
u8 ipv4[4] = {};
|
||||
bool completed = false;
|
||||
bool success = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Constructs a new LinkMobile object.
|
||||
* @param timeout Number of *frames* without completing a request to reset a
|
||||
|
|
@ -304,9 +317,9 @@ 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 `password` and `loginId`. If `loginId`
|
||||
* is empty and the adapter has been configured, it will use the one stored in
|
||||
* the configuration.
|
||||
* 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.
|
||||
* @param password The password, as a null-terminated string (max `32`
|
||||
* characters).
|
||||
* @param loginId The login ID, as a null-terminated string (max `32`
|
||||
|
|
@ -333,24 +346,58 @@ class LinkMobile {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Looks up the IPv4 address for a domain name.
|
||||
* @param domain A null-terminated string for the domain name (max `253`
|
||||
* characters).
|
||||
* @param result 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.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active ISP session or available request slots.
|
||||
*/
|
||||
bool dnsQuery(const char* domainName, DNSQuery* result) {
|
||||
if (state != ISP_ACTIVE || userRequests.isFull())
|
||||
return false;
|
||||
|
||||
result->completed = false;
|
||||
result->success = false;
|
||||
u32 size = std::strlen(domainName);
|
||||
if (size > LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH)
|
||||
size = LINK_MOBILE_MAX_DOMAIN_NAME_LENGTH;
|
||||
|
||||
auto request = UserRequest{.type = UserRequest::Type::DNS_QUERY,
|
||||
.send = {.data = {}},
|
||||
.dns = result,
|
||||
.commandSent = false};
|
||||
for (u32 i = 0; i < size; i++)
|
||||
request.send.data[i] = domainName[i];
|
||||
request.send.size = size;
|
||||
|
||||
pushRequest(request);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Requests a data transfer within a P2P connection and responds the
|
||||
* received data.
|
||||
* @param dataToSend The data to send, up to 254 bytes.
|
||||
* @param receivedData A pointer to a `LinkWireless::DataTransfer` struct that
|
||||
* will be filled with data. It can point to `dataToSend`. When the transfer
|
||||
* is completed, the `completed` field will be `true`.
|
||||
* @param result 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 transfer is completed, the `completed` field
|
||||
* will be `true`.
|
||||
* \warning Non-blocking. Returns `true` immediately, or `false` if there's no
|
||||
* active call or available request slots.
|
||||
*/
|
||||
bool transfer(DataTransfer dataToSend, DataTransfer* receivedData) {
|
||||
bool transfer(DataTransfer dataToSend, DataTransfer* result) {
|
||||
if (state != CALL_ESTABLISHED || userRequests.isFull())
|
||||
return false;
|
||||
|
||||
receivedData->completed = false;
|
||||
result->completed = false;
|
||||
auto request = UserRequest{.type = UserRequest::Type::TRANSFER,
|
||||
.send = {.data = {}, .size = dataToSend.size},
|
||||
.receive = receivedData,
|
||||
.receive = result,
|
||||
.commandSent = false};
|
||||
for (u32 i = 0; i < dataToSend.size; i++)
|
||||
request.send.data[i] = dataToSend.data[i];
|
||||
|
|
@ -544,12 +591,13 @@ class LinkMobile {
|
|||
enum AdapterType { BLUE, YELLOW, GREEN, RED, UNKNOWN };
|
||||
|
||||
struct UserRequest {
|
||||
enum Type { CALL, ISP_LOGIN, TRANSFER, HANG_UP, SHUTDOWN };
|
||||
enum Type { CALL, ISP_LOGIN, DNS_QUERY, TRANSFER, HANG_UP, SHUTDOWN };
|
||||
|
||||
Type type;
|
||||
char phoneNumber[LINK_MOBILE_MAX_PHONE_NUMBER_LENGTH + 1];
|
||||
DataTransfer send;
|
||||
DataTransfer* receive;
|
||||
DNSQuery* dns;
|
||||
char loginId[LINK_MOBILE_MAX_LOGIN_ID_LENGTH + 1];
|
||||
char password[LINK_MOBILE_MAX_PASSWORD_LENGTH + 1];
|
||||
bool commandSent;
|
||||
|
|
@ -750,6 +798,18 @@ class LinkMobile {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case UserRequest::Type::DNS_QUERY: {
|
||||
if (state != ISP_ACTIVE) {
|
||||
userRequests.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!asyncCommand.isActive && !request.commandSent) {
|
||||
cmdDNSQuery(request.send.data, request.send.size);
|
||||
request.commandSent = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UserRequest::Type::TRANSFER: {
|
||||
if (state != CALL_ESTABLISHED) {
|
||||
userRequests.pop();
|
||||
|
|
@ -918,13 +978,14 @@ class LinkMobile {
|
|||
break;
|
||||
}
|
||||
case SESSION_ACTIVE: {
|
||||
if (asyncCommand.respondsTo(COMMAND_WAIT_FOR_TELEPHONE_CALL)) {
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
setState(CALL_ESTABLISHED);
|
||||
role = Role::RECEIVER;
|
||||
} else {
|
||||
// (no call received)
|
||||
}
|
||||
if (!asyncCommand.respondsTo(COMMAND_WAIT_FOR_TELEPHONE_CALL))
|
||||
return;
|
||||
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
setState(CALL_ESTABLISHED);
|
||||
role = Role::RECEIVER;
|
||||
} else {
|
||||
// (no call received)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -936,7 +997,7 @@ class LinkMobile {
|
|||
setState(CALL_ESTABLISHED);
|
||||
role = Role::CALLER;
|
||||
} else {
|
||||
// (call terminated)
|
||||
// (call failed)
|
||||
setState(SESSION_ACTIVE);
|
||||
}
|
||||
break;
|
||||
|
|
@ -948,45 +1009,39 @@ class LinkMobile {
|
|||
}
|
||||
if (!asyncCommand.respondsTo(COMMAND_TRANSFER_DATA))
|
||||
return;
|
||||
if (asyncCommand.cmd.header.size == 0)
|
||||
return abort(Error::Type::WEIRD_RESPONSE);
|
||||
if (userRequests.isEmpty())
|
||||
return abort(Error::Type::WTF);
|
||||
auto request = userRequests.peekRef();
|
||||
if (request->type != UserRequest::TRANSFER)
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
auto request = userRequests.peek();
|
||||
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
if (asyncCommand.cmd.header.size == 0)
|
||||
return abort(Error::Type::WEIRD_RESPONSE);
|
||||
|
||||
if (request.type == UserRequest::TRANSFER) {
|
||||
u32 size = asyncCommand.cmd.header.size - 1;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
request.receive->data[i] = asyncCommand.cmd.data.bytes[1 + i];
|
||||
request.receive->size = size;
|
||||
request.receive->completed = true;
|
||||
request.finished = true;
|
||||
} else
|
||||
return abort(Error::Type::WTF);
|
||||
} else {
|
||||
setState(SESSION_ACTIVE);
|
||||
}
|
||||
u32 size = asyncCommand.cmd.header.size - 1;
|
||||
for (u32 i = 0; i < size; i++)
|
||||
request->receive->data[i] = asyncCommand.cmd.data.bytes[1 + i];
|
||||
request->receive->size = size;
|
||||
request->receive->completed = true;
|
||||
request->finished = true;
|
||||
}
|
||||
case ISP_CALLING: {
|
||||
if (!asyncCommand.respondsTo(COMMAND_DIAL_TELEPHONE))
|
||||
return;
|
||||
if (userRequests.isEmpty())
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
auto request = userRequests.peek();
|
||||
|
||||
if (request.type == UserRequest::ISP_LOGIN) {
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
setState(ISP_LOGIN);
|
||||
cmdISPLogin(request.loginId, request.password);
|
||||
}
|
||||
request.finished = true;
|
||||
} else
|
||||
auto request = userRequests.peekRef();
|
||||
if (request->type != UserRequest::ISP_LOGIN)
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
setState(ISP_LOGIN);
|
||||
cmdISPLogin(request->loginId, request->password);
|
||||
} else {
|
||||
// (ISP call failed)
|
||||
setState(SESSION_ACTIVE);
|
||||
}
|
||||
request->finished = true;
|
||||
|
||||
break;
|
||||
}
|
||||
case ISP_LOGIN: {
|
||||
|
|
@ -1003,8 +1058,43 @@ class LinkMobile {
|
|||
setState(SESSION_ACTIVE);
|
||||
return;
|
||||
}
|
||||
if (userRequests.isEmpty())
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
// TODO: IMPLEMENT
|
||||
auto request = userRequests.peekRef();
|
||||
|
||||
if (asyncCommand.respondsTo(COMMAND_DNS_QUERY)) {
|
||||
if (request->type != UserRequest::DNS_QUERY)
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
if (asyncCommand.result == CommandResult::SUCCESS) {
|
||||
if (asyncCommand.cmd.header.size != 4)
|
||||
return abort(Error::Type::WEIRD_RESPONSE);
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
request->dns->ipv4[i] = asyncCommand.cmd.data.bytes[i];
|
||||
request->dns->success = true;
|
||||
} else {
|
||||
request->dns->success = false;
|
||||
}
|
||||
|
||||
request->dns->completed = true;
|
||||
request->finished = true;
|
||||
break;
|
||||
} else if (asyncCommand.respondsTo(COMMAND_TRANSFER_DATA)) {
|
||||
if (request->type != UserRequest::TRANSFER)
|
||||
return abort(Error::Type::WTF);
|
||||
|
||||
// TODO: HANDLE TRANSFER DATA
|
||||
// if (asyncCommand.cmd.header.size == 0)
|
||||
// return abort(Error::Type::WEIRD_RESPONSE);
|
||||
// TODO: IMPLEMENT
|
||||
// u32 size = asyncCommand.cmd.header.size - 1;
|
||||
// for (u32 i = 0; i < size; i++)
|
||||
// request.receive->data[i] = asyncCommand.cmd.data.bytes[1 + i];
|
||||
// request.receive->size = size;
|
||||
// request.receive->completed = true;
|
||||
// request.finished = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ENDING_SESSION: {
|
||||
|
|
@ -1063,7 +1153,7 @@ class LinkMobile {
|
|||
}
|
||||
|
||||
void cmdTelephoneStatus() {
|
||||
sendCommandAsync(buildCommand(COMMAND_TELEPHONE_STATUS, true));
|
||||
sendCommandAsync(buildCommand(COMMAND_TELEPHONE_STATUS));
|
||||
}
|
||||
|
||||
void cmdSIO32(bool enabled) {
|
||||
|
|
@ -1097,6 +1187,12 @@ class LinkMobile {
|
|||
sendCommandAsync(buildCommand(COMMAND_ISP_LOGIN, true));
|
||||
}
|
||||
|
||||
void cmdDNSQuery(const u8* data, u8 size) {
|
||||
for (int i = 0; i < size; i++)
|
||||
addData(data[i], i == 0);
|
||||
sendCommandAsync(buildCommand(COMMAND_DNS_QUERY, true));
|
||||
}
|
||||
|
||||
void setISPNumber() {
|
||||
static const char BCD[16] = "0123456789#*cde";
|
||||
|
||||
|
|
@ -1123,7 +1219,8 @@ class LinkMobile {
|
|||
u8 commandId = asyncCommand.relatedCommandId();
|
||||
return asyncCommand.direction == AsyncCommand::Direction::SENDING ||
|
||||
(commandId != COMMAND_WAIT_FOR_TELEPHONE_CALL &&
|
||||
commandId != COMMAND_DIAL_TELEPHONE);
|
||||
commandId != COMMAND_DIAL_TELEPHONE &&
|
||||
commandId != COMMAND_DNS_QUERY);
|
||||
}
|
||||
|
||||
void addData(u8 value, bool start = false) {
|
||||
|
|
|
|||
|
|
@ -171,6 +171,12 @@ class Queue {
|
|||
return arr[front];
|
||||
}
|
||||
|
||||
T* peekRef() {
|
||||
if (isEmpty())
|
||||
return nullptr;
|
||||
return &arr[front];
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void forEach(F action) {
|
||||
vs32 currentFront = front;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user