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