source: trunk/instant_messenger/socket/BKP_20071105/BKP_20071026/BKP_20071019/BKP_20071018/BKP_20071009/server.c @ 151

Revision 151, 11.3 KB checked in by niltonneto, 16 years ago (diff)

Commit da nova versão do módulo, usando agente em C.
Vide Página do módulo do Trac:
http://www.expressolivre.org/dev/wiki/messenger

A versão anterior encontra-se na subpasta bkp (32/64).

Line 
1#include "server.h"
2
3/* Globally accessible storage for the exception context: */
4struct exception_context the_exception_context[1];
5
6//#define HOST "im.celepar.parana"
7//#define IP "10.15.20.219"
8#define HOST "im.pr.gov.br"
9#define IP "200.189.113.148"
10#define PORT "5222"
11
12int main(int argc, char ** argv)
13{
14        /* variables to parse arguments */
15        extern int optind,
16                           optopt;
17        extern char * optarg;
18
19        char * log_file;
20        int c           = (int)NULL,
21                errflg  = (int)NULL,
22                verbose = (int)NULL,
23                optval  = 1,
24                pid;
25
26        socklen_t optlen = sizeof(optval);
27
28        /* fd -> file descriptor */
29        int socket_server_fd    = (int)NULL,
30                socket_server_port      = (int)NULL,
31                socket_accept_fd        = (int)NULL,
32                sockaddr_in_size        = sizeof(struct sockaddr_in),
33                err                                     = (int)NULL;
34
35        /* Internet socket address stuct */
36        struct sockaddr_in server_addr,
37                                           accept_addr;
38
39        struct client * clients = (struct client *) NULL,
40                                  * current = (struct client *) NULL;
41
42        SSL_CTX * ctx;
43
44        pthread_t threads;
45
46        // clear screen
47        system(__CLEAR_SCREEN__);
48
49        while ( (c = getopt(argc, argv, ":vp:")) != -1 )
50        {
51                switch ( c )
52                {
53                        case 'p':
54                                if ( socket_server_port = strtol(optarg, 0, 10) == 0 )
55                                {
56                                        fprintf(stderr, "Option -%c requires a valid port and '%s' isn't valid\n", optopt, optarg);
57                                        ++errflg;
58                                }
59                                break;
60                        case 'v':
61                                verbose = 1;
62                                break;
63                        case ':':
64                                // -f or -o without operand
65                                fprintf(stderr, "Option -%c requires an operand\n", optopt);
66                                ++errflg;
67                                break;
68                        case '?':
69                                fprintf(stderr, "Unrecognized option: -%c\n", optopt);
70                                ++errflg;
71                }
72        }
73        if ( errflg )
74        {
75                fprintf(stderr, "usage: . . . \n\n");
76                exit(2);
77        }
78
79        OpenSSL_add_all_algorithms();
80        SSL_library_init();
81        SSL_load_error_strings();
82
83        /* make a socket */
84        socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
85        if ( socket_server_fd == __SOCKET_ERROR__ )
86        {
87                printf("\nCould not make a socket\n");
88                return 0;
89        }
90
91        bzero((char *) &server_addr, sockaddr_in_size);
92        bzero((char *) &accept_addr, sockaddr_in_size);
93
94        if ( !socket_server_port )
95                socket_server_port = __DEFAULT_OPEN_PORT__;
96
97        /* fill address struct */
98        server_addr.sin_addr.s_addr     = INADDR_ANY;
99        server_addr.sin_port            = htons(socket_server_port);
100        server_addr.sin_family          = AF_INET;
101        bzero(&(server_addr.sin_zero), 8);
102
103        if ( __DEBUG__  || verbose )
104                printf("\nBinding to port %d...\n", socket_server_port);
105
106        /* bind to a port */
107        if ( bind(socket_server_fd, (struct sockaddr *)&(server_addr), sizeof(server_addr)) == __SOCKET_ERROR__ )
108        {
109                printf("\nCould not connect to host\n");
110                exit(1);
111        }
112
113        /* get port number */
114        getsockname(socket_server_fd, (struct sockaddr *)&(server_addr), (socklen_t *) &(sockaddr_in_size));
115        if ( __DEBUG__  || verbose )
116        {
117                printf("\nopened socket as fd (%d) on port (%d) for stream i/o\n", socket_server_fd, ntohs(server_addr.sin_port));
118
119                printf("Server\n\
120                                sin_family        = %d\n\
121                                sin_addr.s_addr   = %d\n\
122                                sin_port          = %d\n"
123                                , server_addr.sin_family
124                                , server_addr.sin_addr.s_addr
125                                , ntohs(server_addr.sin_port)
126                          );
127                printf("\nMaking a listen queue of %d elements", __QUEUE_SIZE__);
128        }
129
130        /* establish listen queue */
131        if ( listen(socket_server_fd, __QUEUE_SIZE__) == __SOCKET_ERROR__ )
132        {
133                printf("\nCould not listen\n");
134                return 0;
135        }
136
137        for ( ; ; )
138        {
139                if ( __DEBUG__  || verbose )
140                        puts("\nWaiting for a connection\n");
141
142                /* get the connected socket */
143                socket_accept_fd = accept(socket_server_fd, (struct sockaddr *) &(accept_addr), (socklen_t *) &(sockaddr_in_size));
144
145                if ( socket_accept_fd > -1 )
146                {
147                        pid = fork();
148                        if ( pid == 0 )
149                        {
150        if ( !(ctx = SSL_CTX_new(SSLv23_method())) )
151        {
152                printf("Error creating the context.\n");
153                exit(0);
154        }
155
156        if ( SSL_CTX_set_cipher_list(ctx, CIPHER_LIST) < 1 )
157        {
158                printf("Error setting the cipher list.\n");
159                exit(0);
160        }
161
162        //Indicate the certificate file to be used
163        if ( SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM) < 1 )
164        {
165                printf("Error setting the certificate file.\n");
166                exit(0);
167        }
168
169        //Load the password for the Private Key
170        SSL_CTX_set_default_passwd_cb_userdata(ctx, KEY_PASSWD);
171
172        //Indicate the key file to be used
173        if ( SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM) < 1 )
174        {
175                printf("Error setting the key file.\n");
176                exit(0);
177        }
178
179        //Make sure the key and certificate file match
180        if ( !SSL_CTX_check_private_key(ctx) )
181        {
182                printf("Private key does not match the certificate public key\n");
183                exit(0);
184        }
185
186        // Set the list of trusted CAs based on the file and/or directory provided
187        if ( SSL_CTX_load_verify_locations(ctx, CA_FILE, CA_DIR) < 1 )
188        {
189                printf("Error setting verify location\n");
190                exit(0);
191        }
192
193        // Set for server verification
194        SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
195
196                                fcntl(socket_accept_fd, F_SETFL, fcntl(socket_accept_fd, F_GETFL, 0) | O_NONBLOCK | O_NDELAY);
197
198                                if ( clients == (struct client *) NULL )
199                                        current = clients;
200                                else
201                                        while ( (current = clients->next) != (struct client *) NULL );
202
203                                current                         = (struct client *) malloc(sizeof(struct client));
204                                current->next           = (struct client *) NULL;
205                                current->fd                     = socket_accept_fd;
206                                current->sockaddr       = accept_addr;
207                                current->ctx            = ctx;
208                                current->last           = time(NULL);
209
210                                pthread_create(&(threads), NULL, handler, (void *) current);
211                        }
212                }
213        }
214        pthread_exit(NULL);
215}
216
217void * handler(void * pClient)
218{
219    char buffer_client[__BUFFER_SIZE__],
220                 buffer_jabber[__BUFFER_SIZE__];
221    struct client * client = (struct client *) pClient;
222    int i = 0, err, e;
223        time_t last;
224
225        int tls = 0;
226
227        char ip[46];
228        unsigned short port;
229        inet_ntop(AF_INET, &(client->sockaddr.sin_addr), ip, sizeof (ip));
230        port = ntohs(client->sockaddr.sin_port);
231        printf("\nGot a connection from %s, port %hu\n", ip, port);
232        /*---------------------------------------------------*/
233
234        int client_is_connected = -1;
235        int jabber_is_connected = -1;
236
237        struct sockaddr_in socketaddr;
238        int socketfd,
239                nHostPort;
240
241        char buff[4096];
242        SSL_CTX  *ctx;
243        SSL  *myssl;
244
245        char * old_host,
246                 * replace_host;
247
248        replace_host = (char *) malloc(__BUFFER_SIZE__*sizeof(char));
249
250        if ( (nHostPort = strtol(PORT, 0, 10)) == 0 )
251        {
252                printf("\n<port>\n\n");
253                printf("\ncould not make a socket\n");
254                return 0;
255        }
256
257        socketfd = socket(AF_INET, SOCK_STREAM, 0);
258
259        socketaddr.sin_family = AF_INET;
260        socketaddr.sin_addr.s_addr = inet_addr(IP);
261        socketaddr.sin_port = htons(nHostPort);
262
263        if ( !(ctx = SSL_CTX_new(SSLv23_method())) )
264        {
265                printf("Error creating the context.\n");
266                exit(0);
267        }
268
269        err = connect(socketfd, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
270        fcntl(socketfd, F_SETFL, fcntl(socketfd, F_GETFL, 0) | O_NONBLOCK | O_NDELAY);
271
272        if ( err < 0 )
273        {
274                printf("Socket returned error #%d,program terminated\n", err);
275                exit(0);
276        }
277
278        while ( client_is_connected != 0 )
279        {
280                // read from client
281                //puts("\tread - client");
282                bzero(buffer_client, __BUFFER_SIZE__);
283                if ( !tls )
284                        client_is_connected = read(client->fd, buffer_client, __BUFFER_SIZE__);
285                else
286                        client_is_connected = SSL_read(client->myssl, buffer_client, __BUFFER_SIZE__);
287
288                if ( client_is_connected != 0 )
289                {
290                        if ( strlen(buffer_jabber) > 0 )
291                        {
292                                puts("\twriting - client");
293                                printf("\t%s\n\n", buffer_jabber);
294                                // write in the client
295                                Try
296                                {
297                                        if ( !tls )
298                                                write(client->fd, buffer_jabber, strlen(buffer_jabber));
299                                        else
300                                                SSL_write(client->myssl, buffer_jabber, strlen(buffer_jabber));
301                                }
302                                Catch(e) fprintf(stderr, "exception %d\n", e);
303                                puts("\twrote - client");
304                        }
305
306                        if ( strstr(buffer_client, "<stream:stream") && (old_host = strstr(buffer_client, "to=")) )
307                        {
308                                bzero(replace_host, __BUFFER_SIZE__);
309                                strncpy(replace_host, buffer_client, (strlen(buffer_client) - strlen(old_host))+4);
310                                strcat(replace_host, HOST);
311                                old_host = strstr(old_host, " ");
312                                old_host--;
313                                strcat(replace_host, old_host);
314                                bzero(buffer_client, __BUFFER_SIZE__);
315                                strcpy(buffer_client, replace_host);
316                        }
317                }
318
319                // read from jabber service
320                //puts("\tread - jabber");
321                bzero(buffer_jabber, __BUFFER_SIZE__);
322
323                if ( !tls )
324                        jabber_is_connected = read(socketfd, buffer_jabber, __BUFFER_SIZE__);
325                else
326                        jabber_is_connected = SSL_read(myssl, buffer_jabber, __BUFFER_SIZE__);
327
328
329                if ( jabber_is_connected != 0 && strlen(buffer_client) > 0 )
330                {
331                        puts("\twriting - jabber");
332                        printf("\t%s\n\n", buffer_client);
333                        // write in the jabber service
334                        Try
335                        {
336                                if ( !tls )
337                                        write(socketfd, buffer_client, strlen(buffer_client));
338                                else
339                                        SSL_write(myssl, buffer_client, strlen(buffer_client));
340                        }
341                        Catch(e) fprintf(stderr, "exception %d\n", e);
342                        puts("\twrote - jabber");
343                }
344
345                if ( strstr(buffer_jabber, "<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>") )
346                {
347                        puts("\tbegin tls with jabber");
348                        fcntl( socketfd, F_SETFL, fcntl( socketfd, F_GETFL ) & ~O_NONBLOCK & ~O_NDELAY);
349                        SSL_CTX_set_verify(ctx,SSL_VERIFY_NONE,NULL);
350                        //Create new ssl object
351                        myssl = SSL_new(ctx);
352
353                        if ( !myssl )
354                        {
355                                printf("Error creating SSL structure.\n");
356                                exit(0);
357                        }
358
359                        //Bind the socket to the SSL structure
360                        SSL_set_fd(myssl, socketfd);
361
362                        //Connect to the server, SSL layer.
363                        err = SSL_connect(myssl);
364                        //printf("SSL error #%d in accept,program terminated\n",err);
365                        //Check for error in connect.
366                        if ( err < 1 )
367                        {
368                                err = SSL_get_error(myssl,err);
369                                printf("SSL error #%d in accept, program terminated\n",err);
370                                printf("%d -- %d\n\n", SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE);
371
372                                if(err==5){printf("sockerrno is:\n");}
373
374                                SSL_CTX_free(ctx);
375                                client_is_connected = 0;
376                        }
377
378                        fcntl(socketfd, F_SETFL, fcntl(socketfd, F_GETFL, 0) | O_NONBLOCK | O_NDELAY);
379                        puts("\tend tls with jabber");
380
381                        puts("\twriting proceed in the client");
382                        printf("%s - %d\n", buffer_jabber, strlen(buffer_jabber));
383                        write(client->fd, buffer_jabber, strlen(buffer_jabber));
384                        bzero(buffer_jabber, __BUFFER_SIZE__);
385
386                        puts("\tbegin tls with client");
387                        fcntl( client->fd, F_SETFL, fcntl( client->fd, F_GETFL ) & ~O_NONBLOCK & ~O_NDELAY );
388
389                        //Create new ssl object
390                        if( !(client->myssl = SSL_new(client->ctx)) )
391                        {
392                                printf("Error creating SSL structure.\n");
393                                exit(0);
394                        }
395
396                        //Bind the socket to the SSL structure
397                        SSL_set_fd(client->myssl, client->fd);
398
399                        //Connect to the server, SSL layer.
400                        err = SSL_accept(client->myssl);
401
402                        //Check for error in connect.
403                        if ( err < 1 )
404                        {
405                                printf("SSL error #%d in accept,program terminated\n", err);
406                                err = SSL_get_error(client->myssl, 0);
407                                printf("SSL error #%d in accept,program terminated\n", err);
408
409                                switch ( err )
410                                {
411                                        case SSL_ERROR_NONE : puts("SSL_ERROR_NONE");break;
412                                        case SSL_ERROR_SSL : puts("SSL_ERROR_SSL");break;
413                                        case SSL_ERROR_WANT_READ : puts("SSL_ERROR_WANT_READ");
414                                }
415
416                                if ( err == 5 )
417                                        printf("sockerrno is: %d\n", err);
418
419
420                                SSL_CTX_free(client->ctx);
421                                client_is_connected = 0;
422                        }
423                        fcntl(client->fd, F_SETFL, fcntl(client->fd, F_GETFL, 0) | O_NONBLOCK | O_NDELAY);
424                        puts("\tend tls with client");
425
426                        tls = 1;
427                }
428
429                if ( jabber_is_connected == 0 )
430                        client_is_connected = jabber_is_connected;
431
432                //puts("end loop");
433                usleep(1000);
434        }
435        puts("\n=========================\n");
436    if ( close(socketfd) == __SOCKET_ERROR__ )
437    {
438        printf("\nCould not close jabber socket\n");
439        return 0;
440    }
441        //---------------------------------------------------
442    if ( close(client->fd) == __SOCKET_ERROR__ )
443    {
444        printf("\nCould not close socket\n");
445        return 0;
446    }
447
448    fflush(stdin);
449    fflush(stdout);
450        free(client);
451    pthread_exit(NULL);
452}
Note: See TracBrowser for help on using the repository browser.