1 /***************************************************************************
2 netfilecontrol.cpp - Automatic downloading + uploading of data files
3 -------------------
4 begin : di aug 30 2005
5 copyright : (C) 2005 by CJP
6 email : cornware-cjp@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include <cstdio>
19
20 #include "netfilecontrol.h"
21
22 #include "clientnet.h"
23 #include "filechunk.h"
24 #include "datafile.h"
25 #include "netmessages.h"
26
CNetFileControl()27 CNetFileControl::CNetFileControl() : CFileControl(false)
28 {
29 m_OriginalFileControl = theFileControl;
30 theFileControl = this;
31 m_Network = NULL;
32 }
33
~CNetFileControl()34 CNetFileControl::~CNetFileControl()
35 {
36 theFileControl = m_OriginalFileControl;
37 }
38
setNetwork(CClientNet * net)39 void CNetFileControl::setNetwork(CClientNet *net)
40 {
41 m_Network = net;
42 }
43
getLongFilename(const CString & shortName)44 CString CNetFileControl::getLongFilename(const CString &shortName)
45 {
46 CString localfile = m_OriginalFileControl->getLongFilename(shortName);
47
48 //TODO: check if this is the same file as on the server
49 if(localfile != "") return localfile;
50
51 //Just in cases when there is no network available (should not happen here)
52 if(m_Network == NULL)
53 return "";
54
55 //File transfer over network
56 int retID = m_Network->sendTextMessage(CString(USNET_GET) + shortName); //requesting the file
57 if(retID > 0) //It has the file
58 {
59 CFileChunk theChunk;
60
61 printf("Downloading file %s\n", shortName.c_str());
62
63 //Downloading the first chunk
64 while(theChunk.m_Filename != shortName)
65 {
66 //the first chunk, timeout of 5 seconds
67 CMessageBuffer *buf = m_Network->receiveExpectedData(CMessageBuffer::fileChunk, 5000);
68
69 if(buf == NULL)
70 {
71 printf(" Warning: server didn't send file %s\n", shortName.c_str());
72 return ""; //server didn't send any chunk
73 }
74
75 m_Network->sendConfirmation(*buf, 0);
76
77 theChunk.setBuffer(*buf);
78 delete buf;
79 }
80
81 //File properties
82 unsigned int fileSize = theChunk.m_FileSize;
83 unsigned int numChunks = fileSize / FILECHUNK_SIZE;
84 if(FILECHUNK_SIZE * numChunks < fileSize) numChunks++; //there is a last, smaller chunk
85
86 //The data buffer
87 vector<CBinBuffer> receivedBuffers;
88 receivedBuffers.resize(numChunks);
89 receivedBuffers[theChunk.m_ChunkID] = theChunk.m_Data;
90 unsigned int numReceived = 1;
91
92 //Downloading the other chunks
93 while(numReceived < numChunks)
94 {
95 CMessageBuffer *buf = m_Network->receiveExpectedData(CMessageBuffer::fileChunk, 5000);
96
97 if(buf == NULL)
98 {
99 printf(" Warning: downloading of file %s has stopped\n", shortName.c_str());
100 return ""; //didn't receive any chunks anymore
101 }
102
103 m_Network->sendConfirmation(*buf, 0);
104
105 theChunk.setBuffer(*buf);
106 delete buf;
107
108 if(theChunk.m_Filename != shortName) continue; //not a chunk for this file
109
110 if(receivedBuffers[theChunk.m_ChunkID].size() == 0) //we receive this chunk for the first time
111 {
112 receivedBuffers[theChunk.m_ChunkID] = theChunk.m_Data;
113 numReceived++;
114 printf("Downloading %s (%d / %d)\r", shortName.c_str(), numReceived, numChunks);
115 }
116 }
117
118 printf("Downloading %s finished, saving...\n", shortName.c_str());
119
120 //Saving the file
121 CDataFile theFile(shortName, true);
122 for(unsigned int i=0; i < receivedBuffers.size(); i++)
123 theFile.writeBytes(receivedBuffers[i]);
124
125 return theFile.useExtern();
126 }
127
128 return "";
129 }
130