| // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // This is a utility program for testing that a Dart program can connect to an |
| // abstract UNIX socket created by a non-Dart program. It creates such a socket |
| // accepts one connection, echoes back the first message it receives, and then |
| // closes the connection and UNIX socket. |
| |
| #include "platform/globals.h" |
| #if defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <unistd.h> |
| |
| const intptr_t kOffsetOfPtr = 32; |
| |
| #define OFFSET_OF(type, field) \ |
| (reinterpret_cast<intptr_t>( \ |
| &(reinterpret_cast<type*>(kOffsetOfPtr)->field)) - \ |
| kOffsetOfPtr) // NOLINT |
| |
| int main(int argc, char* argv[]) { |
| struct sockaddr_un addr; |
| char* socket_path; |
| int server_socket; |
| char buf[1024]; |
| |
| if (argc < 2) { |
| fprintf( |
| stderr, |
| "Usage: abstract_socket_test <address>\n\n" |
| "<address> should be an abstract UNIX socket address like @hidden\n"); |
| exit(-1); |
| } |
| |
| socket_path = argv[1]; |
| if (socket_path[0] != '@') { |
| fprintf(stderr, |
| "The first argument should be an abstract socket " |
| "address and start with '@'\n"); |
| exit(-1); |
| } |
| |
| if ((server_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { |
| perror("socket error"); |
| exit(-1); |
| } |
| |
| memset(&addr, 0, sizeof(addr)); |
| addr.sun_family = AF_UNIX; |
| addr.sun_path[0] = '\0'; |
| strncpy(addr.sun_path + 1, socket_path + 1, sizeof(addr.sun_path) - 2); |
| |
| int address_length = |
| OFFSET_OF(struct sockaddr_un, sun_path) + strlen(socket_path); |
| if (bind(server_socket, (struct sockaddr*)&addr, address_length) == -1) { |
| perror("bind error"); |
| exit(-1); |
| } |
| |
| if (listen(server_socket, 5) == -1) { |
| perror("listen error"); |
| exit(-1); |
| } |
| |
| int client_socket; |
| if ((client_socket = accept(server_socket, NULL, NULL)) == -1) { |
| perror("accept error"); |
| exit(-1); |
| } |
| |
| int read_count; |
| while ((read_count = read(client_socket, buf, sizeof(buf))) > 0) { |
| int write_count = 0; |
| while (write_count < read_count) { |
| int w; |
| if ((w = write(client_socket, buf, read_count)) < 0) { |
| perror("write"); |
| exit(-1); |
| } |
| write_count += w; |
| } |
| } |
| if (read_count == -1) { |
| perror("read"); |
| exit(-1); |
| } |
| |
| close(client_socket); |
| close(server_socket); |
| return 0; |
| } |
| |
| #else |
| |
| int main() { |
| return -1; |
| } |
| |
| #endif // defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID) |