diff options
| author | Jason Rumney | 2002-03-20 20:38:44 +0000 |
|---|---|---|
| committer | Jason Rumney | 2002-03-20 20:38:44 +0000 |
| commit | 962955c57422af811b70efda580a4236c72e4056 (patch) | |
| tree | fb162148f8dd2b32a92b3f052393a033e34c4d00 /src | |
| parent | 3635ecad99b30100ec673c93d6a496df68ad4f9d (diff) | |
| download | emacs-962955c57422af811b70efda580a4236c72e4056.tar.gz emacs-962955c57422af811b70efda580a4236c72e4056.zip | |
(init_winsock): Dynamically load new server and UDP
socket functions.
(socket_to_fd): New function.
(sys_socket): Use it.
(sys_setsockopt, sys_listen, sys_getsockname, sys_accept)
(sys_recvfrom, sys_sendto): New wrapper functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 336 |
1 files changed, 249 insertions, 87 deletions
| @@ -85,6 +85,12 @@ Boston, MA 02111-1307, USA. | |||
| 85 | #undef gethostbyname | 85 | #undef gethostbyname |
| 86 | #undef getservbyname | 86 | #undef getservbyname |
| 87 | #undef shutdown | 87 | #undef shutdown |
| 88 | #undef setsockopt | ||
| 89 | #undef listen | ||
| 90 | #undef getsockname | ||
| 91 | #undef accept | ||
| 92 | #undef recvfrom | ||
| 93 | #undef sendto | ||
| 88 | #endif | 94 | #endif |
| 89 | 95 | ||
| 90 | #include "w32.h" | 96 | #include "w32.h" |
| @@ -2421,7 +2427,18 @@ unsigned long (PASCAL *pfn_inet_addr) (const char * cp); | |||
| 2421 | int (PASCAL *pfn_gethostname) (char * name, int namelen); | 2427 | int (PASCAL *pfn_gethostname) (char * name, int namelen); |
| 2422 | struct hostent * (PASCAL *pfn_gethostbyname) (const char * name); | 2428 | struct hostent * (PASCAL *pfn_gethostbyname) (const char * name); |
| 2423 | struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto); | 2429 | struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto); |
| 2424 | 2430 | ||
| 2431 | int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname, | ||
| 2432 | const char * optval, int optlen); | ||
| 2433 | int (PASCAL *pfn_listen) (SOCKET s, int backlog); | ||
| 2434 | int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name, | ||
| 2435 | int * namelen); | ||
| 2436 | SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen); | ||
| 2437 | int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags, | ||
| 2438 | struct sockaddr * from, int * fromlen); | ||
| 2439 | int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags, | ||
| 2440 | const struct sockaddr * to, int tolen); | ||
| 2441 | |||
| 2425 | /* SetHandleInformation is only needed to make sockets non-inheritable. */ | 2442 | /* SetHandleInformation is only needed to make sockets non-inheritable. */ |
| 2426 | BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags); | 2443 | BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags); |
| 2427 | #ifndef HANDLE_FLAG_INHERIT | 2444 | #ifndef HANDLE_FLAG_INHERIT |
| @@ -2491,7 +2508,12 @@ init_winsock (int load_now) | |||
| 2491 | LOAD_PROC( gethostbyname ); | 2508 | LOAD_PROC( gethostbyname ); |
| 2492 | LOAD_PROC( getservbyname ); | 2509 | LOAD_PROC( getservbyname ); |
| 2493 | LOAD_PROC( WSACleanup ); | 2510 | LOAD_PROC( WSACleanup ); |
| 2494 | 2511 | LOAD_PROC( setsockopt ); | |
| 2512 | LOAD_PROC( listen ); | ||
| 2513 | LOAD_PROC( getsockname ); | ||
| 2514 | LOAD_PROC( accept ); | ||
| 2515 | LOAD_PROC( recvfrom ); | ||
| 2516 | LOAD_PROC( sendto ); | ||
| 2495 | #undef LOAD_PROC | 2517 | #undef LOAD_PROC |
| 2496 | 2518 | ||
| 2497 | /* specify version 1.1 of winsock */ | 2519 | /* specify version 1.1 of winsock */ |
| @@ -2662,12 +2684,12 @@ sys_strerror(int error_no) | |||
| 2662 | #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd) | 2684 | #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd) |
| 2663 | #endif | 2685 | #endif |
| 2664 | 2686 | ||
| 2687 | int socket_to_fd (SOCKET s); | ||
| 2688 | |||
| 2665 | int | 2689 | int |
| 2666 | sys_socket(int af, int type, int protocol) | 2690 | sys_socket(int af, int type, int protocol) |
| 2667 | { | 2691 | { |
| 2668 | int fd; | 2692 | SOCKET s; |
| 2669 | long s; | ||
| 2670 | child_process * cp; | ||
| 2671 | 2693 | ||
| 2672 | if (winsock_lib == NULL) | 2694 | if (winsock_lib == NULL) |
| 2673 | { | 2695 | { |
| @@ -2678,105 +2700,114 @@ sys_socket(int af, int type, int protocol) | |||
| 2678 | check_errno (); | 2700 | check_errno (); |
| 2679 | 2701 | ||
| 2680 | /* call the real socket function */ | 2702 | /* call the real socket function */ |
| 2681 | s = (long) pfn_socket (af, type, protocol); | 2703 | s = pfn_socket (af, type, protocol); |
| 2682 | 2704 | ||
| 2683 | if (s != INVALID_SOCKET) | 2705 | if (s != INVALID_SOCKET) |
| 2684 | { | 2706 | return socket_to_fd (s); |
| 2685 | /* Although under NT 3.5 _open_osfhandle will accept a socket | ||
| 2686 | handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT, | ||
| 2687 | that does not work under NT 3.1. However, we can get the same | ||
| 2688 | effect by using a backdoor function to replace an existing | ||
| 2689 | descriptor handle with the one we want. */ | ||
| 2690 | 2707 | ||
| 2691 | /* allocate a file descriptor (with appropriate flags) */ | 2708 | set_errno (); |
| 2692 | fd = _open ("NUL:", _O_RDWR); | 2709 | return -1; |
| 2693 | if (fd >= 0) | 2710 | } |
| 2694 | { | 2711 | |
| 2712 | /* Convert a SOCKET to a file descriptor. */ | ||
| 2713 | int | ||
| 2714 | socket_to_fd (SOCKET s) | ||
| 2715 | { | ||
| 2716 | int fd; | ||
| 2717 | child_process * cp; | ||
| 2718 | |||
| 2719 | /* Although under NT 3.5 _open_osfhandle will accept a socket | ||
| 2720 | handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT, | ||
| 2721 | that does not work under NT 3.1. However, we can get the same | ||
| 2722 | effect by using a backdoor function to replace an existing | ||
| 2723 | descriptor handle with the one we want. */ | ||
| 2724 | |||
| 2725 | /* allocate a file descriptor (with appropriate flags) */ | ||
| 2726 | fd = _open ("NUL:", _O_RDWR); | ||
| 2727 | if (fd >= 0) | ||
| 2728 | { | ||
| 2695 | #ifdef SOCK_REPLACE_HANDLE | 2729 | #ifdef SOCK_REPLACE_HANDLE |
| 2696 | /* now replace handle to NUL with our socket handle */ | 2730 | /* now replace handle to NUL with our socket handle */ |
| 2697 | CloseHandle ((HANDLE) _get_osfhandle (fd)); | 2731 | CloseHandle ((HANDLE) _get_osfhandle (fd)); |
| 2698 | _free_osfhnd (fd); | 2732 | _free_osfhnd (fd); |
| 2699 | _set_osfhnd (fd, s); | 2733 | _set_osfhnd (fd, s); |
| 2700 | /* setmode (fd, _O_BINARY); */ | 2734 | /* setmode (fd, _O_BINARY); */ |
| 2701 | #else | 2735 | #else |
| 2702 | /* Make a non-inheritable copy of the socket handle. Note | 2736 | /* Make a non-inheritable copy of the socket handle. Note |
| 2703 | that it is possible that sockets aren't actually kernel | 2737 | that it is possible that sockets aren't actually kernel |
| 2704 | handles, which appears to be the case on Windows 9x when | 2738 | handles, which appears to be the case on Windows 9x when |
| 2705 | the MS Proxy winsock client is installed. */ | 2739 | the MS Proxy winsock client is installed. */ |
| 2740 | { | ||
| 2741 | /* Apparently there is a bug in NT 3.51 with some service | ||
| 2742 | packs, which prevents using DuplicateHandle to make a | ||
| 2743 | socket handle non-inheritable (causes WSACleanup to | ||
| 2744 | hang). The work-around is to use SetHandleInformation | ||
| 2745 | instead if it is available and implemented. */ | ||
| 2746 | if (pfn_SetHandleInformation) | ||
| 2706 | { | 2747 | { |
| 2707 | /* Apparently there is a bug in NT 3.51 with some service | 2748 | pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); |
| 2708 | packs, which prevents using DuplicateHandle to make a | 2749 | } |
| 2709 | socket handle non-inheritable (causes WSACleanup to | 2750 | else |
| 2710 | hang). The work-around is to use SetHandleInformation | 2751 | { |
| 2711 | instead if it is available and implemented. */ | 2752 | HANDLE parent = GetCurrentProcess (); |
| 2712 | if (pfn_SetHandleInformation) | 2753 | HANDLE new_s = INVALID_HANDLE_VALUE; |
| 2713 | { | 2754 | |
| 2714 | pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); | 2755 | if (DuplicateHandle (parent, |
| 2715 | } | 2756 | (HANDLE) s, |
| 2716 | else | 2757 | parent, |
| 2758 | &new_s, | ||
| 2759 | 0, | ||
| 2760 | FALSE, | ||
| 2761 | DUPLICATE_SAME_ACCESS)) | ||
| 2717 | { | 2762 | { |
| 2718 | HANDLE parent = GetCurrentProcess (); | 2763 | /* It is possible that DuplicateHandle succeeds even |
| 2719 | HANDLE new_s = INVALID_HANDLE_VALUE; | 2764 | though the socket wasn't really a kernel handle, |
| 2720 | 2765 | because a real handle has the same value. So | |
| 2721 | if (DuplicateHandle (parent, | 2766 | test whether the new handle really is a socket. */ |
| 2722 | (HANDLE) s, | 2767 | long nonblocking = 0; |
| 2723 | parent, | 2768 | if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0) |
| 2724 | &new_s, | ||
| 2725 | 0, | ||
| 2726 | FALSE, | ||
| 2727 | DUPLICATE_SAME_ACCESS)) | ||
| 2728 | { | 2769 | { |
| 2729 | /* It is possible that DuplicateHandle succeeds even | 2770 | pfn_closesocket (s); |
| 2730 | though the socket wasn't really a kernel handle, | 2771 | s = (SOCKET) new_s; |
| 2731 | because a real handle has the same value. So | 2772 | } |
| 2732 | test whether the new handle really is a socket. */ | 2773 | else |
| 2733 | long nonblocking = 0; | 2774 | { |
| 2734 | if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0) | 2775 | CloseHandle (new_s); |
| 2735 | { | 2776 | } |
| 2736 | pfn_closesocket (s); | 2777 | } |
| 2737 | s = (SOCKET) new_s; | ||
| 2738 | } | ||
| 2739 | else | ||
| 2740 | { | ||
| 2741 | CloseHandle (new_s); | ||
| 2742 | } | ||
| 2743 | } | ||
| 2744 | } | ||
| 2745 | } | 2778 | } |
| 2746 | fd_info[fd].hnd = (HANDLE) s; | 2779 | } |
| 2780 | fd_info[fd].hnd = (HANDLE) s; | ||
| 2747 | #endif | 2781 | #endif |
| 2748 | 2782 | ||
| 2749 | /* set our own internal flags */ | 2783 | /* set our own internal flags */ |
| 2750 | fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE; | 2784 | fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE; |
| 2751 | 2785 | ||
| 2752 | cp = new_child (); | 2786 | cp = new_child (); |
| 2753 | if (cp) | 2787 | if (cp) |
| 2754 | { | 2788 | { |
| 2755 | cp->fd = fd; | 2789 | cp->fd = fd; |
| 2756 | cp->status = STATUS_READ_ACKNOWLEDGED; | 2790 | cp->status = STATUS_READ_ACKNOWLEDGED; |
| 2757 | |||
| 2758 | /* attach child_process to fd_info */ | ||
| 2759 | if (fd_info[ fd ].cp != NULL) | ||
| 2760 | { | ||
| 2761 | DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd)); | ||
| 2762 | abort (); | ||
| 2763 | } | ||
| 2764 | |||
| 2765 | fd_info[ fd ].cp = cp; | ||
| 2766 | 2791 | ||
| 2767 | /* success! */ | 2792 | /* attach child_process to fd_info */ |
| 2768 | winsock_inuse++; /* count open sockets */ | 2793 | if (fd_info[ fd ].cp != NULL) |
| 2769 | return fd; | 2794 | { |
| 2795 | DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd)); | ||
| 2796 | abort (); | ||
| 2770 | } | 2797 | } |
| 2771 | 2798 | ||
| 2772 | /* clean up */ | 2799 | fd_info[ fd ].cp = cp; |
| 2773 | _close (fd); | 2800 | |
| 2801 | /* success! */ | ||
| 2802 | winsock_inuse++; /* count open sockets */ | ||
| 2803 | return fd; | ||
| 2774 | } | 2804 | } |
| 2775 | pfn_closesocket (s); | ||
| 2776 | h_errno = EMFILE; | ||
| 2777 | } | ||
| 2778 | set_errno (); | ||
| 2779 | 2805 | ||
| 2806 | /* clean up */ | ||
| 2807 | _close (fd); | ||
| 2808 | } | ||
| 2809 | pfn_closesocket (s); | ||
| 2810 | h_errno = EMFILE; | ||
| 2780 | return -1; | 2811 | return -1; |
| 2781 | } | 2812 | } |
| 2782 | 2813 | ||
| @@ -2915,6 +2946,137 @@ sys_shutdown (int s, int how) | |||
| 2915 | return SOCKET_ERROR; | 2946 | return SOCKET_ERROR; |
| 2916 | } | 2947 | } |
| 2917 | 2948 | ||
| 2949 | int | ||
| 2950 | sys_setsockopt (int s, int level, int optname, const char * optval, int optlen) | ||
| 2951 | { | ||
| 2952 | if (winsock_lib == NULL) | ||
| 2953 | { | ||
| 2954 | h_errno = ENETDOWN; | ||
| 2955 | return SOCKET_ERROR; | ||
| 2956 | } | ||
| 2957 | |||
| 2958 | check_errno (); | ||
| 2959 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 2960 | { | ||
| 2961 | int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname, | ||
| 2962 | optval, optlen); | ||
| 2963 | if (rc == SOCKET_ERROR) | ||
| 2964 | set_errno (); | ||
| 2965 | return rc; | ||
| 2966 | } | ||
| 2967 | h_errno = ENOTSOCK; | ||
| 2968 | return SOCKET_ERROR; | ||
| 2969 | } | ||
| 2970 | |||
| 2971 | int | ||
| 2972 | sys_listen (int s, int backlog) | ||
| 2973 | { | ||
| 2974 | if (winsock_lib == NULL) | ||
| 2975 | { | ||
| 2976 | h_errno = ENETDOWN; | ||
| 2977 | return SOCKET_ERROR; | ||
| 2978 | } | ||
| 2979 | |||
| 2980 | check_errno (); | ||
| 2981 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 2982 | { | ||
| 2983 | int rc = pfn_listen (SOCK_HANDLE (s), backlog); | ||
| 2984 | if (rc == SOCKET_ERROR) | ||
| 2985 | set_errno (); | ||
| 2986 | return rc; | ||
| 2987 | } | ||
| 2988 | h_errno = ENOTSOCK; | ||
| 2989 | return SOCKET_ERROR; | ||
| 2990 | } | ||
| 2991 | |||
| 2992 | int | ||
| 2993 | sys_getsockname (int s, struct sockaddr * name, int * namelen) | ||
| 2994 | { | ||
| 2995 | if (winsock_lib == NULL) | ||
| 2996 | { | ||
| 2997 | h_errno = ENETDOWN; | ||
| 2998 | return SOCKET_ERROR; | ||
| 2999 | } | ||
| 3000 | |||
| 3001 | check_errno (); | ||
| 3002 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 3003 | { | ||
| 3004 | int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen); | ||
| 3005 | if (rc == SOCKET_ERROR) | ||
| 3006 | set_errno (); | ||
| 3007 | return rc; | ||
| 3008 | } | ||
| 3009 | h_errno = ENOTSOCK; | ||
| 3010 | return SOCKET_ERROR; | ||
| 3011 | } | ||
| 3012 | |||
| 3013 | int | ||
| 3014 | sys_accept (int s, struct sockaddr * addr, int * addrlen) | ||
| 3015 | { | ||
| 3016 | if (winsock_lib == NULL) | ||
| 3017 | { | ||
| 3018 | h_errno = ENETDOWN; | ||
| 3019 | return -1; | ||
| 3020 | } | ||
| 3021 | |||
| 3022 | check_errno (); | ||
| 3023 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 3024 | { | ||
| 3025 | SOCKET s = pfn_accept (SOCK_HANDLE (s), addr, addrlen); | ||
| 3026 | if (s != INVALID_SOCKET) | ||
| 3027 | return socket_to_fd (s); | ||
| 3028 | |||
| 3029 | set_errno (); | ||
| 3030 | return -1; | ||
| 3031 | } | ||
| 3032 | h_errno = ENOTSOCK; | ||
| 3033 | return -1; | ||
| 3034 | } | ||
| 3035 | |||
| 3036 | int | ||
| 3037 | sys_recvfrom (int s, char * buf, int len, int flags, | ||
| 3038 | struct sockaddr * from, int * fromlen) | ||
| 3039 | { | ||
| 3040 | if (winsock_lib == NULL) | ||
| 3041 | { | ||
| 3042 | h_errno = ENETDOWN; | ||
| 3043 | return SOCKET_ERROR; | ||
| 3044 | } | ||
| 3045 | |||
| 3046 | check_errno (); | ||
| 3047 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 3048 | { | ||
| 3049 | int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen); | ||
| 3050 | if (rc == SOCKET_ERROR) | ||
| 3051 | set_errno (); | ||
| 3052 | return rc; | ||
| 3053 | } | ||
| 3054 | h_errno = ENOTSOCK; | ||
| 3055 | return SOCKET_ERROR; | ||
| 3056 | } | ||
| 3057 | |||
| 3058 | int | ||
| 3059 | sys_sendto (int s, const char * buf, int len, int flags, | ||
| 3060 | const struct sockaddr * to, int tolen) | ||
| 3061 | { | ||
| 3062 | if (winsock_lib == NULL) | ||
| 3063 | { | ||
| 3064 | h_errno = ENETDOWN; | ||
| 3065 | return SOCKET_ERROR; | ||
| 3066 | } | ||
| 3067 | |||
| 3068 | check_errno (); | ||
| 3069 | if (fd_info[s].flags & FILE_SOCKET) | ||
| 3070 | { | ||
| 3071 | int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen); | ||
| 3072 | if (rc == SOCKET_ERROR) | ||
| 3073 | set_errno (); | ||
| 3074 | return rc; | ||
| 3075 | } | ||
| 3076 | h_errno = ENOTSOCK; | ||
| 3077 | return SOCKET_ERROR; | ||
| 3078 | } | ||
| 3079 | |||
| 2918 | #endif /* HAVE_SOCKETS */ | 3080 | #endif /* HAVE_SOCKETS */ |
| 2919 | 3081 | ||
| 2920 | 3082 | ||