mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Added capability to generate QR code
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user