DHT Race crash fix
Some checks are pending
CI Pipeline / Run Tests (push) Waiting to run
CI Pipeline / Lint Code (push) Waiting to run
CI Pipeline / Security Scan (push) Waiting to run
CI Pipeline / E2E Tests (push) Blocked by required conditions

This commit is contained in:
Enki 2025-09-02 20:01:52 -07:00
parent 2b7f44b2d7
commit 1472fb7cfd
4 changed files with 66 additions and 31 deletions

View File

@ -2218,6 +2218,7 @@ func (d *DHT) queryNodesParallel(candidates []*Node, targetID NodeID, queryType
resultChan := make(chan queryResult, len(candidates))
var wg sync.WaitGroup
var queriedMutex sync.Mutex
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
@ -2233,7 +2234,9 @@ func (d *DHT) queryNodesParallel(candidates []*Node, targetID NodeID, queryType
}()
key := fmt.Sprintf("%s:%d", node.Addr.IP, node.Addr.Port)
queriedMutex.Lock()
queried[key] = true
queriedMutex.Unlock()
var discoveredNodes []*Node

View File

@ -1374,22 +1374,23 @@
const baseUrl = window.location.origin;
// Use torrent info hash for magnet if available, otherwise use file hash
let magnetHash = hash;
if (file.torrent_info_hash) {
magnetHash = file.torrent_info_hash;
console.log('Using torrent InfoHash for magnet:', magnetHash);
} else {
console.log('No torrent InfoHash found, using file hash:', magnetHash);
}
const links = {
direct: `${baseUrl}/api/download/${hash}`,
torrent: `${baseUrl}/api/torrent/${hash}`,
magnet: `magnet:?xt=urn:btih:${magnetHash}&dn=${encodeURIComponent(file.name)}`,
stream: file.name.match(/\.(mp4|mkv|avi|mov)$/i) ? `${baseUrl}/api/stream/${hash}` : null
};
// Use the correct magnet link from file data, or fallback to constructed one
if (file.magnet_link) {
links.magnet = file.magnet_link;
console.log('Using API magnet link:', file.magnet_link);
} else {
// Fallback: Use torrent info hash if available, otherwise use file hash
let magnetHash = file.torrent_info_hash || hash;
links.magnet = `magnet:?xt=urn:btih:${magnetHash}&dn=${encodeURIComponent(file.name)}`;
console.log('Using fallback magnet with hash:', magnetHash);
}
showShareModal(file, links);
}
@ -1400,26 +1401,43 @@
fileName.textContent = file.name;
// Escape HTML attributes properly and validate links
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// Ensure all links are defined
const safeLinks = {
direct: links.direct || '',
torrent: links.torrent || '',
magnet: links.magnet || ''
};
let linksHTML = `
<div class="share-link">
<label>Direct Download:</label>
<div class="link-row">
<input type="text" value="${links.direct}" readonly onclick="this.select()">
<button onclick="copyToClipboard('${links.direct}')">Copy</button>
<input type="text" value="${escapeHtml(safeLinks.direct)}" readonly onclick="this.select()">
<button onclick="copyToClipboard(\`${escapeHtml(safeLinks.direct)}\`)">Copy</button>
</div>
</div>
<div class="share-link">
<label>Torrent File:</label>
<div class="link-row">
<input type="text" value="${links.torrent}" readonly onclick="this.select()">
<button onclick="copyToClipboard('${links.torrent}')">Copy</button>
<input type="text" value="${escapeHtml(safeLinks.torrent)}" readonly onclick="this.select()">
<button onclick="copyToClipboard(\`${escapeHtml(safeLinks.torrent)}\`)">Copy</button>
</div>
</div>
<div class="share-link">
<label>Magnet Link:</label>
<div class="link-row">
<input type="text" value="${links.magnet}" readonly onclick="this.select()">
<button onclick="copyToClipboard('${links.magnet}')">Copy</button>
<input type="text" value="${escapeHtml(safeLinks.magnet)}" readonly onclick="this.select()">
<button onclick="copyToClipboard(\`${escapeHtml(safeLinks.magnet)}\`)">Copy</button>
</div>
</div>
`;

View File

@ -614,15 +614,6 @@ class GatewayUI {
const baseUrl = window.location.origin;
// Use torrent info hash for magnet link if available, otherwise use file hash
let magnetHash = hash;
if (fileData && fileData.torrent_hash) {
magnetHash = fileData.torrent_hash;
console.log('Using torrent InfoHash for magnet:', magnetHash);
} else {
console.log('No torrent InfoHash found, using file hash:', magnetHash);
}
const links = {
direct: `${baseUrl}/api/download/${hash}`
};
@ -630,7 +621,17 @@ class GatewayUI {
// Only add torrent/magnet links for torrent storage type
if (fileData && fileData.storage_type === 'torrent') {
links.torrent = `${baseUrl}/api/torrent/${hash}`;
links.magnet = `magnet:?xt=urn:btih:${magnetHash}&dn=${encodeURIComponent(name)}`;
// Use the correct magnet link from API response, or fallback to constructed one
if (fileData.magnet_link) {
links.magnet = fileData.magnet_link;
console.log('Using API magnet link:', fileData.magnet_link);
} else {
// Fallback: Use torrent info hash if available, otherwise use file hash
let magnetHash = fileData.torrent_hash || hash;
links.magnet = `magnet:?xt=urn:btih:${magnetHash}&dn=${encodeURIComponent(name)}`;
console.log('Using fallback magnet with hash:', magnetHash);
}
// Add NIP-71 Nostr link for torrents if available
if (fileData.nip71_share_link) {
@ -686,17 +687,30 @@ class GatewayUI {
{ key: 'nostr', label: 'Share on Nostr', icon: '⚡' }
];
// Escape HTML attributes properly for Firefox compatibility
function escapeHtml(unsafe) {
return (unsafe || '')
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
linksContainer.innerHTML = linkTypes
.filter(type => links[type.key])
.map(type => {
const linkValue = links[type.key] || '';
const escapedLink = escapeHtml(linkValue);
if (type.key === 'nostr') {
return `
<div class="share-link nostr-link">
<label>${type.icon} ${type.label}</label>
<div class="input-group">
<input type="text" value="${links[type.key]}" readonly>
<button onclick="copyToClipboard('${links[type.key].replace(/'/g, '\\\'')}')" class="copy-btn">Copy</button>
<button onclick="window.open('https://njump.me/${links[type.key]}', '_blank')" class="open-btn">Open</button>
<input type="text" value="${escapedLink}" readonly>
<button onclick="copyToClipboard(\`${escapeHtml(linkValue)}\`)" class="copy-btn">Copy</button>
<button onclick="window.open('https://njump.me/${escapeHtml(linkValue)}', '_blank')" class="open-btn">Open</button>
</div>
<small>Opens in Nostr clients or web viewer</small>
</div>
@ -706,8 +720,8 @@ class GatewayUI {
<div class="share-link">
<label>${type.icon} ${type.label}</label>
<div class="input-group">
<input type="text" value="${links[type.key]}" readonly>
<button onclick="copyToClipboard('${links[type.key].replace(/'/g, '\\\'')}')" class="copy-btn">Copy</button>
<input type="text" value="${escapedLink}" readonly>
<button onclick="copyToClipboard(\`${escapeHtml(linkValue)}\`)" class="copy-btn">Copy</button>
</div>
</div>
`;

Binary file not shown.