95e622ae3730acb53ffd8accba2bacfe5180af40
[profile/ivi/dlt-daemon.git] / src / tests / dlt-test-multi-process-client.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  *
16  * \author Lassi Marttala <Lassi.LM.Marttala@partner.bmw.de> BMW 2011-2012
17  *
18  * \file dlt-test-multi-process-client.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23 /*******************************************************************************
24  **                                                                            **
25  **  SRC-MODULE: dlt-test-multi-process-client.c                               **
26  **                                                                            **
27  **  TARGET    : linux                                                         **
28  **                                                                            **
29  **  PROJECT   : DLT                                                           **
30  **                                                                            **
31  **  AUTHOR    : Lassi Marttala <Lassi.LM.Marttala@partner.bmw.de>             **
32  **                                                                            **
33  **  PURPOSE   : Receive, validate and measure data from multi process tester  **
34  **                                                                            **
35  **  REMARKS   :                                                               **
36  **                                                                            **
37  **  PLATFORM DEPENDANT [yes/no]: yes                                          **
38  **                                                                            **
39  **  TO BE CHANGED BY USER [yes/no]: no                                        **
40  **                                                                            **
41  *******************************************************************************/
42 // System includes
43 #include <string.h>
44 #include <stdio.h>
45 #include <unistd.h>
46 #include <ctype.h>
47 #include <stdlib.h>
48 #include <time.h>
49 #include <fcntl.h>
50 #include <sys/uio.h>
51 #include <sys/stat.h>
52
53 // DLT Library includes
54 #include "dlt_client.h"
55 #include "dlt_protocol.h"
56 #include "dlt_user.h"
57 // PRivate includes
58 #include "dlt-test-multi-process.h"
59
60 // Local data structures
61 typedef struct {
62         int max_messages;
63         int verbose;
64         int serial;
65         int baudrate;
66         char *output;
67         int output_handle;
68         int messages_left;
69         DltClient *client_ref;
70 } s_parameters;
71
72 typedef struct {
73          int messages_received;
74          int broken_messages_received;
75          int bytes_received;
76          int first_message_time;
77          int output_bytes;
78 } s_statistics;
79
80 // Forward declarations
81 int receive(DltMessage *msg, void *data);
82
83 /**
84  * Print usage information
85  */
86 void usage(char *name) {
87         char version[255];
88         dlt_get_version(version,255);
89
90         printf("Usage: %s [options] <remote address|serial device>\n", name);
91         printf("Receive messages from dlt-test-multi-process.\n");
92         printf("%s", version);
93         printf("Options:\n");
94         printf(" -m             Total messages to receive. (Default: 10000)\n");
95     printf(" -y             Serial device mode.\n");
96     printf(" -b baudrate    Serial device baudrate. (Default: 115200)\n");
97         printf(" -v             Verbose. Increases the verbosity level of dlt client library.\n");
98     printf(" -o filename    Output messages in new DLT file.\n");
99 }
100
101 /**
102  * Initialize reasonable default parameters.
103  */
104 void init_params(s_parameters *params) {
105         params->max_messages = 10000;
106         params->verbose = 0;
107         params->serial = 0;
108         params->output = NULL;
109         params->output_handle = -1;
110         params->baudrate = 115200;
111 }
112
113 /**
114  * Read the command line parameters
115  */
116 int read_params(s_parameters *params, int argc, char *argv[]) {
117         init_params(params);
118         int c;
119         opterr = 0;
120         while ((c = getopt(argc, argv, "m:yb:vo:")) != -1) {
121                 switch (c) {
122                 case 'm':
123                         params->max_messages = atoi(optarg);
124                         break;
125                 case 'y':
126                         params->serial = 1;
127                         break;
128                 case 'b':
129                         params->baudrate = atoi(optarg);
130                         break;
131                 case 'v':
132                         params->verbose = 1;
133                         break;
134                 case 'o':
135                         params->output = optarg;
136                         break;
137                 case '?':
138                         if(optopt == 'm' || optopt == 'b' || optopt == 'o')
139                         {
140                                 fprintf(stderr, "Option -%c requires an argument.\n", optopt);
141                         }
142                         if (isprint(optopt)) {
143                                 fprintf(stderr, "Unknown option '-%c'.\n", optopt);
144                         } else {
145                                 fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);
146                         }
147                         return -1;
148                         break;
149                 default:
150                         return -1;
151                 }
152         }
153         return 0;
154 }
155
156 /**
157  * Set the connection parameters for dlt client
158  */
159 int init_dlt_connect(DltClient *client, const s_parameters *params, int argc, char *argv[]) {
160         char id[4];
161         if (argc < 2)
162                 return -1;
163         if(params->serial > 0)
164         {
165                 client->serial_mode = 1;
166                 client->serialDevice = argv[argc - 1];
167                 dlt_client_setbaudrate(client, params->baudrate);
168         }
169         else
170         {
171                 client->servIP = argv[argc - 1];
172         }
173         dlt_set_id(id, ECUID);
174         return 0;
175 }
176
177 /**
178  * Entry point
179  */
180 int main(int argc, char *argv[]) {
181         s_parameters params;
182         DltClient client;
183         params.client_ref = &client;
184         int err = read_params(&params, argc, argv);
185
186         if (err != 0) {
187                 usage(argv[0]);
188                 return err;
189         }
190
191         dlt_client_init(&client, params.verbose);
192         dlt_client_register_message_callback(receive);
193
194         err = init_dlt_connect(&client, &params, argc, argv);
195         if (err != 0) {
196                 usage(argv[0]);
197                 return err;
198         }
199
200         err = dlt_client_connect(&client, params.verbose);
201         if (err != 0) {
202                         printf("Failed to connect %s.\n", client.serial_mode > 0 ? client.serialDevice : client.servIP);
203                 return err;
204         }
205
206     if(params.output)
207     {
208         params.output_handle = open(params.output,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
209
210         if (params.output_handle == -1)
211         {
212             fprintf(stderr,"Failed to open %s for writing.\n",params.output);
213             return -1;
214         }
215     }
216
217     params.messages_left = params.max_messages;
218
219         dlt_client_main_loop(&client, &params, params.verbose);
220
221         if(params.output_handle > 0)
222         {
223                 close(params.output_handle);
224         }
225         return 0;
226 }
227
228 /**
229  * Print current test statistics
230  */
231 void print_stats(s_statistics stats, s_parameters params)
232 {
233         static int last_print_time;
234         if(last_print_time >= time(NULL) && // Only print once a second
235            (stats.messages_received+stats.broken_messages_received) % 1000 != 0 &&
236            params.messages_left != 0) // Print also every 1000th message
237         {
238                 return;
239         }
240         printf("\033[2J\033[1;1H"); // Clear screen.
241         printf("Statistics:\n");
242         printf(" Messages received             : %d\n", stats.messages_received);
243         printf(" Broken messages received      : %d\n", stats.broken_messages_received);
244         printf(" Bytes received                : %d\n", stats.bytes_received);
245         printf(" Time running (seconds)        : %ld\n", time(NULL)-stats.first_message_time);
246         printf(" Throughput (msgs/sec)/(B/sec) : %ld/%ld\n",
247                         stats.messages_received/((time(NULL)-stats.first_message_time)+1),
248                         (stats.bytes_received)/((time(NULL)-stats.first_message_time)+1));
249         if(params.messages_left == 0)
250         {
251                 if(stats.broken_messages_received == 0)
252                         printf("All messages received succesfully!\n");
253                 else
254                         printf("Test failure! There were %d broken messages.", stats.broken_messages_received);
255
256         }
257         fflush(stdout);
258         last_print_time = time(NULL);
259 }
260 /**
261  * Callback for dlt client
262  */
263 int receive(DltMessage *msg, void *data) {
264         static s_statistics stats;
265         char apid[5];
266         struct iovec iov[2];
267         s_parameters *params = (s_parameters *)data;
268
269         memset(apid, 0, 5);
270         memcpy(apid, msg->extendedheader->apid, 4);
271
272         if(apid[0] != 'M' || apid[1] != 'T') // TODO: Check through the app description
273                 return 0;
274
275     params->messages_left--;
276
277         if(stats.first_message_time == 0)
278         {
279                 stats.first_message_time = time(NULL);
280         }
281
282         int buflen = msg->datasize + 1;
283         char *buf = malloc(buflen);
284         if(buf==0)
285         {
286                 printf("Out of memory\n");
287                 return -1;
288         }
289         memset(buf, 0, buflen);
290
291         dlt_message_payload(msg,buf,buflen-1,DLT_OUTPUT_ASCII,0);
292
293         if(strcmp(buf, PAYLOAD_DATA) == 0)
294         {
295                 stats.messages_received++;
296         }
297         else
298         {
299                 stats.broken_messages_received++;
300         }
301         stats.bytes_received += msg->datasize+msg->headersize-sizeof(DltStorageHeader);;
302
303         free(buf);
304
305         print_stats(stats, *params);
306
307     if (params->output_handle > 0)
308     {
309         iov[0].iov_base = msg->headerbuffer;
310         iov[0].iov_len = msg->headersize;
311         iov[1].iov_base = msg->databuffer;
312         iov[1].iov_len = msg->datasize;
313
314         stats.output_bytes += writev(params->output_handle, iov, 2);
315     }
316     if(params->messages_left < 1)
317     {
318         dlt_client_cleanup(params->client_ref, params->verbose);
319     }
320         return 0;
321 }