//! Blob handlers — chunked file upload/download. use std::sync::Arc; use bytes::Bytes; use prost::Message; use quicprochat_proto::qpc::v1; use quicprochat_rpc::method::{HandlerResult, RequestContext}; use crate::domain::blobs::BlobService; use crate::domain::types::{CallerAuth, DownloadBlobReq, UploadBlobReq}; use super::{domain_err, require_auth, ServerState}; fn caller_auth(identity_key: Vec) -> CallerAuth { CallerAuth { identity_key, token: Vec::new(), device_id: None, } } pub async fn handle_upload_blob(state: Arc, ctx: RequestContext) -> HandlerResult { let identity_key = match require_auth(&state, &ctx) { Ok(ik) => ik, Err(e) => return e, }; let req = match v1::UploadBlobRequest::decode(ctx.payload) { Ok(r) => r, Err(e) => { return HandlerResult::err( quicprochat_rpc::error::RpcStatus::BadRequest, &format!("decode: {e}"), ) } }; let svc = BlobService { data_dir: state.data_dir.clone(), }; let auth = caller_auth(identity_key); let domain_req = UploadBlobReq { blob_hash: req.blob_hash, chunk: req.chunk, offset: req.offset, total_size: req.total_size, mime_type: req.mime_type, }; match svc.upload_blob(domain_req, &auth) { Ok(resp) => { let proto = v1::UploadBlobResponse { blob_id: resp.blob_id, }; HandlerResult::ok(Bytes::from(proto.encode_to_vec())) } Err(e) => domain_err(e), } } pub async fn handle_download_blob(state: Arc, ctx: RequestContext) -> HandlerResult { let identity_key = match require_auth(&state, &ctx) { Ok(ik) => ik, Err(e) => return e, }; let req = match v1::DownloadBlobRequest::decode(ctx.payload) { Ok(r) => r, Err(e) => { return HandlerResult::err( quicprochat_rpc::error::RpcStatus::BadRequest, &format!("decode: {e}"), ) } }; let svc = BlobService { data_dir: state.data_dir.clone(), }; let auth = caller_auth(identity_key); let domain_req = DownloadBlobReq { blob_id: req.blob_id, offset: req.offset, length: req.length, }; match svc.download_blob(domain_req, &auth) { Ok(resp) => { let proto = v1::DownloadBlobResponse { chunk: resp.chunk, total_size: resp.total_size, mime_type: resp.mime_type, }; HandlerResult::ok(Bytes::from(proto.encode_to_vec())) } Err(e) => domain_err(e), } }