# node-to-node file share
###### tags: `Kizuna-architecture`
<style> .ui-infobar, #doc.markdown-body { max-width: 2000px; } </style>
## User Stories
- [As a user, I want to send files to a chat so that I can share my files.](https://beyonder.atlassian.net/browse/KIZUNA-63)
- [As a user, I want to send media files to a chat so that I can share my images/videos.](https://beyonder.atlassian.net/browse/KIZUNA-64)
- [As a user, I want to send voice notes to a chat/groupchat so that I can share that voice note](https://beyonder.atlassian.net/browse/KIZUNA-65)
- [I want to be notified of incoming file attachment message so I know that someone sent me a file](https://beyonder.atlassian.net/browse/KIZUNA-371)
- [I want to see media files sent to the chat so that I can check what they sent.](https://beyonder.atlassian.net/browse/KIZUNA-61)
- [I want to see shared files/media in a chat/group chat so that I can browse through previously sent files.](https://beyonder.atlassian.net/browse/KIZUNA-96)
- [I want to download files sent to the chat so that I can have it locally.](https://beyonder.atlassian.net/browse/KIZUNA-60)
- [I want to choose whether to auto download files/media ](https://beyonder.atlassian.net/browse/KIZUNA-331)(maybe move to preference?)
- [I want to choose whether to have preview of files/media](https://beyonder.atlassian.net/browse/KIZUNA-332)(maybe move to preference?)
## Notes
* 16Mb file size limit
* will become similar to P2PMessage
* chunking and DHT storage can be done for group file sending
## Entry Relationship Diagram
```mermaid
graph LR
subgraph p2pmessage zome
subgraph agents
alice
bobby
end
subgraph file chunks in DHT
file_chunk_1
file_chunk_2
file_chunk_n
end
subgraph file metadata in source chains
file_metadata_1
alice.->|has in source chain|file_metadata_1
bobby.->|has in source chain|file_metadata_1
file_metadata_1.->file_chunk_1
file_metadata_1.->file_chunk_2
file_metadata_1.->file_chunk_n
end
end
```
## File Sharing (Using external chunking)
### Comments and Questions
* Is it safe storing chunks of files in DHT?
* prolly not
* maybe if we do encryption on chunks
* For synchronous comms, do we do encyrption or is it redundant because of QUIC? How about on Holo? is local device to HoloPort encrypted also?
* Is looping through chunks in the UI and calling a zome function per chunk efficient?
* What is the size limit per call to a zome function from the UI?
* May provide an advantage in error recovery midway through uploads
* TODO: Asynchronous file sending
* Would be better if we can just send the chunks through call_remote
* No ecnryption design yet
* Guillem: seems prone to attacks; can we commit entry in DHT and just and send the link
### Entry Structure
```rust=
#[hdk_entry(id="file_metadata", visibility="private")]
struct FileMetadata {
author: AgentPubKey,
receiver: AgentPubKey,
file_name: String,
file_size: usize,
file_type: String,
time_sent: Timestamp,
time_received: Option<Timestamp>,
chunks: Vec<EntryHash> // addresses of each chunk in the DHT
}
#[hdk_entry(id="file_chunk", visibility="public")]
struct FileChunk(Vec<u8>);
pub struct FileMetadataOutput {
author: AgentPubKey,
receiver: AgentPubKey,
file_name: String,
file_size: usize,
file_type: String,
time_sent: Timestamp,
time_received: Option<Timestamp>,
chunks: Vec<EntryHash>
}
pub struct FileInput {
pub receiver: AgentPubKey,
pub file_name: String,
pub file_size: usize,
pub file_type: String,
pub chunks: Vec<EntryHash>,
pub hash: String
}
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Conversation_Cell
AUI-->>AUI: chunk file
AUI-->>AUI: construct empty metadata struct
loop for all file chunks
rect rgba(0,255,0,0.5)
AUI-->>ACD: call `upload_chunk`
ACD-->>AUI: return chunk address in DHT
end
AUI-->>AUI: add chunk address to metadata
end
AUI-->>AUI: generate hash of entire file
AUI-->>AUI: add file hash to metadata
rect rgba(0,255,0,0.5)
AUI-->>ACD: call `send_file`
ACD-->>AUI: return FileMetadata
end
```
## Zome functions
### upload_chunk
```rust=
// Function to commit a chunk of a file into the DHT.
// Called iteratively in the front-end over the chunks of a file.
pub(crate) fn upload_chunk(
file_chunk_input: FileChunk
) -> ExternResult<EntryHash>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Conversation_Cell
participant DHT as DHT
ACD-->>ACD: construct FileChunk entry
ACD-->>DHT: commit entry to DHT
DHT-->>ACD: return address
ACD-->>AUI: return address of FileChunk in DHT
```
### send_file
```rust=
// Function to send the file metadata synchronously from one agent to another.
pub(crate) fn send_file(
file_input: FileInput
) -> ExternResult<FileMetadataOption>
```
```mermaid
sequenceDiagram
participant AUI as Alice_UI
participant ACD as Alice_Conversation_Cell
participant BCD as Bobby_Conversation_Cell
participant DHT as DHT
loop for all chunk addresses
rect rgba(0,0,255,0.3)
ACD-->>DHT: call `get_bytes_from_chunks`
end
DHT-->>ACD: return file bytes
end
ACD-->>ACD: compute file hash from bytes
alt computed file hash != input file hash
ACD-->>AUI: return error "file integrity check failed"
else computed file hash = input file hash
rect rgba(0,255,0,0.5)
ACD-->>BCD: call_remote `receive_file_metadata`
BCD-->>ACD: return call_remote result
end
alt call_remote ok
ACD-->>ACD: construct FileMetadata entry
ACD-->>ACD: commit FileMetadata entry to source chain
else call_remote timeout
Note over ACD: TODO: async case
else call_remote unauthorized
ACD-->>AUI: return error "No proper authorization"
end
end
```
### get_bytes_from_chunks
```rust=
// internal helper function
pub fn get_bytes_from_chunks(
chunks_hashes: Vec<EntryHash>
) -> ExternResult<Vec<u8>>
```
```mermaid
sequenceDiagram
participant ACD as Alice_Conversation_Cell
participant DHT as DHT
loop for all chunk addresses
rect rgba(0,0,255,0.3)
ACD-->>DHT: call `get_file_chunk`
end
DHT-->>ACD: return file chunk bytes
end
ACD-->>ACD: assemble file from bytes
ACD-->>ACD: return file_bytes
```
### get_file_chunk
```rust=
// internal helper function
pub fn get_file_chunk(
file_chunk_hash: FileChunk
) -> ExternResult<EntryHash>
```
```mermaid
sequenceDiagram
participant ACD as Alice_Conversation_Cell
participant DHT as DHT
ACD-->>DHT: get entry of file chunk in DHT
DHT-->>ACD: return entry
```
### receive_file_metadata
```rust=
pub(crate) fn receive_file_metadata(
metadata_input: FileMetadataOutput
) -> ExternResult<FileMetadataOption>
```
```mermaid
sequenceDiagram
participant ACD as Alice_Conversation_Cell
participant BCD as Bobby_Conversation_Cell
BCD-->>BCD: construct FileMetdataEntry
BCD-->>BCD: generate and add timestamp to time_received field of FileMetadataEntry
BCD-->>BCD: commit entry to source chain
BCD-->>BCD: construct FileMetadataOutput from entry
BCD-->>BUI: emit signal "file has been received"
BCD-->>ACD: return FileMetadataOutput
```
## Validation
### Entries
### Links