void startTcpSocket(auto sock_fd, auto addr, auto port) { struct sockaddr_in SockAddr; SockAddr.sin_family = AF_INET; SockAddr.sin_port = port; SockAddr.sin_addr.s_addr = addr; if (bind(sock_fd, (struct sockaddr *) &SockAddr, sizeof(SockAddr)) == -1) throw syscall_error("bind"); set_nonblock(sock_fd); if (listen(sock_fd, SOMAXCONN) == -1) throw syscall_error("listen"); }
void set_nonblock(int fd) { int flags; if ((flags = fcntl(fd, F_GETFL, 0)) != -1) flags = 0; if (fcntl(fd, F_SETFD, flags | O_NONBLOCK) == -1) { throw syscall_error("fcntl"); } }
std::size_t SocketUtils::sock_fd_read(int sock, void *buf, std::size_t bufsize, int *fd) { //File descriptor received if (fd) { //Declaration auto msg = msghdr(); auto iov = iovec(); union { cmsghdr cmsgheader; char control[CMSG_SPACE(sizeof(int))]; } cmsgu; struct cmsghdr *cmsg; //Definition iov.iov_base = buf; iov.iov_len = bufsize; msg.msg_name = nullptr; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = cmsgu.control; msg.msg_controllen = sizeof(cmsgu.control); //receiving data auto size = recvmsg(sock, &msg, 0); if (size < 0) throw syscall_error("sock_fd_read: recvmsg"); //Getting file descriptor cmsg = CMSG_FIRSTHDR(&msg); if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) { if (cmsg->cmsg_level != SOL_SOCKET) throw syscall_error("Invalid cmsg level"); if (cmsg->cmsg_type != SCM_RIGHTS) throw syscall_error("Invalid cmsg rights"); *fd = *((int *) CMSG_DATA(cmsg)); printf("recieved fd %d\n", *fd); } else *fd = -1; return static_cast<size_t>(size); } //File descriptor is not received auto size = read(sock, buf, bufsize); if (size < 0) throw syscall_error("sock_fd_read: read"); return static_cast<size_t>(size); }
void polling(auto MasterSocket) { static const int POLL_SIZE = 2048; std::array<pollfd, 2048> read_set{}; read_set[0].fd = MasterSocket; read_set[0].events = POLLIN; int read_set_size = 1; while (true) { std::cout << std::endl; if (poll(read_set.data(), static_cast<nfds_t >(read_set_size), -1) == -1) throw syscall_error("poll"); auto tmp_size = read_set_size; for (auto it = read_set.cbegin(); it != read_set.cbegin() + tmp_size; it++) { if (it->revents & POLLIN) { // new connection if (it == read_set.cbegin()) { auto SlaveSocket = accept(MasterSocket, nullptr, 0); if (SlaveSocket == -1) throw syscall_error("accept"); set_nonblock(SlaveSocket); read_set[read_set_size].fd = SlaveSocket; read_set[read_set_size].events = POLLIN; read_set_size++; } // New data else { char buffer[50]; auto nread = recv(it->fd, buffer, sizeof(buffer), MSG_NOSIGNAL); if (nread == -1) throw syscall_error("recv"); if (nread == 0 && errno != EAGAIN) { shutdown(it->fd, SHUT_RDWR); close(it->fd); std::remove_if(read_set.begin(), read_set.begin() + read_set_size, [&it](pollfd &item) { return item.fd == it->fd; }); read_set[--read_set_size].fd = 0; } else { buffer[nread] = '\0'; if (send(it->fd, buffer, static_cast<size_t>(nread + 1), MSG_NOSIGNAL) == -1) throw syscall_error("send"); } } } } } }
void selecting(auto MasterSocket) { std::set<decltype(MasterSocket), std::greater<decltype(MasterSocket)>> Sockets; Sockets.insert(MasterSocket); fd_set read_set, tmp; FD_ZERO(&read_set); FD_SET(MasterSocket, &read_set); while (true) { tmp = read_set; if (select(*Sockets.cbegin() + 1, &tmp, nullptr, nullptr, nullptr) == -1) throw syscall_error("select"); for (auto sock : Sockets) { if (FD_ISSET(sock, &tmp)) { //New connection if (sock == MasterSocket) { decltype(MasterSocket) newSocket; if ((newSocket = accept(sock, nullptr, 0)) == -1) throw syscall_error("accept"); FD_SET(newSocket, &read_set); Sockets.insert(newSocket); } //New data else { char buffer[50]; auto nread = recv(sock, buffer, sizeof(buffer), MSG_NOSIGNAL); if (nread == -1) throw syscall_error("recv"); if (nread == 0 && errno != EAGAIN) { FD_CLR(sock, &read_set); shutdown(sock, SHUT_RDWR); close(sock); Sockets.erase(sock); } else { buffer[nread] = '\0'; if (send(sock, buffer, static_cast<size_t>(nread + 1), MSG_NOSIGNAL) == -1) throw syscall_error("send"); } } } } } close(MasterSocket); }
std::size_t SocketUtils::sock_fd_write(int sock, void *buf, std::size_t buflen, int fd) { //Declaration auto msg = msghdr(); auto iov = iovec(); union { cmsghdr cmsgheader; char control[CMSG_SPACE(sizeof(int))]; } cmsgu; struct cmsghdr *cmsg; //Definition iov.iov_base = buf; iov.iov_len = buflen; msg.msg_name = nullptr; msg.msg_namelen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; //Passing file descriptor if (fd != -1) { msg.msg_control = cmsgu.control; msg.msg_controllen = sizeof(cmsgu.control); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; printf("passing fd %d\n", fd); *((int *) CMSG_DATA(cmsg)) = fd; } //Not passing file descriptor else { msg.msg_control = nullptr; msg.msg_controllen = 0; printf("not passing fd\n"); } //Sending data auto size = sendmsg(sock, &msg, 0); if (size < 0) throw syscall_error("sock_fd_write: sendmsg"); return static_cast<size_t>(size); }
void epolling(auto MasterSocket) { static const int MAX_EVENTS = 32; auto EPoll = epoll_create1(0); if (EPoll == -1) throw syscall_error("epoll_create1"); struct epoll_event Event; Event.data.fd = MasterSocket; Event.events = EPOLLIN; if(epoll_ctl(EPoll, EPOLL_CTL_ADD, MasterSocket, &Event) == -1) throw syscall_error("epoll_ctl"); while(true) { struct epoll_event Events[MAX_EVENTS]; auto N = epoll_wait(EPoll, Events, MAX_EVENTS, -1); if(N==-1) throw syscall_error("epoll_wait"); for (auto i = 0; i < N; i++) { // New connection if (Events[i].data.fd == MasterSocket) { auto SlaveSocket = accept(MasterSocket, nullptr, 0); if (SlaveSocket == -1) throw syscall_error("accept"); set_nonblock(SlaveSocket); struct epoll_event newEvent; newEvent.data.fd = SlaveSocket; newEvent.events = EPOLLIN; if (epoll_ctl(EPoll, EPOLL_CTL_ADD, SlaveSocket, &newEvent) == -1) throw syscall_error("epoll_ctl"); } //New data else { char buffer[50]; auto nread = recv(Events[i].data.fd, buffer, sizeof(buffer), MSG_NOSIGNAL); if (nread == -1) throw syscall_error("recv"); if (nread == 0 && errno != EAGAIN) { shutdown(Events[i].data.fd, SHUT_RDWR); close(Events[i].data.fd); } else { buffer[nread] = '\0'; if (send(Events[i].data.fd, buffer, static_cast<size_t>(nread + 1), MSG_NOSIGNAL) == -1) throw syscall_error("send"); } } } } }
int main(int argc, char **argv) { try { auto MasterSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (MasterSocket == -1) { throw syscall_error("socket"); } startTcpSocket(MasterSocket, htonl(INADDR_ANY), htons(7777)); // selecting(MasterSocket); // polling(MasterSocket); epolling(MasterSocket); } catch (std::exception &e) { std::cout << e.what() << std::endl; } return 0; }
/* Open the next extension in a split sequence */ static void open_split(split_t *split) { int fd; int splitnum = split->total_bytes / split->max_bytes; mode_t perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; char *ext, *fname; ext = getext(split->format, splitnum); asprintf(&fname, "%s.%s", split->name, ext); free(ext); fd = open(fname, O_WRONLY | O_CREAT, perms); if (fd < 0) syscall_error(fname); split->currfd = fd; split->curr_bytes = 0; free(fname); }
int main(int argc, char **argv) { int sockfd; int client_sockfd; int portnum; int clientlen; int bytes_read; int bytes_written; char buffer[BUF_SIZE]; struct sockaddr_in server_addr; // Contains the inet address of the server struct sockaddr_in client_addr; // Contains the inet address of the client // Make sure the program was started with enough arguments if( argc < 2 ) { fprintf(stderr, "ERROR: No port number provided, usage is %s <port>", argv[0]); exit( EXIT_FAILURE ); } // Get our passed port number portnum = atoi( argv[1] ); clientlen = sizeof(client_addr); // Create a new IPv4 socket using TCP sockfd = socket(AF_INET, SOCK_STREAM, 0); if( sockfd < 0 ) { syscall_error("ERROR: Failed to open socket"); } // Clear our struct memset(&server_addr, 0, sizeof(server_addr)); // Set up our address server_addr.sin_family = AF_INET; // Address familly IPv4 (AF_INET6 is IPv6) server_addr.sin_port = htons(portnum); // Port number, converted to network byte order server_addr.sin_addr.s_addr = INADDR_ANY; // Since we're a server bind to our own IP // Try and bind our address to our existing socket if( bind( sockfd, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0 ) { syscall_error("ERROR: Failed to bind address to socket"); } // Allow us to listen to the socket for connections listen( sockfd, MAX_BACKLOG_SIZE ); // Block until we get a connection if( (client_sockfd = accept( sockfd, (struct sockaddr*) &client_addr, &clientlen )) < 0 ) { syscall_error("ERROR: Failed to accept client connection"); } // We now have a client! while( client_sockfd ) { printf("Incoming connection from %s - Waiting for hello\n", inet_ntoa(client_addr.sin_addr)); // Clear our buffer and read one less byte than our size so we are null terminated memset(buffer, 0, sizeof(buffer)); bytes_read = read( client_sockfd, buffer, BUF_SIZE - 1); if( bytes_read < 0 ) { syscall_error("ERROR: Unable to read from socket"); } // We got a message from the client printf("Recieved message from client: %s\n", buffer); if( strncmp(buffer, "HELLO", sizeof(buffer)) == 0) { printf("Recieved HELLO from client, responding SUCCESS\n"); bytes_written = write( client_sockfd, "SUCCESS", strlen("SUCCESS") ); } else { printf("Unknown response from client, responding FAILURE\n"); bytes_written = write( client_sockfd, "FAILURE", strlen("FAILURE") ); } if( bytes_written < 0 ) { error("ERROR: Unable to write to socket"); } // We're done with this client, close the connection and get a new client close(client_sockfd); if( (client_sockfd = accept( sockfd, (struct sockaddr*) &client_addr, &clientlen )) < 0 ) { syscall_error("ERROR: Failed to accept client connection"); } } return EXIT_SUCCESS; }