1.1 --- a/tools/daemon/smud_connections.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,404 +0,0 @@
1.4 -#include "smud_connections.h"
1.5 -#include "smud.h"
1.6 -
1.7 -ConnectionPool::ConnectionPool()
1.8 -{
1.9 - pthread_mutex_init(&m_AddLock, NULL);
1.10 - m_timeOut = 1000;
1.11 -}
1.12 -
1.13 -ConnectionPool::~ConnectionPool()
1.14 -{
1.15 - pthread_mutex_destroy(&m_AddLock);
1.16 -}
1.17 -
1.18 -void ConnectionPool::AddConnection( int fd )
1.19 -{
1.20 - smud_connection *connection = new smud_connection(fd);
1.21 -
1.22 - pthread_mutex_lock(&m_AddLock);
1.23 - m_AddQueue.push_back(connection);
1.24 - pthread_mutex_unlock(&m_AddLock);
1.25 -
1.26 - printf("New Connection Added\n");
1.27 -}
1.28 -
1.29 -void ConnectionPool::Process( bool *terminate )
1.30 -{
1.31 - struct timespec ts_wait;
1.32 -
1.33 - ts_wait.tv_sec = 0;
1.34 - ts_wait.tv_nsec = 50000000; /* 50ms */
1.35 -
1.36 - std::list<smud_connection *>::iterator iter;
1.37 - smud_connection *con = NULL;
1.38 -
1.39 - while (1)
1.40 - {
1.41 - if (*terminate)
1.42 - {
1.43 - return;
1.44 - }
1.45 -
1.46 - iter = m_Links.begin();
1.47 -
1.48 - QueryResult result = QueryResult_Continue;
1.49 - int pollReturn = 0;
1.50 -
1.51 - /* Add all connections that want processing to the sets */
1.52 - while (iter != m_Links.end())
1.53 - {
1.54 - con = (smud_connection *)*iter;
1.55 -
1.56 - pollReturn = poll(&(con->pollData), 1, 0);
1.57 -
1.58 - if (pollReturn == -1)
1.59 - {
1.60 - //Something went badly wrong or the connection closed.
1.61 - result = QueryResult_Complete;
1.62 - }
1.63 - else if (pollReturn == 1)
1.64 - {
1.65 - //Poll returns the number of sockets available (which can only ever be 1)
1.66 - result = ProcessConnection(con);
1.67 - }
1.68 -
1.69 - if (result == QueryResult_Complete)
1.70 - {
1.71 - iter = m_Links.erase(iter);
1.72 - closesocket(con->fd);
1.73 - delete con;
1.74 -
1.75 - printf("Connection Completed!\n");
1.76 -
1.77 - continue;
1.78 - }
1.79 -
1.80 - iter++;
1.81 - }
1.82 -
1.83 - /* Add new items to process */
1.84 -
1.85 - iter = m_Links.end();
1.86 - pthread_mutex_lock(&m_AddLock);
1.87 - m_Links.splice(iter, m_AddQueue);
1.88 - pthread_mutex_unlock(&m_AddLock);
1.89 -
1.90 - nanosleep(&ts_wait, NULL);
1.91 - }
1.92 -}
1.93 -
1.94 -QueryResult ConnectionPool::ProcessConnection( smud_connection *con )
1.95 -{
1.96 - switch (con->state)
1.97 - {
1.98 - case ConnectionState_ReadQueryHeader:
1.99 - {
1.100 - ReadQueryHeader(con);
1.101 - break;
1.102 - }
1.103 -
1.104 - case ConnectionState_ReadQueryData:
1.105 - {
1.106 - ReadQueryContent(con);
1.107 - break;
1.108 - }
1.109 -
1.110 - case ConnectionState_ReplyQuery:
1.111 - {
1.112 - ReplyQuery(con);
1.113 - break;
1.114 - }
1.115 -
1.116 - case ConnectionState_SendingFiles:
1.117 - {
1.118 - SendFile(con);
1.119 - break;
1.120 - }
1.121 -
1.122 - case ConnectionState_SendUnknownList:
1.123 - {
1.124 - SendUnknownList(con);
1.125 - break;
1.126 - }
1.127 -
1.128 - case ConnectionState_Complete:
1.129 - {
1.130 - break;
1.131 - }
1.132 - }
1.133 -
1.134 - if (con->state == ConnectionState_Complete)
1.135 - {
1.136 - printf("Ending connection because it marked itself as finished\n");
1.137 - return QueryResult_Complete;
1.138 - }
1.139 -
1.140 - if (con->start + m_timeOut < time(NULL))
1.141 - {
1.142 - printf("Ending connection because it has passed maximum allowed time\n");
1.143 - return QueryResult_Complete;
1.144 - }
1.145 -
1.146 - return QueryResult_Continue;
1.147 -}
1.148 -
1.149 -void ConnectionPool::ReadQueryHeader( smud_connection *con )
1.150 -{
1.151 - char data[11];
1.152 -
1.153 - if (recv(con->fd, data, sizeof(data), 0) == -1)
1.154 - {
1.155 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.156 - {
1.157 - con->state = ConnectionState_Complete;
1.158 - }
1.159 -
1.160 - return;
1.161 - }
1.162 -
1.163 - if (data[0] != 'A' || data[1] != 'G')
1.164 - {
1.165 - con->state = ConnectionState_Complete;
1.166 - return;
1.167 - }
1.168 -
1.169 - //Ignore the next 8 bytes for the moment. Versioning data is currently unused
1.170 - // uint16[4] - source version major/minor/something/rev
1.171 -
1.172 - con->sentSums = data[10];
1.173 -
1.174 - con->state = ConnectionState_ReadQueryData;
1.175 - printf("Query Header Read Complete, %i md5's expected\n", con->sentSums);
1.176 -}
1.177 -
1.178 -void ConnectionPool::ReplyQuery(smud_connection *con)
1.179 -{
1.180 - char data[12];
1.181 - data[0] = 'A';
1.182 - data[1] = 'G';
1.183 -
1.184 - data[2] = (char)Update_Unknown; //unused versioning crap
1.185 - *(short *)&data[3] = 1;
1.186 - *(short *)&data[5] = 0;
1.187 - *(short *)&data[7] = 0;
1.188 - *(short *)&data[9] = 3;
1.189 -
1.190 - data[11] = (char)con->sendCount;
1.191 -
1.192 - if (send(con->fd, data, sizeof(data), 0) == -1)
1.193 - {
1.194 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.195 - {
1.196 - con->state = ConnectionState_Complete;
1.197 - }
1.198 -
1.199 - return;
1.200 - }
1.201 -
1.202 - //Now we need more send sub functions for all the damn files. Geh.
1.203 - //Alternatively we could just send all at once here. Could make for a damn big query. 100k anyone?
1.204 -
1.205 - con->state = ConnectionState_SendingFiles;
1.206 - printf("Query Reply Header Complete\n");
1.207 -}
1.208 -
1.209 -void ConnectionPool::ReadQueryContent( smud_connection *con )
1.210 -{
1.211 - char *data = new char[16*(con->sentSums)]();
1.212 -
1.213 - if (recv(con->fd, data, 16*(con->sentSums), 0) == -1)
1.214 - {
1.215 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.216 - {
1.217 - con->state = ConnectionState_Complete;
1.218 - }
1.219 -
1.220 - delete [] data;
1.221 - return;
1.222 - }
1.223 -
1.224 - con->shouldSend = new MD5Status[con->sentSums]();
1.225 - con->fileLocation = new int[con->sentSums]();
1.226 - con->headerSent = new bool[con->sentSums]();
1.227 -
1.228 - for (int i=0; i<con->sentSums; i++)
1.229 - {
1.230 - con->fileLocation[i] = -1;
1.231 - con->shouldSend[i] = GetMD5UpdateStatus(data + (16*i), con, i);
1.232 -
1.233 - if (con->shouldSend[i] == MD5Status_NeedsUpdate)
1.234 - {
1.235 - printf("File %i needs updating\n", i);
1.236 - con->sendCount++;
1.237 - con->headerSent[i] = false;
1.238 - continue;
1.239 - }
1.240 -
1.241 - if (con->shouldSend[i] == MD5Status_Unknown)
1.242 - {
1.243 - printf("File %i is unknown\n", i);
1.244 - con->unknownCount++;
1.245 - }
1.246 - }
1.247 -
1.248 - con->state = ConnectionState_ReplyQuery;
1.249 - con->pollData.events = POLLOUT;
1.250 - delete [] data;
1.251 - printf("Query Data Read Complete\n");
1.252 -}
1.253 -
1.254 -MD5Status ConnectionPool::GetMD5UpdateStatus( const char *md5 , smud_connection *con, int fileNum)
1.255 -{
1.256 - //Try find a file with this name in some directory.
1.257 - char path[100] = "./md5/";
1.258 - char temp[4];
1.259 - char md5String[33] = "";
1.260 -
1.261 - for (int i=0; i<16; i++)
1.262 - {
1.263 - snprintf(temp, sizeof(temp), "%02x", (unsigned char)md5[i]);
1.264 - strcat(md5String, temp);
1.265 - }
1.266 -
1.267 - strcat(path, md5String);
1.268 -
1.269 - printf("checking for file \"%s\"\n", path);
1.270 -
1.271 - FILE *file = fopen(path, "r");
1.272 -
1.273 - if (file == NULL)
1.274 - {
1.275 - printf("Couldn't find file!\n");
1.276 - return MD5Status_Unknown;
1.277 - }
1.278 -
1.279 - char latestMD5[33];
1.280 - fgets(latestMD5, 33, file);
1.281 - printf("Latest md5 is: %s\n", latestMD5);
1.282 -
1.283 - if (strcmp(latestMD5, md5String) == 0)
1.284 - {
1.285 - return MD5Status_Current;
1.286 - }
1.287 -
1.288 - char filename[100];
1.289 - filename[0] = '\n';
1.290 -
1.291 - while (filename[0] == '\n')
1.292 - {
1.293 - fgets(filename, sizeof(filename), file);
1.294 - }
1.295 -
1.296 - if (filename[strlen(filename)-1] == '\n')
1.297 - {
1.298 - filename[strlen(filename)-1] = '\0';
1.299 - }
1.300 -
1.301 -
1.302 -
1.303 - printf("Filename is %s\n", filename);
1.304 -
1.305 - //We now need to match this filename with one of our mmap'd files in memory and store it until send gets called.
1.306 - for (int i=0; i<NUM_FILES; i++)
1.307 - {
1.308 - if (strcmp(fileNames[i], filename) == 0)
1.309 - {
1.310 - con->fileLocation[fileNum] = i;
1.311 - printf("File %i mapped to local file %i\n", fileNum, i);
1.312 - return MD5Status_NeedsUpdate;
1.313 - }
1.314 - }
1.315 -
1.316 - return MD5Status_Unknown;
1.317 -}
1.318 -
1.319 -void ConnectionPool::SendFile( smud_connection *con )
1.320 -{
1.321 - //Find the next file to send.
1.322 - while (con->currentFile < con->sentSums &&
1.323 - con->shouldSend[con->currentFile] != MD5Status_NeedsUpdate)
1.324 - {
1.325 - con->currentFile++;
1.326 - }
1.327 -
1.328 - //All files have been sent.
1.329 - if (con->currentFile >= con->sentSums)
1.330 - {
1.331 - printf("All files sent!\n");
1.332 - con->state = ConnectionState_SendUnknownList;
1.333 - return;
1.334 - }
1.335 -
1.336 - void *file = fileLocations[con->fileLocation[con->currentFile]];
1.337 - int filelength = fileLength[con->fileLocation[con->currentFile]];
1.338 -
1.339 - printf("Sending file of length %i\n", filelength);
1.340 - printf("Current file index is: %i, maps to file index: %i\n", con->currentFile, con->fileLocation[con->currentFile]);
1.341 -
1.342 - if (!con->headerSent[con->currentFile])
1.343 - {
1.344 - char buffer[5];
1.345 - buffer[0] = con->currentFile;
1.346 - *((int *)&buffer[1]) = filelength;
1.347 -
1.348 - if (send(con->fd, buffer, 5, 0) == -1)
1.349 - {
1.350 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.351 - {
1.352 - con->state = ConnectionState_Complete;
1.353 - }
1.354 -
1.355 - return;
1.356 - }
1.357 -
1.358 - con->headerSent[con->currentFile] = true;
1.359 - }
1.360 -
1.361 - if (send(con->fd, file, filelength, 0) == -1)
1.362 - {
1.363 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.364 - {
1.365 - con->state = ConnectionState_Complete;
1.366 - }
1.367 -
1.368 - return;
1.369 - }
1.370 -
1.371 - con->currentFile++;
1.372 - printf("Sent a file!: %s\n", fileNames[con->fileLocation[con->currentFile-1]]);
1.373 -}
1.374 -
1.375 -void ConnectionPool::SendUnknownList( smud_connection *con )
1.376 -{
1.377 - int size = con->unknownCount+1;
1.378 - char *packet = new char[size]();
1.379 -
1.380 - packet[0] = con->unknownCount;
1.381 -
1.382 - printf("%i Files are unknown\n", con->unknownCount);
1.383 -
1.384 - int i=1;
1.385 -
1.386 - for (int j=0; j<con->sentSums; j++)
1.387 - {
1.388 - if (con->shouldSend[j] == MD5Status_Unknown)
1.389 - {
1.390 - packet[i] = j;
1.391 - i++;
1.392 - }
1.393 - }
1.394 -
1.395 - if (send(con->fd, packet, size, 0) == -1)
1.396 - {
1.397 - if (errno != EAGAIN && errno != EWOULDBLOCK)
1.398 - {
1.399 - con->state = ConnectionState_Complete;
1.400 - }
1.401 -
1.402 - return;
1.403 - }
1.404 -
1.405 - con->state = ConnectionState_Complete;
1.406 - printf("Unknown's Sent\n");
1.407 -}