int xscope_ep_request_upload(int sockfd, unsigned int length, const unsigned char *data) { char request = XSCOPE_SOCKET_MSG_EVENT_TARGET_DATA; char *requestBuffer = (char *)malloc(sizeof(char)+sizeof(int)+length); int requestBufIndex = 0; int n = 0; if (xscope_ep_upload_pending == 1) return XSCOPE_EP_FAILURE; requestBuffer[requestBufIndex] = request; requestBufIndex += 1; *(unsigned int *)&requestBuffer[requestBufIndex] = length; requestBufIndex += 4; memcpy(&requestBuffer[requestBufIndex], data, length); requestBufIndex += length; n = send(sockfd, requestBuffer, requestBufIndex, 0); if (n != requestBufIndex) print_and_exit("ERROR: Command send failed\n"); xscope_ep_upload_pending = 1; free(requestBuffer); return XSCOPE_EP_SUCCESS; }
void mutex_create(mutex_t *mutex) { *mutex = CreateMutex( NULL, // default security attributes FALSE, // initially not owned NULL); // unnamed mutex if (*mutex == NULL) print_and_exit("ERROR: mutex init failed\n"); }
void *console_thread(void *arg) #endif { int sockfd = *(int *)arg; char buffer[LINE_LENGTH + 1]; do { int i = 0; int c = 0; printf("%s", g_prompt); for (i = 0; (i < LINE_LENGTH) && ((c = getchar()) != EOF) && (c != '\n'); i++) buffer[i] = tolower(c); buffer[i] = '\0'; if (buffer[0] == 'q') { print_and_exit("Done\n"); } else if (buffer[0] == 'e') { tester_command_t cmd = AVB_TESTER_EXPECT_NORMAL; if (get_next_char(&buffer[1]) == 'o') cmd = AVB_TESTER_EXPECT_OVERSUBSCRIBED; xscope_ep_request_upload(sockfd, 4, (unsigned char *)&cmd); } else if (buffer[0] == 'x') { tester_command_t cmd = AVB_TESTER_XSCOPE_PACKETS_DISABLE; if (get_next_char(&buffer[1]) == 'e') cmd = AVB_TESTER_XSCOPE_PACKETS_ENABLE; xscope_ep_request_upload(sockfd, 4, (unsigned char *)&cmd); } else if ((buffer[0] == 'h') || (buffer[0] == '?')) { print_console_usage(); } else { printf("Unrecognised command '%s'\n", buffer); print_console_usage(); } } while (1); #ifdef _WIN32 return 0; #else return NULL; #endif }
static void manage_queue(socket_data_t *socket_data) { int n = 0; upload_queue_entry_t *entry = socket_data->queue.head; // Can't start sending more data until outstanding data complete if (socket_data->upload_active) return; // No more data to send if (entry == NULL) return; // Send the head n = send(socket_data->sockfd, entry->data, entry->length, 0); if (n != entry->length) print_and_exit("ERROR: send failed on socket %d\n", socket_data->sockfd); socket_data->upload_active = 1; }
/* * Library code */ int initialise_socket(char *ip_addr_str, char *port_str) { int sockfd = 0; int n = 0; unsigned char command_buffer[1]; struct sockaddr_in serv_addr; char *end_pointer = NULL; int port = 0; int connect_retries = 0; if (DEBUG) g_log = fopen("run.log", "w"); signal(SIGINT, interrupt_handler); #ifdef _WIN32 { //Start up Winsock WSADATA wsadata; int retval = WSAStartup(0x0202, &wsadata); if (retval) print_and_exit("ERROR: WSAStartup failed with '%d'\n", retval); //Did we get the right Winsock version? if (wsadata.wVersion != 0x0202) { WSACleanup(); print_and_exit("ERROR: WSAStartup version incorrect '%x'\n", wsadata.wVersion); } } #endif // _WIN32 // Need the fflush because there is no newline in the print printf("Connecting"); fflush(stdout); while (1) { if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) print_and_exit("ERROR: Could not create socket\n"); memset(&serv_addr, 0, sizeof(serv_addr)); // Parse the port parameter end_pointer = (char*)port_str; port = strtol(port_str, &end_pointer, 10); if (end_pointer == port_str) print_and_exit("ERROR: Failed to parse port\n"); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); if (inet_pton(AF_INET, ip_addr_str, &serv_addr.sin_addr) <= 0) print_and_exit("ERROR: inet_pton error occured\n"); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { close(sockfd); if (connect_retries < MAX_NUM_CONNECT_RETRIES) { // Need the fflush because there is no newline in the print printf("."); fflush(stdout); #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif connect_retries++; } else { print_and_exit("\nERROR: Connect failed on ip: %s, port: %s\n",ip_addr_str, port_str); } } else { break; } } // Send the command to request which event types to receive command_buffer[0] = XSCOPE_SOCKET_MSG_EVENT_DATA | XSCOPE_SOCKET_MSG_EVENT_PRINT; n = send(sockfd, command_buffer, 1, 0); if (n != 1) print_and_exit("\nERROR: Command send failed\n"); printf(" - connected to ip: %s, port: %s\n",ip_addr_str, port_str); return sockfd; }
/* * Function to handle all data being received on the socket. It handles the * fact that full messages may not be received together and therefore needs * to keep the remainder of any message that hasn't been processed yet. */ void handle_sockets(int *sockfd, int no_of_sock) { int total_bytes = 0; int num_remaining_bytes = 0; unsigned char recv_buffer[MAX_RECV_BYTES]; int i = 0,max_sockfd=0,activity=0,sock_fd=0,n=0; // Keep track of whether a message should be printed at the start of the line // and when the prompt needs to be printed int new_line = 1; //set of socket descriptors fd_set readfds; while(1) { #if 1 // clear the socket set FD_ZERO(&readfds); #endif #if 1 // add sockets to set for(i=0; i < no_of_sock; i++) { // if valid socket descriptor then add to read list if(sockfd[i] > 0) FD_SET(sockfd[i],&readfds); // highest file descriptor number, need it for the select function if(sockfd[i] > max_sockfd) max_sockfd = sockfd[i]; } #endif // wait for an activity on one of the sockets, timeout is NULL, so wait indefinitely activity = select(max_sockfd+1, &readfds, NULL, NULL, NULL); if( (activity < 0) && (errno != EINTR) ) printf("select error\n");fflush(stdout); // If something happened on the socket for(i = 0; i< no_of_sock; i++) { sock_fd = sockfd[i]; if(FD_ISSET(sock_fd, &readfds)) { // read the incoming message #ifdef _WIN32 if((n = recv(sock_fd, &recv_buffer[num_remaining_bytes],sizeof(recv_buffer) - num_remaining_bytes, MSG_PARTIAL)) > 0) { #else if((n = read(sock_fd, &recv_buffer[num_remaining_bytes],sizeof(recv_buffer) - num_remaining_bytes)) > 0) { #endif int i; if (DEBUG) fprintf(g_log, ">> Received %d", n); n += num_remaining_bytes; num_remaining_bytes = 0; if (DEBUG) { for (i = 0; i < n; i++) { if ((i % 16) == 0) fprintf(g_log, "\n"); fprintf(g_log, "%02x ", recv_buffer[i]); } fprintf(g_log, "\n"); } for (i = 0; i < n; ) { // Indicate when a block of data has been handled by the fact that the pointer can move on int increment = 0; if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_PRINT) { // Data to print to the screen has been received unsigned int string_len = 0; // Need one byte for type, then 8 bytes of time stamp and 4 bytes of length if ((i + PRINT_EVENT_BYTES) <= n) { unsigned int string_len = EXTRACT_UINT(recv_buffer, i + 9); int string_start = i + PRINT_EVENT_BYTES; int string_end = i + PRINT_EVENT_BYTES + string_len; // Ensure the buffer won't overflow (has to be after variable // declaration for Windows c89 compile) assert(string_len < MAX_RECV_BYTES); if (string_end <= n) { // Ensure the string is null-terminated - but remember the data byte // in order to be able to restore it. unsigned char tmp = recv_buffer[string_end]; recv_buffer[string_end] = '\0'; if (new_line && (g_prompt != NULL)) { // When starting to print a message, emit a carriage return in order // to overwrite the prompt printf("\r"); new_line = 0; } fwrite(&recv_buffer[string_start], sizeof(unsigned char), string_len, stdout); if (recv_buffer[string_end - 1] == '\n') { // When a string ends with a newline then print the prompt again if (g_prompt != NULL) printf("%s", g_prompt); new_line = 1; } // Because there is no newline character at the end of the prompt and there // may be none at the end of the string then we need to flush explicitly fflush(stdout); // Restore the end character recv_buffer[string_end] = tmp; increment = PRINT_EVENT_BYTES + string_len; } //(string_end <= n) } //((i + PRINT_EVENT_BYTES) <= n) } else if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_DATA) { // Data has been received, put it into the pcap file if ((i + DATA_EVENT_HEADER_BYTES) <= n) { int xscope_probe = recv_buffer[i+1]; int packet_len = EXTRACT_UINT(recv_buffer, i + 4); // Fixed-length data packets are encoded with a length of 0 // but actually carry 8 bytes of data if (packet_len == 0) packet_len = 8; if ((i + packet_len + DATA_EVENT_BYTES) <= n) { // Data starts after the message header int data_start = i + DATA_EVENT_HEADER_BYTES; // An entire packet has been received - write it to the file total_bytes += packet_len; hook_data_received(sock_fd,xscope_probe, &recv_buffer[data_start], packet_len); increment = packet_len + DATA_EVENT_BYTES; } } } else if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_TARGET_DATA) { // The target acknowledges that it has received the message sent if ((i + TARGET_DATA_EVENT_BYTES) <= n) { xscope_ep_upload_pending = 0; increment = TARGET_DATA_EVENT_BYTES; } } else { print_and_exit("ERROR: Message format corrupted (received %u)\n", recv_buffer[i]); } if (increment) { i += increment; } else { // Only part of the packet received - store rest for next iteration num_remaining_bytes = n - i; memmove(recv_buffer, &recv_buffer[i], num_remaining_bytes); if (DEBUG) fprintf(g_log, "%d remaining\n", num_remaining_bytes); break; } } } } } } //while(1) }
int main(int argc, char *argv[]) { #ifdef _WIN32 HANDLE thread; #else pthread_t tid; #endif char *server_ip = DEFAULT_SERVER_IP; char *port_str = DEFAULT_PORT; char *filename = DEFAULT_FILE; int err = 0; int sockfd = 0; int c = 0; while ((c = getopt(argc, argv, "ls:p:")) != -1) { switch (c) { case 's': server_ip = optarg; break; case 'p': port_str = optarg; break; case 'l': g_libpcap_mode = 1; break; case ':': /* -f or -o without operand */ fprintf(stderr, "Option -%c requires an operand\n", optopt); err++; break; case '?': fprintf(stderr, "Unrecognized option: '-%c'\n", optopt); err++; } } for ( ; optind < argc; optind++) { if (filename != DEFAULT_FILE) err++; filename = argv[optind]; break; } if (err) usage(argv); sockfd = initialise_common(server_ip, port_str); g_pcap_fptr = fopen(filename, "wb"); if (g_libpcap_mode) { // Emit libpcap common header emit_pcap_header(g_pcap_fptr); } else { // Emit common header and two interface descriptions as there are two on the tap emit_pcapng_section_header_block(g_pcap_fptr); emit_pcapng_interface_description_block(g_pcap_fptr); emit_pcapng_interface_description_block(g_pcap_fptr); } fflush(g_pcap_fptr); // Now start the console #ifdef _WIN32 thread = CreateThread(NULL, 0, console_thread, &sockfd, 0, NULL); if (thread == NULL) print_and_exit("ERROR: Failed to create console thread\n"); #else err = pthread_create(&tid, NULL, &console_thread, &sockfd); if (err != 0) print_and_exit("ERROR: Failed to create console thread\n"); #endif handle_socket(sockfd); return 0; }
void mutex_acquire(mutex_t *mutex) { if (pthread_mutex_lock(mutex)) print_and_exit("ERROR: mutex acquire failed\n"); }
void mutex_release(mutex_t *mutex) { if (pthread_mutex_unlock(mutex)) print_and_exit("ERROR: mutex release failed\n"); }
void mutex_create(mutex_t *mutex) { if (pthread_mutex_init(mutex, NULL) != 0) print_and_exit("ERROR: mutex init failed\n"); }
void mutex_release(mutex_t *mutex) { if (! ReleaseMutex(*mutex)) print_and_exit("ERROR: mutex release failed\n"); }
void mutex_acquire(mutex_t *mutex) { DWORD result = WaitForSingleObject(*mutex, INFINITE); if (result != WAIT_OBJECT_0) print_and_exit("ERROR: mutex acquire failed\n"); }
int initialise_common(char *ip_addr_str, char *port_str) { int sockfd = 0; int n = 0; unsigned char command_buffer[1]; struct sockaddr_in serv_addr; char *end_pointer = NULL; int port = 0; if (DEBUG) g_log = fopen("run.log", "w"); signal(SIGINT, interrupt_handler); #ifdef _WIN32 { //Start up Winsock WSADATA wsadata; int retval = WSAStartup(0x0202, &wsadata); if (retval) print_and_exit("ERROR: WSAStartup failed with '%d'\n", retval); //Did we get the right Winsock version? if (wsadata.wVersion != 0x0202) { WSACleanup(); print_and_exit("ERROR: WSAStartup version incorrect '%x'\n", wsadata.wVersion); } } #endif // _WIN32 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) print_and_exit("ERROR: Could not create socket\n"); memset(&serv_addr, 0, sizeof(serv_addr)); // Parse the port parameter end_pointer = (char*)port_str; port = strtol(port_str, &end_pointer, 10); if (end_pointer == port_str) print_and_exit("ERROR: Failed to parse port\n"); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(port); if (inet_pton(AF_INET, ip_addr_str, &serv_addr.sin_addr) <= 0) print_and_exit("ERROR: inet_pton error occured\n"); if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) print_and_exit("ERROR: Connect failed\n"); // Send the command to request which event types to receive command_buffer[0] = XSCOPE_SOCKET_MSG_EVENT_DATA | XSCOPE_SOCKET_MSG_EVENT_PRINT; //command_buffer[0] = XSCOPE_SOCKET_MSG_EVENT_DATA; n = send(sockfd, command_buffer, 1, 0); if (n != 1) print_and_exit("ERROR: Command send failed\n"); printf("Connected\n"); return sockfd; }
/* * Function to handle all data being received on the socket. It handles the * fact that full messages may not be received together and therefore needs * to keep the remainder of any message that hasn't been processed yet. */ void handle_socket(int sockfd) { int total_bytes = 0; int num_remaining_bytes = 0; unsigned char recv_buffer[MAX_RECV_BYTES]; int n = 0; // Keep track of whether a message should be printed at the start of the line // and when the prompt needs to be printed int new_line = 1; #ifdef _WIN32 while ((n = recv(sockfd, &recv_buffer[num_remaining_bytes], sizeof(recv_buffer) - num_remaining_bytes, MSG_PARTIAL)) > 0) { #else while ((n = read(sockfd, &recv_buffer[num_remaining_bytes], sizeof(recv_buffer) - num_remaining_bytes)) > 0) { #endif int i; if (DEBUG) fprintf(g_log, ">> Received %d", n); n += num_remaining_bytes; num_remaining_bytes = 0; if (DEBUG) { for (i = 0; i < n; i++) { if ((i % 16) == 0) fprintf(g_log, "\n"); fprintf(g_log, "%02x ", recv_buffer[i]); } fprintf(g_log, "\n"); } for (i = 0; i < n; ) { // Indicate when a block of data has been handled by the fact that the pointer can move on int increment = 0; if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_PRINT) { // Data to print to the screen has been received unsigned int string_len = 0; // Need one byte for type, then 8 bytes of time stamp and 4 bytes of length if ((i + PRINT_EVENT_BYTES) <= n) { unsigned int string_len = EXTRACT_UINT(recv_buffer, i + 9); int string_start = i + PRINT_EVENT_BYTES; int string_end = i + PRINT_EVENT_BYTES + string_len; // Ensure the buffer won't overflow (has to be after variable // declaration for Windows c89 compile) assert(string_len < MAX_RECV_BYTES); if (string_end <= n) { // Ensure the string is null-terminated - but remember the data byte // in order to be able to restore it. unsigned char tmp = recv_buffer[string_end]; recv_buffer[string_end] = '\0'; if (new_line && (g_prompt != NULL)) { // When starting to print a message, emit a carriage return in order // to overwrite the prompt printf("\r"); new_line = 0; } fwrite(&recv_buffer[string_start], sizeof(unsigned char), string_len, stdout); if (recv_buffer[string_end - 1] == '\n') { // When a string ends with a newline then print the prompt again if (g_prompt != NULL) printf("%s", g_prompt); // Because there is no newline character we need to explictly flush fflush(stdout); new_line = 1; } // Restore the end character recv_buffer[string_end] = tmp; increment = PRINT_EVENT_BYTES + string_len; } } } else if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_DATA) { // Data has been received, put it into the pcap file if ((i + DATA_EVENT_HEADER_BYTES) <= n) { int packet_len = EXTRACT_UINT(recv_buffer, i + 4); if ((i + packet_len + DATA_EVENT_BYTES) <= n) { // Data starts after the message header int data_start = i + DATA_EVENT_HEADER_BYTES; // An entire packet has been received - write it to the file total_bytes += packet_len; hook_data_received(&recv_buffer[data_start], packet_len); increment = packet_len + DATA_EVENT_BYTES; } } } else if (recv_buffer[i] == XSCOPE_SOCKET_MSG_EVENT_TARGET_DATA) { // The target acknowledges that it has received the message sent if ((i + TARGET_DATA_EVENT_BYTES) <= n) { assert(xscope_ep_upload_pending > 0); xscope_ep_upload_pending--; increment = TARGET_DATA_EVENT_BYTES; } } else { print_and_exit("ERROR: Message format corrupted (received %u)\n", recv_buffer[0]); } if (increment) { i += increment; } else { // Only part of the packet received - store rest for next iteration num_remaining_bytes = n - i; memmove(recv_buffer, &recv_buffer[i], num_remaining_bytes); if (DEBUG) fprintf(g_log, "%d remaining\n", num_remaining_bytes); break; } } } } void emit_pcap_header(FILE *f) { pcap_hdr_t header = { 0xA1B2C3D4, // Byte-Order Magic 0x2, // Major Version 0x4, // Minor Version 0x0, // Time zone (GMT) 0x0, // Accuracy - simply set 0 CAPTURE_LENGTH, // Snaplength DATA_LINK_ETHERNET, // Data link type }; fwrite(&header, sizeof(header), 1, f); }