mirror of
https://github.com/matrix-construct/construct
synced 2024-11-18 07:50:57 +01:00
modules/media: Distill out some current media room functionality.
This commit is contained in:
parent
9a6dbca127
commit
dc2bd4f66e
3 changed files with 167 additions and 116 deletions
|
@ -35,3 +35,140 @@ file_room_id(const string_view &server,
|
||||||
b58encode(buf, hash), my_host()
|
b58encode(buf, hash), my_host()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
write_file(const m::room &room,
|
||||||
|
const string_view &content,
|
||||||
|
const string_view &content_type)
|
||||||
|
{
|
||||||
|
//TODO: TXN
|
||||||
|
send(room, m::me.user_id, "ircd.file.stat", "size",
|
||||||
|
{
|
||||||
|
{ "value", long(size(content)) }
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO: TXN
|
||||||
|
send(room, m::me.user_id, "ircd.file.stat", "type",
|
||||||
|
{
|
||||||
|
{ "value", content_type }
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto lpath
|
||||||
|
{
|
||||||
|
fs::make_path({fs::DPATH, "media"})
|
||||||
|
};
|
||||||
|
|
||||||
|
char pathbuf[768];
|
||||||
|
size_t pathlen{0};
|
||||||
|
pathlen = strlcpy(pathbuf, lpath);
|
||||||
|
pathlen = strlcat(pathbuf, "/"_sv); //TODO: fs utils
|
||||||
|
const mutable_buffer pathpart
|
||||||
|
{
|
||||||
|
pathbuf + pathlen, sizeof(pathbuf) - pathlen
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t off{0}, wrote{0};
|
||||||
|
while(off < size(content))
|
||||||
|
{
|
||||||
|
const size_t blksz
|
||||||
|
{
|
||||||
|
std::min(size(content) - off, size_t(32_KiB))
|
||||||
|
};
|
||||||
|
|
||||||
|
const const_buffer &block
|
||||||
|
{
|
||||||
|
data(content) + off, blksz
|
||||||
|
};
|
||||||
|
|
||||||
|
const sha256::buf hash_
|
||||||
|
{
|
||||||
|
sha256{block}
|
||||||
|
};
|
||||||
|
|
||||||
|
char b58buf[hash_.size() * 2];
|
||||||
|
const string_view hash
|
||||||
|
{
|
||||||
|
b58encode(b58buf, hash_)
|
||||||
|
};
|
||||||
|
|
||||||
|
send(room, m::me.user_id, "ircd.file.block",
|
||||||
|
{
|
||||||
|
{ "size", long(blksz) },
|
||||||
|
{ "hash", hash }
|
||||||
|
});
|
||||||
|
|
||||||
|
const string_view path
|
||||||
|
{
|
||||||
|
pathbuf, pathlen + copy(pathpart, hash)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!fs::exists(path))
|
||||||
|
wrote += size(fs::write(path, block));
|
||||||
|
|
||||||
|
off += blksz;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(off == size(content));
|
||||||
|
assert(wrote <= off);
|
||||||
|
return wrote;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t
|
||||||
|
read_each_block(const m::room &room,
|
||||||
|
const std::function<void (const string_view &)> &closure)
|
||||||
|
{
|
||||||
|
const auto lpath
|
||||||
|
{
|
||||||
|
fs::make_path({fs::DPATH, "media"})
|
||||||
|
};
|
||||||
|
|
||||||
|
char pathbuf[768];
|
||||||
|
size_t pathlen{0};
|
||||||
|
pathlen = strlcpy(pathbuf, lpath);
|
||||||
|
pathlen = strlcat(pathbuf, "/"_sv); //TODO: fs utils
|
||||||
|
const mutable_buffer pathpart
|
||||||
|
{
|
||||||
|
pathbuf + pathlen, sizeof(pathbuf) - pathlen
|
||||||
|
};
|
||||||
|
|
||||||
|
// Block buffer
|
||||||
|
const unique_buffer<mutable_buffer> buf
|
||||||
|
{
|
||||||
|
64_KiB
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t ret{0};
|
||||||
|
m::room::messages it{room, 0};
|
||||||
|
for(; bool(it); ++it)
|
||||||
|
{
|
||||||
|
const m::event &event{*it};
|
||||||
|
if(at<"type"_>(event) != "ircd.file.block")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const auto &hash
|
||||||
|
{
|
||||||
|
unquote(at<"content"_>(event).at("hash"))
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto &blksz
|
||||||
|
{
|
||||||
|
at<"content"_>(event).get<size_t>("size")
|
||||||
|
};
|
||||||
|
|
||||||
|
const string_view path
|
||||||
|
{
|
||||||
|
pathbuf, pathlen + copy(pathpart, hash)
|
||||||
|
};
|
||||||
|
|
||||||
|
const string_view &block
|
||||||
|
{
|
||||||
|
fs::read(path, buf)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert(size(block) == blksz);
|
||||||
|
ret += size(block);
|
||||||
|
closure(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -11,3 +11,6 @@
|
||||||
using namespace ircd;
|
using namespace ircd;
|
||||||
|
|
||||||
m::room::id::buf file_room_id(const string_view &server, const string_view &file);
|
m::room::id::buf file_room_id(const string_view &server, const string_view &file);
|
||||||
|
|
||||||
|
size_t read_each_block(const m::room &, const std::function<void (const string_view &)> &);
|
||||||
|
size_t write_file(const m::room &room, const string_view &content, const string_view &content_type);
|
||||||
|
|
|
@ -82,16 +82,22 @@ get__thumbnail(client &client,
|
||||||
};
|
};
|
||||||
|
|
||||||
m::vm::opts::commit vmopts;
|
m::vm::opts::commit vmopts;
|
||||||
|
vmopts.history = false;
|
||||||
const m::room room
|
const m::room room
|
||||||
{
|
{
|
||||||
room_id
|
room_id, &vmopts
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//TODO: ABA
|
||||||
if(m::exists(room))
|
if(m::exists(room))
|
||||||
return get__thumbnail_local(client, request, server, file, room);
|
return get__thumbnail_local(client, request, server, file, room);
|
||||||
|
|
||||||
if(!my_host(server))
|
if(!my_host(server))
|
||||||
|
{
|
||||||
|
//TODO: ABA TXN
|
||||||
|
create(room, m::me.user_id, "file");
|
||||||
return get__thumbnail_remote(client, request, server, file, room);
|
return get__thumbnail_remote(client, request, server, file, room);
|
||||||
|
}
|
||||||
|
|
||||||
throw m::NOT_FOUND
|
throw m::NOT_FOUND
|
||||||
{
|
{
|
||||||
|
@ -117,6 +123,7 @@ get__thumbnail_remote(client &client,
|
||||||
const string_view &hostname,
|
const string_view &hostname,
|
||||||
const string_view &mediaid,
|
const string_view &mediaid,
|
||||||
const m::room &room)
|
const m::room &room)
|
||||||
|
try
|
||||||
{
|
{
|
||||||
const net::hostport remote
|
const net::hostport remote
|
||||||
{
|
{
|
||||||
|
@ -200,76 +207,20 @@ get__thumbnail_remote(client &client,
|
||||||
client, remote_request.in.content, content_type
|
client, remote_request.in.content, content_type
|
||||||
};
|
};
|
||||||
|
|
||||||
//TODO: TXN
|
const size_t written
|
||||||
create(room, m::me.user_id, "file");
|
|
||||||
|
|
||||||
//TODO: TXN
|
|
||||||
send(room, m::me.user_id, "ircd.file.stat", "size",
|
|
||||||
{
|
{
|
||||||
{ "value", long(file_size) }
|
write_file(room, remote_request.in.content, content_type)
|
||||||
});
|
|
||||||
|
|
||||||
//TODO: TXN
|
|
||||||
send(room, m::me.user_id, "ircd.file.stat", "type",
|
|
||||||
{
|
|
||||||
{ "value", content_type }
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto lpath{fs::make_path({fs::DPATH, "media"})};
|
|
||||||
thread_local char pathbuf[1024];
|
|
||||||
size_t pathlen{0};
|
|
||||||
pathlen = strlcpy(pathbuf, lpath);
|
|
||||||
pathlen = strlcat(pathbuf, "/"_sv); //TODO: fs utils
|
|
||||||
const mutable_buffer pathpart
|
|
||||||
{
|
|
||||||
pathbuf + pathlen, sizeof(pathbuf) - pathlen
|
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t off{0}, wrote{0};
|
|
||||||
while(off < file_size)
|
|
||||||
{
|
|
||||||
const size_t blksz
|
|
||||||
{
|
|
||||||
std::min(file_size - off, size_t(32_KiB))
|
|
||||||
};
|
|
||||||
|
|
||||||
const const_buffer &block
|
|
||||||
{
|
|
||||||
data(remote_request.in.content) + off, blksz
|
|
||||||
};
|
|
||||||
|
|
||||||
const sha256::buf hash_
|
|
||||||
{
|
|
||||||
sha256{block}
|
|
||||||
};
|
|
||||||
|
|
||||||
char b58buf[hash_.size() * 2];
|
|
||||||
const string_view hash
|
|
||||||
{
|
|
||||||
b58encode(b58buf, hash_)
|
|
||||||
};
|
|
||||||
|
|
||||||
send(room, m::me.user_id, "ircd.file.block",
|
|
||||||
{
|
|
||||||
{ "size", long(blksz) },
|
|
||||||
{ "hash", hash }
|
|
||||||
});
|
|
||||||
|
|
||||||
const string_view path
|
|
||||||
{
|
|
||||||
pathbuf, pathlen + copy(pathpart, hash)
|
|
||||||
};
|
|
||||||
|
|
||||||
if(!fs::exists(path))
|
|
||||||
wrote += size(fs::write(path, block));
|
|
||||||
|
|
||||||
off += blksz;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(off == file_size);
|
|
||||||
assert(wrote <= off);
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
catch(const ircd::server::unavailable &e)
|
||||||
|
{
|
||||||
|
throw http::error
|
||||||
|
{
|
||||||
|
http::BAD_GATEWAY, e.what()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static resource::response
|
static resource::response
|
||||||
get__thumbnail_local(client &client,
|
get__thumbnail_local(client &client,
|
||||||
|
@ -288,7 +239,11 @@ get__thumbnail_local(client &client,
|
||||||
|
|
||||||
// Get the MIME type
|
// Get the MIME type
|
||||||
char type_buf[64];
|
char type_buf[64];
|
||||||
string_view content_type;
|
string_view content_type
|
||||||
|
{
|
||||||
|
"application/octet-stream"
|
||||||
|
};
|
||||||
|
|
||||||
room.get("ircd.file.stat", "type", [&type_buf, &content_type]
|
room.get("ircd.file.stat", "type", [&type_buf, &content_type]
|
||||||
(const m::event &event)
|
(const m::event &event)
|
||||||
{
|
{
|
||||||
|
@ -309,57 +264,13 @@ get__thumbnail_local(client &client,
|
||||||
client, http::OK, content_type, file_size
|
client, http::OK, content_type, file_size
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto lpath{fs::make_path({fs::DPATH, "media"})};
|
size_t sent{0}, read;
|
||||||
thread_local char pathbuf[1024];
|
read = read_each_block(room, [&client, &sent]
|
||||||
size_t pathlen{0};
|
(const string_view &block)
|
||||||
pathlen = strlcpy(pathbuf, lpath);
|
|
||||||
pathlen = strlcat(pathbuf, "/"_sv); //TODO: fs utils
|
|
||||||
const mutable_buffer pathpart
|
|
||||||
{
|
{
|
||||||
pathbuf + pathlen, sizeof(pathbuf) - pathlen
|
|
||||||
};
|
|
||||||
|
|
||||||
// Block buffer
|
|
||||||
const unique_buffer<mutable_buffer> buf
|
|
||||||
{
|
|
||||||
64_KiB
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spool content to client
|
|
||||||
size_t sent{0}, read{0};
|
|
||||||
m::room::messages it{room, 1};
|
|
||||||
for(; bool(it); ++it)
|
|
||||||
{
|
|
||||||
const m::event &event{*it};
|
|
||||||
if(at<"type"_>(event) != "ircd.file.block")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto &hash
|
|
||||||
{
|
|
||||||
unquote(at<"content"_>(event).at("hash"))
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto &blksz
|
|
||||||
{
|
|
||||||
at<"content"_>(event).get<size_t>("size")
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view path
|
|
||||||
{
|
|
||||||
pathbuf, pathlen + copy(pathpart, hash)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view &block
|
|
||||||
{
|
|
||||||
fs::read(path, buf)
|
|
||||||
};
|
|
||||||
|
|
||||||
assert(size(block) == blksz);
|
|
||||||
read += size(block);
|
|
||||||
sent += write_all(*client.sock, block);
|
sent += write_all(*client.sock, block);
|
||||||
}
|
});
|
||||||
|
|
||||||
assert(read == file_size);
|
//assert(sent == file_size);
|
||||||
assert(sent == read);
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue