Files
dat-thang/tests/test_dpi_socket.c
T
divorce b735900f2e 0.0.002
ddat interop with dat js
cable interop with cabal js
ddat's frontend = dat-thang
cable fe = cable-thang
dillo support based on cel's dillo-dat
bootstrap node
xplatform support

Signed-off-by: divo <418@cryspace.space>
2026-10-19 00:17:02 -04:00

119 lines
3.1 KiB
C

#define _POSIX_C_SOURCE 200809L
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static int connect_local(unsigned short port)
{
struct sockaddr_in address;
int fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0) return -1;
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (connect(fd, (struct sockaddr *)&address, sizeof(address))) {
close(fd);
return -1;
}
return fd;
}
static int send_all(int fd, const char *data, size_t length)
{
while (length) {
ssize_t sent = send(fd, data, length, 0);
if (sent < 0 && errno == EINTR) continue;
if (sent <= 0) return -1;
data += sent;
length -= (size_t)sent;
}
return 0;
}
static int request_page(unsigned short port, const char *url)
{
const char *key = "abcdef1234567890";
char request[4096], buffer[4096];
int fd, n;
int length = snprintf(request, sizeof(request),
"<cmd='auth' msg='%s' '>\n<cmd='open_url' url='%s' '>", key, url);
if (length < 0 || (size_t)length >= sizeof(request)) return -1;
fd = connect_local(port);
if (fd < 0) return -1;
if (send_all(fd, request, (size_t)length) || shutdown(fd, SHUT_WR)) {
close(fd);
return -1;
}
while ((n = (int)recv(fd, buffer, sizeof(buffer), 0)) > 0) {
if (fwrite(buffer, 1, (size_t)n, stdout) != (size_t)n) {
close(fd);
return -1;
}
}
close(fd);
if (n < 0) return -1;
return fflush(stdout) ? -1 : 0;
}
int main(int argc, char **argv)
{
struct sockaddr_in address;
socklen_t address_length = sizeof(address);
unsigned short port;
int listener;
pid_t child;
int status, fd;
if (argc != 3) {
fprintf(stderr, "usage: %s DPI-HELPER URL\n", argv[0]);
return 2;
}
listener = socket(AF_INET, SOCK_STREAM, 0);
if (listener < 0) { perror("socket"); return 1; }
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
address.sin_port = 0;
if (bind(listener, (struct sockaddr *)&address, sizeof(address)) ||
listen(listener, 8) || getsockname(listener, (struct sockaddr *)&address, &address_length)) {
perror("bind/listen"); close(listener); return 1;
}
port = ntohs(address.sin_port);
child = fork();
if (child < 0) { perror("fork"); close(listener); return 1; }
if (!child) {
if (dup2(listener, STDIN_FILENO) < 0) _exit(126);
close(listener);
execl(argv[1], argv[1], (char *)NULL);
perror("exec"); _exit(127);
}
close(listener);
if (request_page(port, argv[2])) {
perror("request page");
kill(child, SIGTERM);
waitpid(child, NULL, 0);
return 1;
}
fd = connect_local(port);
{
const char *bye = "<cmd='auth' msg='abcdef1234567890' '>\n<cmd='DpiBye' '>";
if (fd < 0 || send_all(fd, bye, strlen(bye))) {
perror("send DpiBye");
kill(child, SIGTERM);
waitpid(child, NULL, 0);
return 1;
}
}
shutdown(fd, SHUT_WR);
close(fd);
if (waitpid(child, &status, 0) < 0) { perror("waitpid"); return 1; }
return WIFEXITED(status) ? WEXITSTATUS(status) : 1;
}