This commit is contained in:
parent
c5d20305c3
commit
705ed7c5b3
3 changed files with 167 additions and 42 deletions
|
@ -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 */
|
||||
|
|
|
@ -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
101
src/test/tcp_netcat_poll.c
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue