Exemple #1
0
bool Host::sendPacketTo(TargetID targetID,
                        ChannelID channel,
                        PacketType type,
                        const PacketData& data)
{
  switch (targetID)
  {
    case LOCAL:
    {
      if (m_observer)
      {
        PacketData copy = data;
        m_observer->onPacketReceived(targetID, copy);
      }

      return true;
    }

    case BROADCAST:
      return broadcast(channel, type, data);

    case SERVER:
    {
      if (isServer())
        return sendPacketTo(LOCAL, channel, type, data);

      /* FALLTHROUGH */
    }

    default:
    {
      Peer* peer = findPeer(targetID);
      if (!peer)
      {
        logError("Cannot send event to unknown peer %u", targetID);
        return false;
      }

      return peer->sendPacket(channel, type, data);
    }
  }
}
Exemple #2
0
int main(int argc, char **argv) {
    // ------------------------------------------------------------------------
    // Handle commandline arguments
    if (argc != 11) {
        printf("usage: requester -p <port> -f <f_hostname> -h <f_port> ");
        printf("-o <file option> -w <window>\n");
        exit(1);
    }
    char *portStr    = NULL;
    char *fileOption = NULL;
    char *emuHost    = NULL;
    char *emuPortStr = NULL;
    char *windowStr  = NULL;

    int cmd;
    while ((cmd = getopt(argc, argv, "p:o:f:h:w:")) != -1) {
        switch(cmd) {
        case 'p':
            portStr    = optarg;
            break;
        case 'o':
            fileOption = optarg;
            break;
        case 'f':
            emuHost    = optarg;
            break;
        case 'h':
            emuPortStr = optarg;
            break;
        case 'w':
            windowStr  = optarg;
            break;
        case '?':
            if (optopt == 'p' || optopt == 'o' || optopt == 'f'
                    || optopt == 'h' || optopt == 'w')
                fprintf(stderr, "Option -%c requires an argument.\n", optopt);
            else if (isprint(optopt))
                fprintf(stderr, "Unknown option -%c.\n", optopt);
            else
                fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);
            exit(EXIT_FAILURE);
            break;
        default:
            printf("Unhandled argument: %d\n", cmd);
            exit(EXIT_FAILURE);
        }
    }

    // DEBUG
    printf("Port: %s\n", portStr);
    printf("File: %s\n", fileOption);
    printf("Emu Name: %s\n", emuHost);
    printf("Emu Port: %s\n", emuPortStr);
    printf("Window: %s\n", windowStr);

    // Convert program args to values
    int requesterPort = atoi(portStr);
    int windowSize    = atoi(windowStr);
    // TODO: uncomment these once they are used
    //int emuPort       = atoi(emuPortStr);

    // Validate the argument values
    if (requesterPort <= 1024 || requesterPort >= 65536)
        ferrorExit("Invalid requester port");
    if (windowSize <= 0 || windowSize >= 65536) // upper bound is arbitrary
        ferrorExit("Invalid window size");
    puts("");

    // ------------------------------------------------------------------------

    // Parse the tracker file for parts corresponding to the specified file
    struct file_info *fileParts = parseTracker(fileOption);
    assert(fileParts != NULL && "Invalid file_info struct");

    // ------------------------------------------------------------------------
    // Setup requester address info
    struct addrinfo rhints;
    bzero(&rhints, sizeof(struct addrinfo));
    rhints.ai_family   = AF_INET;
    rhints.ai_socktype = SOCK_DGRAM;
    rhints.ai_flags    = AI_PASSIVE;

    // Get the requester's address info
    struct addrinfo *requesterinfo;
    int errcode = getaddrinfo(NULL, portStr, &rhints, &requesterinfo);
    if (errcode != 0) {
        fprintf(stderr, "requester getaddrinfo: %s\n", gai_strerror(errcode));
        exit(EXIT_FAILURE);
    }

    // Loop through all the results of getaddrinfo and try to create a socket for requester
    int sockfd;
    struct addrinfo *rp;
    for(rp = requesterinfo; rp != NULL; rp = rp->ai_next) {
        // Try to create a new socket
        sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (sockfd == -1) {
            perror("Socket error");
            continue;
        }

        // Try to bind the socket
        if (bind(sockfd, rp->ai_addr, rp->ai_addrlen) == -1) {
            perror("Bind error");
            close(sockfd);
            continue;
        }

        break;
    }
    if (rp == NULL) perrorExit("Request socket creation failed");
    else            {
        printf("Requester socket: ");
        printNameInfo(rp);
    }
    // ------------------------------------------------------------------------
    // Emulator hints
    struct addrinfo ehints;
    bzero(&ehints, sizeof(struct addrinfo));
    ehints.ai_family   = AF_INET;
    ehints.ai_socktype = SOCK_DGRAM;
    ehints.ai_flags    = 0;

    FILE *file = fopen("recvd.txt", "at");
    if (file == NULL) perrorExit("File open error");
    struct file_part *part = fileParts->parts;
    //while (part != NULL) {
    // Convert the sender's port # to a string
    /*
    char senderPortStr[6] = "\0\0\0\0\0\0";
    sprintf(senderPortStr, "%d", part->sender_port);
    */

    // Setup emulator address info
    struct addrinfo *emuinfo;
    errcode = getaddrinfo(emuHost, emuPortStr, &ehints, &emuinfo);
    if (errcode != 0) {
        fprintf(stderr, "emulator getaddrinfo: %s\n", gai_strerror(errcode));
        exit(EXIT_FAILURE);
    }

    // Loop through all the results of getaddrinfo and try to create a socket for emulator
    // NOTE: this is done so that we can find which of the getaddrinfo results is the emulator
    int emusockfd;
    struct addrinfo *ep;
    for(ep = emuinfo; ep != NULL; ep = ep->ai_next) {
        emusockfd = socket(ep->ai_family, ep->ai_socktype, ep->ai_protocol);
        if (emusockfd == -1) {
            perror("Socket error");
            continue;
        }

        break;
    }
    if (ep == NULL) perrorExit("Emulator socket creation failed");
    else            close(emusockfd);

    // ------------------------------------------------------------------------

    struct addrinfo shints;
    bzero(&shints, sizeof(struct addrinfo));
    shints.ai_family   = AF_INET;
    shints.ai_socktype = SOCK_DGRAM;
    shints.ai_flags    = 0;

    int sendersockfd = 0;

    // Setup variables for statistics
    unsigned long numPacketsRecvd = 0;
    unsigned long numBytesRecvd = 0;
    time_t startTime = time(NULL);

    char str[6];
    sprintf(str, "%d", part->sender_port);
    struct addrinfo *senderinfo;
    errcode = getaddrinfo(part->sender_hostname, str, &shints, &senderinfo);
    if (errcode != 0) {
        fprintf(stderr, "emulator getaddrinfo %s\n", gai_strerror(errcode));
        exit(EXIT_FAILURE);
    }

    struct addrinfo *sp;
    for(sp = senderinfo; sp != NULL; sp = ep->ai_next) {
        sendersockfd = socket(sp->ai_family, sp->ai_socktype, sp->ai_protocol);
        if (sendersockfd == -1) {
            perror("Socket error");
            continue;
        }

        break;
    }
    if (sp == NULL) perrorExit("Sender socket creation failed");
    else		close(sendersockfd);
    // ------------------------------------------------------------------------
    // Construct a REQUEST packet and send it to the emulator
    struct new_packet *pkt = NULL;
    pkt = malloc(sizeof(struct new_packet));
    bzero(pkt, sizeof(struct new_packet));
    pkt->priority = 1;
    pkt->src_ip   = ((struct sockaddr_in*)rp)->sin_addr.s_addr; // TODO
    pkt->src_port = requesterPort; // TODO
    pkt->dst_ip   = ((struct sockaddr_in*)sp)->sin_addr.s_addr; // TODO
    pkt->dst_port = part->sender_port; // TODO
    pkt->len      = sizeof(struct packet) - MAX_PAYLOAD + strlen(fileOption) + 1;
    // encapsulated packet
    pkt->pkt.type = 'R';
    pkt->pkt.seq  = 0;
    pkt->pkt.len  = windowSize;
    strcpy(pkt->pkt.payload, fileOption);


    sendPacketTo(sockfd, pkt, (struct sockaddr *)ep->ai_addr);
    free(pkt);


    // ------------------------------------------------------------------------
    // Connect to emulator to receive all parts of requested file

    // Start a recv loop here to get all packets for the given part
    //

    struct new_packet *buffer = malloc(windowSize * sizeof(struct new_packet));
    unsigned int *acked = malloc(windowSize * sizeof(unsigned int));
    int l;
    for( l = 0; l < windowSize; ++l) {
        acked[l] = 0;
    }
    for (;;) {
        // Receive a message
        struct new_packet msg;
        bzero(&msg, sizeof(struct new_packet));
        size_t bytesRecvd = recvfrom(sockfd, &msg, sizeof(struct new_packet), 0,
                                     (struct sockaddr *)ep->ai_addr, &ep->ai_addrlen);
        if (bytesRecvd == -1) perrorExit("Receive error");

        // Deserialize the message into a packet
        struct new_packet p;
        bzero(&p, sizeof(struct new_packet));
        deserializePacket(&msg, &p);

        // Handle DATA packet
        if (p.pkt.type == 'D') {
            // Update statistics
            ++numPacketsRecvd;
            numBytesRecvd += p.len;

            /* FOR DEBUG
            printf("[Packet Details]\n------------------\n");
            printf("type : %c\n", p.type);
            printf("seq  : %lu\n", p.seq);
            printf("len  : %lu\n", p.len);
            printf("payload: %s\n\n", p.payload);
            */

            // Print details about the received packet
            //printf("<- [Received DATA packet] ");
            //printPacketInfo(&p, (struct sockaddr_storage *)ep->ai_addr);

            // See if this packet has already been received
            int i;
            int found = 0;
            for(i = 0; i < windowSize; ++i) {
                if(buffer[i].pkt.seq == p.pkt.seq) {
                    found = 1;
                }
            }
            if(found == 0) {
                buffer[(p.pkt.seq - 1) % windowSize] = p;
            }
            // Save the data so the file can be reassembled later
            //size_t bytesWritten = fprintf(file, "%s", p.pkt.payload);
            //fflush(file);
            //if (bytesWritten == -1) {
            //    fprintf(stderr,
            //        "Incomplete file write: %d bytes written, %lu p len",
            //        (int)bytesWritten, p.pkt.len);
            //}

            // Requester now ACK's this packet
            struct new_packet *ack = NULL;
            ack = malloc(sizeof(struct new_packet));
            bzero(ack, sizeof(struct new_packet));
            ack->priority = 1;
            ack->src_ip   = ((struct sockaddr_in*)rp)->sin_addr.s_addr; // TODO
            ack->src_port = requesterPort; // TODO
            ack->dst_ip   = ((struct sockaddr_in*)sp)->sin_addr.s_addr; // TODO
            ack->dst_port = part->sender_port; // TODO
            ack->len      = sizeof(struct packet) - MAX_PAYLOAD + strlen(fileOption) + 1;
            // encapsulated packet
            ack->pkt.type = 'A';
            ack->pkt.seq  = p.pkt.seq;
            ack->pkt.len  = windowSize;
            strcpy(ack->pkt.payload, fileOption);


            sendPacketTo(sockfd, ack, (struct sockaddr *)ep->ai_addr);
            acked[(p.pkt.seq - 1) % windowSize] = 1;
            free(ack);
        }
        int j;
        int doneAcking = 1;
        for(j = 0; j < windowSize; ++j) {
            if(acked[j] == 0) {
                doneAcking = 0;
            }
        }
        if(doneAcking) {
            // write out to file in order
            int k;
            for(k = 0; k < windowSize; ++k) {
                acked[k] = 0;

                size_t bytesWritten = fprintf(file, "%s", buffer[k].pkt.payload);
                fflush(file);
                if (bytesWritten == -1) {
                    fprintf(stderr,
                            "Incomplete file write: %d bytes written, %lu p len",
                            (int)bytesWritten, buffer[k].pkt.len);
                }
            }
        }


        // Handle END packet
        if (p.pkt.type == 'E') {
            printf("<- *** [Received END packet] ***");
            double dt = difftime(time(NULL), startTime);
            if (dt <= 1) dt = 1;

            // Print statistics
            printf("\n---------------------------------------\n");
            printf("Total packets recvd: %lu\n", numPacketsRecvd);
            printf("Total payload bytes recvd: %lu\n", numBytesRecvd);
            printf("Average packets/second: %d\n", (int)(numPacketsRecvd / dt));
            printf("Duration of test: %f sec\n\n", dt);

            break;
        }
    }
    part = part->next_part;

    freeaddrinfo(emuinfo);


    // TODO: this crashes the program... figure out why
    //fclose(file);

    // Got what we came for, shut it down
    if (close(sockfd) == -1) perrorExit("Close error");
    else                     puts("Connection closed.\n");

    // Cleanup address and file info data
    freeaddrinfo(requesterinfo);
    freeFileInfo(fileParts);

    // All done!
    exit(EXIT_SUCCESS);
}
	void NetworkingObject::sendPacketToSender()
	{
		sendPacketTo( m_senderAddress );
	}
	int NetworkingObject::sendPacket()
	{
		return sendPacketTo( m_senderAddress );
	}