Files
core/protocol/Message Encoding Transfer.go
Akilan Selvacoumar ae5f1d2fd7 New features (#110)
* added upload status

* added changes for progress bar with more logs and bug fixes, Documentation yet to be added

* huge changes that need more doucmenting

* added possibility to get profile using NodeID

* added fix profile listing user profile information

* removed profile image from the explore reult struct

* saving current changes

* added filter to search based on NodeID

* Monday bug fixing

* updates to the profile

* changes for tracing the blockchain profile image not shown

* added condition to ensure TAG is not sent and removed debug prints

* updated webapi docs
2023-06-28 00:38:17 +01:00

137 lines
5.1 KiB
Go

/*
File Username: Message Encoding Transfer.go
Copyright: 2021 Peernet s.r.o.
Author: Peter Kleissner
Transfer message encoding:
Offset Size Info
0 1 Control
1 1 Transfer Protocol
2 32 File Hash
Control = 0: Request Start
34 8 Offset to start reading in the file
42 8 Limit of bytes to read at the offset
50 16 Transfer ID. This will identify lite packets.
Offset + limit must not exceed the file size. Actual data transfer should be sent via lite packets.
The regular Peernet packets would be too CPU expensive and slow due to public key signing.
*/
package protocol
import (
"encoding/binary"
"errors"
"github.com/PeernetOfficial/core/btcec"
"github.com/google/uuid"
)
// MessageTransfer is the decoded transfer message.
// It is sent to initiate a file transfer, and to send data as part of a file transfer. The actual file data is encapsulated via UDT.
type MessageTransfer struct {
*MessageRaw // Underlying raw message.
Control uint8 // Control. See TransferControlX.
TransferProtocol uint8 // Embedded transfer protocol: 0 = UDT
Hash []byte // Hash of the file to transfer.
Offset uint64 // Offset to start reading at. Only TransferControlRequestStart.
Limit uint64 // Limit (count of bytes) to read starting at the offset. Only TransferControlRequestStart.
TransferID uuid.UUID // Transfer ID to identify lite packets.
Data []byte // Embedded protocol data. Only TransferControlActive.
}
const (
TransferControlRequestStart = 0 // Request start transfer of file. Data at byte 34 is offset and limit to read, each 8 bytes. Limit may be 0 to indicate entire file.
TransferControlNotAvailable = 1 // Requested file not available
TransferControlActive = 2 // Active file transfer
TransferControlTerminate = 3 // Terminate
)
const (
TransferProtocolUDT = 0 // UDT via lite packets. No encryption.
)
const transferPayloadHeaderSize = 34
// DecodeTransfer decodes a transfer message
func DecodeTransfer(msg *MessageRaw) (result *MessageTransfer, err error) {
if len(msg.Payload) < transferPayloadHeaderSize {
return nil, errors.New("transfer: invalid minimum length")
}
result = &MessageTransfer{
MessageRaw: msg,
Hash: make([]byte, HashSize),
}
result.Control = msg.Payload[0]
result.TransferProtocol = msg.Payload[1]
copy(result.Hash, msg.Payload[2:2+HashSize])
switch result.Control {
case TransferControlRequestStart:
// Offset and Limit must be provided after the header.
if len(msg.Payload) < transferPayloadHeaderSize+16 {
return nil, errors.New("transfer: invalid minimum length")
}
result.Offset = binary.LittleEndian.Uint64(msg.Payload[34 : 34+8])
result.Limit = binary.LittleEndian.Uint64(msg.Payload[42 : 42+8])
copy(result.TransferID[:], msg.Payload[50:50+16])
case TransferControlActive:
// Data should be transferred via lite packets for performance reasons, but it is allowed to be encapsulated in Peernet packets.
result.Data = msg.Payload[transferPayloadHeaderSize:]
}
return result, nil
}
// TransferMaxEmbedSize is a recommended default upper size of embedded data inside the Transfer message, to be used as MaxPacketSize limit in the embedded protocol.
// This value is chosen as the lowest denominator of different environments (IPv4, IPv6, Ethernet, Internet) for safe transfer, not for highest performance.
// The caller may send bigger payloads but may risk that data packets are simply dropped and never arrive. A MTU negotiation or detection could pimp that.
const TransferMaxEmbedSize = internetSafeMTU - PacketLengthMin - transferPayloadHeaderSize
// Same as TransferMaxEmbedSize but for encoding via lite packets.
const TransferMaxEmbedSizeLite = internetSafeMTU - PacketLiteSizeMin
// EncodeTransfer encodes a transfer message. The embedded packet size must be smaller than TransferMaxEmbedSize.
func EncodeTransfer(senderPrivateKey *btcec.PrivateKey, data []byte, control, transferProtocol uint8, hash []byte, offset, limit uint64, transferID uuid.UUID) (packetRaw []byte, err error) {
if control == TransferControlRequestStart && len(data) != 0 {
return nil, errors.New("transfer encode: payload not allowed in start")
} else if isPacketSizeExceed(transferPayloadHeaderSize, len(data)) {
return nil, errors.New("transfer encode: embedded packet too big")
}
packetSize := transferPayloadHeaderSize
if control == TransferControlRequestStart {
packetSize += 32
} else if control == TransferControlActive {
packetSize += len(data)
}
raw := make([]byte, packetSize)
raw[0] = control
raw[1] = transferProtocol
copy(raw[2:2+HashSize], hash)
if control == TransferControlRequestStart {
binary.LittleEndian.PutUint64(raw[34:34+8], offset)
binary.LittleEndian.PutUint64(raw[42:42+8], limit)
copy(raw[50:50+16], transferID[:])
} else if control == TransferControlActive {
copy(raw[34:34+len(data)], data)
}
return raw, nil
}
// IsLast checks if the incoming message is the last one in this transfer.
func (msg *MessageTransfer) IsLast() bool {
return msg.Control == TransferControlTerminate || msg.Control == TransferControlNotAvailable
}