/** * Sends a cTCP segment to a destination associated with the provided * connection object. * * conn: Connection object. * segment: Pointer to cTCP segment to send. * len: Length of the segment (including the cTCP header and data). * * returns: The number of bytes actually sent, 0 if nothing was sent, -1 if * there in an error. */ int conn_send(conn_t *conn, ctcp_segment_t *segment, size_t len) { ASSERT_CONN; /* Check parameters. */ if (conn == NULL || segment == NULL) { fprintf(stderr, "[ERROR] NULL parameters in conn_send\n"); return -1; } /* Make a copy of the segment first. */ ctcp_segment_t *segment_copy = calloc(len, 1); memcpy(segment_copy, segment, len); /* Fork process off in order to do unreliability. Keep track of whether we are forked or not. */ int fork_level = 0; bool am_i_forked = 0; /* Segment drop. Don't send the segment. */ if ((test_debug_on && !tester_did_unreliable && opt_drop) || (!test_debug_on && rand_percent(fork_level) < opt_drop)) { tester_did_unreliable = true; if (DEBUG) { fprintf(stderr, "[DEBUG] Dropping segment\n"); print_hdr_ctcp(segment_copy); } free(segment_copy); return len; } /* Segment duplication. Fork another process to send the other segment. */ if ((test_debug_on && !tester_did_unreliable && opt_duplicate) || (!test_debug_on && rand_percent(fork_level) < opt_duplicate)) { tester_did_unreliable = true; if (DEBUG) { fprintf(stderr, "[DEBUG] Duplicating segment\n"); print_hdr_ctcp(segment_copy); } if (fork() == 0) { am_i_forked = 1; fork_level++; } } /* Segment delay. Fork another process to delay the segment, and kill the current one. */ if ((test_debug_on && !tester_did_unreliable && opt_delay) || (!test_debug_on && rand_percent(fork_level) < opt_delay)) { tester_did_unreliable = true; if (DEBUG) { fprintf(stderr, "[DEBUG] Delaying segment\n"); print_hdr_ctcp(segment_copy); } /* Forked process. Sleep for a bit. */ if (fork() == 0) { am_i_forked = 1; fork_level++; sleep(rand() % 5); } /* Original process. */ else { free(segment_copy); return len; } } /* Segment corruption. Flip bits in the segment after the TCP flags (to avoid corrupting the flags, which may cause problems). */ bool do_corrupt = rand_percent(fork_level) < opt_corrupt; uint16_t data_length = len - sizeof(ctcp_segment_t) + sizeof(uint32_t); uint16_t rand_bit = rand() % (data_length * 8 - 1) + (sizeof(ctcp_segment_t) - sizeof(uint32_t)) * 8; if ((test_debug_on && !tester_did_unreliable && opt_corrupt) || (!test_debug_on && do_corrupt)) { tester_did_unreliable = true; if (DEBUG) { fprintf(stderr, "[DEBUG] Corrupting segment\n"); print_hdr_ctcp(segment_copy); } flipbit(segment_copy, rand_bit); } uint16_t data_len = len - sizeof(ctcp_segment_t); uint16_t total_len = FULL_HDR_SIZE + data_len; if (log_file != -1 || test_debug_on) { log_segment(log_file, config->ip_addr, config->port, conn, segment_copy, len, true, unix_socket); } /* Convert from a cTCP segment to a real one and finally send the segment. */ char *pkt = convert_to_datagram(conn, segment_copy, len); int n = send_pkt(conn, config->socket, pkt, total_len, 0); if (DEBUG) { fprintf(stderr, "[DEBUG] Sent segment\n"); print_hdr_ctcp(segment_copy); } free(pkt); free(segment_copy); /* Kill forked process. */ if (am_i_forked) exit(0); /* Return number of bytes sent. Need to subtract some because the return value is actually the size of the TCP segment instead of the cTCP segment. */ if (n >= (long int)TCP_HDR_SIZE) return n - (TCP_HDR_SIZE + IP_HDR_SIZE - sizeof(ctcp_segment_t)); return n; }
int main(){ int mv = setbit (5,1); int nnv = flipbit(mv, 2); printf("%x..%x\n", mv, nnv); return 0; }