Added capability to generate QR code

This commit is contained in:
kidfromjupiter
2026-02-01 06:01:18 +00:00
parent 15b26d6174
commit ad7f2173d1
3 changed files with 242 additions and 50 deletions
+147 -48
View File
@@ -28,6 +28,7 @@
#include "sharing/transfer_update_callback.h"
#include "sharing/share_target_discovered_callback.h"
#include "internal/base/file_path.h"
#include "internal/base/files.h"
using namespace nearby::sharing;
using namespace nearby::sharing::linux;
@@ -37,22 +38,24 @@ class MyTransferUpdateCallback : public TransferUpdateCallback {
void OnTransferUpdate(const ShareTarget& share_target,
const AttachmentContainer& attachment_container,
const TransferMetadata& transfer_metadata) override {
std::cout << "\n=== Transfer Update ===" << std::endl;
std::cout << "Device: " << share_target.device_name << std::endl;
std::cout << "Target ID: " << share_target.id << " ← USE THIS ID" << std::endl;
std::cout << "Status: " << TransferMetadata::StatusToString(transfer_metadata.status()) << std::endl;
std::cout << "Progress: " << (transfer_metadata.progress() * 100) << "%" << std::endl;
std::cout << "Transferred: " << transfer_metadata.transferred_bytes() << " bytes" << std::endl;
std::cout << "Total attachments: " << transfer_metadata.total_attachments_count() << std::endl;
std::cout << "\n┌─────────────────────────────────────┐" << std::endl;
std::cout << "│ TRANSFER UPDATE │" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << "│ Device: " << share_target.device_name << std::endl;
std::cout << "│ Target ID: " << share_target.id << " ← USE THIS ID" << std::endl;
std::cout << "│ Status: " << TransferMetadata::StatusToString(transfer_metadata.status()) << std::endl;
std::cout << "│ Progress: " << (transfer_metadata.progress() * 100) << "%" << std::endl;
std::cout << "│ Transferred: " << transfer_metadata.transferred_bytes() << " bytes" << std::endl;
std::cout << "│ Total attachments: " << transfer_metadata.total_attachments_count() << std::endl;
// Track incoming transfer requests
if (transfer_metadata.status() == TransferMetadata::Status::kAwaitingLocalConfirmation) {
std::cout << "\n*** INCOMING TRANSFER REQUEST ***" << std::endl;
std::cout << "From: " << share_target.device_name << std::endl;
std::cout << "Target ID: " << share_target.id << std::endl;
std::cout << "Use menu option 6 to ACCEPT (ID: " << share_target.id << ")" << std::endl;
std::cout << "Use menu option 7 to REJECT (ID: " << share_target.id << ")" << std::endl;
std::cout << "**********************************" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << "│ ⚠️ INCOMING TRANSFER REQUEST │" << std::endl;
std::cout << "│ From: " << share_target.device_name << std::endl;
std::cout << "│ Target ID: " << share_target.id << std::endl;
std::cout << "│ → Press 6 to ACCEPT │" << std::endl;
std::cout << "│ → Press 7 to REJECT │" << std::endl;
pending_target_id_ = share_target.id;
has_pending_request_ = true;
@@ -60,18 +63,19 @@ class MyTransferUpdateCallback : public TransferUpdateCallback {
// Show completed transfers
if (transfer_metadata.status() == TransferMetadata::Status::kComplete) {
std::cout << "\n*** TRANSFER COMPLETE ***" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << "│ ✓ TRANSFER COMPLETE │" << std::endl;
for (const auto& file : attachment_container.GetFileAttachments()) {
std::cout << "Received file: " << file.file_name() << std::endl;
std::cout << "Received file: " << file.file_name() << std::endl;
}
for (const auto& text : attachment_container.GetTextAttachments()) {
std::cout << "Received text: " << text.text_body() << std::endl;
std::cout << "Received text: " << text.text_body() << std::endl;
}
std::cout << "*************************" << std::endl;
has_pending_request_ = false;
}
std::cout << "======================" << std::endl;
std::cout << "└─────────────────────────────────────┘" << std::endl;
PrintMenuAtBottom();
}
bool HasPendingRequest() const { return has_pending_request_; }
@@ -80,24 +84,42 @@ class MyTransferUpdateCallback : public TransferUpdateCallback {
private:
bool has_pending_request_ = false;
int64_t pending_target_id_ = -1;
void PrintMenuAtBottom() {
std::cout << "\n╔═════════════════════════════════════════════════════════╗" << std::endl;
std::cout << "║ NEARBY SHARING - MENU ║" << std::endl;
std::cout << "╠═════════════════════════════════════════════════════════╣" << std::endl;
std::cout << "║ 1. Start as Receiver │ 6. Accept pending request ║" << std::endl;
std::cout << "║ 2. Start as Sender │ 7. Reject pending request ║" << std::endl;
std::cout << "║ 3. List devices │ 8. Cancel transfer ║" << std::endl;
std::cout << "║ 4. Send file │ 9. Print status ║" << std::endl;
std::cout << "║ 5. Send text │ 0. Exit ║" << std::endl;
std::cout << "╚═════════════════════════════════════════════════════════╝" << std::endl;
std::cout << "Choice: ";
}
};
class MyShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback {
public:
void OnShareTargetDiscovered(const ShareTarget& share_target) override {
std::cout << "\n*** Device Discovered ***" << std::endl;
std::cout << "ID: " << share_target.id << std::endl;
std::cout << "Name: " << share_target.device_name << std::endl;
std::cout << "Vendor ID: " << static_cast<int>(share_target.vendor_id) << std::endl;
std::cout << "*************************" << std::endl;
std::cout << "\n┌─────────────────────────────────────┐" << std::endl;
std::cout << "│ 📱 DEVICE DISCOVERED │" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << " ID: " << share_target.id << std::endl;
std::cout << "│ Name: " << share_target.device_name << std::endl;
std::cout << "│ Vendor ID: " << static_cast<int>(share_target.vendor_id) << std::endl;
std::cout << "└─────────────────────────────────────┘" << std::endl;
discovered_targets_.push_back(share_target);
PrintMenuAtBottom();
}
void OnShareTargetLost(const ShareTarget& share_target) override {
std::cout << "\n*** Device Lost ***" << std::endl;
std::cout << "Name: " << share_target.device_name << std::endl;
std::cout << "*******************" << std::endl;
std::cout << "\n┌─────────────────────────────────────┐" << std::endl;
std::cout << "│ ❌ DEVICE LOST │" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << "│ Name: " << share_target.device_name << std::endl;
std::cout << "└─────────────────────────────────────┘" << std::endl;
for (auto it = discovered_targets_.begin(); it != discovered_targets_.end(); ++it) {
if (it->id == share_target.id) {
@@ -105,12 +127,16 @@ class MyShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback {
break;
}
}
PrintMenuAtBottom();
}
void OnShareTargetUpdated(const ShareTarget& share_target) override {
std::cout << "\n*** Device Updated ***" << std::endl;
std::cout << "Name: " << share_target.device_name << std::endl;
std::cout << "**********************" << std::endl;
std::cout << "\n┌─────────────────────────────────────┐" << std::endl;
std::cout << "│ 🔄 DEVICE UPDATED │" << std::endl;
std::cout << "├─────────────────────────────────────┤" << std::endl;
std::cout << "│ Name: " << share_target.device_name << std::endl;
std::cout << "└─────────────────────────────────────┘" << std::endl;
PrintMenuAtBottom();
}
const std::vector<ShareTarget>& GetDiscoveredTargets() const {
@@ -119,6 +145,19 @@ class MyShareTargetDiscoveredCallback : public ShareTargetDiscoveredCallback {
private:
std::vector<ShareTarget> discovered_targets_;
void PrintMenuAtBottom() {
std::cout << "\n╔═════════════════════════════════════════════════════════╗" << std::endl;
std::cout << "║ NEARBY SHARING - MENU ║" << std::endl;
std::cout << "╠═════════════════════════════════════════════════════════╣" << std::endl;
std::cout << "║ 1. Start as Receiver │ 6. Accept pending request ║" << std::endl;
std::cout << "║ 2. Start as Sender │ 7. Reject pending request ║" << std::endl;
std::cout << "║ 3. List devices │ 8. Cancel transfer ║" << std::endl;
std::cout << "║ 4. Send file │ 9. Print status ║" << std::endl;
std::cout << "║ 5. Send text │ 0. Exit ║" << std::endl;
std::cout << "╚═════════════════════════════════════════════════════════╝" << std::endl;
std::cout << "Choice: ";
}
};
class NearbySharingApp {
@@ -142,9 +181,25 @@ class NearbySharingApp {
transfer_callback_.get(),
NearbySharingService::ReceiveSurfaceState::kForeground,
Advertisement::BlockedVendorId::kNone,
[](NearbySharingService::StatusCodes status) {
[this](NearbySharingService::StatusCodes status) {
if (status == NearbySharingService::StatusCodes::kOk) {
std::cout << "Successfully registered as receiver!" << std::endl;
// Display QR code URL
std::string qr_url = service_->GetQrCodeUrl();
if (!qr_url.empty()) {
std::cout << "\n┌──────────────────────────────────────────────────────────────┐" << std::endl;
std::cout << "│ QR CODE URL: │" << std::endl;
std::cout << "" << qr_url;
// Add padding if needed
if (qr_url.length() < 61) {
std::cout << std::string(61 - qr_url.length(), ' ');
}
std::cout << "" << std::endl;
std::cout << "│ │" << std::endl;
std::cout << "│ Scan this with your phone to connect! │" << std::endl;
std::cout << "└──────────────────────────────────────────────────────────────┘" << std::endl;
}
} else {
std::cout << "Failed to register as receiver: "
<< NearbySharingService::StatusCodeToString(status) << std::endl;
@@ -163,9 +218,25 @@ class NearbySharingApp {
NearbySharingService::SendSurfaceState::kForeground,
Advertisement::BlockedVendorId::kNone,
false, // disable_wifi_hotspot
[](NearbySharingService::StatusCodes status) {
[this](NearbySharingService::StatusCodes status) {
if (status == NearbySharingService::StatusCodes::kOk) {
std::cout << "Successfully registered as sender!" << std::endl;
// Display QR code URL
std::string qr_url = service_->GetQrCodeUrl();
if (!qr_url.empty()) {
std::cout << "\n┌──────────────────────────────────────────────────────────────┐" << std::endl;
std::cout << "│ QR CODE URL: │" << std::endl;
std::cout << "" << qr_url;
// Add padding if needed
if (qr_url.length() < 61) {
std::cout << std::string(61 - qr_url.length(), ' ');
}
std::cout << "" << std::endl;
std::cout << "│ │" << std::endl;
std::cout << "│ Scan this with your phone to connect! │" << std::endl;
std::cout << "└──────────────────────────────────────────────────────────────┘" << std::endl;
}
} else {
std::cout << "Failed to register as sender: "
<< NearbySharingService::StatusCodeToString(status) << std::endl;
@@ -180,9 +251,34 @@ class NearbySharingApp {
std::cout << "Target ID: " << target_id << std::endl;
std::cout << "File: " << file_path << std::endl;
nearby::FilePath path(file_path);
auto file_size = nearby::Files::GetFileSize(path);
if (!file_size.has_value()) {
std::cout << "Error: Could not get file size for " << file_path << std::endl;
return;
}
auto attachment_container = std::make_unique<AttachmentContainer>();
attachment_container->AddFileAttachment(FileAttachment(nearby::FilePath(file_path)));
// Use the constructor that accepts size
std::string file_name = path.GetFileName().ToString();
std::string mime_type = ""; // Will be auto-detected from extension
// Create file attachment with proper size
FileAttachment file_attachment(
/*id=*/0, // ID will be auto-generated
/*size=*/static_cast<int64_t>(*file_size),
/*file_name=*/file_name,
/*mime_type=*/mime_type,
/*type=*/service::proto::FileMetadata::UNKNOWN,
/*parent_folder=*/"",
/*batch_id=*/0
);
// Set the file path after construction
file_attachment.set_file_path(path);
attachment_container->AddFileAttachment(std::move(file_attachment));
service_->SendAttachments(
target_id,
@@ -328,19 +424,16 @@ class NearbySharingApp {
};
void PrintMenu() {
std::cout << "\n========== Nearby Sharing Menu ==========" << std::endl;
std::cout << "1. Start as Receiver (advertise)" << std::endl;
std::cout << "2. Start as Sender (discover)" << std::endl;
std::cout << "3. List discovered devices" << std::endl;
std::cout << "4. Send file to device" << std::endl;
std::cout << "5. Send text to device" << std::endl;
std::cout << "6. Accept pending incoming share (auto-detects ID)" << std::endl;
std::cout << "7. Reject pending incoming share (auto-detects ID)" << std::endl;
std::cout << "8. Cancel transfer" << std::endl;
std::cout << "9. Print status" << std::endl;
std::cout << "0. Exit" << std::endl;
std::cout << "=========================================" << std::endl;
std::cout << "Enter choice: ";
std::cout << "\n╔═════════════════════════════════════════════════════════╗" << std::endl;
std::cout << "║ NEARBY SHARING - MENU ║" << std::endl;
std::cout << "╠═════════════════════════════════════════════════════════╣" << std::endl;
std::cout << "║ 1. Start as Receiver │ 6. Accept pending request ║" << std::endl;
std::cout << "║ 2. Start as Sender │ 7. Reject pending request ║" << std::endl;
std::cout << "║ 3. List devices │ 8. Cancel transfer ║" << std::endl;
std::cout << "║ 4. Send file │ 9. Print status ║" << std::endl;
std::cout << "║ 5. Send text │ 0. Exit ║" << std::endl;
std::cout << "╚═════════════════════════════════════════════════════════╝" << std::endl;
std::cout << "Choice: ";
}
int main(int argc, char* argv[]) {
@@ -350,9 +443,15 @@ int main(int argc, char* argv[]) {
device_name = argv[1];
}
std::cout << "========================================" << std::endl;
std::cout << " Nearby Sharing Linux Application" << std::endl;
std::cout << "========================================" << std::endl;
// Clear screen and show header
std::cout << "\033[2J\033[1;1H"; // Clear screen
std::cout << "╔═════════════════════════════════════════════════════════╗" << std::endl;
std::cout << "║ ║" << std::endl;
std::cout << "║ NEARBY SHARING - LINUX APPLICATION ║" << std::endl;
std::cout << "║ Device: " << device_name << std::string(32 - device_name.length(), ' ') << "" << std::endl;
std::cout << "║ ║" << std::endl;
std::cout << "╚═════════════════════════════════════════════════════════╝" << std::endl;
std::cout << "\n[LOG AREA - Updates will appear above the menu]\n" << std::endl;
NearbySharingApp app(device_name);
+91 -2
View File
@@ -21,6 +21,7 @@
#include <string>
#include <utility>
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "connections/advertising_options.h"
@@ -31,10 +32,14 @@
#include "connections/payload.h"
#include "connections/status.h"
#include "connections/strategy.h"
#include "internal/crypto_cros/ec_private_key.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/file.h"
#include "internal/platform/logging.h"
#include "sharing/certificates/common.h"
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/evp.h>
namespace nearby::sharing::linux {
namespace {
@@ -240,12 +245,96 @@ bool NearbySharingServiceLinux::IsBluetoothPowered() const {
}
bool NearbySharingServiceLinux::IsExtendedAdvertisingSupported() const {
return false;
return true;
}
bool NearbySharingServiceLinux::IsLanConnected() const { return false; }
std::string NearbySharingServiceLinux::GetQrCodeUrl() const { return ""; }
std::string NearbySharingServiceLinux::GenerateQrCodeUrl() const {
// Generate ECDSA P-256 key pair
auto ec_key = nearby::crypto::ECPrivateKey::Create();
if (!ec_key) {
LOG(ERROR) << "Failed to generate EC key for QR code";
return "";
}
// Get the EC_KEY from EVP_PKEY
EC_KEY* raw_ec_key = EVP_PKEY_get0_EC_KEY(ec_key->key());
if (!raw_ec_key) {
LOG(ERROR) << "Failed to get EC_KEY from EVP_PKEY";
return "";
}
const EC_GROUP* group = EC_KEY_get0_group(raw_ec_key);
const EC_POINT* pub_key = EC_KEY_get0_public_key(raw_ec_key);
if (!group || !pub_key) {
LOG(ERROR) << "Failed to get EC group or public key";
return "";
}
// Get the X and Y coordinates
BIGNUM* x = BN_new();
BIGNUM* y = BN_new();
if (!x || !y) {
BN_free(x);
BN_free(y);
LOG(ERROR) << "Failed to allocate BIGNUMs";
return "";
}
if (!EC_POINT_get_affine_coordinates_GFp(group, pub_key, x, y, nullptr)) {
BN_free(x);
BN_free(y);
LOG(ERROR) << "Failed to get affine coordinates";
return "";
}
// Convert X coordinate to bytes (32 bytes for P-256)
std::vector<uint8_t> x_bytes(32, 0);
int x_len = BN_num_bytes(x);
if (x_len > 32) {
BN_free(x);
BN_free(y);
LOG(ERROR) << "X coordinate too large";
return "";
}
// Pad with leading zeros if needed
int offset = 32 - x_len;
BN_bn2bin(x, x_bytes.data() + offset);
// Determine prefix byte based on Y coordinate parity
// 0x02 if Y is even, 0x03 if Y is odd
uint8_t prefix = BN_is_odd(y) ? 0x03 : 0x02;
BN_free(x);
BN_free(y);
// Build the key data: [version (2 bytes), prefix (1 byte), X coordinate (32 bytes)]
std::vector<uint8_t> key_data;
key_data.reserve(35); // 2 + 1 + 32
key_data.push_back(0x00); // Version byte 1
key_data.push_back(0x00); // Version byte 2
key_data.push_back(prefix); // Prefix byte (0x02 or 0x03)
key_data.insert(key_data.end(), x_bytes.begin(), x_bytes.end()); // X coordinate
// Base64url encode
std::string encoded;
absl::WebSafeBase64Escape(
std::string(reinterpret_cast<const char*>(key_data.data()), key_data.size()),
&encoded);
// Build the final URL
return "https://quickshare.google/qrcode#key=" + encoded;
}
std::string NearbySharingServiceLinux::GetQrCodeUrl() const {
// Generate the URL once and cache it
if (qr_code_url_.empty()) {
qr_code_url_ = GenerateQrCodeUrl();
}
return qr_code_url_;
}
void NearbySharingServiceLinux::SendAttachments(
int64_t share_target_id,
@@ -222,6 +222,10 @@ class NearbySharingServiceLinux : public NearbySharingService {
int64_t next_share_target_id_ = 1;
bool last_advertise_with_name_ = false;
uint8_t last_advertise_vendor_id_ = 0;
// QR code related
mutable std::string qr_code_url_;
std::string GenerateQrCodeUrl() const;
};
} // namespace nearby::sharing::linux