void find(vertex *v, command com) /* Procedure checks if BST cointains [com.arg] value. * * * * If current vertex contains [com.arg] value it returns [v->counter] * * into output. If not so, it sends a [com] (FIND) command into suitable * * (right if [com.arg] > [v->value], left otherwise) child, awaits for * * answer and prints it into output. If there is no proper child, * * procedure prints `0`. */ { int result; child_pipe *child; if(com.arg == v->value) { checked_write(1, &v->count, sizeof(v->count)); } else { child = (com.arg > v->value ? &v->right : &v->left); if(child->in == -1) { result = 0; checked_write(1, &result, sizeof(result)); } else { checked_write(child->out, &com, sizeof(com)); checked_read(child->in, &result, sizeof(result)); checked_write(1, &result, sizeof(result)); } } return ; }
int dict_decompress (MemSize BlockSize, int MinCompression, int MinWeakChars, int MinLargeCnt, int MinMediumCnt, int MinSmallCnt, int MinRatio, CALLBACK_FUNC *callback, void *auxdata) { BYTE* In = NULL; // указатель на входные данные BYTE* Out= NULL; // указатель на выходные данные int x; // код произошедшей ошибки for(;;) { int InSize; unsigned OutSize; // количество байт во входном и выходном буфере, соответственно checked_read (&InSize, sizeof(InSize)); if (InSize<0) { // скопируем неупакованные данные In = (BYTE*) BigAlloc(-InSize); checked_read (In, -InSize); checked_write (In, -InSize); BigFreeAndNil(In); } else { // Произвести декодирование и получить размер выходных данных In = (BYTE*) BigAlloc(InSize); Out = (BYTE*) BigAlloc(BlockSize); checked_read (In, InSize); x = DictDecode (In, InSize, Out, &OutSize); //x = DictDecode (InSize, callback, auxdata); // для работы в фиксированном объёме памяти if (x) break; BigFreeAndNil(In); //Out = (BYTE*) realloc (Out, OutSize); -- impossible since we used BigAlloc checked_write (Out, OutSize); BigFreeAndNil(Out); } } finished: BigFreeAndNil(In); BigFreeAndNil(Out); return x<=0? x : FREEARC_ERRCODE_GENERAL; // 0, если всё в порядке, и код ошибки иначе }
void add(vertex *v, command com) /* Procedure * * - Increments counter in [v] if [com.arg] is equal to [v->value] * * or * * - Sends [com] into suitable (right if [com.arg] > [v->value], left * * otherwise) * * and then prints `1` as confirmation message into output. * * * * MUTABLE PARAMETERS: v */ { int result = 1; child_pipe *child; if(com.arg == v->value) { v->count++; checked_write(1, &result, sizeof(result)); return ; } child = (com.arg > v->value ? &v->right : &v->left); if(child->in == -1) add_fork(child, com.arg, v); else { checked_write(child->out, &com, sizeof(com)); checked_read(child->in, &result, sizeof(result)); checked_write(1, &result, sizeof(result)); } return ; }
static void _write_escaped(int fd, char* buf, ssize_t n) { uint8_t out[2]; size_t escaped = 0; while(n--) { char c = *buf++; switch(c) { case LINE_FRAME_DELIMITER: out[0] = LINE_ESC_CHAR; out[1] = (LINE_FRAME_DELIMITER ^ 0x20); checked_write(fd, out, 2); escaped++; break; case LINE_ESC_CHAR: out[0] = LINE_ESC_CHAR; out[1] = (LINE_ESC_CHAR ^ 0x20); checked_write(fd, out, 2); escaped++; break; default: checked_write(fd, &c, 1); } } }
int dict_compress (MemSize BlockSize, int MinCompression, int MinWeakChars, int MinLargeCnt, int MinMediumCnt, int MinSmallCnt, int MinRatio, CALLBACK_FUNC *callback, void *auxdata) { BYTE* In = NULL; // указатель на входные данные BYTE* Out= NULL; // указатель на выходные данные int x; // код произошедшей ошибки while ( (x = callback ("read", (In = (BYTE*) BigAlloc(BlockSize)), BlockSize, auxdata)) > 0 ) { unsigned InSize, OutSize; // количество байт во входном и выходном буфере, соответственно InSize=x; // impossible: In = (BYTE*) realloc(In,InSize=x); x = DictEncode(In,InSize,&Out,&OutSize,MinWeakChars,MinLargeCnt,MinMediumCnt,MinSmallCnt,MinRatio); if (x || OutSize/MinCompression>=InSize/100) { // упаковать данные [достаточно хорошо] не удалось, запишем вместо них исходные данные int WrSize=-InSize; BigFreeAndNil(Out); // Записать исходный блок и выйти, если при записи произошла ошибка/больше данных не нужно checked_write (&WrSize, sizeof(WrSize)); checked_write (In, InSize); BigFreeAndNil(In); } else { // данные успешно упакованы, можно освободить входной буфер прежде чем записывать их // (чтобы освободить больше памяти для следующего алгоритма в цепочке алгоритмов сжатия) BigFreeAndNil(In); // Записать сжатый блок и выйти, если при записи произошла ошибка/больше данных не нужно checked_write (&OutSize, sizeof(OutSize)); checked_write (Out, OutSize); BigFreeAndNil(Out); } } finished: BigFreeAndNil(In); BigFreeAndNil(Out); return x; // 0, если всё в порядке, и код ошибки иначе }
static void _send_hello(int serial_fd, serial_t *serial, unsigned type) { char delim = LINE_FRAME_DELIMITER; char head[] = { LINE_FRAME_DELIMITER, LINE_ESC_CHAR, (type ^ 0x20) }; checked_write(serial_fd, head, sizeof(head)); checked_write(serial_fd, serial->local_l2_addr, 6); checked_write(serial_fd, &delim, 1); }
void walk_ask_child_val(const child_pipe *child) /* Procedure awaits for signal from parent, than asks [child] for one value * * and sends it to the output. Procedure assuming that process is currently * * WALKing through tree values. */ { int count, val = 1, signal; checked_read(0, &signal, sizeof(signal)); checked_write(child->out, &val, sizeof(val)); checked_read(child->in, &count, sizeof(count)); checked_read(child->in, &val, sizeof(val)); checked_write(1, &count, sizeof(count)); checked_write(1, &val, sizeof(val)); return ; }
void add_fork(child_pipe *child, int value, vertex *v) /* Procedure forks vertex. Child process will be initialized with [value] as * * value, count equal to one and pipes duped into {0, 1} descriptors. * * Parent process populates [child] structure with analogical descriptors * * providing way to communication. Then sends confirmation signal into * * output. * * * * MUTABLE PARAMETERS: v, child */ { int result = 1; int *in = make_pipe(), *out = make_pipe(); switch(fork()) { case -1: syserr("fork failed"); break; case 0: setup_child(in, out); vertex_init(v, value); break; default: setup_parent(child, in, out); checked_write(1, &result, sizeof(result)); break; } free(in); free(out); return ; }
void walk(const vertex *v) /* Procedure calculates size of the tree, sends its into output, and than * * sends values from the tree in infix order. Every value transmition have * * to be invoked by parent. */ { int lcount = 0, rcount = 0, count, i, signal; walk_ask_childs_count(v, &lcount, &rcount); count = lcount + rcount + 1; checked_write(1, &count, sizeof(count)); for(i = 0; i < lcount; i++) walk_ask_child_val(&v->left); checked_read(0, &signal, sizeof(signal)); checked_write(1, &v->count, sizeof(v->count)); checked_write(1, &v->value, sizeof(v->value)); for(i = 0; i < rcount; i++) walk_ask_child_val(&v->right); return ; }
void flush() { if (ptr != buffer) { checked_write(fh, buffer, (size32_t)(ptr-buffer)); ptr = buffer; } }
void walk_ask_childs_count(const vertex *v, int *lcount, int *rcount) /* Procedure sends a WALK command to the children, then reads sizes of * * subtrees and puts them in [lcount] and [rcount]. * * * * MUTABLE PARAMETERS: lcount, rcount */ { command com; com.code = COM_WALK; if(v->left.in != -1) checked_write(v->left.out, &com, sizeof(com)); if(v->right.in != -1) checked_write(v->right.out, &com, sizeof(com)); /* Reading from the first child before sending request to the second one * * will freeze the program, so the calculation would not be parallel. * * Although, it is not very lucrative in this particular case, it * * would be for more complex vertex operations. */ if(v->left.in != -1) checked_read(v->left.in, lcount, sizeof(int)); if(v->right.in != -1) checked_read(v->right.in, rcount, sizeof(int)); return ; }
void destroy_child(child_pipe *child) { command com; com.code = COM_STOP; checked_write(child->out, &com, sizeof(com)); close(child->in); close(child->out); if(wait(0) == -1) syserr("wait failed"); return ; }
void *thread2_func(void *arg) { int i; char buf[512]; for(i=0;i<20;i++) { snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg); checked_write(1, buf, strlen(buf)); usleep(150 * 1000); } return NULL; }
static void _write_escaped(int fd, char* buf, ssize_t n) { /* * Certain USB-to-UART adapters/drivers will immediately send a USB packet * with a single byte instead of buffering internally when the application * does writes one byte at a time. Since USB Full Speed can only send 1 * packet per 1 ms, this causes huge latencies for the network, because each * byte of data will then add at least 1 ms on the latency. * Observed on NXP OpenSDAv2 (Kinetis FRDM boards), both CMSIS/mbed DAPlink * and Segger Jlink firmware are affected. */ /* Our workaround is to prepare the data to send in a local buffer and then * call write() on the buffer instead of one char at a time */ uint8_t out[SERIAL_BUFFER_SIZE]; size_t escaped = 0; size_t buffered = 0; while(n--) { unsigned char c = *buf++; if (c == LINE_FRAME_DELIMITER || c == LINE_ESC_CHAR) { out[buffered++] = LINE_ESC_CHAR; c ^= 0x20; ++escaped; if (buffered >= SERIAL_BUFFER_SIZE) { checked_write(fd, out, buffered); buffered = 0; } } out[buffered++] = c; if (buffered >= SERIAL_BUFFER_SIZE) { checked_write(fd, out, buffered); buffered = 0; } } if (buffered) { checked_write(fd, out, buffered); } }
void putBytes(const void *src, size32_t _size) { fpos += _size; size32_t left = remaining(); if (_size>left) { if (ptr!=buffer) { // don't buffer if entire block memcpy(ptr, src, left); ptr += left; src = (char *)src + left; _size -= left; flush(); left = bufSize; } while (_size>=bufSize) // write out directly { checked_write(fh, src, bufSize); // stick to writing bufSize blocks src = (char *)src + bufSize; _size -= bufSize; } } memcpy(ptr, src, _size); ptr += _size; }
void CUnbufferedReadWriteSeq::putn(const void *src, unsigned n) { checked_write(fh, src, size*n); fpos += size*n; }
void CUnbufferedReadWriteSeq::put(const void *src) { checked_write(fh, src, size); fpos += size; }
int main(int argc, char *argv[]) { char inbuf[MTU]; unsigned baudrate = BAUDRATE_DEFAULT; serial_t serial = {0}; if (argc < 3) { usage(); return 1; } if (argc >= 4 && _parse_baudrate(argv[3], &baudrate) == -1) { fprintf(stderr, "Invalid baudrate specified: %s\n", argv[3]); return 1; } char ifname[IFNAMSIZ]; strncpy(ifname, argv[1], IFNAMSIZ); int tap_fd = tun_alloc(ifname, IFF_TAP | IFF_NO_PI); if (tap_fd < 0) { return 1; } int serial_fd = open(argv[2], O_RDWR | O_NOCTTY | O_SYNC); if (serial_fd < 0) { fprintf(stderr, "Error opening serial device %s\n", argv[2]); return 1; } set_serial_attribs(serial_fd, baudrate, 0); set_blocking(serial_fd, 1); fd_set readfds; int max_fd = (serial_fd > tap_fd) ? serial_fd : tap_fd; fprintf(stderr, "----> ethos: sending hello.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); fprintf(stderr, "----> ethos: activating serial pass through.\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO); while(1) { int activity; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); FD_SET(tap_fd, &readfds); FD_SET(serial_fd, &readfds); activity = select( max_fd + 1 , &readfds , NULL , NULL , NULL); if ((activity < 0) && (errno != EINTR)) { perror("select error"); } if (FD_ISSET(serial_fd, &readfds)) { ssize_t n = read(serial_fd, inbuf, sizeof(inbuf)); if (n > 0) { char *ptr = inbuf; while (n--) { size_t res = _serial_handle_byte(&serial, *ptr++); if (res) { switch (serial.frametype) { case LINE_FRAME_TYPE_DATA: checked_write(tap_fd, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_TEXT: checked_write(STDOUT_FILENO, serial.frame, serial.framebytes); break; case LINE_FRAME_TYPE_HELLO: case LINE_FRAME_TYPE_HELLO_REPLY: if (serial.framebytes == 6) { memcpy(serial.remote_l2_addr, serial.frame, 6); if (serial.frametype == LINE_FRAME_TYPE_HELLO) { fprintf(stderr, "----> ethos: hello received\n"); _send_hello(serial_fd, &serial, LINE_FRAME_TYPE_HELLO_REPLY); } else { fprintf(stderr, "----> ethos: hello reply received\n"); } _clear_neighbor_cache(ifname); } break; } memset(&serial, '\0', sizeof(serial)); } } } else { fprintf(stderr, "lost serial connection.\n"); exit(1); } } if (FD_ISSET(tap_fd, &readfds)) { ssize_t res = read(tap_fd, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from tap device. res=%zi\n", res); continue; } char delim = LINE_FRAME_DELIMITER; checked_write(serial_fd, &delim, 1); _write_escaped(serial_fd, inbuf, res); checked_write(serial_fd, &delim, 1); } if (FD_ISSET(STDIN_FILENO, &readfds)) { ssize_t res = read(STDIN_FILENO, inbuf, sizeof(inbuf)); if (res <= 0) { fprintf(stderr, "error reading from stdio. res=%zi\n", res); continue; } if (res) { char delim = LINE_FRAME_DELIMITER; char head[] = { LINE_FRAME_DELIMITER, LINE_ESC_CHAR, (LINE_FRAME_TYPE_TEXT ^ 0x20) }; checked_write(serial_fd, head, sizeof(head)); _write_escaped(serial_fd, inbuf, res); checked_write(serial_fd, &delim, 1); } } } return 0; }