xref: /aosp_15_r20/external/wmediumd/tests/wmediumd_ack_test_client.c (revision 621120a22a0cd8ba80b131fe8bcb37c86ff453e3)
1 #include <errno.h>
2 #include <getopt.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/socket.h>
8 #include <sys/un.h>
9 #include <unistd.h>
10 
11 #include "wmediumd/api.h"
12 
print_help(int exit_code)13 void print_help(int exit_code) {
14   printf(
15       "wmediumd_ack_test_client - test client for wmediumd crash that is "
16       "related with ack\n\n");
17   printf("Usage: wmediumd_ack_test_client -s PATH\n");
18   printf("  Options:\n");
19   printf("     - h : Print help\n");
20   printf("     - s : Path for unix socket of wmediumd api server\n");
21 
22   exit(exit_code);
23 }
24 
write_fixed(int sock,void * data,int len)25 int write_fixed(int sock, void *data, int len) {
26   int remain = len;
27   int pos = 0;
28 
29   while (remain > 0) {
30     int actual_written = write(sock, ((char *)data) + pos, remain);
31 
32     if (actual_written <= 0) {
33       return actual_written;
34     }
35 
36     remain -= actual_written;
37     pos += actual_written;
38   }
39 
40   return pos;
41 }
42 
read_fixed(int sock,void * data,int len)43 int read_fixed(int sock, void *data, int len) {
44   int remain = len;
45   int pos = 0;
46 
47   while (remain > 0) {
48     int actual_read = read(sock, ((char *)data) + pos, remain);
49 
50     if (actual_read <= 0) {
51       return actual_read;
52     }
53 
54     remain -= actual_read;
55     pos += actual_read;
56   }
57 
58   return pos;
59 }
60 
wmediumd_send_packet(int sock,uint32_t type,void * data,uint32_t len)61 int wmediumd_send_packet(int sock, uint32_t type, void *data, uint32_t len) {
62   struct wmediumd_message_header header;
63 
64   header.type = type;
65   header.data_len = len;
66 
67   write_fixed(sock, &header, sizeof(uint32_t) * 2);
68 
69   if (len != 0) {
70     write_fixed(sock, data, len);
71   }
72 
73   return 0;
74 }
75 
wmediumd_read_packet(int sock)76 int wmediumd_read_packet(int sock) {
77   struct wmediumd_message_header header;
78 
79   read_fixed(sock, &header, sizeof(uint32_t) * 2);
80 
81   if (header.data_len != 0) {
82     char buf[4096];
83 
84     read_fixed(sock, buf, header.data_len);
85   }
86 
87   return 0;
88 }
89 
main(int argc,char ** argv)90 int main(int argc, char **argv) {
91   int opt;
92   char *wmediumd_api_server_path = NULL;
93 
94   while ((opt = getopt(argc, argv, "hs:")) != -1) {
95     switch (opt) {
96       case ':':
97         fprintf(stderr,
98                 "error: Option `%c' "
99                 "needs a value\n\n",
100                 optopt);
101         break;
102       case 'h':
103         print_help(0);
104         break;
105       case 's':
106         if (wmediumd_api_server_path != NULL) {
107           fprintf(stderr,
108                   "error: You must provide just one option for `%c`\n\n",
109                   optopt);
110         }
111 
112         wmediumd_api_server_path = strdup(optarg);
113         break;
114       default:
115         break;
116     }
117   }
118 
119   if (wmediumd_api_server_path == NULL) {
120     fprintf(stderr, "error: must specify wmediumd api server path\n\n");
121     print_help(-1);
122   }
123 
124   int sock = socket(AF_UNIX, SOCK_STREAM, 0);
125 
126   struct sockaddr_un addr;
127 
128   addr.sun_family = AF_UNIX;
129 
130   if (strlen(wmediumd_api_server_path) >= sizeof(addr.sun_path)) {
131     fprintf(stderr, "error: unix socket path is too long(maximum %zu)\n",
132             sizeof(addr.sun_path) - 1);
133     print_help(-1);
134   }
135 
136   strncpy(addr.sun_path, wmediumd_api_server_path,
137           strlen(wmediumd_api_server_path));
138 
139   if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
140     fprintf(stderr, "Cannot connect to %s\n", wmediumd_api_server_path);
141     return -1;
142   }
143 
144   struct wmediumd_message_control control_message;
145 
146   control_message.flags = WMEDIUMD_CTL_RX_ALL_FRAMES;
147 
148   wmediumd_send_packet(sock, WMEDIUMD_MSG_REGISTER, NULL, 0);
149   wmediumd_read_packet(sock); /* Ack */
150   wmediumd_send_packet(sock, WMEDIUMD_MSG_SET_CONTROL, &control_message,
151                        sizeof(control_message));
152   wmediumd_read_packet(sock); /* Ack */
153 
154   wmediumd_read_packet(sock);
155 
156   /* Send packet while receiving packet from wmediumd */
157   wmediumd_send_packet(sock, WMEDIUMD_MSG_SET_CONTROL, &control_message,
158                        sizeof(control_message));
159   wmediumd_read_packet(sock);
160 
161   wmediumd_send_packet(sock, WMEDIUMD_MSG_ACK, NULL, 0);
162 
163   close(sock);
164 
165   free(wmediumd_api_server_path);
166 
167   return 0;
168 }
169