| #include <errno.h> |
| #include <getopt.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/socket.h> |
| #include <sys/un.h> |
| #include <unistd.h> |
| |
| #include "wmediumd/api.h" |
| |
| void print_help(int exit_code) { |
| printf( |
| "wmediumd_ack_test_client - test client for wmediumd crash that is " |
| "related with ack\n\n"); |
| printf("Usage: wmediumd_ack_test_client -s PATH\n"); |
| printf(" Options:\n"); |
| printf(" - h : Print help\n"); |
| printf(" - s : Path for unix socket of wmediumd api server\n"); |
| |
| exit(exit_code); |
| } |
| |
| int write_fixed(int sock, void *data, int len) { |
| int remain = len; |
| int pos = 0; |
| |
| while (remain > 0) { |
| int actual_written = write(sock, ((char *)data) + pos, remain); |
| |
| if (actual_written <= 0) { |
| return actual_written; |
| } |
| |
| remain -= actual_written; |
| pos += actual_written; |
| } |
| |
| return pos; |
| } |
| |
| int read_fixed(int sock, void *data, int len) { |
| int remain = len; |
| int pos = 0; |
| |
| while (remain > 0) { |
| int actual_read = read(sock, ((char *)data) + pos, remain); |
| |
| if (actual_read <= 0) { |
| return actual_read; |
| } |
| |
| remain -= actual_read; |
| pos += actual_read; |
| } |
| |
| return pos; |
| } |
| |
| int wmediumd_send_packet(int sock, uint32_t type, void *data, uint32_t len) { |
| struct wmediumd_message_header header; |
| |
| header.type = type; |
| header.data_len = len; |
| |
| write_fixed(sock, &header, sizeof(uint32_t) * 2); |
| |
| if (len != 0) { |
| write_fixed(sock, data, len); |
| } |
| |
| return 0; |
| } |
| |
| int wmediumd_read_packet(int sock) { |
| struct wmediumd_message_header header; |
| |
| read_fixed(sock, &header, sizeof(uint32_t) * 2); |
| |
| if (header.data_len != 0) { |
| char buf[4096]; |
| |
| read_fixed(sock, buf, header.data_len); |
| } |
| |
| return 0; |
| } |
| |
| int main(int argc, char **argv) { |
| int opt; |
| char *wmediumd_api_server_path = NULL; |
| |
| while ((opt = getopt(argc, argv, "hs:")) != -1) { |
| switch (opt) { |
| case ':': |
| fprintf(stderr, |
| "error: Option `%c' " |
| "needs a value\n\n", |
| optopt); |
| break; |
| case 'h': |
| print_help(0); |
| break; |
| case 's': |
| if (wmediumd_api_server_path != NULL) { |
| fprintf(stderr, |
| "error: You must provide just one option for `%c`\n\n", |
| optopt); |
| } |
| |
| wmediumd_api_server_path = strdup(optarg); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| if (wmediumd_api_server_path == NULL) { |
| fprintf(stderr, "error: must specify wmediumd api server path\n\n"); |
| print_help(-1); |
| } |
| |
| int sock = socket(AF_UNIX, SOCK_STREAM, 0); |
| |
| struct sockaddr_un addr; |
| |
| addr.sun_family = AF_UNIX; |
| |
| if (strlen(wmediumd_api_server_path) >= sizeof(addr.sun_path)) { |
| fprintf(stderr, "error: unix socket path is too long(maximum %zu)\n", |
| sizeof(addr.sun_path) - 1); |
| print_help(-1); |
| } |
| |
| strncpy(addr.sun_path, wmediumd_api_server_path, |
| strlen(wmediumd_api_server_path)); |
| |
| if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
| fprintf(stderr, "Cannot connect to %s\n", wmediumd_api_server_path); |
| return -1; |
| } |
| |
| struct wmediumd_message_control control_message; |
| |
| control_message.flags = WMEDIUMD_CTL_RX_ALL_FRAMES; |
| |
| wmediumd_send_packet(sock, WMEDIUMD_MSG_REGISTER, NULL, 0); |
| wmediumd_read_packet(sock); /* Ack */ |
| wmediumd_send_packet(sock, WMEDIUMD_MSG_SET_CONTROL, &control_message, |
| sizeof(control_message)); |
| wmediumd_read_packet(sock); /* Ack */ |
| |
| wmediumd_read_packet(sock); |
| |
| /* Send packet while receiving packet from wmediumd */ |
| wmediumd_send_packet(sock, WMEDIUMD_MSG_SET_CONTROL, &control_message, |
| sizeof(control_message)); |
| wmediumd_read_packet(sock); |
| |
| wmediumd_send_packet(sock, WMEDIUMD_MSG_ACK, NULL, 0); |
| |
| close(sock); |
| |
| free(wmediumd_api_server_path); |
| |
| return 0; |
| } |