~ubuntu-branches/ubuntu/natty/centerim/natty

« back to all changes in this revision

Viewing changes to libjabber/jconn.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-03-26 19:51:53 UTC
  • mfrom: (1.1.5 upstream) (3.1.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090326195153-dxo63t1lwbp2m592
Tags: 4.22.7-1ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - Packages that Depend/Recommend/Suggest firefox (metapackage) must
    must alternatively Depend/Recommend/Suggest abrowser.
* Bugfix-only release, fixed bugs: LP: #146308 and LP: #186381.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
#include "jabber.h"
21
21
#include "connwrap.h"
22
22
 
 
23
#ifdef HAVE_THREAD
 
24
#include <pthread.h>
 
25
#endif
23
26
/* local macros for launching event handlers */
24
27
#define STATE_EVT(arg) if(j->on_state) { (j->on_state)(j, (arg) ); }
25
28
 
 
29
 
26
30
/* prototypes of the local functions */
27
31
static void startElement(void *userdata, const char *name, const char **attribs);
28
32
static void endElement(void *userdata, const char *name);
29
33
static void charData(void *userdata, const char *s, int slen);
30
34
 
 
35
 
31
36
/*
32
37
 *  jab_new -- initialize a new jabber connection
33
38
 *
538
543
    if (j->current)
539
544
        xmlnode_insert_cdata(j->current, s, slen);
540
545
}
 
546
 
 
547
void cleanup_thread(void *arg)
 
548
{
 
549
        struct pargs_r *argument = (struct pargs_r*)arg;
 
550
        if(argument)
 
551
        {
 
552
                close(argument->fd_file);
 
553
                close(argument->sock);
 
554
                if(argument->hash)
 
555
                        free(argument->hash);
 
556
                if(argument->rfile)
 
557
                        free(argument->rfile);
 
558
                free(argument);
 
559
        }
 
560
}
 
561
 
 
562
void jabber_send_file(jconn j, const char *filename, long int size, struct send_file *file, void *rfile, void (*function)(void *file, long int bytes, long int size, int status, int conn_type), int start_port, int end_port) //returning ip address and port after binding
 
563
{
 
564
#ifdef HAVE_THREAD
 
565
        int sock;
 
566
        struct sockaddr_in addr;
 
567
        int optval = 1;
 
568
         
 
569
        int fd_file = open(filename, O_RDONLY);
 
570
        if( fd_file < 0 )
 
571
                return;
 
572
 
 
573
        sock = socket(AF_INET, SOCK_STREAM, 0);
 
574
        if(sock < 0)
 
575
        {
 
576
                close( fd_file );
 
577
                return;
 
578
        }
 
579
         
 
580
        addr.sin_family = AF_INET;
 
581
         
 
582
        if( (start_port == 0) || (end_port == 0))
 
583
                addr.sin_port = htons(0); //
 
584
        else
 
585
                addr.sin_port = htons(next_random(start_port,end_port)); //
 
586
 
 
587
        struct sockaddr_in sa;
 
588
        int sa_len = sizeof( sa );
 
589
        getsockname( j->fd, (struct sockaddr *) &sa, &sa_len ); //geting address for bind
 
590
        addr.sin_addr.s_addr = sa.sin_addr.s_addr;
 
591
         
 
592
        //      addr.sin_addr.s_addr = htonl(INADDR_ANY);
 
593
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)) < 0)
 
594
        {
 
595
                close( fd_file );
 
596
                close( sock );
 
597
                return;
 
598
        }
 
599
        if ( (bind(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr)) ) < 0 ) 
 
600
        {
 
601
                do
 
602
                {
 
603
                        if( errno == EADDRINUSE ) //select another port
 
604
                                addr.sin_port = htons(next_random(start_port, end_port)); //geting another random port
 
605
                        else 
 
606
                        {
 
607
                                close( fd_file );
 
608
                                close( sock );
 
609
                                return;
 
610
                        }
 
611
                }
 
612
                while(bind(sock, (struct sockaddr *) &addr, sizeof(struct sockaddr)) < 0);
 
613
        }
 
614
        listen(sock, 5);
 
615
        file->host = strdup(inet_ntoa(sa.sin_addr));
 
616
         
 
617
        getsockname( sock, (struct sockaddr *) &sa, &sa_len );
 
618
        file->port = (int) ntohs(sa.sin_port);
 
619
         
 
620
        struct pargs_r *arg;
 
621
        arg = (struct pargs_r *)calloc(1, sizeof(struct pargs_r));
 
622
        if( arg )
 
623
 
 
624
        {
 
625
                arg->sock = sock;
 
626
                arg->fd_file = fd_file;
 
627
                arg->size = size;
 
628
                arg->rfile = rfile;
 
629
                arg->hash = NULL;
 
630
                arg->url = NULL;
 
631
                arg->callback = function;
 
632
                if (pthread_create(&file->thread, NULL, jabber_send_file_fd, (void *)arg ))
 
633
                {
 
634
                        free( arg );
 
635
                        close( fd_file );
 
636
                        close( sock );
 
637
                }
 
638
        }
 
639
        else
 
640
        {
 
641
                close( fd_file );
 
642
                close( sock );
 
643
        }
 
644
#endif
 
645
}
 
646
 
 
647
 
 
648
void *jabber_send_file_fd(void *arg)
 
649
{
 
650
#ifdef HAVE_THREAD
 
651
        struct pargs_r *argument;
 
652
        int sock;
 
653
        int fd_file;
 
654
        struct sockaddr_in *addr;
 
655
        long int size;
 
656
        argument = (struct pargs_r*)arg;
 
657
 
 
658
        sock = argument->sock;
 
659
        fd_file = argument->fd_file;
 
660
        size = argument->size;
 
661
         
 
662
        pthread_cleanup_push(cleanup_thread, argument);
 
663
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 
664
 
 
665
        int client;
 
666
        char buff[SEND_BUF+1];
 
667
         
 
668
        char sbuf[SEND_BUF+1];
 
669
 
 
670
        int n;
 
671
        int addr_size = sizeof( addr );
 
672
        client = accept(sock, (struct sockaddr *) &addr, &addr_size);
 
673
        int counter = 0;
 
674
        if( client > 0 )
 
675
        {
 
676
                n = recv(client, buff, SEND_BUF, 0);
 
677
                if( strstr( buff, "GET /" ) )
 
678
                {
 
679
                        snprintf( sbuf, SEND_BUF, "%d\r\n\r\n", size );
 
680
                        strncpy( buff, "HTTP/1.0 200 OK\r\nContent-Type: application/data\r\nContent-Length: ", SEND_BUF );
 
681
                        strncat( buff, sbuf, SEND_BUF );
 
682
                        int str_len = strlen( buff );
 
683
                        send( client, buff, str_len, 0);
 
684
                        while( ( n = read( fd_file, buff, SEND_BUF )) > 0 ) 
 
685
                        {
 
686
                                counter += n;
 
687
                                if( send( client, buff, n, 0) != n )
 
688
                                        break;
 
689
                                else
 
690
                                        argument->callback(argument->rfile, counter, size, 0,  1);
 
691
                        }
 
692
                }
 
693
                close( client );
 
694
        }
 
695
         
 
696
        
 
697
        if( counter == size )
 
698
                argument->callback(argument->rfile, counter, size, 1, 1);
 
699
        else
 
700
                argument->callback(argument->rfile, counter, size, 2, 1);
 
701
         
 
702
        pthread_cleanup_pop(1);
 
703
         
 
704
        pthread_exit(0);
 
705
#endif
 
706
}
 
707
 
 
708
int next_random( int start_port, int end_port ) //generate random number between two digits
 
709
{
 
710
        srand( time( NULL ) );
 
711
        return (start_port + rand() % (end_port-start_port+1));
 
712
}
 
713
 
 
714
void jabber_get_file(jconn j, const char *filename, long int size, struct send_file *file, void *rfile, void (*function)(void *file, long int bytes, long int size, int status, int conn_type) ) //returning ip address and port after binding
 
715
{
 
716
#ifdef HAVE_THREAD
 
717
        int sock;
 
718
        struct sockaddr_in addr;
 
719
        int optval = 1;
 
720
        char *ip_addr = file->host;
 
721
        char *sid_from_to = file->sid_from_to;
 
722
        int port = file->port;
 
723
         
 
724
        int fd_file = open(filename, O_CREAT | O_WRONLY | O_TRUNC,  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH );
 
725
        if( fd_file < 0 )
 
726
                return;
 
727
 
 
728
        sock = socket(AF_INET, SOCK_STREAM, 0);
 
729
        if(sock < 0)
 
730
        {
 
731
                close( fd_file );
 
732
                return;
 
733
        }
 
734
         
 
735
        struct hostent *host = gethostbyname(ip_addr);
 
736
        bcopy(host->h_addr, &addr.sin_addr, host->h_length);
 
737
         
 
738
        addr.sin_family = AF_INET;
 
739
        addr.sin_port = htons( port ); 
 
740
 
 
741
 
 
742
        if ( connect(sock, (struct sockaddr *) &addr, sizeof(addr) ) < 0 )
 
743
        {
 
744
                close( sock );
 
745
                close( fd_file );
 
746
                return;
 
747
        }
 
748
         
 
749
 
 
750
         
 
751
        char *hash = NULL;
 
752
        if(sid_from_to)
 
753
                hash = shahash(sid_from_to);
 
754
         
 
755
        struct pargs_r *arg;
 
756
        arg = (struct pargs_r *)calloc(1, sizeof(struct pargs_r));
 
757
        if( arg )
 
758
 
 
759
        {
 
760
                arg->sock = sock;
 
761
                arg->fd_file = fd_file;
 
762
                arg->size = size;
 
763
                if( hash )
 
764
                        arg->hash = strdup( hash );
 
765
                arg->rfile = rfile;
 
766
                arg->url = file->url;
 
767
                arg->callback = function;
 
768
                if(file->transfer_type == 0)
 
769
                {
 
770
                        if (pthread_create(&file->thread, NULL, jabber_recieve_file_fd, (void *)arg ))
 
771
                        {
 
772
 
 
773
                                free( arg );
 
774
                                close( fd_file );
 
775
                                close( sock );
 
776
                        }
 
777
                }
 
778
                else
 
779
                {
 
780
                        if (pthread_create(&file->thread, NULL, jabber_recieve_file_fd_http, (void *)arg ))
 
781
                        {
 
782
 
 
783
                                free( arg );
 
784
                                close( fd_file );
 
785
                                close( sock );
 
786
                        }
 
787
                }
 
788
        }
 
789
        else
 
790
        {
 
791
                close( fd_file );
 
792
                close( sock );
 
793
        }
 
794
#endif
 
795
}
 
796
 
 
797
void *jabber_recieve_file_fd(void *arg)
 
798
{
 
799
#ifdef HAVE_THREAD
 
800
        struct pargs_r *argument;
 
801
        int sock;
 
802
        int fd_file;
 
803
        long int size;
 
804
        char *hash;
 
805
        argument = (struct pargs_r*)arg;
 
806
         
 
807
        sock = argument->sock;
 
808
        fd_file = argument->fd_file;
 
809
        size = argument->size;
 
810
        hash = argument->hash;
 
811
        pthread_cleanup_push(cleanup_thread, argument);
 
812
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 
813
         
 
814
        char buff[SEND_BUF];
 
815
         
 
816
 
 
817
 
 
818
        buff[0] = 0x05;
 
819
        buff[1] = 0x01;
 
820
        buff[2] = 0x00;
 
821
         
 
822
        if( send( sock, buff, 3, 0 ) != 3 )
 
823
        {
 
824
                free(hash);
 
825
                close(sock);
 
826
                close(fd_file);
 
827
                return;
 
828
        }
 
829
         
 
830
        recv( sock, buff, SEND_BUF, 0 );
 
831
        if( buff[0] != 0x05 || buff[1] != 0x00 ) 
 
832
        {
 
833
                free(hash);
 
834
                close(sock);
 
835
                close(fd_file);
 
836
                return;
 
837
        }
 
838
         
 
839
//socks5 bytestream packet       
 
840
        buff[0] = 0x05;
 
841
        buff[1] = 0x01;
 
842
        buff[2] = 0x00;
 
843
        buff[3] = 0x03;
 
844
        buff[4] = 0x28;
 
845
        strncpy( (char*)(buff + 5), hash, 40 );
 
846
        buff[45] = 0x00;
 
847
        buff[46] = 0x00;
 
848
                 
 
849
        if( send( sock, buff, 47, 0 ) != 47 )
 
850
        {
 
851
                free(hash);
 
852
                close(sock);
 
853
                close(fd_file);
 
854
                return;
 
855
        }
 
856
        recv( sock, buff, 47, 0 );
 
857
        if( buff[0] != 0x05 || buff[3] != 0x03 )
 
858
        {
 
859
                free(hash);
 
860
                close(sock);
 
861
                close(fd_file);
 
862
                return;
 
863
        }
 
864
 
 
865
 
 
866
        int bytes = 0;
 
867
        int counter = 0;
 
868
        while(1)
 
869
        {
 
870
                bytes = recv( sock, buff, SEND_BUF, 0 );
 
871
                if( bytes < 1 )
 
872
                        break;
 
873
                else
 
874
                {
 
875
                        write(fd_file, buff, bytes);
 
876
                        counter += bytes;
 
877
                        argument->callback(argument->rfile, counter, size, 0, 0);
 
878
                }
 
879
                                
 
880
        }
 
881
        if( counter == size )
 
882
                argument->callback(argument->rfile, counter, size, 1, 0);
 
883
        else
 
884
                argument->callback(argument->rfile, counter, size, 2, 0);
 
885
         
 
886
        pthread_cleanup_pop(1);
 
887
 
 
888
        pthread_exit(0);
 
889
 
 
890
         
 
891
#endif
 
892
}
 
893
 
 
894
 
 
895
void *jabber_recieve_file_fd_http(void *arg)
 
896
{
 
897
#ifdef HAVE_THREAD
 
898
        struct pargs_r *argument;
 
899
        int sock;
 
900
        int fd_file;
 
901
        long int size;
 
902
        char *url;
 
903
        argument = (struct pargs_r*)arg;
 
904
         
 
905
        sock = argument->sock;
 
906
        fd_file = argument->fd_file;
 
907
        size = argument->size;
 
908
        url = argument->url;
 
909
        pthread_cleanup_push(cleanup_thread, argument);
 
910
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 
911
        
 
912
        char buff[SEND_BUF];
 
913
         
 
914
        snprintf( buff, SEND_BUF, "GET %s HTTP/1.0\r\n\r\n", url );
 
915
        send( sock, buff, strlen(buff), 0 );
 
916
         
 
917
 
 
918
        int but = recv( sock, buff, SEND_BUF, 0 );
 
919
        if( strstr(buff, "200 OK" ) )
 
920
        {
 
921
                char *length = strstr( buff, "Content-Length:" );
 
922
                sscanf( length, "Content-Length: %d", &size );
 
923
 
 
924
                int i = 0;
 
925
                while(i < but-4)
 
926
                {
 
927
                        if(buff[i] == '\r' && buff[i+1] == '\n' && buff[i+2] == '\r' && buff[i+3] == '\n' )
 
928
                        {
 
929
                                break;
 
930
                        }
 
931
                        i++;
 
932
                }
 
933
                i = i + 4;
 
934
                int bytes = 0;
 
935
                int counter = 0;
 
936
 
 
937
                bytes = but-i;
 
938
                write(fd_file, (buff+i), bytes);
 
939
                counter += bytes;
 
940
 
 
941
                while(1)
 
942
                {
 
943
                        bytes = recv( sock, buff, SEND_BUF, 0 );
 
944
                        if( bytes < 1 )
 
945
                                break;
 
946
                        else
 
947
                        {
 
948
                                write(fd_file, buff, bytes);
 
949
                                counter += bytes;
 
950
                                argument->callback(argument->rfile, counter, size, 0, 0);
 
951
                        }
 
952
 
 
953
                }
 
954
                if( counter == size )
 
955
                        argument->callback(argument->rfile, counter, size, 1, 0);
 
956
                else
 
957
                        argument->callback(argument->rfile, counter, size, 2, 0);
 
958
        }
 
959
         
 
960
        pthread_cleanup_pop(1);
 
961
 
 
962
        pthread_exit(0);
 
963
#endif
 
964
         
 
965
}