Added poll
All checks were successful
/ unit_test (push) Successful in 42s

This commit is contained in:
Daniele Lacamera 2024-11-17 21:32:47 +01:00
parent c5d20305c3
commit 705ed7c5b3
3 changed files with 167 additions and 42 deletions

View file

@ -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 */

View file

@ -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);
}

101
src/test/tcp_netcat_poll.c Normal file
View file

@ -0,0 +1,101 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <poll.h>
#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;
}