~ubuntu-branches/ubuntu/lucid/samba/lucid-proposed

« back to all changes in this revision

Viewing changes to source/lib/util_sock.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-07-21 17:53:23 UTC
  • mfrom: (0.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050721175323-m3oh6aoigywohfnq
Tags: 3.0.14a-6ubuntu1
Resynchronise with Debian, resolving merge conflicts (#12360)

Show diffs side-by-side

added added

removed removed

Lines of Context:
798
798
}
799
799
 
800
800
/****************************************************************************
 
801
 Create an outgoing TCP socket to any of the addrs. This is for
 
802
 simultaneous connects to port 445 and 139 of a host or even a variety
 
803
 of DC's all of which are equivalent for our purposes.
 
804
**************************************************************************/
 
805
 
 
806
BOOL open_any_socket_out(struct sockaddr_in *addrs, int num_addrs,
 
807
                         int timeout, int *fd_index, int *fd)
 
808
{
 
809
        int i, resulting_index, res;
 
810
        int *sockets;
 
811
        BOOL good_connect;
 
812
 
 
813
        fd_set r_fds, wr_fds;
 
814
        struct timeval tv;
 
815
        int maxfd;
 
816
 
 
817
        int connect_loop = 10000; /* 10 milliseconds */
 
818
 
 
819
        timeout *= 1000;        /* convert to microseconds */
 
820
 
 
821
        sockets = SMB_MALLOC_ARRAY(int, num_addrs);
 
822
 
 
823
        if (sockets == NULL)
 
824
                return False;
 
825
 
 
826
        resulting_index = -1;
 
827
 
 
828
        for (i=0; i<num_addrs; i++)
 
829
                sockets[i] = -1;
 
830
 
 
831
        for (i=0; i<num_addrs; i++) {
 
832
                sockets[i] = socket(PF_INET, SOCK_STREAM, 0);
 
833
                if (sockets[i] < 0)
 
834
                        goto done;
 
835
                set_blocking(sockets[i], False);
 
836
        }
 
837
 
 
838
 connect_again:
 
839
        good_connect = False;
 
840
 
 
841
        for (i=0; i<num_addrs; i++) {
 
842
 
 
843
                if (sockets[i] == -1)
 
844
                        continue;
 
845
 
 
846
                if (connect(sockets[i], (struct sockaddr *)&(addrs[i]),
 
847
                            sizeof(*addrs)) == 0) {
 
848
                        /* Rather unlikely as we are non-blocking, but it
 
849
                         * might actually happen. */
 
850
                        resulting_index = i;
 
851
                        goto done;
 
852
                }
 
853
 
 
854
                if (errno == EINPROGRESS || errno == EALREADY ||
 
855
                    errno == EAGAIN) {
 
856
                        /* These are the error messages that something is
 
857
                           progressing. */
 
858
                        good_connect = True;
 
859
                } else if (errno != 0) {
 
860
                        /* There was a direct error */
 
861
                        close(sockets[i]);
 
862
                        sockets[i] = -1;
 
863
                }
 
864
        }
 
865
 
 
866
        if (!good_connect) {
 
867
                /* All of the connect's resulted in real error conditions */
 
868
                goto done;
 
869
        }
 
870
 
 
871
        /* Lets see if any of the connect attempts succeeded */
 
872
 
 
873
        maxfd = 0;
 
874
        FD_ZERO(&wr_fds);
 
875
        FD_ZERO(&r_fds);
 
876
 
 
877
        for (i=0; i<num_addrs; i++) {
 
878
                if (sockets[i] == -1)
 
879
                        continue;
 
880
                FD_SET(sockets[i], &wr_fds);
 
881
                FD_SET(sockets[i], &r_fds);
 
882
                if (sockets[i]>maxfd)
 
883
                        maxfd = sockets[i];
 
884
        }
 
885
 
 
886
        tv.tv_sec = 0;
 
887
        tv.tv_usec = connect_loop;
 
888
 
 
889
        res = sys_select(maxfd+1, &r_fds, &wr_fds, NULL, &tv);
 
890
 
 
891
        if (res < 0)
 
892
                goto done;
 
893
 
 
894
        if (res == 0)
 
895
                goto next_round;
 
896
 
 
897
        for (i=0; i<num_addrs; i++) {
 
898
 
 
899
                if (sockets[i] == -1)
 
900
                        continue;
 
901
 
 
902
                /* Stevens, Network Programming says that if there's a
 
903
                 * successful connect, the socket is only writable. Upon an
 
904
                 * error, it's both readable and writable. */
 
905
 
 
906
                if (FD_ISSET(sockets[i], &r_fds) &&
 
907
                    FD_ISSET(sockets[i], &wr_fds)) {
 
908
                        /* readable and writable, so it's an error */
 
909
                        close(sockets[i]);
 
910
                        sockets[i] = -1;
 
911
                        continue;
 
912
                }
 
913
 
 
914
                if (!FD_ISSET(sockets[i], &r_fds) &&
 
915
                    FD_ISSET(sockets[i], &wr_fds)) {
 
916
                        /* Only writable, so it's connected */
 
917
                        resulting_index = i;
 
918
                        goto done;
 
919
                }
 
920
        }
 
921
 
 
922
 next_round:
 
923
 
 
924
        timeout -= connect_loop;
 
925
        if (timeout <= 0)
 
926
                goto done;
 
927
        connect_loop *= 1.5;
 
928
        if (connect_loop > timeout)
 
929
                connect_loop = timeout;
 
930
        goto connect_again;
 
931
 
 
932
 done:
 
933
        for (i=0; i<num_addrs; i++) {
 
934
                if (i == resulting_index)
 
935
                        continue;
 
936
                if (sockets[i] >= 0)
 
937
                        close(sockets[i]);
 
938
        }
 
939
 
 
940
        if (resulting_index >= 0) {
 
941
                *fd_index = resulting_index;
 
942
                *fd = sockets[*fd_index];
 
943
                set_blocking(*fd, True);
 
944
        }
 
945
 
 
946
        free(sockets);
 
947
 
 
948
        return (resulting_index >= 0);
 
949
}
 
950
/****************************************************************************
801
951
 Open a connected UDP socket to host on port
802
952
**************************************************************************/
803
953