Пример #1
0
pid_t
sampling_fork ()
{
    kern_return_t       err;
    mach_port_t         parent_recv_port = MACH_PORT_NULL;
    mach_port_t         child_recv_port = MACH_PORT_NULL;

    if (setup_recv_port (&parent_recv_port) != 0)
        return -1;
    err = task_set_bootstrap_port (mach_task_self (), parent_recv_port);
    CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:");

    pid_t               pid;
    switch (pid = fork ()) {
    case -1:
        err = mach_port_deallocate (mach_task_self(), parent_recv_port);
        CHECK_MACH_ERROR (err, "mach_port_deallocate failed:");
        return pid;
    case 0: /* child */
        err = task_get_bootstrap_port (mach_task_self (), &parent_recv_port);
        CHECK_MACH_ERROR (err, "task_get_bootstrap_port failed:");
        if (setup_recv_port (&child_recv_port) != 0)
            return -1;
        if (send_port (parent_recv_port, mach_task_self ()) != 0)
            return -1;
        if (send_port (parent_recv_port, child_recv_port) != 0)
            return -1;
        if (recv_port (child_recv_port, &bootstrap_port) != 0)
            return -1;
        err = task_set_bootstrap_port (mach_task_self (), bootstrap_port);
        CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:");
        break;
    default: /* parent */
        err = task_set_bootstrap_port (mach_task_self (), bootstrap_port);
        CHECK_MACH_ERROR (err, "task_set_bootstrap_port failed:");
        if (recv_port (parent_recv_port, &child_task) != 0)
            return -1;
        if (recv_port (parent_recv_port, &child_recv_port) != 0)
            return -1;
        if (send_port (child_recv_port, bootstrap_port) != 0)
            return -1;
        err = mach_port_deallocate (mach_task_self(), parent_recv_port);
        CHECK_MACH_ERROR (err, "mach_port_deallocate failed:");
        break;
    }

    return pid;
}
Пример #2
0
/* Get the Mach port upon which we'll receive requests from our parent */
static mach_port_t get_hex_fiend_receive_port(void) {
    mach_port_t launchdReceivePort = MACH_PORT_NULL, hexFiendReceivePort = MACH_PORT_NULL;
    launch_data_t resp = NULL, machServices = NULL, msg = NULL, service = NULL;
    int err = 0;
    
    /* Check in with launchd */
    msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
	resp = launch_msg(msg);
	if (resp == NULL) {
		if (ERR_FILE) fprintf(ERR_FILE, "launch_msg(): %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	}
    
    /* Guard against errors */
	if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) {
		errno = launch_data_get_errno(resp);
		if (ERR_FILE) fprintf(ERR_FILE, "launch_msg() response: %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	}
    
    /* Get our MachServices dictioanry */
	machServices = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_MACHSERVICES);
    
    /* Die if it's not there */
	if (machServices == NULL) {
		if (ERR_FILE) fprintf(ERR_FILE, "No mach services found!\n");
		exit(EXIT_FAILURE);
	}
    
    /* Get the one we care about */
    service = launch_data_dict_lookup(machServices, kPrivilegedHelperLaunchdLabel);
    if (service == NULL) {
		if (ERR_FILE) fprintf(ERR_FILE, "Mach service %s not found!\n", kPrivilegedHelperLaunchdLabel);
		exit(EXIT_FAILURE);
    }
    
    /* Make sure we've got a mach port */
    if (launch_data_get_type(service) != LAUNCH_DATA_MACHPORT) {
        if (ERR_FILE) fprintf(ERR_FILE, "%s: not a mach port\n", kPrivilegedHelperLaunchdLabel);
        exit(EXIT_FAILURE);
    }
    
    /* Now get the launchd mach port */
    launchdReceivePort = launch_data_get_machport(service);
    
    /* We don't want to use launchd's port - we want one from Hex Fiend (so we can get a no senders notification). So receive a port from Hex Fiend on our launchd port. */
    hexFiendReceivePort = MACH_PORT_NULL;
    if ((err = recv_port(launchdReceivePort, &hexFiendReceivePort))) {
        if (ERR_FILE) fprintf(ERR_FILE, "recv_port() failed with Mach error %d\n", err);
        exit(EXIT_FAILURE);
    }
    
    /* Make sure we got something back */
    if (hexFiendReceivePort == MACH_PORT_NULL) {
        if (ERR_FILE) fprintf(ERR_FILE, "recv_port() returned a null Mach port\n");
        exit(EXIT_FAILURE);
    }
    
    /* Clean up */
    if (msg) launch_data_free(msg);
    if (resp) launch_data_free(resp);
    
    return hexFiendReceivePort;
}
Пример #3
0
int main(int argc, char *argv[]) {

    if(argc != 7) {
        printf("usage: host port R stream_id window_size filename\n");
        exit(0);
    }

    char *endptr;
    long R = strtol(argv[3], &endptr, 10);
    char *stream_id = argv[4];
    int window_size = strtol(argv[5], NULL, 10);

    if(endptr != (argv[3] + strlen(argv[3]))) {
        fprintf(stderr, "R must be an integer (milliseconds).\n");
        exit(1);
    }


    struct addrinfo* p;
    int send_sock = send_port(argv[1], argv[2], &p);
    int recv_sock = recv_port(NULL, argv[2]);// TODO fix


    printf("Stream id = %s\n", stream_id);
    ee122_packet pkt;
    pkt.R = R;
    pkt.stream = *stream_id;
    printf("pkt.stream = %c\n", pkt.stream);
    pkt.avg_len = 0;
    pkt.window_size = window_size;

    int read_count;
    char fbuff[sizeof(pkt.payload)];
    memset(fbuff,0,sizeof(fbuff));
    FILE *fd = fopen(argv[6], "rb");
    if(NULL == fd) {
        fprintf(stderr, "fopen() error\n");
        return 1;
    }

    ee122_packet rcv_pkt;

    struct timespec sleep_spec;
    sleep_spec.tv_sec = 0;

    struct timeval curr_time, start_time, last_generated, diff_time;
    gettimeofday(&start_time, NULL);
    gettimeofday(&last_generated, NULL);

    int seq_no = 0;
    int available_window = window_size;

    struct timeval timeouts[window_size+1];
    ee122_packet packets[window_size+1];

    int i;
    struct timeval zero_timeout;
    zero_timeout.tv_usec = 0;
    zero_timeout.tv_sec = 0;

    for(i = 0; i < window_size+1; i++) {
        memcpy(&timeouts[i], &zero_timeout, sizeof(zero_timeout));
    }

    bytequeue q;
    bytequeue_init(&q, sizeof(ee122_packet), window_size);

    float rtt = 400*1000;
    char buff[sizeof(ee122_packet)];

    float next_wait = rand_poisson(R);
    printf("next wait: %f\n", next_wait);

    int bytes_read;
    struct sockaddr src_addr;
    int src_len = sizeof(src_addr);
    int last_received = -1;
    unsigned total_attempts = 0;
    unsigned seconds = 0;
    unsigned errors = 0;

    while (1) {
        gettimeofday(&curr_time, NULL);

        timeval_subtract(&diff_time, &curr_time, &start_time);

        if (diff_time.tv_sec * 1000000 + diff_time.tv_usec > seconds * 1000000) {
            printf("%f,%d\n", rtt, seconds);
            seconds++;
        }
        // Stop sending after 60 seconds
        if(diff_time.tv_sec * 1000000 + diff_time.tv_usec > 60*1000000) {
            break;
        }

        // Check timeouts. If timeout reached, retransmit that packet and all following.
        int retransmitting = -1;
        int i;
        for(i=0; i < window_size+1; i++) {
            struct timeval timeout = timeouts[i];
            if(timeout.tv_sec == 0 && timeout.tv_usec == 0) continue;

            timeval_subtract(&diff_time, &curr_time, &timeouts[i]);
            if(diff_time.tv_sec * 1000000 + diff_time.tv_usec > rtt) {
                retransmitting = i;
                break;
            }
        }

        if(retransmitting != -1) {
            i = retransmitting;
            do {
                struct timeval timeout = timeouts[i];
                if(timeout.tv_sec == 0 && timeout.tv_usec == 0) {
                    i = (i + 1) % (window_size+1);
                    continue;
                }
                //printf("Retransmitting seq_no == %d, stream == %c, rtt == %f\n", packets[i].seq_number, packets[i].stream, rtt);
                // Reset the timeout for this packet and send.
                gettimeofday(&(timeouts[i]), NULL);
                serialize_packet(buff, packets[i]);
                sendto(send_sock, buff, sizeof(packets[i]), 0, p->ai_addr, p->ai_addrlen);
                i = (i + 1) % (window_size+1);
                total_attempts++;
                errors++;
            } while (i != retransmitting);
        }

        // Check if new packet should be generated by now
        timeval_subtract(&diff_time, &curr_time, &last_generated);
        if(diff_time.tv_sec * 1000000 + diff_time.tv_usec > next_wait * 1000) {
            // Enqueue the packet.
            bytequeue_push(&q, &pkt);
            next_wait = rand_poisson(R);
        }

        // Read from socket. Increase available window for each ack received
        int bytes_read = recvfrom(recv_sock, buff, sizeof(ee122_packet), 0, &src_addr, &src_len);
        if(bytes_read > 0) {
            rcv_pkt = deserialize_packet(buff);
            if(rcv_pkt.stream == 'Z' && rcv_pkt.seq_number == (last_received + 1) % (window_size+1)) {
                struct timeval timeout_start = rcv_pkt.timestamp;

                // Learn RTT
                timeval_subtract(&diff_time, &curr_time, &timeout_start);
                //printf("RTT difftime, tv_sec == %d, tv_usec == %d\n", diff_time.tv_sec, diff_time.tv_usec);
                rtt = (0.6 * (diff_time.tv_sec * 1000000 + diff_time.tv_usec)) + 0.4*rtt;

                // Reset this timeout
                timeouts[rcv_pkt.seq_number].tv_usec = 0;
                timeouts[rcv_pkt.seq_number].tv_sec = 0;

                available_window += 1;
                last_received = rcv_pkt.seq_number % (window_size+1);
            }
            else {
                //printf("Received ACK with seq = %d, expecting = %d\n", rcv_pkt.seq_number, (last_received + 1) % window_size);
            }
        }

        // Check available window. If available, dequeue and send a packet.
        if(available_window > 0 && q.filled != 0) {
            bytequeue_pop(&q, &pkt);

            total_attempts++;

            pkt.seq_number = (seq_no) % (window_size+1);
            pkt.timestamp = curr_time;
            pkt.total_attempts = total_attempts;
            pkt.timeout = rtt;
            read_count = fread(pkt.payload, sizeof(char), sizeof(pkt.payload), fd);

            //printf("Sending. Seq_no == %d, stream == %c\n", pkt.seq_number, pkt.stream);
            serialize_packet(buff, pkt);

            //Store the packet into the packets buffer for possible transmission
            memcpy(&packets[pkt.seq_number], &pkt, sizeof(pkt));

            sendto(send_sock, buff, sizeof(pkt), 0, p->ai_addr, p->ai_addrlen);
            pkt = deserialize_packet(buff);
            available_window -= 1;

            if (feof(fd)) break;
            if(ferror(fd)) {
                fprintf(stderr, "error: %s\n", strerror(errno));
                exit(3);
            }

            // Set this timeout
            gettimeofday(&timeouts[pkt.seq_number], NULL);

            seq_no++;
        }

    }

    printf("Total errors: %d. Total total:%d\n", errors, total_attempts);

    close(send_sock);
    close(recv_sock);
    exit(0);
}