static void partial_recv(uint32_t* readoff, uint32_t* writeoff, uint32_t bufsize, char* readbuf, struct message_header* message, int* current_bytes, int target_bytes) { while(*current_bytes < target_bytes) { if(drain_events(singleton_screen->socketfd) == -1) { printf("Socket error draining events\n"); exit(1); } int this_recv = recvsome(readoff, writeoff, bufsize, readbuf, (void*)((char*)message + *current_bytes), target_bytes - *current_bytes); if(this_recv == 0) { if(analyse_waits) printf("Wait: receive buffer empty\n"); if(wait_for_rx_not_empty() == -1) { printf("Socket error waiting for rx-not-empty\n"); exit(1); } } discard_ring_bytes(readoff, bufsize, this_recv); *current_bytes += this_recv; } }
int main(int argc, char const *argv[]) { int qflag = 0; char const *host = 0; unsigned short port = 0; args = argv; /* parse arguments */ while (argv[1]) { if (!strcmp(argv[1], "-q")) { if (!argv[2]) { usage(); } qflag = atoi(argv[2]); if (qflag <= 0) { usage(); } ++argv; --argc; } else if (argv[1][0] == '-') { usage(); } else { if (!host) { host = argv[1]; } else if (!port) { int i = atoi(argv[1]); if (i < 1 || i > 65535) { usage(); } port = (unsigned short)i; } } ++argv; --argc; } if (!host) { usage(); } if (!port) { usage(); } /* connect to host */ char buf[8192]; int r, s = connect_to(host, port); /* do an echo thing */ while (true) { r = read(0, buf, sizeof(buf)); if (r < 0) { perror("read(stdin)"); exit(1); } if (r == 0) { break; } int off = 0; while (r > off) { int q = send(s, &buf[off], r-off, 0); if (q < 0) { perror("send()"); exit(1); } if (q == 0) { break; } off += q; } r = recvsome(s, buf, sizeof(buf)); if (r == -2) { // closed break; } if (r < 0) { perror("recv()"); exit(1); } if (r > 0) { if (write(1, buf, r) < 0) { perror("write()"); exit(1); } } } shutdown(s, SHUT_WR); time_t now, then; time(&now); then = now + qflag; r = 1; while (now <= then || r > 0) { r = recvsome(s, buf, sizeof(buf)); if (r == -2) { // closed break; } if (r < 0) { perror("recv()"); exit(1); } if (r > 0) { if (write(1, buf, r) < 0) { perror("write()"); exit(1); } } time(&now); } close(s); return 0; }
void discard_asynchronous_messages(int block) { uint32_t bufsize = ((uint32_t*)singleton_screen->rx_buffer)[0]; uint32_t* readoff = &(((uint32_t*)singleton_screen->rx_buffer)[1]); uint32_t* writeoff = &(((uint32_t*)singleton_screen->rx_buffer)[2]); char* readbuf = (char*)&(((uint32_t*)singleton_screen->rx_buffer)[3]); if(block) { DBG("Discarding async messages (blocking)\n"); } else { DBG("Discarding async messages (non-blocking)\n"); } // WARNING HERE: This method assumes that no async failure notification // is bigger than the ring. If one were, we would wait fruitlessly until // the entire thing were present before deleting it from the ring. /* If block is set, we should wait until a synchronous message arrives. If block is not set, we should return as soon as we're short of data. */ int need_more_bytes = 0; while(1) { struct message_header head; if(need_more_bytes) { if(block) { DBG("Insufficient data, but invoked blocking: sleeping\n"); wait_for_rx_not_empty(); need_more_bytes = 0; DBG("Woken\n"); } else { DBG("Non-blocking discard_async_messages: exiting\n"); return; } } if(drain_events(singleton_screen->socketfd) == -1) { printf("Socket error draining events in discard_async\n"); return; } int bytes_peeked = recvsome(readoff, writeoff, bufsize, readbuf, (char*)&head, sizeof(struct message_header)); if(bytes_peeked < sizeof(struct message_header)) { DBG(" Less than a header available (%d bytes); exiting\n", bytes_peeked); need_more_bytes = 1; continue; } if(!message_is_asynchronous(head.opcode)) { DBG(" Next message (%s) not asynchronous: exiting\n", optotext(head.opcode)); return; } int bytes_available = read_avail(readoff, writeoff, bufsize); if(bytes_available < head.length) { DBG(" Message had length %d but only %d available: exiting\n", head.length, bytes_available); need_more_bytes = 1; continue; } char* message_proper = malloc(head.length); if(!message_proper) { printf("OOM checking for asynchronous failures\n"); return; } int bytes_read = recvsome(readoff, writeoff, bufsize, readbuf, message_proper, head.length); if(bytes_read < head.length) { printf("BUG! read_avail returned %d, yet we could only actually read %d bytes\n", bytes_available, bytes_read); free(message_proper); return; } DBG(" Got a message: checking its result\n"); check_async_result(message_proper, head.opcode); free(message_proper); discard_ring_bytes(readoff, bufsize, head.length); } }