DHT Race crash fix
This commit is contained in:
parent
2b7f44b2d7
commit
1472fb7cfd
@ -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
|
||||
|
||||
|
@ -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, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
// 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>
|
||||
`;
|
||||
|
@ -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, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
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>
|
||||
`;
|
||||
|
BIN
torrent-gateway
BIN
torrent-gateway
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user