diff --git a/generation.c b/generation.c index 65b0632..f8a9b1e 100644 --- a/generation.c +++ b/generation.c @@ -1,28 +1,61 @@ /* @file generation.c */ +#include #include #include #include #include +#include #include -int reproduce(void *pic_address, int *pic_size) +#define MAX_LEN 1024 +#define PORT 5000 + +int reproduce(void *pic_address, int pic_size) { int status = 0; - printf("{\"address\": \"%p\",\"length\": \"%d\"}\n", pic_address, - *pic_size); + printf("{\"address\":\"%p\",\"size\":\"%d\"}\n", pic_address, pic_size); + + struct sockaddr_in server; + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + server.sin_family = AF_INET; + server.sin_port = htons(PORT); + int sock = socket(AF_INET, SOCK_STREAM, 0); + + status = connect(sock, (struct sockaddr *)&server, sizeof(server)); + + status = send(sock, pic_address, pic_size, 0); status = 1; CLONE_CLEANUP: + if (sock) + { + close(sock); + } + return status; } -int generation(void *child, int *child_len) +int generation(void) { int status = 0; + char reply[MAX_LEN]; + struct sockaddr_in server; + server.sin_addr.s_addr = inet_addr("127.0.0.1"); + server.sin_family = AF_INET; + server.sin_port = htons(PORT); + int sock = socket(AF_INET, SOCK_STREAM, 0); + + printf("connecting\n"); + + status = connect(sock, (struct sockaddr *)&server, sizeof(server)); + + status = recv(sock, reply, MAX_LEN, 0); + + int child_len = (int)reply; int prot = (PROT_READ | PROT_WRITE | PROT_EXEC); int flags = (MAP_ANON | MAP_PRIVATE); @@ -34,36 +67,55 @@ int generation(void *child, int *child_len) goto GEN_CLEANUP; } - memcpy(child, pic_buffer, *child_len); + int iter = child_len; + while (1) + { + status = recv(sock, reply, MAX_LEN, 0); + + if (!status) + { + break; + } + + if ((status + iter) > child_len) + { + break; + } + + memcpy(&pic_buffer[iter - child_len], reply, status); + + iter -= status; + } int (*reproduce_function)(void *, int) = reproduce; - void (*pic_function)(void *, int *, void *) = pic_buffer; + void (*pic_function)(void *, int, void *) = pic_buffer; pic_function(pic_buffer, child_len, reproduce_function); status = 1; GEN_CLEANUP: + if (sock) + { + close(sock); + } + return status; } -int gen_fork(void *child, int *child_len) +int main(int argc, const char **argv) { pid_t process_id; int status = 0; - *child_len = 999; - - return 0; - process_id = fork(); if (0 == process_id) { - status = generation(child, child_len); + status = generation(); if (status) { - return 0; + return 1; } } diff --git a/run.py b/run.py index 7a20037..f2fd7bd 100755 --- a/run.py +++ b/run.py @@ -1,21 +1,82 @@ #! /usr/bin/env python3 +from datetime import datetime from random import randint +from threading import Thread, Lock +from time import sleep import binascii -import ctypes import logging import os +import socket import subprocess logging.getLogger(__name__) -class Sins: + +class Server: + children = list() + + host = ('127.0.0.1', 5000) + sock = socket.socket() + sock.bind(host) + sock.listen(1) + client = None + + def __init__(self): + self.lock = Lock() + self.thread = Thread(target=self.recv) + self.thread.start() + + def __enter__(self): + self.client, address = self.sock.accept() + logging.info('address [{}]'.format(address)) + return self + + def __exit__(self, *args): + return + + def __del__(self): + self.sock.shutdown(socket.SHUT_RD) + self.sock.close() + + def recv(self, size: int=int()) -> list: + while self.client: + try: + child = self.client.recv(size) + except OSError as error: + logging.error('socket error [{}]'.format(error)) + break + + if not child: + continue + + self.lock.acquire() + self.children.append((child, datetime.utcnow())) + self.lock.release() + + logging.info('recevied child') + + def send(self, data: bytes): + if not self.client: + raise BrokenPipeError('client connection missing') + + self.client.sendall(data) + + @property + def children(self): + if not self.children: + return None + + children = self.children + self.children = list() + return children + + +class Genorator: seed = bytes() def __init__(self, *, parent: str, seed: str=str(), run_dir: str=str()): - self.parent = ctypes.CDLL(parent) - self.parent.gen_fork.restype = ctypes.c_int - self.parent.gen_fork.argtypes = [ctypes.c_void_p, ctypes.c_void_p] + self.parent = os.path.abspath(parent) if seed: with open(seed, 'rb') as seed_file: @@ -30,15 +91,15 @@ class Sins: self.run_dir = run_dir - child = self.generation( - parent=self.parent, - scrap=self.seed, - cwd=self.run_dir) + parent_args = { + 'parent': self.parent, + 'scrap': self.seed, + 'cwd': self.run_dir} - if child: - logging.info(child) + self.thread = Thread(target=self.generation, kwargs=parent_args) + self.thread.start() - def scrap_recent(self, *, run_dir: str)->str: + def scrap_recent(self, *, run_dir: str) -> str: scraps = sorted(os.listdir(run_dir)) if scraps: @@ -46,20 +107,30 @@ class Sins: return None - def generation(self, *, parent: ctypes.CDLL, scrap: bytes, cwd: str): + def generation(self, *, parent: str, scrap: bytes, cwd: str): offset = randint(0, len(scrap)) flip = randint(0, 255) - scrap_len = len(scrap) - logging.info('scrap_length [{}]'.format(scrap_len)) logging.info('scrap\n{}'.format(binascii.b2a_hex(scrap))) - status = parent.gen_fork(scrap, scrap_len) + cmd = [parent] + logging.info(cmd) - logging.info('status {}'.format(status)) - logging.info('scrap_length [{}]'.format(scrap_len)) - logging.info('scrap\n{}'.format(binascii.b2a_hex(scrap))) + proc = subprocess.Popen( + [parent], + cwd=cwd) + with Server() as server: + server.send(bytes(len(scrap))) + server.send(scrap) + + logging.info('child send') + + server.recv() + children = server.children + + if children: + raise Exception(children) def hex_dumps(scrap_dir): @@ -84,6 +155,19 @@ def hex_dumps(scrap_dir): file_out.writelines('\'\\x{:02X}\',\n'.format(each)) +def provision(): + provision = ['sudo', 'sh', 'provision-ubuntu.sh'] + prov_proc = subprocess.run(provision) + + os.environ['CC'] = 'clang' + waf = [sys.executable, 'waf.py', 'configure'] + waf_proc = subprocess.run(waf) + + +def build(): + waf = [sys.executable, 'waf.py', 'build'] + waf_proc = subprocess.run(waf) + if __name__ == '__main__': import argparse import sys @@ -98,7 +182,7 @@ if __name__ == '__main__': parser.add_argument('-logfile', help='log to file.') parser.add_argument('-seed', default='build/seed.asm.2.o', help='path to PIC image.') - parser.add_argument('-parent', default='build/libgeneration.so', + parser.add_argument('-parent', default='build/generation.elf', help='path to generation lib.') parser.add_argument('-dir', default='sandbox', help='path to execution directory.') @@ -107,7 +191,8 @@ if __name__ == '__main__': args = parser.parse_args() logger = logging.getLogger() - logger.setLevel(logging.DEBUG) if args.verbose else logger.setLevel(logging.INFO) + logger.setLevel( + logging.DEBUG) if args.verbose else logger.setLevel(logging.INFO) formatter = logging.Formatter('# %(filename)s:%(lineno)s\n%(message)s') stream_handler = logging.StreamHandler() @@ -122,20 +207,13 @@ if __name__ == '__main__': logging.info(args) if args.provision: - provision = ['sudo', 'sh', 'provision-ubuntu.sh'] - prov_proc = subprocess.run(provision) - - os.environ['CC'] = 'clang' - waf = [sys.executable, 'waf.py', 'configure'] - waf_proc = subprocess.run(waf) + provision() elif args.build: - waf = [sys.executable, 'waf.py', 'build'] - waf_proc = subprocess.run(waf) - logging.info(waf_proc.stdout) + build() elif args.dumps: hex_dumps(args.dir) else: - sins = Sins(parent=args.parent, seed=args.seed, run_dir=args.dir) + gen = Genorator(parent=args.parent, seed=args.seed, run_dir=args.dir) diff --git a/wscript b/wscript index 682663d..0e7c3d3 100644 --- a/wscript +++ b/wscript @@ -14,9 +14,9 @@ def configure(conf): def build(bld): - bld.shlib( + bld.program( source='generation.c', - target='generation', + target='generation.elf', cflags=['-g', '-std=gnu11'] ) bld(features='asm', source='seed.asm', target='seed')