diff --git a/femtotcp.h b/femtotcp.h index 15e81d2..8643d59 100644 --- a/femtotcp.h +++ b/femtotcp.h @@ -101,9 +101,9 @@ ip4 atoip4(const char *ip); /* Callback flags */ #define CB_EVENT_READABLE 0x01 /* Accepted connection or data available */ -#define CB_EVENT_WRITABLE 0x02 /* Connected or space available to send */ -#define CB_EVENT_CLOSED 0x04 /* Connection closed by peer */ -#define CB_EVENT_TIMEOUT 0x08 /* Timeout */ +#define CB_EVENT_TIMEOUT 0x02 /* Timeout */ +#define CB_EVENT_WRITABLE 0x04 /* Connected or space available to send */ +#define CB_EVENT_CLOSED 0x10 /* Connection closed by peer */ void ipstack_register_callback(struct ipstack *s, int sock_fd, void (*cb)(int sock_fd, uint16_t events, void *arg), void *arg); /* External requirements */ diff --git a/src/port/posix/bsd_socket.c b/src/port/posix/bsd_socket.c index 6921cd6..0e70d5e 100644 --- a/src/port/posix/bsd_socket.c +++ b/src/port/posix/bsd_socket.c @@ -186,15 +186,15 @@ int ft_poll(struct ipstack *ipstack, struct pollfd *fds, nfds_t nfds, int timeou nfds_t i; int fd; int ret; - printf("Called poll\n"); + int miss = 0; if (in_the_stack) { return host_poll(fds, nfds, timeout); } memset(tcp_pollers, 0, sizeof(tcp_pollers)); memset(udp_pollers, 0, sizeof(udp_pollers)); for (i = 0; i < nfds; i++) { + struct bsd_poll_helper *poller = NULL; fd = fds[i].fd; - struct bsd_poll_helper *poller; if ((fd & MARK_TCP_SOCKET) != 0) poller = &tcp_pollers[fd & ~MARK_TCP_SOCKET]; @@ -202,7 +202,6 @@ int ft_poll(struct ipstack *ipstack, struct pollfd *fds, nfds_t nfds, int timeou poller = &udp_pollers[fd & ~MARK_UDP_SOCKET]; else continue; - printf("Found fd %d\n", fd); if (pipe(poller->pipefds) < 0) { perror("pipe"); return -1; @@ -212,52 +211,78 @@ int ft_poll(struct ipstack *ipstack, struct pollfd *fds, nfds_t nfds, int timeou /* Replace the original fd with the read end of the pipe */ fds[i].fd = poller->pipefds[0]; fds[i].events = POLLIN; + fds[i].revents = 0; /* Assign the callback */ - printf("registering callback\n"); ipstack_register_callback(ipstack, fd, poller_callback, ipstack); } /* Call the original poll */ - printf("Calling host_poll\n"); +repeat: + miss = 0; pthread_mutex_unlock(&ipstack_mutex); ret = host_poll(fds, nfds, timeout); pthread_mutex_lock(&ipstack_mutex); + if (ret <= 0) + return ret; for (i = 0; i < nfds; i++) { - struct bsd_poll_helper *poller; - if ((fds[i].fd & MARK_TCP_SOCKET) != 0) - poller = &tcp_pollers[fds[i].fd & ~MARK_TCP_SOCKET]; - else if ((fds[i].fd & MARK_UDP_SOCKET) != 0) - poller = &udp_pollers[fds[i].fd & ~MARK_UDP_SOCKET]; - else - continue; - printf("Replacing events\n"); - if (fds[i].revents & POLLIN) { - char c; - host_read(poller->pipefds[0], &c, 1); - switch(c) { - case 'r': - fds[i].revents |= POLLIN; - break; - case 'w': - fds[i].revents |= POLLOUT; - break; - case 'e': - fds[i].revents |= POLLERR; - break; - case 'h': - fds[i].revents |= POLLHUP; - break; + struct bsd_poll_helper *poller = NULL; + int j; + int fd = fds[i].fd; + char c = 0; + for (j = 0; j < MAX_TCPSOCKETS; j++) { + if (tcp_pollers[j].fd == 0) + continue; + if (tcp_pollers[j].pipefds[0] == fd) { + poller = &tcp_pollers[j]; + break; } - fds[i].revents &= fds[i].events & (POLLHUP | POLLERR); } - printf("Closing pipes\n"); - host_close(poller->pipefds[0]); - host_close(poller->pipefds[1]); - poller->fd = 0; - fds[i].fd = poller->fd; - fds[i].events = poller->events; - ipstack_register_callback(ipstack, poller->fd, NULL, NULL); + if (!poller) { + for (j = 0; j < MAX_UDPSOCKETS; j++) { + if (udp_pollers[j].fd == 0) + continue; + if (udp_pollers[j].pipefds[0] == fd) { + poller = &udp_pollers[j]; + break; + } + } + } + if (poller) { + if ((fds[i].revents & POLLIN) != 0) { + fds[i].revents = 0; + host_read(poller->pipefds[0], &c, 1); + switch(c) { + case 'r': + fds[i].revents |= POLLIN; + break; + case 'w': + fds[i].revents |= POLLOUT; + break; + case 'e': + fds[i].revents |= POLLERR; + break; + case 'h': + fds[i].revents |= POLLHUP; + break; + } + if ((fds[i].revents != 0) && (fds[i].revents & (poller->events | POLLHUP | POLLERR)) == 0) { + miss++; + ret--; + continue; + } + fds[i].revents &= (POLLHUP | POLLERR | poller->events); + } else { + fds[i].revents = 0; + } + fds[i].fd = poller->fd; + fds[i].events = poller->events; + host_close(poller->pipefds[0]); + host_close(poller->pipefds[1]); + poller->fd = 0; + ipstack_register_callback(ipstack, poller->fd, NULL, NULL); + } } - printf("Returning\n"); + if ((miss != 0) && (ret == 0)) + goto repeat; return ret; } @@ -449,7 +474,6 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { } ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) { - printf("Called recv(): len=%lu\n", len); conditional_steal_blocking_call(recvfrom, sockfd, buf, len, flags, addr, addrlen); } diff --git a/src/test/tcp_netcat_poll.c b/src/test/tcp_netcat_poll.c new file mode 100644 index 0000000..edbe7db --- /dev/null +++ b/src/test/tcp_netcat_poll.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PORT 12345 + +int main() { + int server_fd, new_socket = -1, nfds; + struct sockaddr_in server_addr; + struct pollfd fds[2]; + + // Create a TCP socket + server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd == -1) { + perror("Socket creation failed"); + exit(EXIT_FAILURE); + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(PORT); + + // Bind the socket to the address + if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { + perror("Bind failed"); + close(server_fd); + exit(EXIT_FAILURE); + } + + // Listen for incoming connections + if (listen(server_fd, 3) == -1) { + perror("Listen failed"); + close(server_fd); + exit(EXIT_FAILURE); + } + + // Set up poll to monitor stdin and the socket + fds[0].fd = STDIN_FILENO; // Monitor stdin + fds[1].fd = server_fd; // Monitor the server socket + + while (1) { + fds[0].events = POLLIN; + fds[1].events = POLLIN; + // Poll for events + nfds = poll(fds, 2, -1); // -1 means wait indefinitely + if (nfds == -1) { + perror("Poll error"); + close(server_fd); + exit(EXIT_FAILURE); + } + + if (fds[0].revents & POLLIN) { + // Data available on stdin + char buffer[1024]; + ssize_t bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer)); + if (bytes_read > 0) { + // Write stdin data to the socket + if (new_socket != -1) { + send(new_socket, buffer, bytes_read, 0); + } + } + } + + if (fds[1].revents & POLLIN) { + // New connection on the socket + if (new_socket == -1) { + printf("Calling accept()\n"); + new_socket = accept(server_fd, NULL, NULL); + if (new_socket == -1) { + perror("Accept failed"); + continue; + } + fds[1].fd = new_socket; + printf("New connection established\n"); + continue; + } else { + // Data available on the socket + char buffer[1024]; + ssize_t bytes_received = recv(new_socket, buffer, sizeof(buffer), 0); + if (bytes_received > 0) { + // Write socket data to stdout + write(STDOUT_FILENO, buffer, bytes_received); + } else if (bytes_received == 0) { + // Connection closed by the client + close(new_socket); + new_socket = -1; + fds[1].fd = server_fd; + printf("Connection closed\n"); + } + } + } + } + + close(server_fd); + return 0; +}