|
pred@2129
|
1 |
#include "smud_connections.h" |
|
pred@2129
|
2 |
#include "smud.h" |
|
pred@2129
|
3 |
|
|
pred@2129
|
4 |
ConnectionPool::ConnectionPool() |
|
pred@2129
|
5 |
{ |
|
pred@2129
|
6 |
pthread_mutex_init(&m_AddLock, NULL); |
|
pred@2129
|
7 |
m_timeOut = 1000; |
|
pred@2129
|
8 |
} |
|
pred@2129
|
9 |
|
|
pred@2129
|
10 |
ConnectionPool::~ConnectionPool() |
|
pred@2129
|
11 |
{ |
|
pred@2129
|
12 |
pthread_mutex_destroy(&m_AddLock); |
|
pred@2129
|
13 |
} |
|
pred@2129
|
14 |
|
|
pred@2129
|
15 |
void ConnectionPool::AddConnection( int fd ) |
|
pred@2129
|
16 |
{ |
|
pred@2129
|
17 |
smud_connection *connection = new smud_connection(fd); |
|
pred@2129
|
18 |
|
|
pred@2129
|
19 |
pthread_mutex_lock(&m_AddLock); |
|
pred@2129
|
20 |
m_AddQueue.push_back(connection); |
|
pred@2129
|
21 |
pthread_mutex_unlock(&m_AddLock); |
|
pred@2129
|
22 |
|
|
pred@2129
|
23 |
printf("New Connection Added\n"); |
|
pred@2129
|
24 |
} |
|
pred@2129
|
25 |
|
|
pred@2129
|
26 |
void ConnectionPool::Process( bool *terminate ) |
|
pred@2129
|
27 |
{ |
|
pred@2129
|
28 |
struct timespec ts_wait; |
|
pred@2129
|
29 |
|
|
pred@2129
|
30 |
ts_wait.tv_sec = 0; |
|
pred@2129
|
31 |
ts_wait.tv_nsec = 50000000; /* 50ms */ |
|
pred@2129
|
32 |
|
|
pred@2129
|
33 |
std::list<smud_connection *>::iterator iter; |
|
pred@2129
|
34 |
smud_connection *con = NULL; |
|
pred@2129
|
35 |
|
|
pred@2129
|
36 |
while (1) |
|
pred@2129
|
37 |
{ |
|
pred@2129
|
38 |
if (*terminate) |
|
pred@2129
|
39 |
{ |
|
pred@2129
|
40 |
return; |
|
pred@2129
|
41 |
} |
|
pred@2129
|
42 |
|
|
pred@2129
|
43 |
iter = m_Links.begin(); |
|
pred@2129
|
44 |
|
|
pred@2129
|
45 |
QueryResult result = QueryResult_Continue; |
|
pred@2129
|
46 |
int pollReturn = 0; |
|
pred@2129
|
47 |
|
|
pred@2129
|
48 |
/* Add all connections that want processing to the sets */ |
|
pred@2129
|
49 |
while (iter != m_Links.end()) |
|
pred@2129
|
50 |
{ |
|
pred@2129
|
51 |
con = (smud_connection *)*iter; |
|
pred@2129
|
52 |
|
|
pred@2129
|
53 |
pollReturn = poll(&(con->pollData), 1, 0); |
|
pred@2129
|
54 |
|
|
pred@2129
|
55 |
if (pollReturn == -1) |
|
pred@2129
|
56 |
{ |
|
pred@2129
|
57 |
//Something went badly wrong or the connection closed. |
|
pred@2129
|
58 |
result = QueryResult_Complete; |
|
pred@2129
|
59 |
} |
|
pred@2129
|
60 |
else if (pollReturn == 1) |
|
pred@2129
|
61 |
{ |
|
pred@2129
|
62 |
//Poll returns the number of sockets available (which can only ever be 1) |
|
pred@2129
|
63 |
result = ProcessConnection(con); |
|
pred@2129
|
64 |
} |
|
pred@2129
|
65 |
|
|
pred@2129
|
66 |
if (result == QueryResult_Complete) |
|
pred@2129
|
67 |
{ |
|
pred@2129
|
68 |
iter = m_Links.erase(iter); |
|
pred@2129
|
69 |
closesocket(con->fd); |
|
pred@2129
|
70 |
delete con; |
|
pred@2129
|
71 |
|
|
pred@2129
|
72 |
printf("Connection Completed!\n"); |
|
pred@2129
|
73 |
|
|
pred@2129
|
74 |
continue; |
|
pred@2129
|
75 |
} |
|
pred@2129
|
76 |
|
|
pred@2129
|
77 |
iter++; |
|
pred@2129
|
78 |
} |
|
pred@2129
|
79 |
|
|
pred@2129
|
80 |
/* Add new items to process */ |
|
pred@2129
|
81 |
|
|
pred@2129
|
82 |
iter = m_Links.end(); |
|
pred@2129
|
83 |
pthread_mutex_lock(&m_AddLock); |
|
pred@2129
|
84 |
m_Links.splice(iter, m_AddQueue); |
|
pred@2129
|
85 |
pthread_mutex_unlock(&m_AddLock); |
|
pred@2129
|
86 |
|
|
pred@2129
|
87 |
nanosleep(&ts_wait, NULL); |
|
pred@2129
|
88 |
} |
|
pred@2129
|
89 |
} |
|
pred@2129
|
90 |
|
|
pred@2129
|
91 |
QueryResult ConnectionPool::ProcessConnection( smud_connection *con ) |
|
pred@2129
|
92 |
{ |
|
pred@2129
|
93 |
switch (con->state) |
|
pred@2129
|
94 |
{ |
|
pred@2129
|
95 |
case ConnectionState_ReadQueryHeader: |
|
pred@2129
|
96 |
{ |
|
pred@2129
|
97 |
ReadQueryHeader(con); |
|
pred@2129
|
98 |
break; |
|
pred@2129
|
99 |
} |
|
pred@2129
|
100 |
|
|
pred@2129
|
101 |
case ConnectionState_ReadQueryData: |
|
pred@2129
|
102 |
{ |
|
pred@2129
|
103 |
ReadQueryContent(con); |
|
pred@2129
|
104 |
break; |
|
pred@2129
|
105 |
} |
|
pred@2129
|
106 |
|
|
pred@2129
|
107 |
case ConnectionState_ReplyQuery: |
|
pred@2129
|
108 |
{ |
|
pred@2129
|
109 |
ReplyQuery(con); |
|
pred@2129
|
110 |
break; |
|
pred@2129
|
111 |
} |
|
pred@2129
|
112 |
|
|
pred@2129
|
113 |
case ConnectionState_SendingFiles: |
|
pred@2129
|
114 |
{ |
|
pred@2129
|
115 |
SendFile(con); |
|
pred@2129
|
116 |
break; |
|
pred@2129
|
117 |
} |
|
pred@2129
|
118 |
|
|
pred@2129
|
119 |
case ConnectionState_SendUnknownList: |
|
pred@2129
|
120 |
{ |
|
pred@2129
|
121 |
SendUnknownList(con); |
|
pred@2129
|
122 |
break; |
|
pred@2129
|
123 |
} |
|
pred@2129
|
124 |
|
|
pred@2129
|
125 |
case ConnectionState_Complete: |
|
pred@2129
|
126 |
{ |
|
pred@2129
|
127 |
break; |
|
pred@2129
|
128 |
} |
|
pred@2129
|
129 |
} |
|
pred@2129
|
130 |
|
|
pred@2129
|
131 |
if (con->state == ConnectionState_Complete) |
|
pred@2129
|
132 |
{ |
|
pred@2129
|
133 |
printf("Ending connection because it marked itself as finished\n"); |
|
pred@2129
|
134 |
return QueryResult_Complete; |
|
pred@2129
|
135 |
} |
|
pred@2129
|
136 |
|
|
pred@2129
|
137 |
if (con->start + m_timeOut < time(NULL)) |
|
pred@2129
|
138 |
{ |
|
pred@2129
|
139 |
printf("Ending connection because it has passed maximum allowed time\n"); |
|
pred@2129
|
140 |
return QueryResult_Complete; |
|
pred@2129
|
141 |
} |
|
pred@2129
|
142 |
|
|
pred@2129
|
143 |
return QueryResult_Continue; |
|
pred@2129
|
144 |
} |
|
pred@2129
|
145 |
|
|
pred@2129
|
146 |
void ConnectionPool::ReadQueryHeader( smud_connection *con ) |
|
pred@2129
|
147 |
{ |
|
pred@2129
|
148 |
char data[11]; |
|
pred@2129
|
149 |
|
|
pred@2129
|
150 |
if (recv(con->fd, data, sizeof(data), 0) == -1) |
|
pred@2129
|
151 |
{ |
|
pred@2129
|
152 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
153 |
{ |
|
pred@2129
|
154 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
155 |
} |
|
pred@2129
|
156 |
|
|
pred@2129
|
157 |
return; |
|
pred@2129
|
158 |
} |
|
pred@2129
|
159 |
|
|
pred@2129
|
160 |
if (data[0] != 'A' || data[1] != 'G') |
|
pred@2129
|
161 |
{ |
|
pred@2129
|
162 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
163 |
return; |
|
pred@2129
|
164 |
} |
|
pred@2129
|
165 |
|
|
pred@2129
|
166 |
//Ignore the next 8 bytes for the moment. Versioning data is currently unused |
|
pred@2129
|
167 |
// uint16[4] - source version major/minor/something/rev |
|
pred@2129
|
168 |
|
|
pred@2129
|
169 |
con->sentSums = data[10]; |
|
pred@2129
|
170 |
|
|
pred@2129
|
171 |
con->state = ConnectionState_ReadQueryData; |
|
pred@2129
|
172 |
printf("Query Header Read Complete, %i md5's expected\n", con->sentSums); |
|
pred@2129
|
173 |
} |
|
pred@2129
|
174 |
|
|
pred@2129
|
175 |
void ConnectionPool::ReplyQuery(smud_connection *con) |
|
pred@2129
|
176 |
{ |
|
pred@2129
|
177 |
char data[12]; |
|
pred@2129
|
178 |
data[0] = 'A'; |
|
pred@2129
|
179 |
data[1] = 'G'; |
|
pred@2129
|
180 |
|
|
pred@2129
|
181 |
data[2] = (char)Update_Unknown; //unused versioning crap |
|
pred@2129
|
182 |
*(short *)&data[3] = 1; |
|
pred@2129
|
183 |
*(short *)&data[5] = 0; |
|
pred@2129
|
184 |
*(short *)&data[7] = 0; |
|
pred@2129
|
185 |
*(short *)&data[9] = 3; |
|
pred@2129
|
186 |
|
|
pred@2129
|
187 |
data[11] = (char)con->sendCount; |
|
pred@2129
|
188 |
|
|
pred@2129
|
189 |
if (send(con->fd, data, sizeof(data), 0) == -1) |
|
pred@2129
|
190 |
{ |
|
pred@2129
|
191 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
192 |
{ |
|
pred@2129
|
193 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
194 |
} |
|
pred@2129
|
195 |
|
|
pred@2129
|
196 |
return; |
|
pred@2129
|
197 |
} |
|
pred@2129
|
198 |
|
|
pred@2129
|
199 |
//Now we need more send sub functions for all the damn files. Geh. |
|
pred@2129
|
200 |
//Alternatively we could just send all at once here. Could make for a damn big query. 100k anyone? |
|
pred@2129
|
201 |
|
|
pred@2129
|
202 |
con->state = ConnectionState_SendingFiles; |
|
pred@2129
|
203 |
printf("Query Reply Header Complete\n"); |
|
pred@2129
|
204 |
} |
|
pred@2129
|
205 |
|
|
pred@2129
|
206 |
void ConnectionPool::ReadQueryContent( smud_connection *con ) |
|
pred@2129
|
207 |
{ |
|
pred@2129
|
208 |
char *data = new char[16*(con->sentSums)](); |
|
pred@2129
|
209 |
|
|
pred@2129
|
210 |
if (recv(con->fd, data, 16*(con->sentSums), 0) == -1) |
|
pred@2129
|
211 |
{ |
|
pred@2129
|
212 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
213 |
{ |
|
pred@2129
|
214 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
215 |
} |
|
pred@2129
|
216 |
|
|
pred@2129
|
217 |
delete [] data; |
|
pred@2129
|
218 |
return; |
|
pred@2129
|
219 |
} |
|
pred@2129
|
220 |
|
|
pred@2129
|
221 |
con->shouldSend = new MD5Status[con->sentSums](); |
|
pred@2129
|
222 |
con->fileLocation = new int[con->sentSums](); |
|
pred@2129
|
223 |
con->headerSent = new bool[con->sentSums](); |
|
pred@2129
|
224 |
|
|
pred@2129
|
225 |
for (int i=0; i<con->sentSums; i++) |
|
pred@2129
|
226 |
{ |
|
pred@2129
|
227 |
con->fileLocation[i] = -1; |
|
pred@2129
|
228 |
con->shouldSend[i] = GetMD5UpdateStatus(data + (16*i), con, i); |
|
pred@2129
|
229 |
|
|
pred@2129
|
230 |
if (con->shouldSend[i] == MD5Status_NeedsUpdate) |
|
pred@2129
|
231 |
{ |
|
pred@2129
|
232 |
printf("File %i needs updating\n", i); |
|
pred@2129
|
233 |
con->sendCount++; |
|
pred@2129
|
234 |
con->headerSent[i] = false; |
|
pred@2129
|
235 |
continue; |
|
pred@2129
|
236 |
} |
|
pred@2129
|
237 |
|
|
pred@2129
|
238 |
if (con->shouldSend[i] == MD5Status_Unknown) |
|
pred@2129
|
239 |
{ |
|
pred@2129
|
240 |
printf("File %i is unknown\n", i); |
|
pred@2129
|
241 |
con->unknownCount++; |
|
pred@2129
|
242 |
} |
|
pred@2129
|
243 |
} |
|
pred@2129
|
244 |
|
|
pred@2129
|
245 |
con->state = ConnectionState_ReplyQuery; |
|
pred@2129
|
246 |
con->pollData.events = POLLOUT; |
|
pred@2129
|
247 |
delete [] data; |
|
pred@2129
|
248 |
printf("Query Data Read Complete\n"); |
|
pred@2129
|
249 |
} |
|
pred@2129
|
250 |
|
|
pred@2129
|
251 |
MD5Status ConnectionPool::GetMD5UpdateStatus( const char *md5 , smud_connection *con, int fileNum) |
|
pred@2129
|
252 |
{ |
|
pred@2129
|
253 |
//Try find a file with this name in some directory. |
|
pred@2129
|
254 |
char path[100] = "./md5/"; |
|
pred@2129
|
255 |
char temp[4]; |
|
pred@2129
|
256 |
char md5String[33] = ""; |
|
pred@2129
|
257 |
|
|
pred@2129
|
258 |
for (int i=0; i<16; i++) |
|
pred@2129
|
259 |
{ |
|
pred@2129
|
260 |
snprintf(temp, sizeof(temp), "%02x", (unsigned char)md5[i]); |
|
pred@2129
|
261 |
strcat(md5String, temp); |
|
pred@2129
|
262 |
} |
|
pred@2129
|
263 |
|
|
pred@2129
|
264 |
strcat(path, md5String); |
|
pred@2129
|
265 |
|
|
pred@2129
|
266 |
printf("checking for file \"%s\"\n", path); |
|
pred@2129
|
267 |
|
|
pred@2129
|
268 |
FILE *file = fopen(path, "r"); |
|
pred@2129
|
269 |
|
|
pred@2129
|
270 |
if (file == NULL) |
|
pred@2129
|
271 |
{ |
|
pred@2129
|
272 |
printf("Couldn't find file!\n"); |
|
pred@2129
|
273 |
return MD5Status_Unknown; |
|
pred@2129
|
274 |
} |
|
pred@2129
|
275 |
|
|
pred@2129
|
276 |
char latestMD5[33]; |
|
pred@2129
|
277 |
fgets(latestMD5, 33, file); |
|
pred@2129
|
278 |
printf("Latest md5 is: %s\n", latestMD5); |
|
pred@2129
|
279 |
|
|
pred@2129
|
280 |
if (strcmp(latestMD5, md5String) == 0) |
|
pred@2129
|
281 |
{ |
|
pred@2129
|
282 |
return MD5Status_Current; |
|
pred@2129
|
283 |
} |
|
pred@2129
|
284 |
|
|
pred@2129
|
285 |
char filename[100]; |
|
pred@2140
|
286 |
filename[0] = '\n'; |
|
pred@2140
|
287 |
|
|
pred@2140
|
288 |
while (filename[0] == '\n') |
|
pred@2129
|
289 |
{ |
|
pred@2140
|
290 |
fgets(filename, sizeof(filename), file); |
|
pred@2129
|
291 |
} |
|
pred@2129
|
292 |
|
|
pred@2141
|
293 |
if (filename[strlen(filename)-1] == '\n') |
|
pred@2141
|
294 |
{ |
|
pred@2141
|
295 |
filename[strlen(filename)-1] = '\0'; |
|
pred@2141
|
296 |
} |
|
pred@2141
|
297 |
|
|
pred@2213
|
298 |
fclose(file); |
|
pred@2140
|
299 |
|
|
pred@2129
|
300 |
printf("Filename is %s\n", filename); |
|
pred@2129
|
301 |
|
|
pred@2129
|
302 |
//We now need to match this filename with one of our mmap'd files in memory and store it until send gets called. |
|
pred@2129
|
303 |
for (int i=0; i<NUM_FILES; i++) |
|
pred@2129
|
304 |
{ |
|
pred@2129
|
305 |
if (strcmp(fileNames[i], filename) == 0) |
|
pred@2129
|
306 |
{ |
|
pred@2129
|
307 |
con->fileLocation[fileNum] = i; |
|
pred@2129
|
308 |
printf("File %i mapped to local file %i\n", fileNum, i); |
|
pred@2129
|
309 |
return MD5Status_NeedsUpdate; |
|
pred@2129
|
310 |
} |
|
pred@2129
|
311 |
} |
|
pred@2129
|
312 |
|
|
pred@2129
|
313 |
return MD5Status_Unknown; |
|
pred@2129
|
314 |
} |
|
pred@2129
|
315 |
|
|
pred@2129
|
316 |
void ConnectionPool::SendFile( smud_connection *con ) |
|
pred@2129
|
317 |
{ |
|
pred@2129
|
318 |
//Find the next file to send. |
|
pred@2129
|
319 |
while (con->currentFile < con->sentSums && |
|
pred@2129
|
320 |
con->shouldSend[con->currentFile] != MD5Status_NeedsUpdate) |
|
pred@2129
|
321 |
{ |
|
pred@2129
|
322 |
con->currentFile++; |
|
pred@2129
|
323 |
} |
|
pred@2129
|
324 |
|
|
pred@2129
|
325 |
//All files have been sent. |
|
pred@2129
|
326 |
if (con->currentFile >= con->sentSums) |
|
pred@2129
|
327 |
{ |
|
pred@2129
|
328 |
printf("All files sent!\n"); |
|
pred@2129
|
329 |
con->state = ConnectionState_SendUnknownList; |
|
pred@2129
|
330 |
return; |
|
pred@2129
|
331 |
} |
|
pred@2129
|
332 |
|
|
pred@2129
|
333 |
void *file = fileLocations[con->fileLocation[con->currentFile]]; |
|
pred@2129
|
334 |
int filelength = fileLength[con->fileLocation[con->currentFile]]; |
|
pred@2129
|
335 |
|
|
pred@2129
|
336 |
printf("Sending file of length %i\n", filelength); |
|
pred@2129
|
337 |
printf("Current file index is: %i, maps to file index: %i\n", con->currentFile, con->fileLocation[con->currentFile]); |
|
pred@2129
|
338 |
|
|
pred@2129
|
339 |
if (!con->headerSent[con->currentFile]) |
|
pred@2129
|
340 |
{ |
|
pred@2129
|
341 |
char buffer[5]; |
|
pred@2129
|
342 |
buffer[0] = con->currentFile; |
|
pred@2129
|
343 |
*((int *)&buffer[1]) = filelength; |
|
pred@2129
|
344 |
|
|
pred@2129
|
345 |
if (send(con->fd, buffer, 5, 0) == -1) |
|
pred@2129
|
346 |
{ |
|
pred@2129
|
347 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
348 |
{ |
|
pred@2129
|
349 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
350 |
} |
|
pred@2129
|
351 |
|
|
pred@2129
|
352 |
return; |
|
pred@2129
|
353 |
} |
|
pred@2129
|
354 |
|
|
pred@2129
|
355 |
con->headerSent[con->currentFile] = true; |
|
pred@2129
|
356 |
} |
|
pred@2129
|
357 |
|
|
pred@2129
|
358 |
if (send(con->fd, file, filelength, 0) == -1) |
|
pred@2129
|
359 |
{ |
|
pred@2129
|
360 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
361 |
{ |
|
pred@2129
|
362 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
363 |
} |
|
pred@2129
|
364 |
|
|
pred@2129
|
365 |
return; |
|
pred@2129
|
366 |
} |
|
pred@2129
|
367 |
|
|
pred@2129
|
368 |
con->currentFile++; |
|
pred@2129
|
369 |
printf("Sent a file!: %s\n", fileNames[con->fileLocation[con->currentFile-1]]); |
|
pred@2129
|
370 |
} |
|
pred@2129
|
371 |
|
|
pred@2129
|
372 |
void ConnectionPool::SendUnknownList( smud_connection *con ) |
|
pred@2129
|
373 |
{ |
|
pred@2129
|
374 |
int size = con->unknownCount+1; |
|
pred@2129
|
375 |
char *packet = new char[size](); |
|
pred@2129
|
376 |
|
|
pred@2129
|
377 |
packet[0] = con->unknownCount; |
|
pred@2129
|
378 |
|
|
pred@2129
|
379 |
printf("%i Files are unknown\n", con->unknownCount); |
|
pred@2129
|
380 |
|
|
pred@2129
|
381 |
int i=1; |
|
pred@2129
|
382 |
|
|
pred@2129
|
383 |
for (int j=0; j<con->sentSums; j++) |
|
pred@2129
|
384 |
{ |
|
pred@2129
|
385 |
if (con->shouldSend[j] == MD5Status_Unknown) |
|
pred@2129
|
386 |
{ |
|
pred@2129
|
387 |
packet[i] = j; |
|
pred@2129
|
388 |
i++; |
|
pred@2129
|
389 |
} |
|
pred@2129
|
390 |
} |
|
pred@2129
|
391 |
|
|
pred@2129
|
392 |
if (send(con->fd, packet, size, 0) == -1) |
|
pred@2129
|
393 |
{ |
|
pred@2129
|
394 |
if (errno != EAGAIN && errno != EWOULDBLOCK) |
|
pred@2129
|
395 |
{ |
|
pred@2129
|
396 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
397 |
} |
|
pred@2129
|
398 |
|
|
pred@2129
|
399 |
return; |
|
pred@2129
|
400 |
} |
|
pred@2129
|
401 |
|
|
pred@2129
|
402 |
con->state = ConnectionState_Complete; |
|
pred@2129
|
403 |
printf("Unknown's Sent\n"); |
|
pred@2129
|
404 |
} |