diff options
author | Igal Chernobelsky | 2012-09-13 09:03:10 -0500 |
---|---|---|
committer | Igal Chernobelsky | 2012-09-13 09:03:10 -0500 |
commit | 37c7d38f3c3f6ceca5c53a7fa4117d682e7c2511 (patch) | |
tree | d6df0951dce87e0553c3a0165a3c5320dd83905a | |
parent | cfff7784f4442b30c7075aedc653934130b0b7fa (diff) | |
download | ti-utils-37c7d38f3c3f6ceca5c53a7fa4117d682e7c2511.tar.gz ti-utils-37c7d38f3c3f6ceca5c53a7fa4117d682e7c2511.tar.xz ti-utils-37c7d38f3c3f6ceca5c53a7fa4117d682e7c2511.zip |
wl_logproxy: updated to latest version
Update logproxy service to the latest version.
Signed-off-by: Igal Chernobelsky <igalc@ti.com>
-rwxr-xr-x | wl_logproxy.c | 461 |
1 files changed, 332 insertions, 129 deletions
diff --git a/wl_logproxy.c b/wl_logproxy.c index fa82b2f..dee4a4b 100755 --- a/wl_logproxy.c +++ b/wl_logproxy.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * Description: Log Proxy for real-time log viewing | 3 | * Description: wl Firmware Log Service for off-line and real-time log viewing |
4 | * Author: Gil Barak | 4 | * Maintainer: gil.barak@ti.com |
5 | * Date: 15/06/2012 | 5 | * Last Update: 14/08/2012 |
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | #include <stdio.h> | 8 | #include <stdio.h> |
@@ -16,21 +16,32 @@ | |||
16 | #include <sys/time.h> | 16 | #include <sys/time.h> |
17 | #include <netinet/in.h> | 17 | #include <netinet/in.h> |
18 | #include <signal.h> | 18 | #include <signal.h> |
19 | #include <errno.h> | ||
19 | 20 | ||
21 | |||
22 | /* Defines */ | ||
20 | #define INVALID_HANDLE -1 | 23 | #define INVALID_HANDLE -1 |
21 | 24 | ||
22 | #define BUFFER_SIZE 256 | 25 | #define FILE_NAME "wl_fwlog.log" |
23 | #define FILE_POLL_INTERVAL 2 // in seconds | 26 | #define FILE_NAME_PREV "wl_fwlog_prev.log" |
24 | #define KEEP_ALIVE_INTERVAL 5 // in seconds | ||
25 | 27 | ||
28 | #define BUFFER_SIZE 1024 | ||
29 | #define FILE_POLL_INTERVAL 60 // in seconds | ||
30 | #define KEEP_ALIVE_INTERVAL 1 // in seconds | ||
31 | #define MAX_PATH 256 | ||
32 | #define MAX_FILE_SIZE 100000000 // Max file size is 100mb | ||
33 | /***********/ | ||
26 | 34 | ||
27 | int socket_connected = 0; | ||
28 | 35 | ||
36 | /* Globals */ | ||
37 | int socket_connected = 0; | ||
38 | int socket_enabled = 0; | ||
39 | /***********/ | ||
29 | 40 | ||
30 | 41 | ||
31 | void error(const char *msg) | 42 | void error(const char *msg) |
32 | { | 43 | { |
33 | printf("FW LOGGER: %s\r\n", msg); | 44 | printf("FW LOGGER ERROR: %s\r\n", msg); |
34 | } | 45 | } |
35 | 46 | ||
36 | 47 | ||
@@ -40,152 +51,344 @@ void sigpipe_handler() | |||
40 | socket_connected = 0; | 51 | socket_connected = 0; |
41 | } | 52 | } |
42 | 53 | ||
54 | // ************************************************** // | ||
55 | // | ||
56 | // Function name: create_listen_socket | ||
57 | // | ||
58 | // Description: Listen on a local port for remote | ||
59 | // client connections | ||
60 | // | ||
61 | // | ||
62 | // | ||
63 | // | ||
64 | // ************************************************** // | ||
65 | int create_listen_socket(int listen_port) | ||
66 | { | ||
67 | struct sockaddr_in serv_addr, cli_addr; | ||
68 | int sock_flags = 0; | ||
69 | int listen_sock = INVALID_HANDLE; | ||
70 | |||
71 | if(listen_port == 0) | ||
72 | { | ||
73 | socket_enabled = 0; | ||
74 | return -1; | ||
75 | } | ||
76 | |||
77 | listen_sock = socket(AF_INET, SOCK_STREAM, 0); | ||
78 | if (listen_sock == INVALID_HANDLE) | ||
79 | { | ||
80 | error("opening socket\r\n"); | ||
81 | exit(1); | ||
82 | } | ||
83 | |||
84 | bzero((char *) &serv_addr, sizeof(serv_addr)); | ||
85 | serv_addr.sin_family = AF_INET; | ||
86 | serv_addr.sin_addr.s_addr = INADDR_ANY; | ||
87 | serv_addr.sin_port = htons(listen_port); | ||
88 | |||
89 | // Bind to local port | ||
90 | if (bind(listen_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) | ||
91 | { | ||
92 | error("on binding\r\n"); | ||
93 | exit(1); | ||
94 | } | ||
95 | |||
96 | listen(listen_sock,1); | ||
97 | |||
98 | // Set the callback for socket timeout signal handling | ||
99 | signal(SIGPIPE,sigpipe_handler); | ||
100 | |||
101 | |||
102 | // Set the listening socket to non-blocking mode | ||
103 | sock_flags = fcntl(listen_sock, F_GETFL, 0); | ||
104 | fcntl(listen_sock, F_SETFL, sock_flags | O_NONBLOCK); | ||
105 | |||
106 | return listen_sock; | ||
107 | } | ||
43 | 108 | ||
44 | int main(int argc, char *argv[]) | 109 | // ************************************************** // |
110 | // | ||
111 | // Function Name: accept_client | ||
112 | // | ||
113 | // Description: | ||
114 | // Monitor client activity and allow new | ||
115 | // connections if the client is disconnected | ||
116 | // | ||
117 | // | ||
118 | // ************************************************** // | ||
119 | int accept_client(int listen_sock) | ||
45 | { | 120 | { |
46 | int sockfd, newsockfd, portno; | 121 | int client_sock = INVALID_HANDLE; |
47 | socklen_t clilen; | 122 | socklen_t clilen; |
48 | char buffer[BUFFER_SIZE + 1] = {0}; // +1 for safety | 123 | struct sockaddr_in cli_addr; |
49 | char ka_buff; | 124 | struct timeval tv; |
50 | struct sockaddr_in serv_addr, cli_addr; | 125 | |
51 | int n = 0; | 126 | tv.tv_sec = KEEP_ALIVE_INTERVAL; |
52 | int sent_bytes = 0; | 127 | tv.tv_usec = 0; |
53 | int fp_fwlog = INVALID_HANDLE; | 128 | |
54 | struct timeval tv; | 129 | clilen = sizeof(cli_addr); |
130 | // Non-Blocking accept for remote client connections | ||
131 | client_sock = accept(listen_sock, (struct sockaddr *) &cli_addr, &clilen); | ||
132 | |||
133 | if(client_sock != INVALID_HANDLE) | ||
134 | { | ||
135 | printf("Client connected!\r\n"); | ||
136 | if(setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))) | ||
137 | { | ||
138 | error("failed to set timeout for recv\r\n"); | ||
139 | close(client_sock); | ||
140 | close(listen_sock); | ||
141 | exit(EXIT_FAILURE); | ||
142 | } | ||
143 | socket_connected = 1; | ||
144 | } | ||
145 | |||
146 | return client_sock; | ||
147 | } | ||
55 | 148 | ||
149 | // ************************************************** // | ||
150 | // | ||
151 | // Function Name: send_data | ||
152 | // | ||
153 | // Description: | ||
154 | // Send the binary logs to the remote | ||
155 | // client that is currently connected | ||
156 | // | ||
157 | // | ||
158 | // ************************************************** // | ||
159 | void send_data(int client_sock, char *buffer, int buf_size) | ||
160 | { | ||
161 | int sent_bytes = 0; | ||
162 | // Send the buffer to the remote client | ||
163 | if(socket_connected) | ||
164 | { | ||
165 | sent_bytes = 0; | ||
166 | while( buf_size > 0 ) | ||
167 | { | ||
168 | sent_bytes = send(client_sock,(char *)(buffer + sent_bytes),buf_size,0); | ||
169 | if (sent_bytes < 0) | ||
170 | { | ||
171 | printf("Send failed! %d %d\n", buf_size, client_sock); | ||
172 | close(client_sock); | ||
173 | socket_connected = 0; | ||
174 | break; | ||
175 | } | ||
176 | buf_size -= sent_bytes; | ||
177 | } | ||
178 | } | ||
179 | } | ||
56 | 180 | ||
181 | // ************************************************** // | ||
182 | // | ||
183 | // Function Name: keep_alive | ||
184 | // | ||
185 | // Description: | ||
186 | // Verify that the remote client is | ||
187 | // alive by receiving keep alive data | ||
188 | // | ||
189 | // | ||
190 | // ************************************************** // | ||
191 | void keep_alive(int client_sock) | ||
192 | { | ||
193 | char ka_buff; | ||
194 | int n = 0; | ||
195 | // Verify keep alive | ||
196 | if(socket_connected) | ||
197 | { | ||
198 | n = recv(client_sock, &ka_buff, 1, 0); | ||
199 | if (n < 0) | ||
200 | { | ||
201 | error("Client disconnected"); | ||
202 | close(client_sock); | ||
203 | socket_connected = 0; | ||
204 | } | ||
205 | } | ||
206 | } | ||
57 | 207 | ||
58 | if (argc < 3) { | 208 | // ************************************************** // |
59 | fprintf(stderr,"Usage: ./logProxy [listen port] [log file path]\n"); | 209 | // |
60 | exit(1); | 210 | // Function Name: open_fwlog |
61 | } | 211 | // |
212 | // Description: | ||
213 | // Wait until the fwlog file is created | ||
214 | // and open it for read access | ||
215 | // | ||
216 | // Return: | ||
217 | // file handle to fwlog | ||
218 | // | ||
219 | // ************************************************** // | ||
220 | int open_fwlog(int fp_fwlog, char *file_path) | ||
221 | { | ||
222 | if(fp_fwlog == INVALID_HANDLE) | ||
223 | { | ||
224 | fp_fwlog = open(file_path, O_RDONLY); | ||
225 | } | ||
62 | 226 | ||
63 | sockfd = socket(AF_INET, SOCK_STREAM, 0); | 227 | return fp_fwlog; |
64 | if (sockfd < 0) { | 228 | } |
65 | error("opening socket\r\n"); | ||
66 | exit(1); | ||
67 | } | ||
68 | 229 | ||
69 | bzero((char *) &serv_addr, sizeof(serv_addr)); | 230 | // ************************************************** // |
70 | portno = atoi(argv[1]); | 231 | // |
71 | serv_addr.sin_family = AF_INET; | 232 | // Function Name: read_fwlog |
72 | serv_addr.sin_addr.s_addr = INADDR_ANY; | 233 | // |
73 | serv_addr.sin_port = htons(portno); | 234 | // Description: |
74 | 235 | // read the binary logs from the fwlog | |
75 | // Bind to local port | 236 | // into the buffer |
76 | if (bind(sockfd, (struct sockaddr *) &serv_addr, | 237 | // |
77 | sizeof(serv_addr)) < 0) { | 238 | // Return: |
78 | error("on binding\r\n"); | 239 | // file handle to fwlog |
79 | exit(1); | 240 | // |
80 | } | 241 | // ************************************************** // |
242 | int read_fwlog(int fp_fwlog, char *buffer) | ||
243 | { | ||
244 | int n = 0; | ||
245 | bzero(buffer,BUFFER_SIZE); | ||
246 | |||
247 | // Attempt to read logs from the fwlog | ||
248 | n = read(fp_fwlog,buffer,BUFFER_SIZE); | ||
249 | if (n < 0) | ||
250 | { | ||
251 | error("reading from file\r\n"); | ||
252 | return INVALID_HANDLE; | ||
253 | } | ||
254 | return n; | ||
255 | } | ||
81 | 256 | ||
82 | listen(sockfd,1); | 257 | void backup_log(int fp_bkplog, char *buffer, int buf_size) |
258 | { | ||
259 | int wr_bytes = 0; | ||
260 | |||
261 | do | ||
262 | { | ||
263 | wr_bytes = write(fp_bkplog, buffer, buf_size); | ||
264 | if(wr_bytes < 0) | ||
265 | { | ||
266 | error("writing to backup log!"); | ||
267 | exit(EXIT_FAILURE); | ||
268 | } | ||
269 | } | ||
270 | while (wr_bytes < buf_size); | ||
271 | } | ||
272 | |||
273 | int create_file(char *filename) | ||
274 | { | ||
275 | int fp_bkplog; | ||
276 | #ifdef ANDROID | ||
277 | fp_bkplog = open(filename, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR); | ||
278 | #else | ||
279 | fp_bkplog = open(filename, O_RDWR|O_TRUNC|O_CREAT, S_IREAD|S_IWRITE); | ||
280 | #endif | ||
281 | |||
282 | if (fp_bkplog == INVALID_HANDLE) | ||
283 | { | ||
284 | error("Could not open output log file"); | ||
285 | exit(EXIT_FAILURE); | ||
286 | } | ||
287 | |||
288 | return fp_bkplog; | ||
289 | } | ||
290 | // ************************************************** // | ||
291 | // | ||
292 | // Function Name: main | ||
293 | // | ||
294 | // Description: | ||
295 | // | ||
296 | //x | ||
297 | // | ||
298 | // | ||
299 | // ************************************************** // | ||
300 | int main(int argc, char *argv[]) | ||
301 | { | ||
302 | int listen_sock, client_sock = INVALID_HANDLE; | ||
303 | char buffer[BUFFER_SIZE + 1] = {0}; // +1 for safety | ||
304 | int n = 0, buf_size = 0; | ||
305 | int fp_fwlog = INVALID_HANDLE; | ||
306 | int fp_bkplog = INVALID_HANDLE; | ||
307 | char filename[MAX_PATH + 1] = {0}; // +1 for safety | ||
308 | char filename_prev[MAX_PATH + 1] = {0}; // +1 for safety | ||
309 | uint max_file_size = MAX_FILE_SIZE; | ||
310 | struct stat st; | ||
83 | 311 | ||
84 | signal(SIGPIPE,sigpipe_handler); | ||
85 | 312 | ||
86 | clilen = sizeof(cli_addr); | 313 | if (argc < 3) |
87 | while(1) | ||
88 | { | 314 | { |
89 | newsockfd = accept(sockfd, | 315 | fprintf(stderr,"Usage: ./logProxy [listen port] [log file] [backup directory]\n"); |
90 | (struct sockaddr *) &cli_addr, | 316 | exit(EXIT_FAILURE); |
91 | &clilen); | 317 | } |
92 | 318 | ||
93 | socket_connected = 1; | 319 | // Max file size is an optional value |
320 | if(argc > 4) | ||
321 | { | ||
322 | max_file_size = atol(argv[4]); | ||
323 | } | ||
94 | 324 | ||
95 | if (newsockfd <= 0) { | 325 | listen_sock = create_listen_socket(atoi(argv[1])); |
96 | error("accept\r\n"); | ||
97 | close(sockfd); | ||
98 | exit(1); | ||
99 | } | ||
100 | 326 | ||
101 | printf("Client connected!\r\n"); | 327 | // |
328 | // If we arrive here the listen socket was created successfully, otherwise we would have exited the process | ||
329 | // | ||
102 | 330 | ||
103 | bzero(buffer,BUFFER_SIZE); | 331 | // Create the backup file names |
332 | strncpy(filename,argv[3], MAX_PATH - sizeof(FILE_NAME)); | ||
333 | strncpy(filename_prev,argv[3], MAX_PATH - sizeof(FILE_NAME)); | ||
334 | strcat(filename, FILE_NAME); | ||
335 | strcat(filename_prev, FILE_NAME_PREV); | ||
104 | 336 | ||
105 | tv.tv_sec = KEEP_ALIVE_INTERVAL; | 337 | fp_bkplog = create_file(filename); |
106 | tv.tv_usec = 0; | ||
107 | if(setsockopt(newsockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv))) { | ||
108 | error("failed to set timeout for recv\r\n"); | ||
109 | close(newsockfd); | ||
110 | close(sockfd); | ||
111 | exit(1); | ||
112 | } | ||
113 | 338 | ||
339 | // Main Loop | ||
340 | while(1) | ||
341 | { | ||
342 | // Check on the client connection status | ||
343 | if ( (socket_enabled == 1) && | ||
344 | (client_sock == INVALID_HANDLE || socket_connected == 0) ) | ||
345 | { | ||
346 | client_sock = accept_client(listen_sock); | ||
347 | } | ||
348 | |||
349 | if(fp_fwlog != INVALID_HANDLE) | ||
350 | { | ||
351 | // Read the fwlog sysfs file - This is a blocking function | ||
352 | buf_size = read_fwlog(fp_fwlog, buffer); | ||
353 | |||
354 | if(buf_size == INVALID_HANDLE) | ||
355 | { | ||
356 | error("driver unloaded: fwlog has been removed"); | ||
357 | fp_fwlog = INVALID_HANDLE; | ||
358 | continue; | ||
359 | } | ||
114 | 360 | ||
115 | // attempt to read the log file every 5 seconds | 361 | // Create a new file if the log file exceeds the max size |
116 | // this is done in case the driver is down and the file is removed | 362 | stat(filename, &st); |
117 | do | 363 | if(st.st_size >= max_file_size) |
118 | { | 364 | { |
119 | if(!socket_connected) { | 365 | close(fp_bkplog); |
120 | error("socket not connected anymore\r\n"); | 366 | rename(filename, filename_prev); |
121 | break; | 367 | fp_bkplog = create_file(filename); |
122 | } | 368 | } |
123 | 369 | ||
124 | n = recv(newsockfd, &ka_buff, 1, 0); | 370 | // keep alive |
371 | keep_alive(client_sock); | ||
125 | 372 | ||
126 | if (n < 0) { | 373 | if(buf_size > 0) |
127 | error("keep alive timeout\r\n"); | 374 | { |
128 | socket_connected = 0; | 375 | // write the log data into the backup file |
129 | close(newsockfd); | 376 | backup_log(fp_bkplog, buffer, buf_size); |
130 | if(fp_fwlog != INVALID_HANDLE) { | 377 | |
131 | close(fp_fwlog); | 378 | // Try to send the logs to the remote client |
132 | fp_fwlog = INVALID_HANDLE; | 379 | send_data(client_sock, buffer, buf_size); |
133 | } | ||
134 | break; | ||
135 | } | 380 | } |
136 | 381 | ||
137 | fp_fwlog = open(argv[2], O_RDONLY); | ||
138 | sleep(FILE_POLL_INTERVAL); | ||
139 | 382 | ||
140 | } while(fp_fwlog <= 0); | 383 | } |
384 | else | ||
385 | { | ||
386 | // To prevent high io/cpu usage sleep between attempts | ||
387 | sleep(FILE_POLL_INTERVAL); | ||
388 | // Try to open the fwlog file | ||
389 | fp_fwlog = open_fwlog(fp_fwlog, argv[2]); | ||
390 | } | ||
141 | 391 | ||
142 | if(socket_connected) | ||
143 | { | ||
144 | do | ||
145 | { | ||
146 | if(!socket_connected) { | ||
147 | error("socket not connected anymore\r\n"); | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | n = read(fp_fwlog,&buffer,BUFFER_SIZE); | ||
152 | if (n < 0) { | ||
153 | error("reading from file\r\n"); | ||
154 | if(fp_fwlog != INVALID_HANDLE) { | ||
155 | close(fp_fwlog); | ||
156 | fp_fwlog = INVALID_HANDLE; | ||
157 | } | ||
158 | close(newsockfd); | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | sent_bytes = 0; | ||
163 | while( n > 0 ) | ||
164 | { | ||
165 | printf("recved = %d\r\n",n); | ||
166 | sent_bytes = send(newsockfd,(char *)(buffer + sent_bytes),n,0); | ||
167 | if (sent_bytes < 0) | ||
168 | { | ||
169 | error("Send failed!"); | ||
170 | break; | ||
171 | } | ||
172 | n -= sent_bytes; | ||
173 | printf("sent_bytes=%d, n=%d\n", sent_bytes,n); | ||
174 | } | ||
175 | |||
176 | n = recv(newsockfd, &ka_buff, 1, 0); | ||
177 | |||
178 | if (n < 0) { | ||
179 | error("keep alive timeout\r\n"); | ||
180 | if(fp_fwlog != INVALID_HANDLE) { | ||
181 | close(fp_fwlog); | ||
182 | fp_fwlog = INVALID_HANDLE; | ||
183 | } | ||
184 | close(newsockfd); | ||
185 | break; | ||
186 | } | ||
187 | } while(1); | ||
188 | } | ||
189 | } | 392 | } |
190 | 393 | ||
191 | return 0; | 394 | return 0; |