void Server::run_clients() { for (int i = 0; i < m_maxclients; i++) { Client *client = &m_clients[i]; if (!client->m_active) { continue; } if (!read_client_message(client)) { drop_client(client, false); continue; } if (!client->m_spawned) { memset(&client->m_cmd, 0, sizeof(client->m_cmd)); continue; } if (!m_paused && (m_maxclients > 1)) {// || key_dest == key_game)) { client_think(client); } } }
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; } } } }
/* * Loop forever handling clients as they come and go. * Access to the framebuffer may be interleaved, if the user * wants it that way. */ static void main_loop(void) { int nopens = 0; int ncloses = 0; while ( !fb_server_got_fb_free ) { long refresh_rate = 60000000; /* old default */ fd_set infds; struct timeval tv; int i; if (fb_server_fbp) { if (fb_poll_rate(fb_server_fbp) > 0) refresh_rate = fb_poll_rate(fb_server_fbp); } infds = select_list; /* struct copy */ tv.tv_sec = 0L; tv.tv_usec = refresh_rate; if ((select( max_fd+1, &infds, (fd_set *)0, (fd_set *)0, (struct timeval *)&tv ) == 0)) { /* Process fb events while waiting for client */ /*printf("select timeout waiting for client\n");*/ if (fb_server_fbp) { if (fb_poll(fb_server_fbp)) { return; } } continue; } /* Handle any events from the framebuffer */ if (fb_is_set_fd(fb_server_fbp, &infds)) { fb_poll(fb_server_fbp); } /* Accept any new client connections */ if (netfd > 0 && FD_ISSET(netfd, &infds)) { new_client( pkg_getclient( netfd, fb_server_pkg_switch, comm_error, 0 ) ); nopens++; } /* Process arrivals from existing clients */ /* First, pull the data out of the kernel buffers */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (1)\n"); } if (! FD_ISSET( clients[i]->pkc_fd, &infds )) continue; if (pkg_suckin( clients[i] ) <= 0) { /* Probably EOF */ drop_client( i ); ncloses++; continue; } } /* Second, process all the finished ones that we just got */ for (i = MAX_CLIENTS-1; i >= 0; i--) { if (clients[i] == NULL ) continue; if (pkg_process( clients[i] ) < 0) { fprintf(stderr, "pkg_process error encountered (2)\n"); } } if (once_only && nopens > 1 && ncloses > 1) return; } }