]> git.ozlabs.org Git - ccan/blobdiff - ccan/antithread/examples/md5_server.c
Add antithread. Not finished, but useful as example of module whose
[ccan] / ccan / antithread / examples / md5_server.c
diff --git a/ccan/antithread/examples/md5_server.c b/ccan/antithread/examples/md5_server.c
new file mode 100644 (file)
index 0000000..3aa98bb
--- /dev/null
@@ -0,0 +1,129 @@
+/* Tries to find data with a given MD5 (up to N bits). */
+#include "ccan/antithread/antithread.h"
+#include "ccan/string/string.h"
+#include "ccan/talloc/talloc.h"
+#include "md5_finder.h"
+#include <err.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void usage(void)
+{
+       errx(1, "Usage: md5calc <hexstring> <numcpus>");
+}
+
+static void parse_hexstring(const char *string, struct md5_search *md5s)
+{
+       unsigned int i;
+
+       if (strstarts(string, "0x") || strstarts(string, "0X"))
+               string += 2;
+
+       for (i = 0; i < MD5_HASH_WORDS; i++) {
+               unsigned int n[4], j;
+               int ret;
+
+               ret = sscanf(string, "%02x%02x%02x%02x",
+                            &n[0], &n[1], &n[2], &n[3]);
+               string += 8;
+
+               if (ret == EOF)
+                       break;
+               for (j = 0; j < ret; j++) {
+                       md5s->mask[MD5_HASH_WORDS-i-1] |= (0xFF << (8*j));
+                       md5s->md5[MD5_HASH_WORDS-i-1] |= (n[j] << (8*j));
+               }
+
+               if (ret != 4)
+                       break;
+       }
+}
+
+static void init_pattern(u8 *pattern, unsigned int num_bytes, u64 total)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_bytes; i++) {
+               pattern[i] = 'A' + (total % 26);
+               total /= 26;
+       }
+}
+
+#define PATTERN_BYTES 32
+
+int main(int argc, char *argv[])
+{
+       struct at_pool *atp;
+       struct md5_search md5s;
+       unsigned int i, maxfd, numathreads = argc == 3 ? atoi(argv[2]) : 0;
+       u64 total = 0;
+       fd_set fds;
+       char *cmdline[] = { "./md5_worker", NULL };
+       struct athread *at[numathreads];
+
+       if (numathreads == 0)
+               usage();
+
+       memset(&md5s, 0, sizeof(md5s));
+       parse_hexstring(argv[1], &md5s);
+
+       md5s.num_tries = 1024*1024;
+       md5s.num_bytes = PATTERN_BYTES;
+
+       /* *2 to allow for allocation inefficiency. */
+       atp = at_pool((sizeof(md5s) + PATTERN_BYTES) * (numathreads + 1) * 2);
+       if (!atp)
+               err(1, "Can't create pool");
+
+       /* Free pool on exit. */
+//     talloc_steal(talloc_autofree_context(), atp);
+
+       FD_ZERO(&fds);
+       maxfd = 0;
+       for (i = 0; i < numathreads; i++) {
+               at[i] = at_spawn(atp, NULL, cmdline);
+               if (!at[i])
+                       err(1, "Can't spawn child");
+               FD_SET(at_fd(at[i]), &fds);
+               if (at_fd(at[i]) > maxfd)
+                       maxfd = at_fd(at[i]);
+       }
+
+       for (;;) {
+               struct md5_search *m, *res;
+               fd_set in = fds;
+
+               /* Shouldn't fail! */
+               m = talloc(at_pool_ctx(atp), struct md5_search);
+               *m = md5s;
+               md5s.num_tries++;
+               m->pattern = talloc_array(m, u8, m->num_bytes);
+               init_pattern(m->pattern, m->num_bytes, total);
+
+               select(maxfd+1, &in, NULL, NULL, NULL);
+               for (i = 0; i < numathreads; i++)
+                       if (FD_ISSET(at_fd(at[i]), &in))
+                               break;
+               if (i == numathreads)
+                       errx(1, "Select returned, but noone ready?");
+
+               res = at_read(at[i]);
+               if (res == NULL) {
+                       warn("Thread died?");
+                       FD_CLR(at_fd(at[i]), &fds);
+                       continue;
+               }
+               if (res != INITIAL_POINTER) {
+                       if (res->success) {
+                               printf("Success! '%.*s'\n",
+                                      res->num_bytes, (char *)res->pattern);
+                               exit(0);
+                       }
+                       m->num_tries++;
+                       talloc_free(res);
+               }
+               at_tell(at[i], m);
+               total += m->num_tries;
+       }
+}