// C includes #include #include #include #include #include #include #include #include #include #include // C++ includes #include #include #include using namespace std; struct message { uint8_t type; uint16_t length; char recipient_name[32]; char sender_name[32]; char *message; }__attribute__((packed)); int read_message(struct message* m, int fd){ if(67 != recv(fd, m, 67, MSG_WAITALL)) return 1; m->message = (char*)malloc(m->length); sleep(1); // From the mutex demo, don't do this in a real server if(m->length != recv(fd, m->message, m->length, MSG_WAITALL)) return 2; return 0; } struct client_data { int fd; mutex send_mutex; // Probably want a name, room, etc }; void send_message(struct message* m, client_data* c){ c->send_mutex.lock(); write(c->fd, m, 67); sleep(1); // From the mutex demo, don't really do this write(c->fd, m->message, m->length); c->send_mutex.unlock(); } mutex clients_mutex; vector clients; /* Client should send a length of filename, then filename */ void handle_client(int client_fd, struct sockaddr_in client_address){ struct message m; client_data our_cd = {client_fd, mutex()}; clients_mutex.lock(); clients.push_back(&our_cd); clients_mutex.unlock(); while(1){ if(read_message(&m, client_fd)) break; clients_mutex.lock(); printf("Received message from %s to %s (%d bytes): %s\n", m.sender_name, m.recipient_name, m.length, m.message); for(auto &c : clients) if(c->fd != client_fd) send_message(&m, c); free(m.message); clients_mutex.unlock(); } printf("Closing connection with client %d\n", client_fd); // Remove from list of clients before we close for(int i = 0; i < clients.size(); i++){ if(clients[i]->fd == client_fd){ clients_mutex.lock(); clients.erase(clients.begin() + i); // Could this cause a race condition? clients_mutex.unlock(); } } close(client_fd); } int main(int argc, char ** argv){ struct sockaddr_in sad; sad.sin_port = htons(5143); sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; int skt = socket(AF_INET, SOCK_STREAM, 0); // Step 1 if(skt == -1){ perror("socket"); return 1; } if( bind(skt, (struct sockaddr*)(&sad), sizeof(struct sockaddr_in)) ){ // step 2 perror("bind"); return 1; } if( listen(skt, 5) ){ // step 3 perror("listen"); return 1; } while(1){ int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); client_fd = accept(skt, (struct sockaddr *)(&client_address), &address_size); // step 4 thread client_thread(handle_client, client_fd, client_address); client_thread.detach(); } return 0; }