tiny
tiny copied to clipboard
Support for DCC file transfers
Some IRC servers with search bots are based on DCC transfers to send search results in the .txt format to the user, such as #bookz or #ebooks and others.
tiny
sends a notification about the DCC transfer being initiated, but can't actually receive anything. I am afraid it would be a lot of work to implement, but it is worth asking. For reference, this is how irssi
handles DCC transfers: https://irssi.org/documentation/help/dcc/
I have no objection to supporting IRC extensions.
Going to start building this because it is something that I really want too. Right now I only need receiving files, so I don't think I will try and implement anything more than handling DCC SEND and then a command to DCC GET a file. I'm going to keep it as simple as possible.
Overview:
-
PRIVMSG
is already parsing CTCP messages, so I will addDCC
to thewire:CTCP
enum. - I believe I will have to store a
DCCRecord
that holds the address:port, filename, etc. I think I'll store these onstate.rs
for now, but @osa1 probably has a better idea. - Then if the client wants to accept this file, they type
/DCC GET sender filename
and the file just downloads to some configurable directory, or ignores it (and the DCCRecord times out?).
Spec: https://modern.ircdocs.horse/dcc.html
Actually I just need receive too to be able to receive those .zip or .txt files from search bots, so just receive would be perfect for me already, but I assume some would expect send/receive in the future.
Just want to comment that I have the client accepting DCC SEND and I have /dcc GET <sender> <file>
working, and I'm excited so I wanted to tell someone. I have never used tokio
before, so this is a pretty fun learning experience for me.
Next steps:
- Add download directory to config
- Add support for client-side SEND (so you can send files to people)
- Add support for
/dcc CLOSE [send|get] <sender/receiver> <filename>
to cancel a download? - Add ability to rename file (maybe?)
- Clean up my messy code and add comments
I'm excited so I wanted to tell someone
I'm looking forward to trying it too now.
@osa1 Hey, if/when you get the time, I would like your opinion on how to handle caching DCC records and then expiring them after a duration... What I have now is as follows:
- Receive DCC message
- Store
DCCRecord
on eachClient
'sState
in a hashmap
It does not expire the records, only removes them when they're accessed.
I'm finding it difficult to spawn a task that expires the records, so I'm thinking that I might need to create another task just for handling DCC stuff in main.rs
.
Do you have any expert advice? 😃
@trevarj What do you mean by "DCC record" exactly? Open DCC connections? Or something else?
@osa1 When the client receives a DCC command (someone wants to send you a file) you should store the record of it. So, when the user decides to accept the request (file or private chat) then you can go retrieve the record, which has the IP and port to connect to. If the user doesn't want to accept, the record should expire and get freed from memory.
Basically, when you get a CTCP message for DCC (Version is already there) in conn.rs
it will push a DCCRecord into the cache. When the user wants to do a 'GET' in cmd.rs
it will try to read from the cache.
I've been looking into using tokio::time::DelayQueue
and building a custom cache with that, but maybe it is overkill and there's a simpler way we add a cache like this.
Hmm, so for every connection we need a HashMap<Nick, (Ip, Port)>
for file send requests. The questions are:
- Where to store this hash map
- How to remove entries
For (1) I think we should put it in Client
, because it's not shared between servers, and I think we'll need some support from Client
anyway to start file download or upload.
We already have a similar state in Client
: StateInner::chans
. You could add one more field there, I think.
For (2) I think it's fine to not remove entries for now. I think 99.9% of users will never use DCC so the HashMap
will always be empty (I've been using IRC for more than 10 years and never used DCC). For the rare cases where you use it, size of the hash map will be bounded by the number of unique nicks you receive a DCC message from. I think this will be a tiny number (e.g. not more than 10 in the worst case). It seems like removing entries is not worth adding any more code.
@trevarj does this make sense? Let me know if my assumptions about DCC are wrong.
@osa1 Ok, great, this is pretty much what I have already. Thanks for the help!