1 /// \file FileListTransfer.h
2 /// \brief A plugin to provide a simple way to compress and incrementally send the files in the FileList structure.
3 ///
4 /// This file is part of RakNet Copyright 2003 Jenkins Software LLC
5 ///
6 /// Raknet is available under the terms of the GPLv3 license, see /usr/local/share/licenses/raknet-3.9.2_10,1/GPLv3.
7 
8 #include "NativeFeatureIncludes.h"
9 #if _RAKNET_SUPPORT_FileListTransfer==1
10 
11 #ifndef __FILE_LIST_TRANFER_H
12 #define __FILE_LIST_TRANFER_H
13 
14 #include "RakNetTypes.h"
15 #include "Export.h"
16 #include "PluginInterface2.h"
17 #include "DS_Map.h"
18 #include "RakNetTypes.h"
19 #include "PacketPriority.h"
20 #include "RakMemoryOverride.h"
21 #include "FileList.h"
22 #include "DS_Queue.h"
23 #include "SimpleMutex.h"
24 
25 class IncrementalReadInterface;
26 class FileListTransferCBInterface;
27 class FileListProgress;
28 struct FileListReceiver;
29 
30 /// \defgroup FILE_LIST_TRANSFER_GROUP FileListTransfer
31 /// \brief A plugin to provide a simple way to compress and incrementally send the files in the FileList structure.
32 /// \details
33 /// \ingroup PLUGINS_GROUP
34 
35 /// \brief A plugin to provide a simple way to compress and incrementally send the files in the FileList structure.
36 /// \details Similar to the DirectoryDeltaTransfer plugin, except that it doesn't send deltas based on pre-existing files or actually write the files to disk.
37 ///
38 /// Usage:
39 /// Call SetupReceive to allow one file set to arrive.  The value returned by FileListTransfer::SetupReceive()
40 /// is the setID that is allowed.
41 /// It's up to you to transmit this value to the other system, along with information indicating what kind of files you want to get.
42 /// The other system should then prepare a FileList and call FileListTransfer::Send(), passing the return value of FileListTransfer::SetupReceive()
43 /// as the \a setID parameter to FileListTransfer::Send()
44 /// \ingroup FILE_LIST_TRANSFER_GROUP
45 class RAK_DLL_EXPORT FileListTransfer : public PluginInterface2
46 {
47 public:
48 	FileListTransfer();
49 	virtual ~FileListTransfer();
50 
51 	/// \brief Allows one corresponding Send() call from another system to arrive.
52 	/// \param[in] handler The class to call on each file
53 	/// \param[in] deleteHandler True to delete the handler when it is no longer needed.  False to not do so.
54 	/// \param[in] allowedSender Which system to allow files from.
55 	/// \return A set ID value, which should be passed as the \a setID value to the Send() call on the other system.  This value will be returned in the callback and is unique per file set.  Returns 65535 on failure (not connected to sender)
56     unsigned short SetupReceive(FileListTransferCBInterface *handler, bool deleteHandler, SystemAddress allowedSender);
57 
58 	/// \brief Send the FileList structure to another system, which must have previously called SetupReceive().
59 	/// \param[in] fileList A list of files.  The data contained in FileList::data will be sent incrementally and compressed among all files in the set
60 	/// \param[in] rakPeer The instance of RakNet to use to send the message. Pass 0 to use the instance the plugin is attached to
61 	/// \param[in] recipient The address of the system to send to
62 	/// \param[in] setID The return value of SetupReceive() which was previously called on \a recipient
63 	/// \param[in] priority Passed to RakPeerInterface::Send()
64 	/// \param[in] orderingChannel Passed to RakPeerInterface::Send()
65 	/// \param[in] compressData deprecated, unsupported
66 	/// \param[in] _incrementalReadInterface If a file in \a fileList has no data, filePullInterface will be used to read the file in chunks of size \a chunkSize
67 	/// \param[in] _chunkSize How large of a block of a file to send at once
68 	void Send(FileList *fileList, RakPeerInterface *rakPeer, SystemAddress recipient, unsigned short setID, PacketPriority priority, char orderingChannel, bool compressData, IncrementalReadInterface *_incrementalReadInterface=0, unsigned int _chunkSize=262144*4*16);
69 
70 	/// Return number of files waiting to go out to a particular address
71 	unsigned int GetPendingFilesToAddress(SystemAddress recipient);
72 
73 	/// \brief Stop a download.
74 	void CancelReceive(unsigned short setId);
75 
76 	/// \brief Remove all handlers associated with a particular system address.
77 	void RemoveReceiver(SystemAddress systemAddress);
78 
79 	/// \brief Is a handler passed to SetupReceive still running?
80 	bool IsHandlerActive(unsigned short setId);
81 
82 	/// \brief Set a callback to get progress reports about what the file list instances do.
83 	/// \param[in] cb A pointer to an externally defined instance of FileListProgress. This pointer is held internally, so should remain valid as long as this class is valid.
84 	void SetCallback(FileListProgress *cb);
85 
86 	/// \returns what was sent to SetCallback
87 	/// \return What was sent to SetCallback
88 	FileListProgress *GetCallback(void) const;
89 
90 	/// \internal For plugin handling
91 	virtual PluginReceiveResult OnReceive(Packet *packet);
92 	/// \internal For plugin handling
93 	virtual void OnRakPeerShutdown(void);
94 	/// \internal For plugin handling
95 	virtual void OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason );
96 	/// \internal For plugin handling
97 	virtual void Update(void);
98 
99 protected:
100 	bool DecodeSetHeader(Packet *packet);
101 	bool DecodeFile(Packet *packet, bool fullFile);
102 
103 	void Clear(void);
104 
105 	void OnReferencePush(Packet *packet, bool fullFile);
106 	void OnReferencePushAck(Packet *packet);
107 	void SendIRIToAddress(SystemAddress systemAddress);
108 
109 	DataStructures::Map<unsigned short, FileListReceiver*> fileListReceivers;
110 	unsigned short setId;
111 	FileListProgress *callback;
112 
113 	struct FileToPush
114 	{
115 		FileListNode fileListNode;
116 		PacketPriority packetPriority;
117 		char orderingChannel;
118 		unsigned int currentOffset;
119 		unsigned short setID;
120 		unsigned int setIndex;
121 		IncrementalReadInterface *incrementalReadInterface;
122 		unsigned int chunkSize;
123 	};
124 	struct FileToPushRecipient
125 	{
126 		SystemAddress systemAddress;
127 		DataStructures::Queue<FileToPush*> filesToPush;
128 	};
129 	DataStructures::List< FileToPushRecipient* > filesToPushAllSameAddress;
130 	// TODO - overagressive, only one read can happen at a time. See SendIRIToAddress
131 	SimpleMutex filesToPushAllSameAddressMutex;
132 };
133 
134 #endif
135 
136 #endif // _RAKNET_SUPPORT_*
137