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 / Build Docker Images (push) Blocked by required conditions
CI Pipeline / E2E Tests (push) Blocked by required conditions
92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
package chunker
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
const ChunkSize = 2 * 1024 * 1024 // 2MB
|
|
|
|
type Chunk struct {
|
|
Index int
|
|
Hash string // SHA-256 for Blossom
|
|
SHA1Hash [20]byte // SHA-1 for BitTorrent
|
|
Data []byte
|
|
Size int
|
|
}
|
|
|
|
type ChunkResult struct {
|
|
Chunks []Chunk
|
|
TotalSize int64
|
|
FileHash string
|
|
}
|
|
|
|
func ChunkFile(reader io.Reader) (*ChunkResult, error) {
|
|
var chunks []Chunk
|
|
var totalSize int64
|
|
index := 0
|
|
|
|
fileHasher := sha256.New()
|
|
|
|
for {
|
|
buffer := make([]byte, ChunkSize)
|
|
n, err := reader.Read(buffer)
|
|
if err != nil && err != io.EOF {
|
|
return nil, fmt.Errorf("error reading chunk: %w", err)
|
|
}
|
|
|
|
if n == 0 {
|
|
break
|
|
}
|
|
|
|
chunkData := buffer[:n]
|
|
|
|
// Update file hash
|
|
fileHasher.Write(chunkData)
|
|
|
|
// Calculate chunk hashes (both SHA-256 for Blossom and SHA-1 for BitTorrent)
|
|
sha256Hasher := sha256.New()
|
|
sha256Hasher.Write(chunkData)
|
|
chunkHash := fmt.Sprintf("%x", sha256Hasher.Sum(nil))
|
|
|
|
sha1Hasher := sha1.New()
|
|
sha1Hasher.Write(chunkData)
|
|
var sha1Hash [20]byte
|
|
copy(sha1Hash[:], sha1Hasher.Sum(nil))
|
|
|
|
chunks = append(chunks, Chunk{
|
|
Index: index,
|
|
Hash: chunkHash,
|
|
SHA1Hash: sha1Hash,
|
|
Data: chunkData,
|
|
Size: n,
|
|
})
|
|
|
|
totalSize += int64(n)
|
|
index++
|
|
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
}
|
|
|
|
fileHash := fmt.Sprintf("%x", fileHasher.Sum(nil))
|
|
|
|
return &ChunkResult{
|
|
Chunks: chunks,
|
|
TotalSize: totalSize,
|
|
FileHash: fileHash,
|
|
}, nil
|
|
}
|
|
|
|
func ReassembleChunks(chunks []Chunk, writer io.Writer) error {
|
|
for _, chunk := range chunks {
|
|
_, err := writer.Write(chunk.Data)
|
|
if err != nil {
|
|
return fmt.Errorf("error writing chunk %d: %w", chunk.Index, err)
|
|
}
|
|
}
|
|
return nil
|
|
} |