source: tags/instant_messenger/webjabber/webjabber.c @ 305

Revision 305, 31.7 KB checked in by niltonneto, 16 years ago (diff)

Correçoes

Line 
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.
22const size_t BUF_SIZE = 4096;
23
24// Typedef for a signal handler function.
25typedef void (*signal_handler_t) (int);
26
27// Global variables
28char g_program_name[100];       // Initialised from argv[0] in ParseArgs()
29struct allowed_ip * allowed_ips = (struct allowed_ip *)NULL;
30int quantity_of_fd = 0;         // quantity of file descriptor
31
32static struct connections * connections = (struct connections *)NULL;
33pthread_mutex_t mutexsum;
34
35// structs
36struct allowed_ip
37{
38        char * ip;
39        struct allowed_ip * next;
40};
41
42struct 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
51struct client
52{
53        char * user,
54                 * pass;
55        int * jabber_fd,
56                * read_fd;
57        time_t last_access;
58};
59
60struct connections
61{
62        struct client * client;
63        struct connections * next;
64};
65
66struct read_write
67{
68        int * jabber,
69                client,
70                type;
71        pthread_t read,
72                          write;
73};
74
75void recursive (int, struct in_addr, unsigned short);
76int getPermission(char *);
77void ParseArgs (int, char **, struct in_addr *, unsigned short *, struct in_addr *, unsigned short *);
78void Initialise (void);
79void sig_child (int);
80int CreateServerSocket (struct in_addr, unsigned short);
81void Daemonise (void);
82void MainLoop (int, struct in_addr, unsigned short);
83void ClearList(void);
84struct accept * AcceptClientConnection (int);
85void VerifyClient(void *);
86struct client * Handshake (struct accept *, struct read_write *);
87void * withConnections(void * (*func)(), ...);
88//struct client * LookFor (char *, char *);
89//void * LookFor (struct connections *, char *, char *);
90void * LookFor (char *, char *);
91void Reading (void *);
92void Writing (void *);
93int ConnectToServer (struct in_addr, unsigned short);
94int NameToAddr (const char *, struct in_addr *);
95int 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
105void set_signal_handler (int, signal_handler_t);
106
107int 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
140void 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.
175void 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
212int getPermission(char * ip)
213{
214        struct allowed_ip * allow_ip = allowed_ips;
215        int allow = 0;
216
217        while ( !allow && allow_ip != (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.
231void 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.
282void 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.
309int 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.
349void 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.
403void 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
428void 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)
454struct 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
500void 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
567struct 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
635                //if ( *(client->read_fd) != (int)NULL )
636                //{
637                //      shutdown(*(client->read_fd), SHUT_RDWR);
638                //      close(*(client->read_fd));
639                //}
640                //*(client->read_fd) = *(accept->fd);
641
642                //puts("\n\n:::::::::::::::: INFO #1 :::::::::::::::::::::\n");
643                if ( *(client->jabber_fd) == (int)NULL )
644                {
645                        //puts("\n\n:::::::::::::::: JABBER IN HANDSHAKE #1 :::::::::::::::::::::\n");
646                        *(client->jabber_fd) = ConnectToServer(accept->jabber_addr, accept->jabber_port);
647                        sprintf(buf, "new ");
648                        //puts("\n\n:::::::::::::::: JABBER IN HANDSHAKE #2 :::::::::::::::::::::\n");
649                }
650                else
651                        sprintf(buf, "rec ");
652
653                //puts("\n\n:::::::::::::::: INFO #2 :::::::::::::::::::::\n");
654
655                //printf("connection: %s\n\n\n", buf);
656                for ( i = 0; i < sizeof(buf); i += bytes_sent )
657                {
658                        bytes_sent = send (*(accept->fd), buf + i, sizeof(buf) - i, 0);
659
660                        if ( bytes_sent < 0 )
661                                break;
662                }
663
664                //puts("\n\n:::::::::::::::: INFO #3 :::::::::::::::::::::\n");
665
666                if ( strcmp(type, "read") == 0 )
667                        read_write->type = 1;
668                else
669                        if ( strcmp(type, "write") == 0 )
670                                read_write->type = 2;
671                //puts("\n\n:::::::::::::::: INFO #4 :::::::::::::::::::::\n");
672
673        }
674        //free(str);
675        free(buf);
676
677        return client;
678}
679
680void * withConnections(void * (*func)(), ...)
681{
682        //static struct connections * connections = (struct connections *)NULL;
683        if ( (*func) == LookFor )
684        {
685                va_list ap;
686                char * user,
687                         * pass;
688                void * _return;
689
690                va_start(ap, (*func));
691                user = va_arg(ap, char *);
692                pass = va_arg(ap, char *);
693                va_end(ap);
694
695                pthread_mutex_lock(&mutexsum);
696                _return = (*func)(user, pass);
697                pthread_mutex_unlock(&mutexsum);
698                return _return;
699        }
700        else
701        {
702        }
703}
704
705//struct client * LookFor (char * user, char * pass)
706//void * LookFor (struct connections * connections, char * user, char * pass)
707void * LookFor (char * user, char * pass)
708{
709        //puts("\n\n:::::::::::::::: LOOKFOR :::::::::::::::::::::\n");
710        //static struct connections * connections = (struct connections *)NULL;
711
712        //pthread_mutex_lock(&mutexsum);
713        if ( connections == (struct connections *)NULL )
714        {
715                //puts("\n\n:::::::::::::::: FIRST CONNECTION :::::::::::::::::::::\n");
716                connections = (struct connections *) malloc(sizeof(struct connections));
717                if ( connections == NULL )
718                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
719
720                connections->client = (struct client *) malloc(sizeof(struct client));
721                if ( connections->client == NULL )
722                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
723
724                connections->client->user = user;
725                connections->client->pass = pass;
726
727                connections->client->read_fd = (int *) malloc(sizeof(int));
728                if ( connections->client->read_fd == NULL )
729                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
730
731                connections->client->jabber_fd = (int *) malloc(sizeof(int));
732                if ( connections->client->jabber_fd == NULL )
733                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
734
735                *(connections->client->read_fd) = (int)NULL;
736                *(connections->client->jabber_fd) = (int)NULL;
737
738                connections->client->last_access = time(NULL);
739
740                connections->next = (struct connections *)NULL;
741
742                //pthread_mutex_unlock(&mutexsum);
743                return connections->client;
744        }
745        else
746        {
747                //puts("\n\n:::::::::::::::: HAS CONNECTION :::::::::::::::::::::\n");
748                struct connections * connection = connections,
749                                                   * last;
750                while ( connection != (struct connections *)NULL )
751                {
752                        //puts(":::::::::::::::: PROCURANDO :::::::::::::::::::::");
753                        if ( strcmp(connection->client->user, user) == 0 )
754                                if ( strcmp(connection->client->pass, pass) == 0 )
755                                {
756                                        //pthread_mutex_unlock(&mutexsum);
757                                        //puts(":::::::::::::::: ACHOU #1 :::::::::::::::::::::");
758                                        connection->client->last_access = time(NULL);
759                                        return connection->client;
760                                }
761                                else
762                                {
763                                        //pthread_mutex_unlock(&mutexsum);
764                                        //puts(":::::::::::::::: ACHOU #2 :::::::::::::::::::::");
765                                        return (struct client *)NULL;
766                                }
767                        last = connection;
768                        connection = connection->next;
769                }
770                //puts(":::::::::::::::: ACHOU #3 :::::::::::::::::::::");
771
772                last->next = (struct connections *) malloc(sizeof(struct connections));
773                if ( last->next == NULL )
774                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
775
776                connection = last->next;
777
778                connection->client = (struct client *) malloc(sizeof(struct client));
779                if ( connection->client == NULL )
780                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
781
782                connection->client->user = user;
783                connection->client->pass = pass;
784                connection->client->jabber_fd = (int *) malloc(sizeof(int));
785                if ( connection->client->jabber_fd == NULL )
786                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
787
788                *(connection->client->jabber_fd) = (int)NULL;
789                connection->client->last_access = time(NULL);
790
791                connection->next = (struct connections *)NULL;
792                //pthread_mutex_unlock(&mutexsum);
793                return connection->client;
794        }
795}
796
797void Reading (void * read_write)
798{
799        unsigned char * const buf_2_jabber = (char *) malloc (sizeof(char) * BUF_SIZE);
800        unsigned char * const buf_2_client = (char *) malloc (sizeof(char) * BUF_SIZE);
801        bzero(buf_2_jabber, BUF_SIZE);
802        bzero(buf_2_client, BUF_SIZE);
803
804        if ( buf_2_jabber == NULL || buf_2_client == NULL )
805                syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
806
807        struct read_write * read = (struct read_write *) read_write;
808
809        int jabber_fd = *(read->jabber),
810                client_fd = read->client;
811
812        fcntl(jabber_fd, F_SETFL, fcntl(jabber_fd, F_GETFL, 0) | O_NDELAY);
813        fcntl(client_fd, F_SETFL, fcntl(client_fd, F_GETFL, 0) | O_NDELAY);
814
815        int bytes_rcvd_jabber = (int) NULL,
816                bytes_sent_jabber = (int) NULL,
817                bytes_rcvd_client = (int) NULL,
818                bytes_sent_client = (int) NULL,
819                i,
820                do_auth = 0;
821
822        // @TODO: verificar alocacao buffer
823        //if ( buf == NULL )
824        //      syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
825
826        do
827        {
828                bzero(buf_2_jabber, BUF_SIZE);
829                bytes_rcvd_client = recv (client_fd, buf_2_jabber, BUF_SIZE, 0);
830                if ( (bytes_rcvd_client != 0) && (strlen(buf_2_client) > 0) )
831                {
832                        for ( i = 0; i < bytes_rcvd_jabber; i += bytes_sent_client )
833                        {
834                                bytes_sent_client = send (client_fd, buf_2_client + i, bytes_rcvd_jabber - i, 0);
835
836                                if ( bytes_sent_client < 0 )
837                                        break;
838                        }
839                }
840                if ( strlen(buf_2_jabber) > 0 )
841                {
842                        printf("(client/jabber[#%d])[%d]:\n{\n%s.......\n}\n", jabber_fd, strlen(buf_2_jabber), buf_2_jabber);
843                        if ( strstr(buf_2_jabber, "<?xml") != NULL )
844                                do_auth = 1;
845                }
846
847                bzero(buf_2_client, BUF_SIZE);
848                if ( do_auth || read->type == 1 )
849                        bytes_rcvd_jabber = recv (jabber_fd, buf_2_client, BUF_SIZE, 0);
850                else
851                        bytes_rcvd_jabber = -1;
852                if ( (bytes_rcvd_jabber != 0) && (strlen(buf_2_jabber) > 0) )
853                {
854                        for ( i = 0; i < bytes_rcvd_client; i += bytes_sent_jabber )
855                        {
856                                bytes_sent_jabber = send (jabber_fd, buf_2_jabber + i, bytes_rcvd_client - i, 0);
857
858                                if ( bytes_sent_jabber < 0 )
859                                        break;
860                        }
861                }
862                if ( strlen(buf_2_client) > 0 )
863                {
864                        if ( do_auth && strstr(buf_2_jabber, "<iq xmlns='jabber:client'") != NULL )
865                                do_auth = 0;
866                        printf("(jabber/client[#%d])[%d]:\n{\n%s.......\n}\n", client_fd, strlen(buf_2_client), buf_2_client);
867                }
868
869                usleep(500);
870        }
871        while ( (bytes_rcvd_client != 0) && (bytes_rcvd_jabber != 0) );
872
873        puts("\n\n\nFIM.......................\n\n\n");
874
875        free(buf_2_jabber);
876        free(buf_2_client);
877
878        shutdown(read->client, SHUT_RDWR);
879        close (read->client);
880}
881
882/*
883void Reading (void * read_write)
884{
885        struct read_write * read = (struct read_write *) read_write;
886
887        //printf("read->type: %d\n\n\n", read->type);
888        if ( !read->type || read->type == 1 )
889        {
890                unsigned char * const buf = (char *) malloc (sizeof(char) * BUF_SIZE);
891                if ( buf == NULL )
892                {
893                        puts("\n\nmalloc() : buf #2\n\n\n");
894                        exit (EXIT_FAILURE);
895                }
896                int bytes_rcvd,
897                        bytes_sent = (int) NULL,
898                        i;
899
900                int in_fd = *(read->jabber),
901                        out_fd = read->client;
902
903                //syslog (LOG_INFO, "Reading(fd%d, fd%d)", in_fd, out_fd);
904
905                // @TODO: verificar alocacao buffer
906                //if ( buf == NULL )
907                //      syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
908
909                do
910                {
911                        //puts("\n\n:::::::::::::::: DO - READ :::::::::::::::::::::\n");
912                        bzero(buf, BUF_SIZE);
913                        bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0);
914
915                        if ( strlen(buf) > 0 )
916                        {
917                                // descomentar para ver oq esta passado de informacao
918                                printf("Reading(#%d/jabber,#%d/client)[%d]:\n{\n%s.......\n}\n", in_fd, out_fd, strlen(buf), buf);
919
920                                for ( i = 0; i < bytes_rcvd && *(read->jabber) != (int)NULL; i += bytes_sent )
921                                {
922                                        bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0);
923
924                                        if ( bytes_sent < 0 )
925                                                break;
926                                }
927                        }
928                }
929                while ( (bytes_rcvd > 0) && (bytes_sent > 0) );
930
931                printf("\n[Reading] FINALIZANDO TREAD CLIENTE COM FD #%d\n\n", out_fd);
932                pthread_cancel(read->write);
933
934                //if ( bytes_rcvd < 1 )
935                //      *(read->jabber) = (int)NULL;
936
937                printf("\n\nFIM Reading [#%d#%d]\nbytes_rcvd = %d : bytes_sent = %d\n\n\n", in_fd, out_fd, bytes_rcvd, bytes_sent);
938
939                free (buf);
940        }
941        else
942                while ( 1 )     usleep(500);
943
944        //pthread_kill(read->write, 0);
945
946        shutdown(read->client, SHUT_RDWR);
947        close (read->client);
948        //pthread_exit(0);
949}
950*/
951
952void Writing (void * read_write)
953{
954        struct read_write * write = (struct read_write *) read_write;
955
956        //printf("write->type: %d\n\n\n", write->type);
957        //if ( !write->type || write->type == 2 )
958        //{
959                unsigned char * const buf = (char *) malloc (sizeof(char) * (BUF_SIZE + 1));
960                if ( buf == NULL )
961                {
962                        syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
963                }
964                int bytes_rcvd,
965                        bytes_sent = (int) NULL,
966                        i;
967
968                int in_fd = write->client,
969                        out_fd = *(write->jabber);
970
971                //syslog (LOG_INFO, "Writing(fd%d, fd%d)", in_fd, out_fd);
972
973                // @TODO: verificar alocacao buffer
974                //if ( buf == NULL )
975                //      syslog (LOG_ERR, "malloc(): %m"), exit (EXIT_FAILURE);
976
977                do
978                {
979                        //puts("\n\n:::::::::::::::: DO - WRITE :::::::::::::::::::::");
980                        bzero(buf, BUF_SIZE + 1);
981                        //puts(":::::::::::::::: WRITE - RECV :::::::::::::::::::::");
982                        bytes_rcvd = recv (in_fd, buf, BUF_SIZE, 0);
983
984                        //puts(":::::::::::::::: WRITE - IF #1 :::::::::::::::::::::");
985                        if ( strlen(buf) > 0 )
986                        {
987                                // descomentar para ver oq esta passado de informacao
988                                //printf("Writing(#%d/client,#%d/jabber)[%d]:\n{\n%s.......\n}\n", in_fd, out_fd, strlen(buf), buf);
989
990                                for ( i = 0; i < bytes_rcvd && *(write->jabber) != (int)NULL; i += bytes_sent )
991                                {
992                                        bytes_sent = send (out_fd, buf + i, bytes_rcvd - i, 0);
993
994                                        if ( bytes_sent < 0 )
995                                                break;
996                                }
997                        }
998                        //puts(":::::::::::::::: WRITE - IF #2 :::::::::::::::::::::\n");
999                }
1000                while ( (bytes_rcvd > 0) && (bytes_sent > 0) );
1001
1002                //printf("\n[Writing] FINALIZANDO TREAD CLIENTE COM FD #%d\n\n", in_fd);
1003                pthread_cancel(write->read);
1004
1005                //if ( bytes_sent < 1 )
1006                //      *(write->jabber) = (int)NULL;
1007
1008                //printf("\n\nFIM Writing [#%d#%d]\nbytes_rcvd = %d : bytes_sent = %d\n\n\n", in_fd, out_fd, bytes_rcvd, bytes_sent);
1009
1010                free (buf);
1011        //}
1012        //else
1013        //      while ( 1 ) usleep(500);
1014
1015        //pthread_kill(write->read, 0);
1016
1017        shutdown(write->client, SHUT_RDWR);
1018        close (write->client);
1019        //pthread_exit(0);
1020}
1021
1022// ConnectToServer()
1023// attempts a tcp connect to the server specified
1024// by addr and port.  Bombs on failure to connect,
1025// returns the fd of the new socket on success.
1026int ConnectToServer (struct in_addr addr, unsigned short port)
1027{
1028        // TODO: have a timeout for connect() - see Unix socket FAQ 6.2
1029
1030        int fd, err;
1031        struct sockaddr_in sa;
1032
1033        // Create a socket and get its descriptor.
1034        fd = socket (AF_INET, SOCK_STREAM, 0);
1035
1036        if ( fd < 0 )
1037                syslog (LOG_ERR, "socket(): %m"), exit (EXIT_FAILURE);
1038
1039        sa.sin_family = AF_INET;
1040        sa.sin_port = htons (port);
1041        sa.sin_addr = addr;
1042        memset (sa.sin_zero, 0, sizeof (sa.sin_zero));
1043
1044        err = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
1045        if (err < 0)
1046        {
1047                syslog (LOG_ERR, "Unable to connect socket fd%d to server: %m", fd);
1048                exit (EXIT_FAILURE);
1049        }
1050
1051        quantity_of_fd++;
1052        syslog (LOG_INFO, "Connected socket fd%d to server", fd);
1053
1054        return fd;
1055}
1056
1057// NameToAddress()
1058// Convert name to an ip address.
1059// Returns 0 on success, -1 on failure.
1060int NameToAddr (const char * name, struct in_addr * p_inaddr)
1061{
1062        struct hostent * he;
1063
1064        // First, attempt to convert from string ip format
1065        // TODO: use inet_aton() instead
1066        p_inaddr->s_addr = inet_addr (name);
1067        if ( p_inaddr->s_addr != -1U ) // Success
1068                return 0;
1069
1070        // Next, attempt to read from /etc/hosts or do a DNS lookup
1071        he = gethostbyname (name);
1072        if ( he != NULL ) // Success
1073        {
1074                memcpy (p_inaddr, he->h_addr, sizeof (struct in_addr));
1075                return 0;
1076        }
1077
1078        return -1; // Failed to resolve name to an ip address
1079}
1080
1081// NameToPort()
1082// Convert name to a port number. Name can either be a port name
1083// (in which case proto must also be set to either "tcp" or "udp")
1084// or name can be the ascii representation of the port number.
1085// Returns 0 on success, -1 on failure.
1086int NameToPort (const char * name, unsigned short * port, const char * proto)
1087{
1088        unsigned long lport;
1089        char * errpos;
1090        struct servent * se;
1091
1092        // First, attempt to convert string to integer
1093        lport = strtoul (name, &errpos, 0);
1094        if ( (*errpos == 0) && (lport <= 65535) ) // Success
1095        {
1096                *port = lport;
1097                return 0;
1098        }
1099
1100        // Next, attempt to read the string from /etc/services
1101        se = getservbyname (name, proto);
1102        if ( se != NULL) // Success
1103        {
1104                *port = ntohs (se->s_port);
1105                return 0;
1106        }
1107
1108        return -1; // Failed to resolve port name to a number
1109}
1110
1111// quit()
1112// Print an error message to stderr
1113// and syslog, then exit the program.
1114void quit (const char * fmt, ...) // quit with msg
1115{
1116        va_list ap;
1117
1118        fflush (stdout);
1119
1120        fprintf (stderr, "%s: ", g_program_name);
1121
1122        va_start (ap, fmt);
1123        vfprintf (stderr, fmt, ap);
1124        va_end (ap);
1125
1126        fputc ('\n', stderr);
1127
1128        syslog (LOG_ERR, "I quit!");
1129
1130        exit (EXIT_FAILURE);
1131}
1132
1133// pbomb()
1134// Print an error message to stderr
1135// and syslog, then exit the program.
1136// pbomb() additionally include the
1137// string representation of errno.
1138void pbomb (const char * fmt, ...) // bomb with perror
1139{
1140        va_list ap;
1141        int errno_save = errno;
1142        char buf[100];
1143
1144        fflush (stdout);
1145
1146        fprintf (stderr, "%s: ", g_program_name);
1147
1148        va_start (ap, fmt);
1149        vsnprintf (buf, sizeof (buf), fmt, ap);
1150        va_end (ap);
1151
1152        errno = errno_save;
1153        perror (buf);
1154
1155        syslog (LOG_ERR, "Bang!: %s: %m", buf);
1156
1157        exit (EXIT_FAILURE);
1158}
1159
1160// hbomb()
1161// Print an error message to stderr
1162// and syslog, then exit the program.
1163// hbomb() additionally include the
1164// string representation of h_errno.
1165void hbomb (const char * fmt, ...) // bomb with herror
1166{
1167        va_list ap;
1168        int h_errno_save = h_errno;
1169        char buf[100];
1170
1171        fflush (stdout);
1172
1173        fprintf (stderr, "%s: ", g_program_name);
1174
1175        va_start (ap, fmt);
1176        vsnprintf (buf, sizeof (buf), fmt, ap);
1177        va_end (ap);
1178
1179        h_errno = h_errno_save;
1180        herror (buf);
1181
1182        syslog (LOG_ERR, "Bang!: %s: %s", buf, hstrerror (h_errno));
1183
1184        exit (EXIT_FAILURE);
1185}
1186
1187// set_signal_handler(): Sets a signal handler function.  Similar to signal()
1188// but this method is more portable between platforms.
1189void set_signal_handler (int signum, signal_handler_t sa_handler_func)
1190{
1191        struct sigaction act;
1192
1193        act.sa_handler = sa_handler_func;
1194        sigemptyset (&(act.sa_mask));
1195        act.sa_flags = 0;
1196
1197        if (sigaction (signum, &act, NULL) < 0)
1198        {
1199                syslog (LOG_ERR, "Error setting handler for signal %d: %m", signum);
1200                exit (EXIT_FAILURE);
1201        }
1202}
Note: See TracBrowser for help on using the repository browser.