File: NetFileTransfer.h

package info (click to toggle)
0ad 0~r11863-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 30,560 kB
  • sloc: cpp: 201,230; ansic: 28,387; sh: 10,593; perl: 4,847; python: 2,240; makefile: 658; java: 412; xml: 243; sql: 40
file content (133 lines) | stat: -rw-r--r-- 3,668 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* Copyright (C) 2011 Wildfire Games.
 * This file is part of 0 A.D.
 *
 * 0 A.D. is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0 A.D. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef NETFILETRANSFER_H
#define NETFILETRANSFER_H

#include <map>

class CNetMessage;
class CNetClientSession;
class CNetServerSession;
class INetSession;

// Assume this is sufficiently less than MTU that packets won't get
// fragmented or dropped.
static const size_t DEFAULT_FILE_TRANSFER_PACKET_SIZE = 1024;

// To improve performance without flooding ENet's internal buffers,
// maintain a small number of in-flight packets.
// Pick numbers so that with e.g. 200ms round-trip latency
// we can hopefully get windowSize*packetSize*1000/200 = 160KB/s bandwidth
static const size_t DEFAULT_FILE_TRANSFER_WINDOW_SIZE = 32;

// Some arbitrary limit to make it slightly harder to use up all of someone's RAM
static const size_t MAX_FILE_TRANSFER_SIZE = 8*MiB;

/**
 * Asynchronous file-receiving task.
 * Other code should subclass this, implement OnComplete(),
 * then pass it to CNetFileTransferer::StartTask.
 */
class CNetFileReceiveTask
{
public:
	CNetFileReceiveTask() : m_RequestID(0), m_Length(0) { }
	virtual ~CNetFileReceiveTask() {}

	/**
	 * Called when m_Buffer contains the full received data.
	 */
	virtual void OnComplete() = 0;

	// TODO: Ought to have an OnFailure, e.g. when the session drops or there's another error

	/**
	 * Uniquely identifies the request within the scope of its CNetFileTransferer.
	 * Set automatically by StartTask.
	 */
	u32 m_RequestID;

	size_t m_Length;

	std::string m_Buffer;
};

/**
 * Handles transferring files between clients and servers.
 */
class CNetFileTransferer
{
public:
	CNetFileTransferer(INetSession* session)
		: m_Session(session), m_NextRequestID(1), m_LastProgressReportTime(0)
	{
	}

	/**
	 * Should be called when a message is received from the network.
	 * Returns INFO::SKIPPED if the message is not one that this class handles.
	 * Returns INFO::OK if the message is handled successfully,
	 * or ERR::FAIL if handled unsuccessfully.
	 */
	Status HandleMessageReceive(const CNetMessage* message);

	/**
	 * Registers a file-receiving task.
	 */
	void StartTask(const shared_ptr<CNetFileReceiveTask>& task);

	/**
	 * Registers data to be sent in response to a request.
	 * (Callers are expected to have their own mechanism for receiving
	 * requests and deciding what to respond with.)
	 */
	void StartResponse(u32 requestID, const std::string& data);

	/**
	 * Call frequently (e.g. once per frame) to trigger any necessary
	 * packet processing.
	 */
	void Poll();

private:
	/**
	 * Asynchronous file-sending task.
	 */
	struct CNetFileSendTask
	{
		u32 requestID;
		std::string buffer;
		size_t offset;
		size_t maxWindowSize;
		size_t packetsInFlight;
	};

	INetSession* m_Session;

	u32 m_NextRequestID;

	typedef std::map<u32, shared_ptr<CNetFileReceiveTask> > FileReceiveTasksMap;
	FileReceiveTasksMap m_FileReceiveTasks;

	typedef std::map<u32, CNetFileSendTask> FileSendTasksMap;
	FileSendTasksMap m_FileSendTasks;

	double m_LastProgressReportTime;
};

#endif // NETFILETRANSFER_H