Files
utun2/tools/chatgui-android/libutun_lite/attachment_sender.c
T
evgeny 38c9f229bc stcp: ed25519 pubkey exchange in handshake, fix instance destroy segfault, fix chat_tcp_test
- u_async.c: process immediate_queue BEFORE epoll_wait in uasync_poll
- stcp_link.c: defensive NULL etcp_conn/etcp_link in stcp_link_close
- utun_instance.c: move stcp_server_list_destroy_all to Phase J (before ETCP),
  add deferred drain in both Phase J and L
- stcp.h/c: STCP_HS_ENC_CLIENT 6→38, STCP_HS_ENC_SERVER 7→39,
  exchange ed25519_pubkey in both handshake directions
- etcp_connections.c: copy peer_ed25519 from STCP to ETCP_CONN in
  etcp_link_enter_ready_tcp; guard link->etcp in tcp_link_close_cb
- chat_sync.c: fix lk->conn NULL dereference for TCP links
- test_stcp.c: update stcp_server_create/stcp_client_connect callsites
- tools/chat_tcp_test: change transport udp→tcp
2026-08-07 00:48:27 +03:00

85 lines
3.3 KiB
C

#include "attachment_sender.h"
#include "instance_lite.h"
#include "../../../lib/debug_config.h"
#include "../../../lib/mem.h"
#include "../../../lib/u_async.h"
#include "../../../src/chat/chat_core.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
int attachment_send(const char* channel_id, const char* src_file_path, const char* db_path) {
if (!channel_id || !src_file_path || !db_path) {
DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "attachment_send: invalid args");
return -1;
}
struct UASYNC* ua = instance_lite_get_uasync();
if (!ua) { DEBUG_ERROR(DEBUG_CATEGORY_GENERAL, "attachment_send: no uasync"); return -1; }
/* get original basename for display, then make unique filename for storage */
char path_copy[1024];
snprintf(path_copy, sizeof(path_copy), "%s", src_file_path);
char* fname = basename(path_copy);
char original_basename[256];
snprintf(original_basename, sizeof(original_basename), "%s", fname);
char* dot = strrchr(fname, '.');
char ext[32] = "";
if (dot) { snprintf(ext, sizeof(ext), "%s", dot + 1); *dot = '\0'; }
struct stat st; memset(&st, 0, sizeof(st));
stat(src_file_path, &st);
/* generate dt/suffix for unique filename */
time_t t = time(NULL);
struct tm tm_buf; localtime_r(&t, &tm_buf);
char dt[32]; snprintf(dt, sizeof(dt), "%04d%02d%02d-%02d%02d%02d",
tm_buf.tm_year + 1900, tm_buf.tm_mon + 1, tm_buf.tm_mday,
tm_buf.tm_hour, tm_buf.tm_min, tm_buf.tm_sec);
int rnd = rand() & 0xFFFF;
char suffix[8]; snprintf(suffix, sizeof(suffix), "%04x", rnd);
/* ensure media dir exists */
char media_dir[1024];
snprintf(media_dir, sizeof(media_dir), "%s/media/%s", db_path, channel_id);
{
char tmp[1024]; size_t off = 0;
for (size_t i = 0; media_dir[i] && off < sizeof(tmp) - 1; i++) {
tmp[off++] = media_dir[i];
if (media_dir[i] == '/' && off > 1) { tmp[off] = '\0'; mkdir(tmp, 0755); }
}
mkdir(tmp, 0755);
}
/* single file path — no splitting */
char media_file[1280];
snprintf(media_file, sizeof(media_file), "%s/%s_%s_%s.%s",
media_dir, dt, fname, suffix, ext[0] ? ext : "bin");
/* post chat_msg_submit — media_copy=1 so media_index copies src to dest
data = original_basename — becomes first part of message "d" field: "name.ext|size|..." */
size_t datalen = strlen(original_basename);
struct chat_msg_submit* req = u_calloc(1, sizeof(struct chat_msg_submit) + datalen + 1);
if (!req) return -1;
snprintf(req->channel_id, sizeof(req->channel_id), "%s", channel_id);
snprintf(req->content_type, sizeof(req->content_type), "application/octet-stream");
snprintf(req->media_src, sizeof(req->media_src), "%s", src_file_path);
snprintf(req->media_dest, sizeof(req->media_dest), "%s", media_file);
req->media_copy = 1;
req->data = (uint8_t*)(req + 1);
memcpy(req->data, original_basename, datalen);
req->data_len = (uint32_t)datalen;
req->timestamp = 0;
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "attachment_send: ch=%s src=%s dst=%s name=%s size=%lld",
channel_id, src_file_path, media_file, original_basename, (long long)st.st_size);
uasync_post(ua, chat_core_submit_trampoline, req);
return 0;
}