torchat 0.0.1.rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +43 -0
- data/bin/torchatd +537 -0
- data/doc/protocol/broadcast.md +26 -0
- data/doc/protocol/groupchat.md +140 -0
- data/doc/protocol/latency.md +30 -0
- data/doc/protocol/standard.md +279 -0
- data/doc/protocol/typing.md +41 -0
- data/etc/torchat.yml +12 -0
- data/lib/torchat.rb +239 -0
- data/lib/torchat/protocol.rb +256 -0
- data/lib/torchat/protocol/broadcast.rb +40 -0
- data/lib/torchat/protocol/groupchat.rb +197 -0
- data/lib/torchat/protocol/latency.rb +44 -0
- data/lib/torchat/protocol/standard.rb +367 -0
- data/lib/torchat/protocol/typing.rb +36 -0
- data/lib/torchat/session.rb +603 -0
- data/lib/torchat/session/broadcast/message.rb +50 -0
- data/lib/torchat/session/broadcasts.rb +72 -0
- data/lib/torchat/session/buddies.rb +152 -0
- data/lib/torchat/session/buddy.rb +343 -0
- data/lib/torchat/session/buddy/joined_group_chat.rb +42 -0
- data/lib/torchat/session/buddy/joined_group_chats.rb +46 -0
- data/lib/torchat/session/buddy/latency.rb +54 -0
- data/lib/torchat/session/event.rb +79 -0
- data/lib/torchat/session/file_transfer.rb +173 -0
- data/lib/torchat/session/file_transfer/block.rb +51 -0
- data/lib/torchat/session/file_transfers.rb +89 -0
- data/lib/torchat/session/group_chat.rb +123 -0
- data/lib/torchat/session/group_chat/participant.rb +38 -0
- data/lib/torchat/session/group_chat/participants.rb +52 -0
- data/lib/torchat/session/group_chats.rb +74 -0
- data/lib/torchat/session/incoming.rb +187 -0
- data/lib/torchat/session/outgoing.rb +102 -0
- data/lib/torchat/tor.rb +107 -0
- data/lib/torchat/utils.rb +87 -0
- data/lib/torchat/version.rb +24 -0
- data/test/file_transfer/receiver.rb +41 -0
- data/test/file_transfer/sender.rb +45 -0
- data/test/group_chat/a.rb +37 -0
- data/test/group_chat/b.rb +37 -0
- data/test/group_chat/c.rb +57 -0
- data/torchat.gemspec +21 -0
- metadata +140 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
Broadcast extension lifecycle and packet description
|
2
|
+
====================================================
|
3
|
+
The broadcast protocol is made to share anonymous messages with all the reachable torchat
|
4
|
+
network.
|
5
|
+
|
6
|
+
This feature could be used to spam but users will always be able to disable such a feature.
|
7
|
+
|
8
|
+
Packets
|
9
|
+
-------
|
10
|
+
Following is a list and description of the packets in the broadcast extension.
|
11
|
+
|
12
|
+
### Broadcast Message
|
13
|
+
|
14
|
+
This packet is used to send a simple broadcast message, it just contains the message.
|
15
|
+
|
16
|
+
A broadcast message can contain *hashtags* which a person can follow/ignore.
|
17
|
+
|
18
|
+
When you send a broadcast *message* you send it to every logged in contact you have, on reception
|
19
|
+
of the *message* the contact will check if the same message has already been sent recently and if
|
20
|
+
not it will send the same message to every other contact in his contact list and so on.
|
21
|
+
|
22
|
+
The check for messages already broadcasted is made by hashing the message itself.
|
23
|
+
|
24
|
+
```
|
25
|
+
> broadcast_message broadcast messages in #torchat rock
|
26
|
+
```
|
@@ -0,0 +1,140 @@
|
|
1
|
+
Groupchat extension lifecycle and packet description
|
2
|
+
====================================================
|
3
|
+
The person that starts the groupchat starts it by inviting the first person
|
4
|
+
to it, the *invite* packet has a cookie inside that will also be the id of the
|
5
|
+
groupchat throughout its lifecycle, it also contains a list of modes for the groupchat.
|
6
|
+
|
7
|
+
After the *invite* packet a *participants* packet is sent to the invited person,
|
8
|
+
this packet has inside the list of ids of the current groupchat.
|
9
|
+
|
10
|
+
After receiving the *participants* packet the invited starts connections to all the
|
11
|
+
participants and sends them a packet asking them if they're really participating
|
12
|
+
in the groupchat. The contacts that aren't in his buddy list are added as temporary
|
13
|
+
buddies. If any of the participants are in his blocked list, a *leave* packet will be
|
14
|
+
sent, refusing to join the groupchat, otherwise a a *participants* packet is sent back
|
15
|
+
with the current participants in the groupchat, on receiving that packet the invitor will
|
16
|
+
send back a *participants* packet with possible new participants, this packet sending back
|
17
|
+
and forth will end when the invitor sends an empty *participants* packet, at that point
|
18
|
+
a *join* packet will be sent.
|
19
|
+
|
20
|
+
After the *join* packet an *invited* packet will be sent to the already present participants,
|
21
|
+
in this way they'll know who invited that person and that that person is going to join the
|
22
|
+
groupchat.
|
23
|
+
|
24
|
+
The messaging in the groupchat is simply sent to every other participant from the sender
|
25
|
+
of the message.
|
26
|
+
|
27
|
+
To exit the groupchat a *leave* packet is sent to every participant present in the groupchat.
|
28
|
+
|
29
|
+
When a participant disconnects it's seen as leaving the groupchat.
|
30
|
+
|
31
|
+
When there are no more participants in a groupchat that groupchat is destroyed.
|
32
|
+
|
33
|
+
Packets
|
34
|
+
-------
|
35
|
+
Following is a list and description of the packets in the groupchat extension.
|
36
|
+
|
37
|
+
In the examples `>` refers to packet sent to the buddy, while `<` refers to packet received
|
38
|
+
from the buddy.
|
39
|
+
|
40
|
+
### Groupchat Invite
|
41
|
+
|
42
|
+
This packet is used to invite someone to a groupchat, it contains the id of the groupchat
|
43
|
+
and a list of modes.
|
44
|
+
|
45
|
+
The modes will be useful in implementing extensions to the groupchat protocol, for example in
|
46
|
+
the implementation of redundancy and permanent groupchats.
|
47
|
+
|
48
|
+
```
|
49
|
+
> groupchat_invite 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
50
|
+
```
|
51
|
+
|
52
|
+
```
|
53
|
+
> groupchat_invite 6f012391-883d-4f4f-8d54-52c4227b3ac9 noredundancy
|
54
|
+
```
|
55
|
+
|
56
|
+
### Groupchat Participants
|
57
|
+
|
58
|
+
This packet is used to tell the invited person the current participants, it contains the
|
59
|
+
groupchat id and a space separated list of ids. The should not contain the id of the person
|
60
|
+
sending the packet.
|
61
|
+
|
62
|
+
```
|
63
|
+
> groupchat_participants 6f012391-883d-4f4f-8d54-52c4227b3ac9 bgboqr35plm637wp
|
64
|
+
```
|
65
|
+
|
66
|
+
### Groupchat Is Participating
|
67
|
+
|
68
|
+
This packet is sent to ask someone if he's participating in a groupchat, it contains the id of
|
69
|
+
the groupchat.
|
70
|
+
|
71
|
+
```
|
72
|
+
> groupchat_is_participating 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
73
|
+
< groupchat_participating
|
74
|
+
```
|
75
|
+
|
76
|
+
### Groupchat Participating
|
77
|
+
|
78
|
+
This packet is sent as answer to the *is_participating* packet and is used to answer that we
|
79
|
+
are participating, it contains the id of the groupchat.
|
80
|
+
|
81
|
+
|
82
|
+
```
|
83
|
+
< groupchat_is_participating 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
84
|
+
> groupchat_participating 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
85
|
+
```
|
86
|
+
|
87
|
+
### Groupchat Not Participating
|
88
|
+
|
89
|
+
This packet is sent as answer to the *is_participating* packet and is used to answer that we
|
90
|
+
are not participating, it contains the id of the groupchat.
|
91
|
+
|
92
|
+
```
|
93
|
+
< groupchat_is_participating 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
94
|
+
> groupchat_not_participating 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
95
|
+
```
|
96
|
+
|
97
|
+
### Groupchat Join
|
98
|
+
|
99
|
+
This packet is sent in answer to the invitor if accepting to join the groupchat, it contains
|
100
|
+
the id of the groupchat.
|
101
|
+
|
102
|
+
```
|
103
|
+
< groupchat_invite 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
104
|
+
< groupchat_participants 6f012391-883d-4f4f-8d54-52c4227b3ac9 bgboqr35plm637wp
|
105
|
+
> groupchat_join 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
106
|
+
```
|
107
|
+
|
108
|
+
### Groupchat Leave
|
109
|
+
|
110
|
+
This packet is sent in answer to the invitor if refusing to join the groupchat or as packet to
|
111
|
+
tell everyone that you're leaving the groupchat, it contains the id and an optional reason for
|
112
|
+
leaving.
|
113
|
+
|
114
|
+
```
|
115
|
+
< groupchat_invite 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
116
|
+
< groupchat_participants 6f012391-883d-4f4f-8d54-52c4227b3ac9 bgboqr35plm637wp
|
117
|
+
> groupchat_leave 6f012391-883d-4f4f-8d54-52c4227b3ac9
|
118
|
+
```
|
119
|
+
|
120
|
+
```
|
121
|
+
> groupchat_leave 6f012391-883d-4f4f-8d54-52c4227b3ac9 I'm a bad person, and so are you
|
122
|
+
```
|
123
|
+
|
124
|
+
### Groupchat Invited
|
125
|
+
|
126
|
+
This packet is sent by the invitor to every participant of the groupchat if the invited accepts to
|
127
|
+
join the groupchat, it contains the id of the groupchat and the id of the invited.
|
128
|
+
|
129
|
+
```
|
130
|
+
> groupchat_invited 6f012391-883d-4f4f-8d54-52c4227b3ac9 4dlrnr744xsibjcd
|
131
|
+
```
|
132
|
+
|
133
|
+
### Groupchat Message
|
134
|
+
|
135
|
+
This packet is used to send a message to the groupchat, it is sent to every participant and contains
|
136
|
+
the id of the groupchat and the message.
|
137
|
+
|
138
|
+
```
|
139
|
+
> groupchat_message 6f012391-883d-4f4f-8d54-52c4227b3ac9 Hi guise
|
140
|
+
```
|
@@ -0,0 +1,30 @@
|
|
1
|
+
Latency extension lifecycle and packet description
|
2
|
+
==================================================
|
3
|
+
The latency extension is made to check latency between you and your buddies.
|
4
|
+
|
5
|
+
Packets
|
6
|
+
-------
|
7
|
+
Following is a list and description of the packets in the broadcast extension.
|
8
|
+
|
9
|
+
### Latency Ping
|
10
|
+
|
11
|
+
This packet is used to ask for the latency between you and the other end.
|
12
|
+
|
13
|
+
It just contains an id.
|
14
|
+
|
15
|
+
```
|
16
|
+
> latency_ping 5d928e59-1ad1-4e4d-8f19-e4a885ac7c4a
|
17
|
+
< latency_pong 5d928e59-1ad1-4e4d-8f19-e4a885ac7c4a
|
18
|
+
|
19
|
+
```
|
20
|
+
|
21
|
+
### Latency Pong
|
22
|
+
|
23
|
+
This packet is used as answer for the latency check.
|
24
|
+
|
25
|
+
It just contains the ping id.
|
26
|
+
|
27
|
+
```
|
28
|
+
< latency_ping 5d928e59-1ad1-4e4d-8f19-e4a885ac7c4a
|
29
|
+
> latency_pong 5d928e59-1ad1-4e4d-8f19-e4a885ac7c4a
|
30
|
+
```
|
@@ -0,0 +1,279 @@
|
|
1
|
+
Standard protocol lifecycle and packet description
|
2
|
+
==================================================
|
3
|
+
The connection to a buddy can be initiated from the buddy or from yourself,
|
4
|
+
to establish a connection succesfully both ends must be connected to eachother
|
5
|
+
with two different sockets. This is needed to ensure that we're talking with
|
6
|
+
the real owner of the id. The id is nothing more than an onion id for a Tor hidden service.
|
7
|
+
The protocol requires in fact that a Tor session is running with a hidden service
|
8
|
+
configured to receive connections on the 11109 port.
|
9
|
+
|
10
|
+
When we receive an incoming connection from a buddy he has to send a *ping* packet,
|
11
|
+
this packet contains the address of the presumed connected buddy and a cookie.
|
12
|
+
|
13
|
+
Once we receive this ping packet we try connecting on the address contained in the ping.
|
14
|
+
Once the connection is successful we send a ping packet with our address and a new cookie,
|
15
|
+
and a pong packet with the received cookie. After this the other end is supposed to send
|
16
|
+
us a pong packet with our cookie. If everything went right and all cookies were right
|
17
|
+
the connection has been verified correctly. It obviously can go the other way around.
|
18
|
+
|
19
|
+
Once the connection has been verified, both ends send a certain number of packets.
|
20
|
+
|
21
|
+
- the *client* packet, that tells what client we are using
|
22
|
+
- the *version* packet, that tells the version of the client
|
23
|
+
- the *supports* packet with the supported extensions (this is an extension itself)
|
24
|
+
- the *profile name* packet, that tells our name (optional)
|
25
|
+
- the *profile text*, that tells our description (optional)
|
26
|
+
- if this is a permanent buddy, an *add me* packet
|
27
|
+
- a *status* packet telling what's our status
|
28
|
+
|
29
|
+
After this, the *status* packet is used as a keep alive and must be sent every 120 seconds.
|
30
|
+
|
31
|
+
A *remove me* packet can be sent to make the other end remove us from their contact list.
|
32
|
+
|
33
|
+
Messages are simply sent to the buddy with a *message* packet.
|
34
|
+
|
35
|
+
Packet encoding/decoding
|
36
|
+
------------------------
|
37
|
+
The protocol is line based with data torchat-encoded to avoid the presence of line breaks, the
|
38
|
+
packet **must** end with a `\n`.
|
39
|
+
|
40
|
+
Every packet starts with the name of the packet in `this_style`, and if the packet has data
|
41
|
+
the name is followed by a space and the torchat-encoded string. The packet name can only contain
|
42
|
+
`[a-z_]`.
|
43
|
+
|
44
|
+
The torchat encoding is a simple find and replace of every `\\` into `\\/` and `\n` into `\\n`.
|
45
|
+
|
46
|
+
To decode it just replace every `\\n` with `\n` and every `\/` into `\\`.
|
47
|
+
|
48
|
+
Usually the packet data is a list of strings separated by spaces unless the item can contain
|
49
|
+
spaces itself, in that case it's put at the end of the list.
|
50
|
+
|
51
|
+
Base packets
|
52
|
+
------------
|
53
|
+
In the examples `>` refers to packet sent to the buddy, while `<` refers to packet received
|
54
|
+
from the buddy.
|
55
|
+
|
56
|
+
### Not Implemented
|
57
|
+
|
58
|
+
This packet is sent when we receive a packet we don't know about, its only parameter is
|
59
|
+
the name of the command that we received and is also optional.
|
60
|
+
|
61
|
+
```
|
62
|
+
> supports groupchat
|
63
|
+
< not_implemented supports
|
64
|
+
```
|
65
|
+
|
66
|
+
### Ping
|
67
|
+
|
68
|
+
This packet is used as entry point for the authentication, it contains the address of the sender
|
69
|
+
and a cookie, which is then used by the other end to pong.
|
70
|
+
|
71
|
+
Keep in mind that the ping packet is answerable only when both connections are established, and once
|
72
|
+
verified it shouldn't be sent anymore and will be ignored.
|
73
|
+
|
74
|
+
Despite the name this packet is not used as keepalive.
|
75
|
+
|
76
|
+
```
|
77
|
+
> ping 7acbk6jpofsanyfp 777bc33f-ab25-4f96-baad-135ca2048c3a
|
78
|
+
< pong 777bc33f-ab25-4f96-baad-135ca2048c3a
|
79
|
+
```
|
80
|
+
|
81
|
+
### Pong
|
82
|
+
|
83
|
+
This packet is used as endpoint for the authentication, it contains the cookie that has been
|
84
|
+
received in the *ping* packet.
|
85
|
+
|
86
|
+
Despite the name this packet is not used as keepalive.
|
87
|
+
|
88
|
+
```
|
89
|
+
< ping 7acbk6jpofsanyfp 777bc33f-ab25-4f96-baad-135ca2048c3a
|
90
|
+
> pong 777bc33f-ab25-4f96-baad-135ca2048c3a
|
91
|
+
```
|
92
|
+
|
93
|
+
### Client
|
94
|
+
|
95
|
+
This packet is used to tell the other end what is the name of the client we're using.
|
96
|
+
|
97
|
+
The only value of this packet is the client name.
|
98
|
+
|
99
|
+
```
|
100
|
+
> client ruby-torchat
|
101
|
+
```
|
102
|
+
|
103
|
+
### Version
|
104
|
+
|
105
|
+
This packet is used to tell the other end what is the version of the client we're using.
|
106
|
+
|
107
|
+
The only value of this packet is the version code.
|
108
|
+
|
109
|
+
```
|
110
|
+
> version 0.0.1
|
111
|
+
```
|
112
|
+
|
113
|
+
### Supports
|
114
|
+
|
115
|
+
This packet is an extension that has to be included in the standard protocol, it tells the other end
|
116
|
+
what extensions our client supports.
|
117
|
+
|
118
|
+
It's a space separated list of extension names.
|
119
|
+
|
120
|
+
```
|
121
|
+
> supports groupchat broadcast
|
122
|
+
```
|
123
|
+
|
124
|
+
### Status
|
125
|
+
|
126
|
+
This packet is used to tell the other end our current status.
|
127
|
+
|
128
|
+
The only value of this packet is the status name; currently supported statuses are: available, away, xa.
|
129
|
+
|
130
|
+
This packet is also used as keepalive and must be sent at least every 120 seconds, otherwise the
|
131
|
+
connection will be marked as timed out and the buddy will be disconnected.
|
132
|
+
|
133
|
+
```
|
134
|
+
> status available
|
135
|
+
```
|
136
|
+
|
137
|
+
```
|
138
|
+
> status away
|
139
|
+
```
|
140
|
+
|
141
|
+
```
|
142
|
+
> status xa
|
143
|
+
```
|
144
|
+
|
145
|
+
### Add Me
|
146
|
+
|
147
|
+
This packet is sent to tell the other end to add us to their buddy list, if the buddy is temporary
|
148
|
+
this packet **must not** be sent.
|
149
|
+
|
150
|
+
```
|
151
|
+
> add_me
|
152
|
+
```
|
153
|
+
|
154
|
+
### Remove Me
|
155
|
+
|
156
|
+
This packet is sent to tell the other end to remove us from their buddy list.
|
157
|
+
|
158
|
+
The other end will disconnect us when they received the *remove me* packet.
|
159
|
+
|
160
|
+
```
|
161
|
+
> remove_me
|
162
|
+
```
|
163
|
+
|
164
|
+
### Message
|
165
|
+
|
166
|
+
This packet is sent to give the other end a message.
|
167
|
+
|
168
|
+
The message must be UTF-8 encoded.
|
169
|
+
|
170
|
+
```
|
171
|
+
> message yo, we are legiun XDXDXD
|
172
|
+
```
|
173
|
+
|
174
|
+
Profile packets
|
175
|
+
---------------
|
176
|
+
### Profile Name
|
177
|
+
|
178
|
+
This packet tells the other end our name.
|
179
|
+
|
180
|
+
It can have no value or our name UTF-8 encoded.
|
181
|
+
|
182
|
+
```
|
183
|
+
> profile_name Anonymous
|
184
|
+
```
|
185
|
+
|
186
|
+
### Profile Text
|
187
|
+
|
188
|
+
This packet tells the other end our description, or status message, take it as you wish.
|
189
|
+
|
190
|
+
It can have no value or our description UTF-8 encoded.
|
191
|
+
|
192
|
+
```
|
193
|
+
> profile_text Never forgive. Never forget.
|
194
|
+
```
|
195
|
+
|
196
|
+
### Profile Avatar Alpha
|
197
|
+
|
198
|
+
This packet contains the alpha channel of the avatar, this means that it contains a list
|
199
|
+
of bytes referring to the alpha value of said pixel starting from the top left.
|
200
|
+
|
201
|
+
This packet **must** be sent even if the avatar has no alpha channel, and the content will
|
202
|
+
be empty.
|
203
|
+
|
204
|
+
Keep in mind that the avatar has to be 64x64.
|
205
|
+
|
206
|
+
```
|
207
|
+
> profile_avatar_alpha
|
208
|
+
```
|
209
|
+
|
210
|
+
### Profile Avatar
|
211
|
+
|
212
|
+
This packet contains the rgb channels of the avatar, this means that it contains a list
|
213
|
+
of 3 bytes for every pixel in the image starting from the top left.
|
214
|
+
|
215
|
+
Keep in mind that the avatar has to be 64x64.
|
216
|
+
|
217
|
+
|
218
|
+
File transfer packets
|
219
|
+
---------------------
|
220
|
+
|
221
|
+
### Filename
|
222
|
+
|
223
|
+
This packet is the entry point of any file transfer, it contains the id of the file transfer,
|
224
|
+
the size of the file, the size of the blocks and the name of the file that is going to be
|
225
|
+
transferred.
|
226
|
+
|
227
|
+
This packet has to be sent as first to start a file transfer.
|
228
|
+
|
229
|
+
```
|
230
|
+
> filename 92be7d8b-6f10-405b-bde2-a77e71c06afd 4096 10 lol.txt
|
231
|
+
```
|
232
|
+
|
233
|
+
### Filedata
|
234
|
+
|
235
|
+
This packet contains a block of data for a given file transfer, it contains the id of the transfer,
|
236
|
+
the offset of the transfer, an useless md5 of the data and the data.
|
237
|
+
|
238
|
+
```
|
239
|
+
> filedata 92be7d8b-6f10-405b-bde2-a77e71c06afd 0 e09c80c42fda55f9d992e59ca6b3307d aaaaaaaaaa
|
240
|
+
< filedata_ok 92be7d8b-6f10-405b-bde2-a77e71c06afd 0
|
241
|
+
```
|
242
|
+
|
243
|
+
### Filedata Ok
|
244
|
+
|
245
|
+
This packet is sent after every *filedata* packet to tell the other end we received a block,
|
246
|
+
it contains the id of the file transfer and the offset of the block.
|
247
|
+
|
248
|
+
```
|
249
|
+
< filedata 92be7d8b-6f10-405b-bde2-a77e71c06afd 0 e09c80c42fda55f9d992e59ca6b3307d aaaaaaaaaa
|
250
|
+
> filedata_ok 92be7d8b-6f10-405b-bde2-a77e71c06afd 0
|
251
|
+
```
|
252
|
+
|
253
|
+
### Filedata Error
|
254
|
+
|
255
|
+
This packet is sent after every failing *filedata* packet to tell the other end an error happend
|
256
|
+
with the transfer of a block, it should be practically impossible but ok.
|
257
|
+
|
258
|
+
```
|
259
|
+
< filedata 92be7d8b-6f10-405b-bde2-a77e71c06afd 0 e29c80c42fda55f9d992e59ca6b3307d aaaaaaaaaa
|
260
|
+
> filedata_error 92be7d8b-6f10-405b-bde2-a77e71c06afd 0
|
261
|
+
```
|
262
|
+
|
263
|
+
### File Stop Sending
|
264
|
+
|
265
|
+
This packet is used to tell the other end we have stopped an inbound file transfer, it contains
|
266
|
+
the id of the file transfer.
|
267
|
+
|
268
|
+
```
|
269
|
+
> file_stop_sending 92be7d8b-6f10-405b-bde2-a77e71c06afd
|
270
|
+
```
|
271
|
+
|
272
|
+
### File Stop Receiving
|
273
|
+
|
274
|
+
This packet is used to tell the other end we have interrupted an outbound file transfer, it contains
|
275
|
+
the id of the file transfer.
|
276
|
+
|
277
|
+
```
|
278
|
+
> file_stop_receiving 92be7d8b-6f10-405b-bde2-a77e71c06afd
|
279
|
+
```
|