Пример #1
0
int main(void) {
  int listenfd;
  int fd, nbytes;
  int inbuf;
  int room;
  char *after;

  struct sockaddr_in client;
  socklen_t socklen;
  char buf[30];

  listenfd = setup();
  while (1) {
    socklen = sizeof(client);
    if ((fd = accept(listenfd, (struct sockaddr *)&peer, &socklen)) < 0) {
      perror("accept");
    } else {
      printf("New connection on port %d\n",
             ntohs(client.sin_port));
      // Receive messages
      inbuf = 0; // empty buffer
      room = sizeof(buf); // whole buffer is room
      after = buf;
      while ((nbytes = read(fd, after, room)) > 0) {
        inbuf = inbuf + nbytes;
        int where = find_network_newline(buf, inbuf);
        while (where >= 0) {
          buf[where - 1] = '\n';
          buf[where] = '\0';
          printf ("Next message: %s", buf);
          where++;
          inbuf = inbuf - where;
          memmove(buf, buf + where, inbuf);
          // possibly the last read completed more than 1 line
          where = find_network_newline(buf, inbuf);
        }
        room = sizeof(buf) - inbuf;
        after = buf + inbuf;
      }
      close (fd);
    }
  }
}
Пример #2
0
/**
 * Process 's' battle command where client p is attacking and wants to speak.
 */
