]> git.sesse.net Git - freerainbowtables/blob - BOINC software/BOINC client apps/distrrtgen_cuda/distrrtgen.cpp
linux cuda boinc build!
[freerainbowtables] / BOINC software / BOINC client apps / distrrtgen_cuda / distrrtgen.cpp
1 // This file is part of BOINC.
2 // http://boinc.berkeley.edu
3 // Copyright (C) 2008 University of California
4 //
5 // BOINC is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Lesser General Public License
7 // as published by the Free Software Foundation,
8 // either version 3 of the License, or (at your option) any later version.
9 //
10 // BOINC is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 // See the GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
17
18 // This program serves as both
19 // - An example BOINC application, illustrating the use of the BOINC API
20 // - A program for testing various features of BOINC
21 //
22 // NOTE: this file exists as both
23 // boinc/apps/upper_case.C
24 // and
25 // boinc_samples/example_app/uc2.C
26 // If you update one, please update the other!
27
28 // The program converts a mixed-case file to upper case:
29 // read "in", convert to upper case, write to "out"
30 //
31 // command line options
32 // -run_slow: sleep 1 second after each character
33 // -cpu_time N: use about N CPU seconds after copying files
34 // -early_exit: exit(10) after 30 chars
35 // -early_crash: crash after 30 chars
36 //
37
38 #ifdef _WIN32
39 #include "boinc_win.h"
40 #else
41 #include "config.h"
42 #include <cstdio>
43 #include <cctype>
44 #include <ctime>
45 #include <cstring>
46 #include <cstdlib>
47 #include <csignal>
48 #include <unistd.h>
49 #endif
50
51 #include <string>
52 #include <fstream>
53 #include <iostream>
54 #include "str_util.h"
55 #include "util.h"
56 #include "filesys.h"
57 #include "boinc_api.h"
58 #include "Public.h"
59 //typedef unsigned int uint32;
60 //typedef unsigned __int64 uint64;
61 #include "rcuda.h"
62 #include "rcuda_ext.h"
63
64 #define EXIT_CODE_TEMP_SLEEP -20
65
66
67 using std::string;
68
69 /*
70 bool early_exit = false;
71 bool early_crash = false;
72 bool early_sleep = false;
73 double cpu_time = 20, comp_result;
74 */
75 /*
76 int QuickSortPartition(RainbowChainCP* pChain, int nLow, int nHigh)
77 {
78         int nRandomIndex = nLow + ((uint32)rand() * ((uint32)RAND_MAX + 1) + (uint32)rand()) % (nHigh - nLow + 1);
79         RainbowChainCP TempChain;
80         TempChain = pChain[nLow];
81         pChain[nLow] = pChain[nRandomIndex];
82         pChain[nRandomIndex] = TempChain;
83
84         TempChain = pChain[nLow];
85         uint64 nPivotKey = pChain[nLow].nIndexE;
86         while (nLow < nHigh)
87         {
88                 while (nLow < nHigh && pChain[nHigh].nIndexE >= nPivotKey)
89                         nHigh--;
90                 pChain[nLow] = pChain[nHigh];
91                 while (nLow < nHigh && pChain[nLow].nIndexE <= nPivotKey)
92                         nLow++;
93                 pChain[nHigh] = pChain[nLow];
94         }
95         pChain[nLow] = TempChain;
96         return nLow;
97 }
98
99 void QuickSort(RainbowChainCP* pChain, int nLow, int nHigh)
100 {
101         if (nLow < nHigh)
102         {
103                 int nPivotLoc = QuickSortPartition(pChain, nLow, nHigh);
104                 QuickSort(pChain, nLow, nPivotLoc - 1);
105                 QuickSort(pChain, nPivotLoc + 1, nHigh);
106         }
107 }
108 */
109 int main(int argc, char **argv) {    
110     int retval;
111     double fd;
112     char output_path[512], chkpt_path[512];
113     FILE* state;        
114     retval = boinc_init();
115     if (retval) {
116         fprintf(stderr, "boinc_init returned %d\n", retval);
117         exit(retval);
118     }
119
120         // extract a --device option
121         std::vector<char*> argVec;
122         int cudaDevice = -1;
123         for(int ii = 0; ii < argc; ii++) {
124                 if(cudaDevice < 0 && strcmp(argv[ii], "--device") == 0 && ii + 1 < argc)
125                         cudaDevice = atoi(argv[++ii]);
126                 else
127                         argVec.push_back(argv[ii]);
128         }
129         argc = (int)argVec.size();
130         argv = &argVec[0];
131         if(!(cudaDevice < 0))
132                 // set the cuda device
133                 if(rcuda::SetCudaDevice(cudaDevice) != 0)
134                 {
135                         //XXX this call doesn't work on linux
136                         // fixed in upstream source 2010-09-16
137                         // http://bolt.berkeley.edu/trac/changeset/22382
138                         #ifdef _WIN32
139                                 boinc_temporary_exit(60);
140                         #else
141                                 sleep(60);
142                                 exit(EXIT_CODE_TEMP_SLEEP);
143                         #endif
144                 }
145
146         if(argc < 10)
147         {
148                 fprintf(stderr, "Not enough parameters");
149                 return -1;
150         }
151         string sHashRoutineName, sCharsetName, sSalt, sCheckPoints;
152         uint32 nRainbowChainCount, nPlainLenMin, nPlainLenMax, nRainbowTableIndex, nRainbowChainLen;
153         uint64 nChainStart;
154         sHashRoutineName = argv[1];
155         sCharsetName = argv[2];
156         nPlainLenMin = atoi(argv[3]);
157         nPlainLenMax = atoi(argv[4]);
158         nRainbowTableIndex = atoi(argv[5]);
159         nRainbowChainLen = atoi(argv[6]);
160         nRainbowChainCount = atoi(argv[7]);
161 #ifdef _WIN32
162
163         nChainStart = _atoi64(argv[8]);
164
165 #else
166         nChainStart = atoll(argv[8]);
167 #endif
168         sCheckPoints = argv[9];
169         vector<int> vCPPositions;
170         char *cp = strtok((char *)sCheckPoints.c_str(), ",");
171         while(cp != NULL)
172         {
173                 vCPPositions.push_back(atoi(cp));
174                 cp = strtok(NULL, ",");
175         }
176         if(argc == 11)
177         {
178                 sSalt = argv[10];
179         }
180         //std::cout << "Starting ChainGenerator" << std::endl;
181         // Setup CChainWalkContext
182         //std::cout << "ChainGenerator started." << std::endl;
183
184         if (!CChainWalkContext::SetHashRoutine(sHashRoutineName))
185         {
186                 fprintf(stderr, "hash routine %s not supported\n", sHashRoutineName.c_str());
187                 return 1;
188         }
189         //std::cout << "Hash routine validated" << std::endl;
190
191         if (!CChainWalkContext::SetPlainCharset(sCharsetName, nPlainLenMin, nPlainLenMax))
192         {       
193                 std::cerr << "charset " << sCharsetName << " not supported" << std::endl;
194                 return 2;
195         }
196         //std::cout << "Plain charset validated" << std::endl;
197
198         if (!CChainWalkContext::SetRainbowTableIndex(nRainbowTableIndex))
199         {
200                 std::cerr << "invalid rainbow table index " << nRainbowTableIndex << std::endl;
201                 return 3;
202         }
203         //std::cout << "Rainbowtable index validated" << std::endl;
204
205         if(sHashRoutineName == "mscache")// || sHashRoutineName == "lmchall" || sHashRoutineName == "halflmchall")
206         {
207                 // Convert username to unicode
208                 const char *szSalt = sSalt.c_str();
209                 int salt_length = strlen(szSalt);
210                 unsigned char cur_salt[256];
211                 for (int i=0; i<salt_length; i++)
212                 {
213                         cur_salt[i*2] = szSalt[i];
214                         cur_salt[i*2+1] = 0x00;
215                 }
216                 CChainWalkContext::SetSalt(cur_salt, salt_length*2);
217         }
218         else if(sHashRoutineName == "halflmchall")
219         { // The salt is hardcoded into the hash routine
220         //      CChainWalkContext::SetSalt((unsigned char*)&salt, 8);
221         }
222         else if(sHashRoutineName == "oracle")
223         {
224                 CChainWalkContext::SetSalt((unsigned char *)sSalt.c_str(), sSalt.length());
225         }
226         //std::cout << "Opening chain file" << std::endl;
227
228         
229         // Open file
230         boinc_resolve_filename("result", output_path, sizeof(output_path));
231         fclose(boinc_fopen(output_path, "a"));
232         FILE *outfile = boinc_fopen(output_path, "r+b");
233         
234         if (outfile == NULL)
235         {
236                 std::cerr << "failed to create " << output_path << std::endl;
237                 return 4;
238         }
239         
240         
241         // Check existing chains
242         unsigned int nDataLen = (unsigned int)GetFileLen(outfile);
243         unsigned int nFileLen;
244         
245         // Round to boundary
246         nDataLen = nDataLen / 10 * 10;
247         if (nDataLen == nRainbowChainCount * 10)
248         {               
249                 std::cerr << "precomputation of this rainbow table already finished" << std::endl;
250                 fclose(outfile);
251                 return 0;
252         }
253
254         fseek(outfile, nDataLen, SEEK_SET);
255         //XXX size_t isn't 32/64 clean
256         size_t nReturn;
257         CChainWalkContext cwc;
258         uint64 nIndex[2];
259         time_t tStart = time(NULL);
260
261 //      std::cout << "Starting to generate chains" << std::endl;
262         int maxCalcBuffSize = rcuda::GetChainsBufferSize(0x2000);
263         uint64 *calcBuff = new uint64[2*maxCalcBuffSize];
264         int ii;
265
266         CudaCWCExtender ex(&cwc);
267         rcuda::RCudaTask cuTask;
268         std::vector<unsigned char> stPlain;
269         ex.Init();
270
271         for(int nCurrentCalculatedChains = nDataLen / 10, calcSize; nCurrentCalculatedChains < nRainbowChainCount; )
272         {               
273                 fd = (double)nCurrentCalculatedChains / (double)nRainbowChainCount;
274                 boinc_fraction_done(fd);
275
276                 cuTask.hash = ex.GetHash();
277                 cuTask.startIdx = nChainStart + nCurrentCalculatedChains;
278                 cuTask.idxCount = std::min<int>(nRainbowChainCount - nCurrentCalculatedChains, maxCalcBuffSize);
279                 cuTask.stPlainSize = ex.IndexToStartPlain(0, stPlain);
280                 cuTask.stPlain = &stPlain[0];
281                 cuTask.dimVec = ex.GetPlainDimVec();
282                 cuTask.dimVecSize = ex.GetPlainDimVecSize()/3;
283                 cuTask.charSet = ex.GetCharSet();
284                 cuTask.charSetSize = ex.GetCharSetSize();
285                 cuTask.cpPositions = &vCPPositions[0];
286                 cuTask.cpPosSize = vCPPositions.size();
287                 cuTask.reduceOffset = ex.GetReduceOffset();
288                 cuTask.plainSpaceTotal = ex.GetPlainSpaceTotal();
289                 cuTask.rainbowChainLen = nRainbowChainLen;
290                 for(ii = 0; ii < cuTask.idxCount; ii++) {
291                         calcBuff[2*ii] = cuTask.startIdx + ii;
292                         calcBuff[2*ii+1] = 0;
293                 }
294                 calcSize = rcuda::CalcChainsOnCUDA(&cuTask, calcBuff);
295
296                 if(calcSize > 0) {
297                         nCurrentCalculatedChains += calcSize;
298                         for(ii = 0; ii < cuTask.idxCount; ii++) {
299                                 nIndex[0] = cuTask.startIdx + ii;
300 //                              nReturn = fwrite(nIndex, 1, 8, outfile);
301                                 nReturn = fwrite(calcBuff+(2*ii), 1, 8, outfile);
302                                 nReturn += fwrite(calcBuff+(2*ii+1), 1, 2, outfile);
303                                 if(nReturn != 10) {
304                                         std::cerr << "disk write fail" << std::endl;
305                                         fclose(outfile);
306                                         return 9;
307                                 }
308                         }
309                 } else {
310                         std::cerr << "Calculations on CUDA failed!" << std::endl;
311                         fclose(outfile);
312                         return 0;
313                 }
314         }
315         delete [] calcBuff;
316 #ifdef _DEBUG
317         std::cout << "Generation completed" << std::endl;
318 #endif
319 /*
320     fseek(outfile, 0, SEEK_SET);
321         nFileLen = GetFileLen(outfile);
322         nRainbowChainCount = nFileLen / 18;
323
324         RainbowChainCP* pChain = (RainbowChainCP*)new unsigned char[sizeof(RainbowChainCP) * nRainbowChainCount];
325
326         if (pChain != NULL)
327         {
328                 // Load file
329 #ifdef _DEBUG
330         std::cout << "Sorting file" << std::endl;
331 #endif
332                 fseek(outfile, 0, SEEK_SET);
333                 for(uint32 i = 0; i < nRainbowChainCount; i++)
334                 {
335                         if(fread(&pChain[i], 1, 16, outfile) != 16)
336                         {
337                                 printf("disk read fail\n");
338                                 return 9;
339                         }
340                         if(fread(&pChain[i].nCheckPoint, 1, sizeof(pChain[i].nCheckPoint), outfile) != 2)
341                         {
342                                 printf("disk read fail\n");
343                                 return 9;
344                         }
345                 }
346
347                 // Sort file
348                 QuickSort(pChain, 0, nRainbowChainCount - 1);
349
350                 // Write file
351                 fseek(outfile, 0, SEEK_SET);
352                 for(uint32 i = 0; i < nRainbowChainCount; i++)
353                 {
354                         fwrite(&pChain[i], 1, 16, outfile);
355                         fwrite(&pChain[i].nCheckPoint, 2, 1, outfile);
356                 }
357                 delete[] pChain;
358         }
359 */
360         fclose(outfile);
361     
362         // main loop - read characters, convert to UC, write
363     //
364
365     boinc_fraction_done(1);
366     boinc_finish(0);
367 }
368
369 #ifdef _WIN32
370 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode) {
371     LPSTR command_line;
372     char* argv[100];
373     int argc;
374
375     command_line = GetCommandLine();
376     argc = parse_command_line( command_line, argv );
377     return main(argc, argv);
378 }
379 #endif