1 | #include <stdio.h> |
---|
2 | #include <stdlib.h> |
---|
3 | #include <stdarg.h> |
---|
4 | #include <syslog.h> |
---|
5 | #include <errno.h> |
---|
6 | #include <string.h> |
---|
7 | #include <sys/socket.h> |
---|
8 | #include <arpa/inet.h> |
---|
9 | #include <netdb.h> |
---|
10 | #include <unistd.h> |
---|
11 | #include <pthread.h> |
---|
12 | #include <signal.h> |
---|
13 | #include <sys/wait.h> |
---|
14 | /* |
---|
15 | #include <sys/stat.h> |
---|
16 | #include <sys/types.h> |
---|
17 | #include <sys/mman.h> |
---|
18 | */ |
---|
19 | #include <fcntl.h> |
---|
20 | |
---|
21 | // Buffer size, in bytes, used for copying in the Cat() function. |
---|
22 | const size_t BUF_SIZE = 4096; |
---|
23 | |
---|
24 | // Typedef for a signal handler function. |
---|
25 | typedef void (*signal_handler_t) (int); |
---|
26 | |
---|
27 | // Global variables |
---|
28 | char g_program_name[100]; // Initialised from argv[0] in ParseArgs() |
---|
29 | struct allowed_ip * allowed_ips = (struct allowed_ip *)NULL; |
---|
30 | int quantity_of_fd = 0; // quantity of file descriptor |
---|
31 | |
---|
32 | static struct connections * connections = (struct connections *)NULL; |
---|
33 | pthread_mutex_t mutexsum; |
---|
34 | |
---|
35 | // structs |
---|
36 | struct allowed_ip |
---|
37 | { |
---|
38 | char * ip; |
---|
39 | struct allowed_ip * next; |
---|
40 | }; |
---|
41 | |
---|
42 | struct accept |
---|
43 | { |
---|
44 | int * fd; |
---|
45 | struct sockaddr_in sa; |
---|
46 | struct in_addr jabber_addr; |
---|
47 | unsigned short jabber_port; |
---|
48 | pthread_t accept_thread; |
---|
49 | }; |
---|
50 | |
---|
51 | struct client |
---|
52 | { |
---|
53 | char * user, |
---|
54 | * pass; |
---|
55 | int * jabber_fd, |
---|
56 | * read; |
---|
57 | time_t last_access; |
---|
58 | }; |
---|
59 | |
---|
60 | struct connections |
---|
61 | { |
---|
62 | struct client * client; |
---|
63 | struct connections * next; |
---|
64 | }; |
---|
65 | |
---|
66 | struct read_write |
---|
67 | { |
---|
68 | int * jabber, |
---|
69 | client, |
---|
70 | type; |
---|
71 | pthread_t read, |
---|
72 | write; |
---|
73 | }; |
---|
74 | |
---|
75 | void recursive (int, struct in_addr, unsigned short); |
---|
76 | int getPermission(char *); |
---|
77 | void ParseArgs (int, char **, struct in_addr *, unsigned short *, struct in_addr *, unsigned short *); |
---|
78 | void Initialise (void); |
---|
79 | void sig_child (int); |
---|
80 | int CreateServerSocket (struct in_addr, unsigned short); |
---|
81 | void Daemonise (void); |
---|
82 | void MainLoop (int, struct in_addr, unsigned short); |
---|
83 | void ClearList(void); |
---|
84 | struct accept * AcceptClientConnection (int); |
---|
85 | void VerifyClient(void *); |
---|
86 | struct client * Handshake (struct accept *, struct read_write *); |
---|
87 | void * withConnections(void * (*func)(), ...); |
---|
88 | //struct client * LookFor (char *, char *); |
---|
89 | //void * LookFor (struct connections *, char *, char *); |
---|
90 | void * LookFor (char *, char *); |
---|
91 | void Reading (void *); |
---|
92 | void Writing (void *); |
---|
93 | int ConnectToServer (struct in_addr, unsigned short); |
---|
94 | int NameToAddr (const char *, struct in_addr *); |
---|
95 | int NameToPort (const char *, unsigned short *, const char *); |
---|
96 | #ifdef __GNUC__ |
---|
97 | void quit (const char *, ...) __attribute__ ((format (printf, 1, 2))); |
---|
98 | void pbomb (const char *, ...) __attribute__ ((format (printf, 1, 2))); |
---|
99 | void hbomb (const char *, ...) __attribute__ ((format (printf, 1, 2))); |
---|
100 | #else |
---|
101 | void quit (const char *, ...); |
---|
102 | void pbomb (const char *, ...); |
---|
103 | void hbomb (const char *, ...); |
---|
104 | #endif |
---|
105 | void set_signal_handler (int, signal_handler_t); |
---|
106 | |
---|
107 | int main (int argc, char ** argv) |
---|
108 | { |
---|
109 | struct in_addr remote_addr, |
---|
110 | local_addr; |
---|
111 | unsigned short remote_port, |
---|
112 | local_port; |
---|
113 | int listen_fd; |
---|
114 | |
---|
115 | //pthread_t clear_list_thread; |
---|
116 | |
---|
117 | ParseArgs (argc, argv, &remote_addr, &remote_port, &local_addr, &local_port); |
---|
118 | |
---|
119 | Initialise (); |
---|
120 | |
---|
121 | // Create server socket before becoming a daemon so |
---|
122 | // there is still a chance to print an error message. |
---|
123 | listen_fd = CreateServerSocket (local_addr, local_port); |
---|
124 | if ( listen_fd < 0 ) |
---|
125 | pbomb ("Unable to create server socket"); |
---|
126 | |
---|
127 | //Daemonise (); |
---|
128 | |
---|
129 | //pthread_mutex_init(&mutexsum, NULL); |
---|
130 | //pthread_create(&clear_list_thread, NULL, (void *) &ClearList, (void *)NULL ); |
---|
131 | |
---|
132 | //MainLoop (listen_fd, remote_addr, remote_port); // never returns |
---|
133 | recursive(listen_fd, remote_addr, remote_port); |
---|
134 | |
---|
135 | //pthread_mutex_destroy(&mutexsum); |
---|
136 | |
---|
137 | exit (EXIT_SUCCESS); |
---|
138 | } |
---|
139 | |
---|
140 | void recursive (int listen_fd, struct in_addr rem_addr, unsigned short rem_port) |
---|
141 | { |
---|
142 | //while ( 1 ) |
---|
143 | // sleep(1); |
---|
144 | //exit(0); |
---|
145 | |
---|
146 | pid_t helper_pid; |
---|
147 | |
---|
148 | syslog (LOG_INFO, "recursive()"); |
---|
149 | |
---|
150 | signal (SIGCHLD, SIG_IGN); |
---|
151 | |
---|
152 | helper_pid = fork (); |
---|
153 | if ( helper_pid == -1 ) |
---|
154 | syslog (LOG_ERR, "fork() on recursive(): %m"), exit (EXIT_FAILURE); |
---|
155 | |
---|
156 | if ( helper_pid ) /* parent */ |
---|
157 | { |
---|
158 | //syslog (LOG_INFO, "Forked child pid %d to help with MainLoop", helper_pid); |
---|
159 | wait(0); /* wait for helper to exit */ |
---|
160 | } |
---|
161 | else /* child (helper) */ |
---|
162 | { |
---|
163 | MainLoop (listen_fd, rem_addr, rem_port); |
---|
164 | |
---|
165 | syslog (LOG_INFO, "exiting"); |
---|
166 | exit (0); /* helper exits here */ |
---|
167 | } |
---|
168 | recursive(listen_fd, rem_addr, rem_port); |
---|
169 | } |
---|
170 | |
---|
171 | // ParseArgs() |
---|
172 | // Parse the command line arguments to extract the remote |
---|
173 | // and local adresses and port numbers, ra, rp, la & lp. |
---|
174 | // Exit the program gracefully upon error. |
---|
175 | void ParseArgs (int argc, char ** argv, struct in_addr * ra, unsigned short * rp, struct in_addr * la, unsigned short * lp) |
---|
176 | { |
---|
177 | // argv[0] = program name |
---|
178 | // argv[1] = remote_addr |
---|
179 | // argv[2] = remote_port |
---|
180 | // argv[3] = local_addr (optional) |
---|
181 | // argv[4] = local_port (optional) |
---|
182 | |
---|
183 | char * p = strrchr (argv[0], '/'); |
---|
184 | |
---|
185 | strncpy (g_program_name, (p == NULL) ? argv[0] : p + 1, sizeof (g_program_name) - 1); |
---|
186 | |
---|
187 | if ( (argc < 3) || (argc > 5) ) |
---|
188 | { |
---|
189 | fprintf (stderr, "usage: %s remote_addr remote_port [local_addr] [local_port]\n", argv[0]); |
---|
190 | exit (EXIT_FAILURE); |
---|
191 | } |
---|
192 | |
---|
193 | if ( NameToAddr (argv[1], ra) ) |
---|
194 | hbomb ("Unable to resolve \"%s\" to an ip address", argv[1]); |
---|
195 | |
---|
196 | if ( NameToPort (argv[2], rp, "tcp") ) |
---|
197 | quit ("Unable to resolve \"%s\" to a port number", argv[2]); |
---|
198 | |
---|
199 | if ( argc < 4 ) |
---|
200 | la->s_addr = htonl (INADDR_ANY); |
---|
201 | else |
---|
202 | if ( NameToAddr (argv[3], la) ) |
---|
203 | hbomb ("Unable to resolve \"%s\" to an ip address", argv[3]); |
---|
204 | |
---|
205 | if ( argc < 5 ) |
---|
206 | memcpy (lp, rp, sizeof (*lp)); |
---|
207 | else |
---|
208 | if ( NameToPort (argv[4], lp, "tcp") ) |
---|
209 | quit ("Unable to resolve \"%s\" to a port number", argv[4]); |
---|
210 | } |
---|
211 | |
---|
212 | int getPermission(char * ip) |
---|
213 | { |
---|
214 | struct allowed_ip * allow_ip = allowed_ips; |
---|
215 | int allow = 0; |
---|
216 | |
---|
217 | while ( !allow && allow_ip->next != (struct allowed_ip *)NULL ) |
---|
218 | { |
---|
219 | //printf("strcmp(%s, %s)\n\n", ip, allow_ip->ip); |
---|
220 | if ( strcmp(ip, allow_ip->ip) == 0 ) |
---|
221 | allow = 1; |
---|
222 | else |
---|
223 | allow_ip = allow_ip->next; |
---|
224 | } |
---|
225 | |
---|
226 | return allow; |
---|
227 | } |
---|
228 | |
---|
229 | // Initialise() |
---|
230 | // Setup syslog, signal handlers, and other intialisation. |
---|
231 | void Initialise (void) |
---|
232 | { |
---|
233 | FILE * allowed_ips_fd; |
---|
234 | struct allowed_ip * allow_ip; |
---|
235 | |
---|
236 | if ( !(allowed_ips_fd = fopen("webjabber.cfg", "r")) ) |
---|
237 | syslog (LOG_ERR, "Impossivel abrir o arquivo 'webjabber.cfg'"), exit (EXIT_FAILURE); |
---|
238 | |
---|
239 | while ( !feof(allowed_ips_fd) ) |
---|
240 | { |
---|
241 | char * line = (char *) malloc(16 * sizeof(char)); |
---|
242 | |
---|
243 | bzero(line, 16); |
---|
244 | fgets(line, 16, allowed_ips_fd); |
---|
245 | |
---|
246 | if ( strlen(line) ) |
---|
247 | { |
---|
248 | if ( line[strlen(line) - 1] == '\n' ) |
---|
249 | line[strlen(line) - 1] = '\0'; |
---|
250 | |
---|
251 | if ( allowed_ips == (struct allowed_ip *)NULL ) |
---|
252 | allow_ip = allowed_ips = (struct allowed_ip *) malloc(sizeof(struct allowed_ip)); |
---|
253 | else |
---|
254 | { |
---|
255 | allow_ip = allowed_ips; |
---|
256 | while ( allow_ip->next != (struct allowed_ip *)NULL ) |
---|
257 | allow_ip = allow_ip->next; |
---|
258 | allow_ip->next = (struct allowed_ip *) malloc(sizeof(struct allowed_ip)); |
---|
259 | allow_ip = allow_ip->next; |
---|
260 | } |
---|
261 | allow_ip->next = (struct allowed_ip *)NULL; |
---|
262 | allow_ip->ip = line; |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | char * initial_path = (char *) malloc(128 * sizeof(char)); |
---|
267 | getcwd(initial_path, 128); |
---|
268 | |
---|
269 | openlog (g_program_name, LOG_PID, LOG_USER); |
---|
270 | syslog (LOG_INFO, "%s started in path [#%d] %s", g_program_name, strlen(initial_path), initial_path); |
---|
271 | |
---|
272 | chdir ("/"); // Change working directory to the root. |
---|
273 | |
---|
274 | umask (0); // Clear our file mode creation mask |
---|
275 | |
---|
276 | set_signal_handler (SIGCHLD, sig_child); |
---|
277 | |
---|
278 | signal (SIGPIPE, SIG_IGN); |
---|
279 | } |
---|
280 | |
---|
281 | // sig_child(): Handles SIGCHLD from exiting child processes. |
---|
282 | void sig_child (int signo) |
---|
283 | { |
---|
284 | pid_t pid; |
---|
285 | |
---|
286 | (void) signo; // suppress compiler warning |
---|
287 | |
---|
288 | for ( ; ; ) |
---|
289 | { |
---|
290 | pid = waitpid (WAIT_ANY, NULL, WNOHANG); |
---|
291 | |
---|
292 | if (pid > 0) |
---|
293 | syslog (LOG_INFO, "Caught SIGCHLD from pid %d", pid); |
---|
294 | else |
---|
295 | break; |
---|
296 | } |
---|
297 | |
---|
298 | if ((pid < 0) && (errno != ECHILD)) |
---|
299 | syslog (LOG_ERR, "waitpid(): %m"), exit (EXIT_FAILURE); |
---|
300 | |
---|
301 | return; |
---|
302 | } |
---|
303 | |
---|
304 | // CreateServerSocket() |
---|
305 | // Create a socket, bind it to the specified address |
---|
306 | // and port, and set it to listen for client connections. |
---|
307 | // Returns < 0 on failure to bind, bombs on error otherwise, |
---|
308 | // returns the fd of the new socket on success. |
---|
309 | int CreateServerSocket (struct in_addr addr, unsigned short port) |
---|
310 | { |
---|
311 | int err, |
---|
312 | fd; |
---|
313 | const int on = 1; |
---|
314 | struct sockaddr_in sa; |
---|
315 | |
---|
316 | // Create a socket and get its descriptor. |
---|
317 | fd = socket (AF_INET, SOCK_STREAM, 0); |
---|
318 | if ( fd < 0 ) |
---|
319 | syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE); |
---|
320 | |
---|
321 | // Set SO_REUSEADDR socket option |
---|
322 | if ( setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 ) |
---|
323 | syslog (LOG_ERR, "setsockopt(fd%d, SO_REUSEADDR): %m", fd); |
---|
324 | |
---|
325 | // Load a sa structure with the specified address and port |
---|
326 | sa.sin_family = AF_INET; |
---|
327 | sa.sin_port = htons (port); |
---|
328 | //sa.sin_addr = addr; |
---|
329 | sa.sin_addr.s_addr = htonl(INADDR_ANY); |
---|
330 | memset (sa.sin_zero, 0, sizeof (sa.sin_zero)); |
---|
331 | |
---|
332 | // Bind our socket to the address and port specified |
---|
333 | err = bind (fd, (struct sockaddr *) &sa, sizeof (sa)); |
---|
334 | if ( err < 0 ) |
---|
335 | { |
---|
336 | syslog (LOG_ERR, "bind(): %m"); |
---|
337 | return err; |
---|
338 | } |
---|
339 | |
---|
340 | // Tell socket to listen and queue up to 5 incoming connections. |
---|
341 | if ( listen (fd, 5) < 0 ) |
---|
342 | syslog (LOG_ERR, "listen(): %m"), exit (EXIT_FAILURE); |
---|
343 | |
---|
344 | return fd; |
---|
345 | } |
---|
346 | |
---|
347 | // Daemonise(): Put the program in the background, set PPID=1, create a new |
---|
348 | // session and process group, without a controlling tty. |
---|
349 | void Daemonise (void) |
---|
350 | { |
---|
351 | pid_t pid; |
---|
352 | |
---|
353 | /* Close stdin, stdout & stderr */ |
---|
354 | /* TODO: open /dev/null and dup the fd to stdin, stdout & stderr |
---|
355 | * close(STDIN_FILENO); |
---|
356 | * close(STDOUT_FILENO); |
---|
357 | * close(STDERR_FILENO); |
---|
358 | * */ |
---|
359 | |
---|
360 | syslog (LOG_INFO, "%s daemonising", g_program_name); |
---|
361 | |
---|
362 | /* Fork the process to put it in the background. */ |
---|
363 | |
---|
364 | pid = fork (); |
---|
365 | if (pid == -1) |
---|
366 | syslog (LOG_ERR, "fork(): %m"), exit (EXIT_FAILURE); |
---|
367 | |
---|
368 | /* parent terminates here, so shell thinks the command is done. */ |
---|
369 | if (pid) |
---|
370 | exit (0); |
---|
371 | |
---|
372 | syslog (LOG_INFO, "%s in background", g_program_name); |
---|
373 | |
---|
374 | /* 1st child continues to run in the background with PPID=1 */ |
---|
375 | |
---|
376 | /* Become leader of a new session and a new process group, |
---|
377 | * with no controlling tty. */ |
---|
378 | setsid (); |
---|
379 | |
---|
380 | /* Fork again to guarantee the process will not be able to aquire a |
---|
381 | * controlling tty. */ |
---|
382 | |
---|
383 | /*signal (SIGHUP, SIG_IGN); *//* required according to Stevens' UNP2 p333 */ |
---|
384 | |
---|
385 | pid = fork (); |
---|
386 | if (pid == -1) |
---|
387 | syslog (LOG_ERR, "fork(): %m"), exit (EXIT_FAILURE); |
---|
388 | |
---|
389 | if (pid) /* 1st child terminates */ |
---|
390 | exit (0); |
---|
391 | |
---|
392 | /* 2nd child continues, no longer a session or group leader */ |
---|
393 | |
---|
394 | syslog (LOG_INFO, "%s daemonised", g_program_name); |
---|
395 | } |
---|
396 | |
---|
397 | // MainLoop() |
---|
398 | // Classic concurrent server model. |
---|
399 | // Wait for a client to connect, fork a child process |
---|
400 | // to do the business with the client, parent process |
---|
401 | // continues to wait for the next connection. |
---|
402 | // This function does not return. |
---|
403 | void MainLoop (int listen_fd, struct in_addr rem_addr, unsigned short rem_port) |
---|
404 | { |
---|
405 | //pid_t helper_pid; |
---|
406 | pthread_t clear_list_thread; |
---|
407 | |
---|
408 | syslog (LOG_INFO, "MainLoop :: listen_fd(fd%d)", listen_fd); |
---|
409 | //signal (SIGCHLD, SIG_IGN); |
---|
410 | |
---|
411 | pthread_mutex_init(&mutexsum, NULL); |
---|
412 | pthread_create(&clear_list_thread, NULL, (void *) &ClearList, (void *)NULL ); |
---|
413 | while ( quantity_of_fd < 50 ) |
---|
414 | { |
---|
415 | struct accept * client; |
---|
416 | |
---|
417 | syslog (LOG_INFO, "[timestamp = %d] quantity_of_fd = %d", time(NULL), quantity_of_fd); |
---|
418 | |
---|
419 | client = AcceptClientConnection (listen_fd); |
---|
420 | client->jabber_addr = rem_addr; |
---|
421 | client->jabber_port = rem_port; |
---|
422 | |
---|
423 | pthread_create(&client->accept_thread, NULL, (void *) &VerifyClient, (void *) client); |
---|
424 | } |
---|
425 | pthread_mutex_destroy(&mutexsum); |
---|
426 | } |
---|
427 | |
---|
428 | void ClearList(void) |
---|
429 | { |
---|
430 | for ( ; ; ) |
---|
431 | { |
---|
432 | pthread_mutex_lock(&mutexsum); |
---|
433 | struct connections * connection = connections; |
---|
434 | while ( connection != (struct connections *)NULL ) |
---|
435 | { |
---|
436 | if ( *(connection->client->jabber_fd) != (int)NULL && time(NULL) - connection->client->last_access > 70 ) |
---|
437 | { |
---|
438 | shutdown(*(connection->client->jabber_fd), SHUT_RDWR); |
---|
439 | close(*(connection->client->jabber_fd)); |
---|
440 | *(connection->client->jabber_fd) = (int)NULL; |
---|
441 | } |
---|
442 | connection = connection->next; |
---|
443 | } |
---|
444 | pthread_mutex_unlock(&mutexsum); |
---|
445 | sleep(5); |
---|
446 | } |
---|
447 | } |
---|
448 | |
---|
449 | // AcceptClientConnection() |
---|
450 | // waits for a tcp connect to the socket listen_fd, which |
---|
451 | // must already be bound and set to listen on a local port. |
---|
452 | // Bombs on error, returns the fd of the new socket on success. |
---|
453 | //int AcceptClientConnection (int listen_fd) |
---|
454 | struct accept * AcceptClientConnection (int listen_fd) |
---|
455 | { |
---|
456 | int * newfd = (int *) malloc(sizeof(int)); |
---|
457 | if ( newfd == NULL ) |
---|
458 | { |
---|
459 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
460 | } |
---|
461 | |
---|
462 | struct sockaddr_in sa; |
---|
463 | socklen_t socklen; |
---|
464 | |
---|
465 | syslog (LOG_INFO, "AcceptClientConnection(fd%d)", listen_fd); |
---|
466 | |
---|
467 | // Accept the connection and create a new socket for it. |
---|
468 | socklen = sizeof (sa); |
---|
469 | memset (&sa, 0, socklen); |
---|
470 | do |
---|
471 | { |
---|
472 | *(newfd) = accept (listen_fd, (struct sockaddr *) &sa, &socklen); |
---|
473 | } |
---|
474 | while ( (*(newfd) < 0) && (errno == EINTR) ); |
---|
475 | |
---|
476 | syslog (LOG_INFO, "Accepted client connection on new socket fd%d", *(newfd)); |
---|
477 | |
---|
478 | if ( *(newfd) < 0 ) |
---|
479 | syslog (LOG_ERR, "accept(): %m"), exit (EXIT_FAILURE); |
---|
480 | |
---|
481 | if ( socklen != sizeof (sa) ) |
---|
482 | syslog (LOG_ERR, "accept() screwed up!"), exit (EXIT_FAILURE); |
---|
483 | |
---|
484 | quantity_of_fd++; |
---|
485 | |
---|
486 | const int on = 1; |
---|
487 | if ( setsockopt (*(newfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 ) |
---|
488 | syslog (LOG_ERR, "setsockopt(fd%d, SO_REUSEADDR): %m", *(newfd)); |
---|
489 | |
---|
490 | struct accept * accepted = (struct accept *) malloc(sizeof(struct accept)); |
---|
491 | if ( accepted == NULL ) |
---|
492 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
493 | |
---|
494 | accepted->fd = newfd; |
---|
495 | accepted->sa = sa; |
---|
496 | |
---|
497 | return (accepted); |
---|
498 | } |
---|
499 | |
---|
500 | void VerifyClient(void * accepted) |
---|
501 | { |
---|
502 | //puts("\n\n:::::::::::::::: VERIFYCLIENT :::::::::::::::::::::\n"); |
---|
503 | unsigned int addr = 0; |
---|
504 | char ip[250]; |
---|
505 | int * jabber_fd = (int *)NULL; |
---|
506 | const int on = 1; |
---|
507 | |
---|
508 | struct accept * accept = (struct accept *) accepted; |
---|
509 | struct client * client = (struct client *)NULL; |
---|
510 | struct read_write * read_write = (struct read_write *) malloc(sizeof(struct read_write)); |
---|
511 | if ( read_write == NULL ) |
---|
512 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
513 | |
---|
514 | read_write->type = 0; |
---|
515 | |
---|
516 | // ip from client |
---|
517 | addr = ntohl(accept->sa.sin_addr.s_addr); |
---|
518 | sprintf(ip, "%d.%d.%d.%d", |
---|
519 | (addr >> 24), (addr >> 16) & 0xFF, |
---|
520 | (addr >> 8) & 0xFF, addr & 0xFF); |
---|
521 | //printf("\nNew connection [#%d]: %s\n", *(accept->fd), ip); |
---|
522 | |
---|
523 | if ( getPermission(ip) ) |
---|
524 | if ( (client = Handshake(accept, read_write)) == (struct client *)NULL ) |
---|
525 | { |
---|
526 | close(*(accept->fd)); |
---|
527 | pthread_kill(accept->accept_thread, 0); |
---|
528 | } |
---|
529 | else |
---|
530 | { |
---|
531 | jabber_fd = client->jabber_fd; |
---|
532 | } |
---|
533 | else |
---|
534 | { |
---|
535 | jabber_fd = (int *) malloc(sizeof(int)); |
---|
536 | if ( jabber_fd == NULL ) |
---|
537 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
538 | |
---|
539 | *(jabber_fd) = (int)NULL; |
---|
540 | } |
---|
541 | |
---|
542 | //puts("\n\n:::::::::::::::: JABBER IN VERIFYCLIENT #1 :::::::::::::::::::::\n"); |
---|
543 | if ( *(jabber_fd) == (int)NULL ) |
---|
544 | *(jabber_fd) = ConnectToServer(accept->jabber_addr, accept->jabber_port); |
---|
545 | //puts("\n\n:::::::::::::::: JABBER IN VERIFYCLIENT #2 :::::::::::::::::::::\n"); |
---|
546 | |
---|
547 | // Set SO_REUSEADDR socket option |
---|
548 | //if ( setsockopt (*(jabber_fd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 ) |
---|
549 | // syslog (LOG_ERR, "setsockopt(fd%d, SO_REUSEADDR) #2: %m", *(jabber_fd)); |
---|
550 | |
---|
551 | //if ( client != (struct client *)NULL ) |
---|
552 | // client->jabber_fd = jabber_fd; |
---|
553 | |
---|
554 | read_write->jabber = jabber_fd; |
---|
555 | read_write->client = *(accept->fd); |
---|
556 | //pthread_t cat_thread; |
---|
557 | //fcntl(read_write->client, F_SETFL, fcntl(read_write->client, F_GETFL, 0) | O_NDELAY); |
---|
558 | |
---|
559 | //puts("\n\n:::::::::::::::: THREADS :::::::::::::::::::::\n"); |
---|
560 | //pthread_create(&read_write->write, NULL, (void *) &Writing, (void *)read_write ); |
---|
561 | pthread_create(&read_write->read, NULL, (void *) &Reading, (void *)read_write ); |
---|
562 | |
---|
563 | //pthread_exit(0); |
---|
564 | pthread_kill(accept->accept_thread, 0); |
---|
565 | } |
---|
566 | |
---|
567 | struct client * Handshake(struct accept * accept, struct read_write * read_write) |
---|
568 | { |
---|
569 | //puts("\n\n:::::::::::::::: HANDSHAKE :::::::::::::::::::::\n"); |
---|
570 | struct client * client = (struct client *)NULL; |
---|
571 | unsigned char * const buf = (char *) malloc (sizeof(char) * 5); |
---|
572 | if ( buf == NULL ) |
---|
573 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
574 | |
---|
575 | char * str = (char *) malloc(128 * sizeof(char)), |
---|
576 | * user = (char *)NULL, |
---|
577 | * pass = (char *)NULL, |
---|
578 | * pass_pos = (char *)NULL, |
---|
579 | * type = (char *)NULL, |
---|
580 | * type_pos = (char *)NULL; |
---|
581 | if ( str == NULL ) |
---|
582 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
583 | |
---|
584 | int bytes_rcvd, |
---|
585 | bytes_sent, |
---|
586 | i; |
---|
587 | |
---|
588 | bzero(str, 128); |
---|
589 | |
---|
590 | if ( (bytes_rcvd = recv (*(accept->fd), str, 128, 0)) < 1 ) |
---|
591 | { |
---|
592 | //puts("error :: str"); |
---|
593 | close(*(accept->fd)); |
---|
594 | return client; |
---|
595 | } |
---|
596 | |
---|
597 | pass_pos = strstr(str, "##") + 2; |
---|
598 | i = strlen(str) - strlen(pass_pos) - 1; |
---|
599 | user = (char *) malloc(i * sizeof(char)); |
---|
600 | if ( user == NULL ) |
---|
601 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
602 | |
---|
603 | bzero(user, i); |
---|
604 | strncpy(user, str, i - 1); |
---|
605 | |
---|
606 | type_pos = strstr(pass_pos, "##") + 2; |
---|
607 | i = strlen(pass_pos) - strlen(type_pos) - 1; |
---|
608 | pass = (char *) malloc(i * sizeof(char)); |
---|
609 | if ( pass == NULL ) |
---|
610 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
611 | |
---|
612 | bzero(pass, i); |
---|
613 | strncpy(pass, pass_pos, i - 1); |
---|
614 | |
---|
615 | i = strlen(type_pos) + 1; |
---|
616 | type = (char *) malloc(i * sizeof(char)); |
---|
617 | if ( type == NULL ) |
---|
618 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
619 | |
---|
620 | bzero(type, i); |
---|
621 | strcpy(type, type_pos); |
---|
622 | |
---|
623 | //printf(" str[%2d]: %s\n", strlen(str), str); |
---|
624 | //printf("user[%2d]: %s\n", strlen(user), user); |
---|
625 | //printf("pass[%2d]: %s\n", strlen(pass), pass); |
---|
626 | //printf("type[%2d]: %s\n", strlen(type), type); |
---|
627 | //printf(" fd[%2d]: client\n", *(accept->fd)); |
---|
628 | |
---|
629 | //if ( (client = LookFor (user, pass)) != (struct client *)NULL ) |
---|
630 | if ( (client = (struct client *) withConnections(LookFor, user, pass)) != (struct client *)NULL ) |
---|
631 | { |
---|
632 | //puts("\n\n:::::::::::::::: INFO #0 :::::::::::::::::::::\n"); |
---|
633 | bzero(buf, 5); |
---|
634 | //puts("\n\n:::::::::::::::: INFO #1 :::::::::::::::::::::\n"); |
---|
635 | if ( *(client->jabber_fd) == (int)NULL ) |
---|
636 | { |
---|
637 | //puts("\n\n:::::::::::::::: JABBER IN HANDSHAKE #1 :::::::::::::::::::::\n"); |
---|
638 | *(client->jabber_fd) = ConnectToServer(accept->jabber_addr, accept->jabber_port); |
---|
639 | sprintf(buf, "new "); |
---|
640 | //puts("\n\n:::::::::::::::: JABBER IN HANDSHAKE #2 :::::::::::::::::::::\n"); |
---|
641 | } |
---|
642 | else |
---|
643 | sprintf(buf, "rec "); |
---|
644 | |
---|
645 | //puts("\n\n:::::::::::::::: INFO #2 :::::::::::::::::::::\n"); |
---|
646 | |
---|
647 | //printf("connection: %s\n\n\n", buf); |
---|
648 | for ( i = 0; i < sizeof(buf); i += bytes_sent ) |
---|
649 | { |
---|
650 | bytes_sent = send (*(accept->fd), buf + i, sizeof(buf) - i, 0); |
---|
651 | |
---|
652 | if ( bytes_sent < 0 ) |
---|
653 | break; |
---|
654 | } |
---|
655 | |
---|
656 | //puts("\n\n:::::::::::::::: INFO #3 :::::::::::::::::::::\n"); |
---|
657 | |
---|
658 | if ( strcmp(type, "read") == 0 ) |
---|
659 | read_write->type = 1; |
---|
660 | else |
---|
661 | if ( strcmp(type, "write") == 0 ) |
---|
662 | read_write->type = 2; |
---|
663 | //puts("\n\n:::::::::::::::: INFO #4 :::::::::::::::::::::\n"); |
---|
664 | |
---|
665 | } |
---|
666 | //free(str); |
---|
667 | free(buf); |
---|
668 | |
---|
669 | return client; |
---|
670 | } |
---|
671 | |
---|
672 | void * withConnections(void * (*func)(), ...) |
---|
673 | { |
---|
674 | //static struct connections * connections = (struct connections *)NULL; |
---|
675 | if ( (*func) == LookFor ) |
---|
676 | { |
---|
677 | va_list ap; |
---|
678 | char * user, |
---|
679 | * pass; |
---|
680 | void * _return; |
---|
681 | |
---|
682 | va_start(ap, (*func)); |
---|
683 | user = va_arg(ap, char *); |
---|
684 | pass = va_arg(ap, char *); |
---|
685 | va_end(ap); |
---|
686 | |
---|
687 | pthread_mutex_lock(&mutexsum); |
---|
688 | _return = (*func)(user, pass); |
---|
689 | pthread_mutex_unlock(&mutexsum); |
---|
690 | return _return; |
---|
691 | } |
---|
692 | else |
---|
693 | { |
---|
694 | } |
---|
695 | } |
---|
696 | |
---|
697 | //struct client * LookFor (char * user, char * pass) |
---|
698 | //void * LookFor (struct connections * connections, char * user, char * pass) |
---|
699 | void * LookFor (char * user, char * pass) |
---|
700 | { |
---|
701 | //puts("\n\n:::::::::::::::: LOOKFOR :::::::::::::::::::::\n"); |
---|
702 | //static struct connections * connections = (struct connections *)NULL; |
---|
703 | |
---|
704 | //pthread_mutex_lock(&mutexsum); |
---|
705 | if ( connections == (struct connections *)NULL ) |
---|
706 | { |
---|
707 | //puts("\n\n:::::::::::::::: FIRST CONNECTION :::::::::::::::::::::\n"); |
---|
708 | connections = (struct connections *) malloc(sizeof(struct connections)); |
---|
709 | if ( connections == NULL ) |
---|
710 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
711 | |
---|
712 | connections->client = (struct client *) malloc(sizeof(struct client)); |
---|
713 | if ( connections->client == NULL ) |
---|
714 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
715 | |
---|
716 | connections->client->user = user; |
---|
717 | connections->client->pass = pass; |
---|
718 | connections->client->jabber_fd = (int *) malloc(sizeof(int)); |
---|
719 | if ( connections->client->jabber_fd == NULL ) |
---|
720 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
721 | |
---|
722 | *(connections->client->jabber_fd) = (int)NULL; |
---|
723 | connections->client->last_access = time(NULL); |
---|
724 | |
---|
725 | connections->next = (struct connections *)NULL; |
---|
726 | |
---|
727 | //pthread_mutex_unlock(&mutexsum); |
---|
728 | return connections->client; |
---|
729 | } |
---|
730 | else |
---|
731 | { |
---|
732 | //puts("\n\n:::::::::::::::: HAS CONNECTION :::::::::::::::::::::\n"); |
---|
733 | struct connections * connection = connections, |
---|
734 | * last; |
---|
735 | while ( connection != (struct connections *)NULL ) |
---|
736 | { |
---|
737 | //puts(":::::::::::::::: PROCURANDO :::::::::::::::::::::"); |
---|
738 | if ( strcmp(connection->client->user, user) == 0 ) |
---|
739 | if ( strcmp(connection->client->pass, pass) == 0 ) |
---|
740 | { |
---|
741 | //pthread_mutex_unlock(&mutexsum); |
---|
742 | //puts(":::::::::::::::: ACHOU #1 :::::::::::::::::::::"); |
---|
743 | connection->client->last_access = time(NULL); |
---|
744 | return connection->client; |
---|
745 | } |
---|
746 | else |
---|
747 | { |
---|
748 | //pthread_mutex_unlock(&mutexsum); |
---|
749 | //puts(":::::::::::::::: ACHOU #2 :::::::::::::::::::::"); |
---|
750 | return (struct client *)NULL; |
---|
751 | } |
---|
752 | last = connection; |
---|
753 | connection = connection->next; |
---|
754 | } |
---|
755 | //puts(":::::::::::::::: ACHOU #3 :::::::::::::::::::::"); |
---|
756 | |
---|
757 | last->next = (struct connections *) malloc(sizeof(struct connections)); |
---|
758 | if ( last->next == NULL ) |
---|
759 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
760 | |
---|
761 | connection = last->next; |
---|
762 | |
---|
763 | connection->client = (struct client *) malloc(sizeof(struct client)); |
---|
764 | if ( connection->client == NULL ) |
---|
765 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
766 | |
---|
767 | connection->client->user = user; |
---|
768 | connection->client->pass = pass; |
---|
769 | connection->client->jabber_fd = (int *) malloc(sizeof(int)); |
---|
770 | if ( connection->client->jabber_fd == NULL ) |
---|
771 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
772 | |
---|
773 | *(connection->client->jabber_fd) = (int)NULL; |
---|
774 | connection->client->last_access = time(NULL); |
---|
775 | |
---|
776 | connection->next = (struct connections *)NULL; |
---|
777 | //pthread_mutex_unlock(&mutexsum); |
---|
778 | return connection->client; |
---|
779 | } |
---|
780 | } |
---|
781 | |
---|
782 | void Reading (void * read_write) |
---|
783 | { |
---|
784 | unsigned char * const buf_2_jabber = (char *) malloc (sizeof(char) * BUF_SIZE); |
---|
785 | unsigned char * const buf_2_client = (char *) malloc (sizeof(char) * BUF_SIZE); |
---|
786 | bzero(buf_2_jabber, BUF_SIZE); |
---|
787 | bzero(buf_2_client, BUF_SIZE); |
---|
788 | |
---|
789 | if ( buf_2_jabber == NULL || buf_2_client == NULL ) |
---|
790 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
791 | |
---|
792 | struct read_write * read = (struct read_write *) read_write; |
---|
793 | |
---|
794 | int jabber_fd = *(read->jabber), |
---|
795 | client_fd = read->client; |
---|
796 | |
---|
797 | fcntl(jabber_fd, F_SETFL, fcntl(jabber_fd, F_GETFL, 0) | O_NDELAY); |
---|
798 | fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL, 0) | O_NDELAY); |
---|
799 | |
---|
800 | int bytes_rcvd_jabber = (int) NULL, |
---|
801 | bytes_sent_jabber = (int) NULL, |
---|
802 | bytes_rcvd_client = (int) NULL, |
---|
803 | bytes_sent_client = (int) NULL, |
---|
804 | i; |
---|
805 | |
---|
806 | //syslog (LOG_INFO, "Reading(fd%d, fd%d)", in_fd, out_fd); |
---|
807 | |
---|
808 | // @TODO: verificar alocacao buffer |
---|
809 | //if ( buf == NULL ) |
---|
810 | // syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
811 | |
---|
812 | do |
---|
813 | { |
---|
814 | bzero(buf_2_jabber, BUF_SIZE); |
---|
815 | if ( (bytes_rcvd_client = recv (client_fd, buf_2_jabber, BUF_SIZE, 0)) != 0 && strlen(buf_2_client) > 0 ) |
---|
816 | { |
---|
817 | // descomentar para ver oq esta passado de informacao |
---|
818 | //printf("(jabber/client[#%d])[%d]:\n{\n%s.......\n}\n", client_fd, strlen(buf_2_client), buf_2_client); |
---|
819 | for ( i = 0; i < bytes_rcvd_jabber; i += bytes_sent_client ) |
---|
820 | { |
---|
821 | bytes_sent_client = send (client_fd, buf_2_client + i, bytes_rcvd_jabber - i, 0); |
---|
822 | |
---|
823 | if ( bytes_sent_client < 0 ) |
---|
824 | break; |
---|
825 | } |
---|
826 | } |
---|
827 | |
---|
828 | bzero(buf_2_client, BUF_SIZE); |
---|
829 | if ( (bytes_rcvd_jabber = recv (jabber_fd, buf_2_client, BUF_SIZE, 0)) != 0 && strlen(buf_2_jabber) > 0 ) |
---|
830 | { |
---|
831 | // descomentar para ver oq esta passado de informacao |
---|
832 | //printf("(client/jabber[#%d])[%d]:\n{\n%s.......\n}\n", jabber_fd, strlen(buf_2_jabber), buf_2_jabber); |
---|
833 | for ( i = 0; i < bytes_rcvd_client; i += bytes_sent_jabber ) |
---|
834 | { |
---|
835 | bytes_sent_jabber = send (jabber_fd, buf_2_jabber + i, bytes_rcvd_client - i, 0); |
---|
836 | |
---|
837 | if ( bytes_sent_jabber < 0 ) |
---|
838 | break; |
---|
839 | } |
---|
840 | } |
---|
841 | |
---|
842 | usleep(500); |
---|
843 | //sleep(2); |
---|
844 | } |
---|
845 | while ( (bytes_rcvd_client != 0) && (bytes_rcvd_jabber != 0) ); |
---|
846 | |
---|
847 | //puts("\n\n\nFIM.......................\n\n\n"); |
---|
848 | |
---|
849 | free(buf_2_jabber); |
---|
850 | free(buf_2_client); |
---|
851 | |
---|
852 | shutdown(read->client, SHUT_RDWR); |
---|
853 | close (read->client); |
---|
854 | } |
---|
855 | |
---|
856 | /* |
---|
857 | void Reading (void * read_write) |
---|
858 | { |
---|
859 | struct read_write * read = (struct read_write *) read_write; |
---|
860 | |
---|
861 | //printf("read->type: %d\n\n\n", read->type); |
---|
862 | if ( !read->type || read->type == 1 ) |
---|
863 | { |
---|
864 | unsigned char * const buf = (char *) malloc (sizeof(char) * BUF_SIZE); |
---|
865 | if ( buf == NULL ) |
---|
866 | { |
---|
867 | puts("\n\nmalloc() : buf #2\n\n\n"); |
---|
868 | exit (EXIT_FAILURE); |
---|
869 | } |
---|
870 | int bytes_rcvd, |
---|
871 | bytes_sent = (int) NULL, |
---|
872 | i; |
---|
873 | |
---|
874 | int in_fd = *(read->jabber), |
---|
875 | out_fd = read->client; |
---|
876 | |
---|
877 | //syslog (LOG_INFO, "Reading(fd%d, fd%d)", in_fd, out_fd); |
---|
878 | |
---|
879 | // @TODO: verificar alocacao buffer |
---|
880 | //if ( buf == NULL ) |
---|
881 | // syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
882 | |
---|
883 | do |
---|
884 | { |
---|
885 | //puts("\n\n:::::::::::::::: DO - READ :::::::::::::::::::::\n"); |
---|
886 | bzero(buf, BUF_SIZE); |
---|
887 | bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0); |
---|
888 | |
---|
889 | if ( strlen(buf) > 0 ) |
---|
890 | { |
---|
891 | // descomentar para ver oq esta passado de informacao |
---|
892 | printf("Reading(#%d/jabber,#%d/client)[%d]:\n{\n%s.......\n}\n", in_fd, out_fd, strlen(buf), buf); |
---|
893 | |
---|
894 | for ( i = 0; i < bytes_rcvd && *(read->jabber) != (int)NULL; i += bytes_sent ) |
---|
895 | { |
---|
896 | bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0); |
---|
897 | |
---|
898 | if ( bytes_sent < 0 ) |
---|
899 | break; |
---|
900 | } |
---|
901 | } |
---|
902 | } |
---|
903 | while ( (bytes_rcvd > 0) && (bytes_sent > 0) ); |
---|
904 | |
---|
905 | printf("\n[Reading] FINALIZANDO TREAD CLIENTE COM FD #%d\n\n", out_fd); |
---|
906 | pthread_cancel(read->write); |
---|
907 | |
---|
908 | //if ( bytes_rcvd < 1 ) |
---|
909 | // *(read->jabber) = (int)NULL; |
---|
910 | |
---|
911 | printf("\n\nFIM Reading [#%d#%d]\nbytes_rcvd = %d : bytes_sent = %d\n\n\n", in_fd, out_fd, bytes_rcvd, bytes_sent); |
---|
912 | |
---|
913 | free (buf); |
---|
914 | } |
---|
915 | else |
---|
916 | while ( 1 ) usleep(500); |
---|
917 | |
---|
918 | //pthread_kill(read->write, 0); |
---|
919 | |
---|
920 | shutdown(read->client, SHUT_RDWR); |
---|
921 | close (read->client); |
---|
922 | //pthread_exit(0); |
---|
923 | } |
---|
924 | */ |
---|
925 | |
---|
926 | void Writing (void * read_write) |
---|
927 | { |
---|
928 | struct read_write * write = (struct read_write *) read_write; |
---|
929 | |
---|
930 | //printf("write->type: %d\n\n\n", write->type); |
---|
931 | //if ( !write->type || write->type == 2 ) |
---|
932 | //{ |
---|
933 | unsigned char * const buf = (char *) malloc (sizeof(char) * (BUF_SIZE + 1)); |
---|
934 | if ( buf == NULL ) |
---|
935 | { |
---|
936 | syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
937 | } |
---|
938 | int bytes_rcvd, |
---|
939 | bytes_sent = (int) NULL, |
---|
940 | i; |
---|
941 | |
---|
942 | int in_fd = write->client, |
---|
943 | out_fd = *(write->jabber); |
---|
944 | |
---|
945 | //syslog (LOG_INFO, "Writing(fd%d, fd%d)", in_fd, out_fd); |
---|
946 | |
---|
947 | // @TODO: verificar alocacao buffer |
---|
948 | //if ( buf == NULL ) |
---|
949 | // syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE); |
---|
950 | |
---|
951 | do |
---|
952 | { |
---|
953 | //puts("\n\n:::::::::::::::: DO - WRITE :::::::::::::::::::::"); |
---|
954 | bzero(buf, BUF_SIZE + 1); |
---|
955 | //puts(":::::::::::::::: WRITE - RECV :::::::::::::::::::::"); |
---|
956 | bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0); |
---|
957 | |
---|
958 | //puts(":::::::::::::::: WRITE - IF #1 :::::::::::::::::::::"); |
---|
959 | if ( strlen(buf) > 0 ) |
---|
960 | { |
---|
961 | // descomentar para ver oq esta passado de informacao |
---|
962 | //printf("Writing(#%d/client,#%d/jabber)[%d]:\n{\n%s.......\n}\n", in_fd, out_fd, strlen(buf), buf); |
---|
963 | |
---|
964 | for ( i = 0; i < bytes_rcvd && *(write->jabber) != (int)NULL; i += bytes_sent ) |
---|
965 | { |
---|
966 | bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0); |
---|
967 | |
---|
968 | if ( bytes_sent < 0 ) |
---|
969 | break; |
---|
970 | } |
---|
971 | } |
---|
972 | //puts(":::::::::::::::: WRITE - IF #2 :::::::::::::::::::::\n"); |
---|
973 | } |
---|
974 | while ( (bytes_rcvd > 0) && (bytes_sent > 0) ); |
---|
975 | |
---|
976 | //printf("\n[Writing] FINALIZANDO TREAD CLIENTE COM FD #%d\n\n", in_fd); |
---|
977 | pthread_cancel(write->read); |
---|
978 | |
---|
979 | //if ( bytes_sent < 1 ) |
---|
980 | // *(write->jabber) = (int)NULL; |
---|
981 | |
---|
982 | //printf("\n\nFIM Writing [#%d#%d]\nbytes_rcvd = %d : bytes_sent = %d\n\n\n", in_fd, out_fd, bytes_rcvd, bytes_sent); |
---|
983 | |
---|
984 | free (buf); |
---|
985 | //} |
---|
986 | //else |
---|
987 | // while ( 1 ) usleep(500); |
---|
988 | |
---|
989 | //pthread_kill(write->read, 0); |
---|
990 | |
---|
991 | shutdown(write->client, SHUT_RDWR); |
---|
992 | close (write->client); |
---|
993 | //pthread_exit(0); |
---|
994 | } |
---|
995 | |
---|
996 | // ConnectToServer() |
---|
997 | // attempts a tcp connect to the server specified |
---|
998 | // by addr and port. Bombs on failure to connect, |
---|
999 | // returns the fd of the new socket on success. |
---|
1000 | int ConnectToServer (struct in_addr addr, unsigned short port) |
---|
1001 | { |
---|
1002 | // TODO: have a timeout for connect() - see Unix socket FAQ 6.2 |
---|
1003 | |
---|
1004 | int fd, err; |
---|
1005 | struct sockaddr_in sa; |
---|
1006 | |
---|
1007 | // Create a socket and get its descriptor. |
---|
1008 | fd = socket (AF_INET, SOCK_STREAM, 0); |
---|
1009 | |
---|
1010 | if ( fd < 0 ) |
---|
1011 | syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE); |
---|
1012 | |
---|
1013 | sa.sin_family = AF_INET; |
---|
1014 | sa.sin_port = htons (port); |
---|
1015 | sa.sin_addr = addr; |
---|
1016 | memset (sa.sin_zero, 0, sizeof (sa.sin_zero)); |
---|
1017 | |
---|
1018 | err = connect (fd, (struct sockaddr *) &sa, sizeof (sa)); |
---|
1019 | if (err < 0) |
---|
1020 | { |
---|
1021 | syslog (LOG_ERR, "Unable to connect socket fd%d to server: %m", fd); |
---|
1022 | exit (EXIT_FAILURE); |
---|
1023 | } |
---|
1024 | |
---|
1025 | quantity_of_fd++; |
---|
1026 | syslog (LOG_INFO, "Connected socket fd%d to server", fd); |
---|
1027 | |
---|
1028 | return fd; |
---|
1029 | } |
---|
1030 | |
---|
1031 | // NameToAddress() |
---|
1032 | // Convert name to an ip address. |
---|
1033 | // Returns 0 on success, -1 on failure. |
---|
1034 | int NameToAddr (const char * name, struct in_addr * p_inaddr) |
---|
1035 | { |
---|
1036 | struct hostent * he; |
---|
1037 | |
---|
1038 | // First, attempt to convert from string ip format |
---|
1039 | // TODO: use inet_aton() instead |
---|
1040 | p_inaddr->s_addr = inet_addr (name); |
---|
1041 | if ( p_inaddr->s_addr != -1U ) // Success |
---|
1042 | return 0; |
---|
1043 | |
---|
1044 | // Next, attempt to read from /etc/hosts or do a DNS lookup |
---|
1045 | he = gethostbyname (name); |
---|
1046 | if ( he != NULL ) // Success |
---|
1047 | { |
---|
1048 | memcpy (p_inaddr, he->h_addr, sizeof (struct in_addr)); |
---|
1049 | return 0; |
---|
1050 | } |
---|
1051 | |
---|
1052 | return -1; // Failed to resolve name to an ip address |
---|
1053 | } |
---|
1054 | |
---|
1055 | // NameToPort() |
---|
1056 | // Convert name to a port number. Name can either be a port name |
---|
1057 | // (in which case proto must also be set to either "tcp" or "udp") |
---|
1058 | // or name can be the ascii representation of the port number. |
---|
1059 | // Returns 0 on success, -1 on failure. |
---|
1060 | int NameToPort (const char * name, unsigned short * port, const char * proto) |
---|
1061 | { |
---|
1062 | unsigned long lport; |
---|
1063 | char * errpos; |
---|
1064 | struct servent * se; |
---|
1065 | |
---|
1066 | // First, attempt to convert string to integer |
---|
1067 | lport = strtoul (name, &errpos, 0); |
---|
1068 | if ( (*errpos == 0) && (lport <= 65535) ) // Success |
---|
1069 | { |
---|
1070 | *port = lport; |
---|
1071 | return 0; |
---|
1072 | } |
---|
1073 | |
---|
1074 | // Next, attempt to read the string from /etc/services |
---|
1075 | se = getservbyname (name, proto); |
---|
1076 | if ( se != NULL) // Success |
---|
1077 | { |
---|
1078 | *port = ntohs (se->s_port); |
---|
1079 | return 0; |
---|
1080 | } |
---|
1081 | |
---|
1082 | return -1; // Failed to resolve port name to a number |
---|
1083 | } |
---|
1084 | |
---|
1085 | // quit() |
---|
1086 | // Print an error message to stderr |
---|
1087 | // and syslog, then exit the program. |
---|
1088 | void quit (const char * fmt, ...) // quit with msg |
---|
1089 | { |
---|
1090 | va_list ap; |
---|
1091 | |
---|
1092 | fflush (stdout); |
---|
1093 | |
---|
1094 | fprintf (stderr, "%s: ", g_program_name); |
---|
1095 | |
---|
1096 | va_start (ap, fmt); |
---|
1097 | vfprintf (stderr, fmt, ap); |
---|
1098 | va_end (ap); |
---|
1099 | |
---|
1100 | fputc ('\n', stderr); |
---|
1101 | |
---|
1102 | syslog (LOG_ERR, "I quit!"); |
---|
1103 | |
---|
1104 | exit (EXIT_FAILURE); |
---|
1105 | } |
---|
1106 | |
---|
1107 | // pbomb() |
---|
1108 | // Print an error message to stderr |
---|
1109 | // and syslog, then exit the program. |
---|
1110 | // pbomb() additionally include the |
---|
1111 | // string representation of errno. |
---|
1112 | void pbomb (const char * fmt, ...) // bomb with perror |
---|
1113 | { |
---|
1114 | va_list ap; |
---|
1115 | int errno_save = errno; |
---|
1116 | char buf[100]; |
---|
1117 | |
---|
1118 | fflush (stdout); |
---|
1119 | |
---|
1120 | fprintf (stderr, "%s: ", g_program_name); |
---|
1121 | |
---|
1122 | va_start (ap, fmt); |
---|
1123 | vsnprintf (buf, sizeof (buf), fmt, ap); |
---|
1124 | va_end (ap); |
---|
1125 | |
---|
1126 | errno = errno_save; |
---|
1127 | perror (buf); |
---|
1128 | |
---|
1129 | syslog (LOG_ERR, "Bang!: %s: %m", buf); |
---|
1130 | |
---|
1131 | exit (EXIT_FAILURE); |
---|
1132 | } |
---|
1133 | |
---|
1134 | // hbomb() |
---|
1135 | // Print an error message to stderr |
---|
1136 | // and syslog, then exit the program. |
---|
1137 | // hbomb() additionally include the |
---|
1138 | // string representation of h_errno. |
---|
1139 | void hbomb (const char * fmt, ...) // bomb with herror |
---|
1140 | { |
---|
1141 | va_list ap; |
---|
1142 | int h_errno_save = h_errno; |
---|
1143 | char buf[100]; |
---|
1144 | |
---|
1145 | fflush (stdout); |
---|
1146 | |
---|
1147 | fprintf (stderr, "%s: ", g_program_name); |
---|
1148 | |
---|
1149 | va_start (ap, fmt); |
---|
1150 | vsnprintf (buf, sizeof (buf), fmt, ap); |
---|
1151 | va_end (ap); |
---|
1152 | |
---|
1153 | h_errno = h_errno_save; |
---|
1154 | herror (buf); |
---|
1155 | |
---|
1156 | syslog (LOG_ERR, "Bang!: %s: %s", buf, hstrerror (h_errno)); |
---|
1157 | |
---|
1158 | exit (EXIT_FAILURE); |
---|
1159 | } |
---|
1160 | |
---|
1161 | // set_signal_handler(): Sets a signal handler function. Similar to signal() |
---|
1162 | // but this method is more portable between platforms. |
---|
1163 | void set_signal_handler (int signum, signal_handler_t sa_handler_func) |
---|
1164 | { |
---|
1165 | struct sigaction act; |
---|
1166 | |
---|
1167 | act.sa_handler = sa_handler_func; |
---|
1168 | sigemptyset (&(act.sa_mask)); |
---|
1169 | act.sa_flags = 0; |
---|
1170 | |
---|
1171 | if (sigaction (signum, &act, NULL) < 0) |
---|
1172 | { |
---|
1173 | syslog (LOG_ERR, "Error setting handler for signal %d: %m", signum); |
---|
1174 | exit (EXIT_FAILURE); |
---|
1175 | } |
---|
1176 | } |
---|