int speak(struct client *p) {
    char buf[256]; //buffer for client data (reading from client)
    char outbuf[512]; //buffer for output to client
    int nbytes;
    int inbuf = 0;          // buffer is empty; has no bytes
    int room = sizeof(buf); // room == capacity of the whole buffer
    char *after = buf;        // start writing at beginning of buf
    while (((nbytes = read(p->fd, after, room)) > 0)) {
        inbuf += nbytes;
        /* Check for buffer overflow */
        if (inbuf >= sizeof(buf)) {
            sprintf(outbuf, "\nServer cant handle this lengthy message..\r\n");
            write(p->fd, outbuf, strlen(outbuf));
            return -1;
        }

        int where = find_network_newline(buf, inbuf);
        if (where >= 0) { // OK. we have a full line
            buf[where] = '\0';
            buf[where+1] = '\0';
            printf("Next message: %s", buf);

            sprintf(outbuf, "You speak:%s\r\n\n", buf);
            write(p->fd, outbuf, strlen(outbuf));
            /* Write the message to opponent */
            sprintf(outbuf, "%s takes a break to tell you:\n%s\r\n\n", (p->partner)->name, buf);
            write((p->partner)->fd, outbuf, strlen(outbuf));

            inbuf -= (where+2);
            int i;
            for (i=0; i< where; i++) {
                buf[i] = '\0';
            }
            memmove(buf,buf+where+2,inbuf);
            break;
        }
        after = &buf[inbuf];
        room = sizeof(buf) - inbuf;
    }
    if (nbytes == 0) { //Socket closed during speak
        return -1; //To be removed by removeclient
    }

    return 0;

}
Пример #3
0
int main() {
    int listenfd, clientfd, maxfd;
    fd_set cset, rset;
    Client *clients = NULL;
    socklen_t clilen;
    struct sockaddr_in cliaddr, servaddr;
    int one = 1;

    unsigned char temp_block_num, temp_block_inverse;
    unsigned short temp_crc, block_crc;
    char temp = 'C';

    /*If a client disconnects while we are writing an ACK/NAK to them it sends
     * a SIGPIPE which needs to be taken care of
     */
    signal(SIGPIPE, SIG_IGN);


    //Setup the main listening socket
    listenfd = Socket(AF_INET, SOCK_STREAM, 0);
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(PORT);

    if ((setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)))
            == -1) {
        perror("setsockopt");
    }
    Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

    Listen(listenfd, 5);
    FD_ZERO(&cset);
    FD_SET(listenfd, &cset);
    maxfd = listenfd;


    while (1) {
        /*
        * Accept any clients that want to connect.
        */
        rset = cset;
        Select(maxfd + 1, &rset, NULL, NULL, 0);

        // Check for new clients.
        if (FD_ISSET(listenfd, &rset)) {
            printf("New Client Connected\n");
            Client *temp = Malloc(sizeof(Client));
            clilen = sizeof(cliaddr);
            clientfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
            FD_SET(clientfd, &cset);
            if (clientfd > maxfd) {
                maxfd = clientfd;
            }

            // Populate the client struct with default starter data.
            temp->fd = clientfd;
            temp->inbuf = 0;
            temp->state = initial;
            temp->next = start;
            temp->prev = NULL;
            if (start) {
                start->prev = temp;
            }
            start = temp;
            continue;
        }

        /*
         * Loop through all the clients in the linked list,
         * checking their file descriptors for activity.
         */

        clients = start;
        while (clients) {
            clientfd = clients->fd;
            if (FD_ISSET(clientfd, &rset)) {
                /*
                 * Using switch statement for states is too messy in terms of proper flow control
                 * so just using if statements instead; they're cleaner and easier to follow.
                 */
                if (clients->state == initial) {

                    // Read name of the file being sent.
                    clients->inbuf += Read(clientfd, &(clients->filename)[clients->inbuf], 20 - clients->inbuf);

                    if (find_network_newline(clients->filename, clients->inbuf) > 0) {

                        clients->filename[clients->inbuf - 2] = '\0';

                        // Open/create a file with the name.
                        clients->fp = open_file_in_dir(clients->filename, FILE_DIR);

                        // Assign defaults to client struct.
                        clients->state = pre_block;
                        clients->inbuf = 0;
                        clients->current_block = 1;

                        // Let the client know that the server is ready for the data.
                        temp = 'C';
                        Write(clientfd, &temp, 1);
                    }
                }

                if (clients->state == pre_block) {
                    // Find out what state the client is in.
                    Read(clientfd, (clients->buf), 1);
                    switch (clients->buf[0]) {
                    case EOT:
                        clients->state = finished;
                        break;
                    case SOH:
                        clients->state = get_block;
                        clients->blocksize = 132;
                        break;
                    case STX:
                        clients->state = get_block;
                        clients->blocksize = 1028;
                        break;
                    default:
                        temp = NAK;
                        Write(clientfd, &temp, 1);
                    }

                }

                if (clients->state == get_block) {
                    // Keep getting more of the payload till you have the required minimum amount.
                    clients->inbuf += Read(clientfd, (clients->buf) + (clients->inbuf), clients->blocksize - clients->inbuf);
                    if (clients->inbuf == clients->blocksize) {
                        clients->state = check_block;
                    }
                }

                if (clients->state == check_block) {
                    // Fetch block numbers from the packet.
                    temp_block_num = (clients->buf)[0];
                    temp_block_inverse = (clients->buf)[1];

                    // Make sure the block numbers are correct - drop the client if they're not.
                    if ((temp_block_num != (255 - temp_block_inverse) || (temp_block_num > clients->current_block))) {
                        FD_CLR(clientfd, &cset);
                        clients = drop_client(clients);
                        /*
                         * Since drop_client gives us the client after the one we dropped,
                         * we use continue to go back to start of the loop.
                         */
                        break;
                    }

                    // Fetch and assemble the CRC given by client for the payload recieved.
                    temp_crc = 0;
                    temp_crc = (unsigned char)(clients->buf)[(clients->blocksize) - 2];
                    temp_crc <<= 8;
                    temp_crc |= (unsigned char)((clients->buf)[(clients->blocksize) - 1]);

                    // Calculate the actual CRC for the payload recieved.
                    block_crc = crc_message(XMODEM_KEY, (unsigned char *)((clients->buf) + 2), (clients->blocksize) - 4);

                    // Compare the given and calculated CRC to ensure payload integrity.
                    if ((temp_block_num == clients->current_block) && (temp_crc == block_crc)) {

                        printf("File: %s \t Block:%d Successfully recieved\n", clients->filename, clients->current_block);

                        // Write the payload to file if CRCs match
                        if (fwrite((clients->buf) + 2, 1, ((clients->blocksize) - 4), clients->fp) == 0) {
                            perror("Write to File error");
                            exit(-1);
                        }

                        // Send the client an ACK
                        temp = ACK;
                        Write(clientfd, &temp, 1);

                        // Increment service side block number counter and prepare for next block.
                        clients->state = pre_block;
                        clients->current_block += 1;

                        // Deal w/ wrap around when block number hits 255.
                        if (clients->current_block == 256) {
                            clients->current_block = 0;
                        }

                        // Reset the buffer position.
                        clients->inbuf = 0;

                    } else if (temp_crc != block_crc) {
                        printf("File: %s \t Block:%d CRC mismatch.\nExpected:%x, Got %x\n",
                         clients->filename, clients->current_block, temp_crc, block_crc);

                        // Sent the client a NAK if the CRCs didn't match and prepare for repeat block.
                        temp = NAK;
                        Write(clientfd, &temp, 1);
                        clients->state = pre_block;
                        clients->inbuf = 0;

                    } else if (temp_block_num < clients->current_block) {

                        // If we got a repeat block, just send the client an ACK.
                        temp = ACK;
                        Write(clientfd, &temp, 1);

                    }
                }

                if (clients->state == finished) {
                    printf("File Transfer Finished: %s\n", clients->filename);

                    // Cleanup after the client when transfer is finished.
                    // Send the client a final ACK.
                    temp = ACK;
                    Write(clientfd, &temp, 1);

                    // Remove the client and their socket from our list/set of clients.
                    FD_CLR(clientfd, &cset);
                    clients = drop_client(clients);

                }
            }

            // Move on to the next client in the list (if any).
            if (clients) {
                clients = clients->next;
            }

        }
    }

}
Пример #4
0
int handleclient(struct client *p, struct client *top) {
    char outbuf[512];
    struct client *oppo;
    int len;
    //New client, ask the name.
    if (p->name == NULL) { //Ask the name

        int inbuf = 0;
        int where;
        // buffer is empty; has no bytes
        int room = sizeof(p->name_buf); // room == capacity of the whole buffer
        char *after;
        after = p->name_buf;
        //Return number of bytes read
        //nbytes = len
        while (( len = read(p->fd, after, sizeof(p->name_buf) - 1)) > 0) {
            inbuf += len;
            where = find_network_newline(p->name_buf, inbuf);

            if (where >= 0) { // OK. we have a full line
                p->name_buf[where] = '\0';
                p->name_buf[where+1] = '\0';
                inbuf -= where + 2 ;
                break;
            }
            room = sizeof(p->name_buf) - inbuf;
            after = p->name_buf + inbuf;
        }
        p->name = p->name_buf;


        //Tell the world someone joined.
        sprintf(outbuf, "\r\n**%s joined the area.**\r\n", p->name);
        broadcast(top, outbuf, strlen(outbuf));
        sprintf(outbuf, "Welcome, %s! Awaiting opponent...\n", p->name);
        write(p->fd, outbuf, strlen(outbuf));
    }

    //Start matching.
    if(p->opponent == NULL) {
        for (oppo = top; oppo != NULL; oppo = oppo->next) {
            if(oppo != p) {
                if(oppo->opponent == NULL && oppo->lastplayed != p) {
                    p->opponent = oppo;
                    p->hitpoints = rand() % 11 + 20;
                    p->powermoves = rand() % 3 + 1;
                    p->status = 1;//Attacking first

                    oppo->opponent = p;
                    oppo->hitpoints = rand() % 11 + 20;
                    oppo->powermoves = rand() % 3 + 1;
                    oppo->status = -1;//Defend first.
                    sprintf(outbuf, "You engage %s!\n", p->opponent->name);
                    write(p->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "You engage %s!\n", p->name);
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "\nReady for battle?(Please type 'y')\n");
                    write(p->fd, outbuf, strlen(outbuf));
                }
            }
        }
        return 0;
    }

    len = read(p->fd, p->buf, sizeof(p->buf) - 1);
    //Handle battle.
    if(p->opponent) {
        if (p->status == 1) {
            sprintf(outbuf, "Your hitpoints:%d\nYour powermoves: %d\n\n%s's hitpoints:%d\n\n",
                    p->hitpoints, p->powermoves, p->opponent->name, p->opponent->hitpoints);
            write(p->fd, outbuf, strlen(outbuf));
            sprintf(outbuf, "Your hitpoints:%d\nYour powermoves: %d\n\n%s's hitpoints:%d\n\n",
                    p->opponent->hitpoints, p->opponent->powermoves, p->name, p->hitpoints);
            write(p->opponent->fd, outbuf, strlen(outbuf));
            sprintf(outbuf, "(a)ttack\n(p)owermove\n(s)peak something\n");
            write(p->fd, outbuf, strlen(outbuf));
            sprintf(outbuf, "Waiting for %s to strike...\n", p->name);
            write(p->opponent->fd, outbuf, strlen(outbuf));
            len = read(p->fd, p->buf, sizeof(p->buf) - 1);
            p->status = -1;
            p->opponent->status = 1;
        } else if(p->status == -1) {
            return 0;
        }
        if (len > 0) {
            if(p->buf[0] == 'a') {
                p->buf[0] = '\0';
                int damage;
                damage = rand() % 5 + 2;
                p->opponent->hitpoints -= damage;
                sprintf(outbuf, "\nYou hit %s for %d damage!\n", p->opponent->name, damage);
                write(p->fd, outbuf, strlen(outbuf));//write outbuf to every client in top.
                sprintf(outbuf, "\n%s hits you for %d damage!\n", p->name, damage);
                write(p->opponent->fd, outbuf, strlen(outbuf));
                sprintf(outbuf, "\nReady for attacking/speaking?(Please say 'y')\n");
                write(p->opponent->fd, outbuf, strlen(outbuf));

                if(p->opponent->hitpoints <= 0) {
                    sprintf(outbuf, "\n%s gives up. You win!\n", p->opponent->name);
                    write(p->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "\nYou are no match for %s. You scurry away...\n", p->name);
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "Awaiting opponent...\n");
                    write(p->fd, outbuf, strlen(outbuf));
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    p->lastplayed = p->opponent;
                    p->opponent->lastplayed = p;
                    moveToEnd(top, p);
                    moveToEnd(top, p->opponent);
                    p->opponent->opponent = NULL;
                    p->opponent = NULL;
                }

                return 0;
            } else if(p->buf[0] == 'p') {
                p->buf[0] = '\0';
                int possibility;
                int damage;
                possibility = rand() % 2 + 0;
                p->powermoves -= 1;
                if(possibility == 0) { //Miss it;
                    sprintf(outbuf, "\nYou missed %s!\n", p->opponent->name);
                    write(p->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "\n%s missed you!\n", p->name);
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "\nReady for attacking/speaking?(Please say 'y')\n");
                    write(p->opponent->fd, outbuf, strlen(outbuf));

                    return 0;
                } else {
                    damage = 3 * (rand() % 5 + 2);
                    p->opponent->hitpoints -= damage;
                    sprintf(outbuf, "\nYou powermoves %s for %d damage!\n", p->opponent->name, damage);
                    write(p->fd, outbuf, strlen(outbuf));//write outbuf to every client in top.
                    sprintf(outbuf, "\n%s powermoves you for %d damage!\n", p->name, damage);
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    sprintf(outbuf, "\nReady for attacking/speaking?(Please say 'y')\n");
                    write(p->opponent->fd, outbuf, strlen(outbuf));
                    if(p->opponent->hitpoints <= 0) {
                        sprintf(outbuf, "\n%s gives up. You win!\n", p->opponent->name);
                        write(p->fd, outbuf, strlen(outbuf));
                        sprintf(outbuf, "\nYou are no match for %s. You scurry away...\n", p->name);
                        write(p->opponent->fd, outbuf, strlen(outbuf));
                        sprintf(outbuf, "Awaiting opponent...\n");
                        write(p->fd, outbuf, strlen(outbuf));
                        write(p->opponent->fd, outbuf, strlen(outbuf));
                        p->lastplayed = p->opponent;
                        p->opponent->lastplayed = p;
                        moveToEnd(top, p);
                        moveToEnd(top, p->opponent);
                        p->opponent->opponent = NULL;
                        p->opponent = NULL;
                    }

                    return 0;
                }
            } else if(p->buf[0] == 's') {
                p->buf[0] = '\0';
                sprintf(outbuf, "Speak:");
                write(p->fd, outbuf, strlen(outbuf));
                int inbuf = 0;
                int where;
                int room = sizeof(p->buf);
                char *after;
                //char name_buf[256];
                p->buf[0] = '\0';
                after = p->buf;

                while (( len = read(p->fd, after, sizeof(p->buf) - 1)) > 0) {
                    inbuf += len;
                    where = find_network_newline(p->buf, inbuf);

                    if (where >= 0) { // OK. we have a full line
                        p->buf[where] = '\0';
                        p->buf[where+1] = '\0';
                        inbuf -= where + 2 ;
                        break;
                    }
                    room = sizeof(p->buf) - inbuf;
                    after = p->buf + inbuf;
                }
                sprintf(outbuf, "You spoke:%s\n", p->buf);
                write(p->fd, outbuf, strlen(outbuf));
                sprintf(outbuf, "%s spoke:%s\n", p->name, p->buf);
                write(p->opponent->fd, outbuf, strlen(outbuf));
                sprintf(outbuf, "\nReady for attacking/speaking?(Please say 'y')\n");
                write(p->opponent->fd, outbuf, strlen(outbuf));

                return 0;
            }
        } else if (len == 0) {//nothing in client p's fd
            // socket is closed
            printf("active\n");
            sprintf(outbuf, "Awaiting opponent...\n");
            write(p->opponent->fd, outbuf, strlen(outbuf));
            p->opponent->opponent = NULL;
            sprintf(outbuf, "--%s dropped. You win!\n", p->name);
            write(p->opponent->fd, outbuf, strlen(outbuf));
            printf("Disconnect from %s\n", inet_ntoa(p->ipaddr));
            return -1;
        } else { // shouldn't happen
            perror("read");
            return -1;
        }
    }
    return -1;
}