Mercurial > emacs
comparison src/w32.c @ 44042:6e7772d1632e
(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.
author | Jason Rumney <jasonr@gnu.org> |
---|---|
date | Wed, 20 Mar 2002 20:38:44 +0000 |
parents | 64341c22fb4c |
children | 81e8a128e49f |
comparison
equal
deleted
inserted
replaced
44041:134644f94850 | 44042:6e7772d1632e |
---|---|
83 #undef inet_addr | 83 #undef inet_addr |
84 #undef gethostname | 84 #undef gethostname |
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" |
91 #include "ndir.h" | 97 #include "ndir.h" |
92 #include "w32heap.h" | 98 #include "w32heap.h" |
2419 u_short (PASCAL *pfn_ntohs) (u_short netshort); | 2425 u_short (PASCAL *pfn_ntohs) (u_short netshort); |
2420 unsigned long (PASCAL *pfn_inet_addr) (const char * cp); | 2426 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 |
2428 #define HANDLE_FLAG_INHERIT 1 | 2445 #define HANDLE_FLAG_INHERIT 1 |
2429 #endif | 2446 #endif |
2489 LOAD_PROC( inet_addr ); | 2506 LOAD_PROC( inet_addr ); |
2490 LOAD_PROC( gethostname ); | 2507 LOAD_PROC( gethostname ); |
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 */ |
2498 if (pfn_WSAStartup (0x101, &winsockData) == 0) | 2520 if (pfn_WSAStartup (0x101, &winsockData) == 0) |
2499 { | 2521 { |
2660 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd)) | 2682 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd)) |
2661 #else | 2683 #else |
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 { |
2674 h_errno = ENETDOWN; | 2696 h_errno = ENETDOWN; |
2675 return INVALID_SOCKET; | 2697 return INVALID_SOCKET; |
2676 } | 2698 } |
2677 | 2699 |
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 | 2707 |
2686 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT, | 2708 set_errno (); |
2687 that does not work under NT 3.1. However, we can get the same | 2709 return -1; |
2688 effect by using a backdoor function to replace an existing | 2710 } |
2689 descriptor handle with the one we want. */ | 2711 |
2690 | 2712 /* Convert a SOCKET to a file descriptor. */ |
2691 /* allocate a file descriptor (with appropriate flags) */ | 2713 int |
2692 fd = _open ("NUL:", _O_RDWR); | 2714 socket_to_fd (SOCKET s) |
2693 if (fd >= 0) | 2715 { |
2694 { | 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; |
2754 | |
2755 if (DuplicateHandle (parent, | |
2756 (HANDLE) s, | |
2757 parent, | |
2758 &new_s, | |
2759 0, | |
2760 FALSE, | |
2761 DUPLICATE_SAME_ACCESS)) | |
2713 { | 2762 { |
2714 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0); | 2763 /* It is possible that DuplicateHandle succeeds even |
2715 } | 2764 though the socket wasn't really a kernel handle, |
2716 else | 2765 because a real handle has the same value. So |
2717 { | 2766 test whether the new handle really is a socket. */ |
2718 HANDLE parent = GetCurrentProcess (); | 2767 long nonblocking = 0; |
2719 HANDLE new_s = INVALID_HANDLE_VALUE; | 2768 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0) |
2720 | |
2721 if (DuplicateHandle (parent, | |
2722 (HANDLE) s, | |
2723 parent, | |
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) |
2788 { | |
2789 cp->fd = fd; | |
2790 cp->status = STATUS_READ_ACKNOWLEDGED; | |
2791 | |
2792 /* attach child_process to fd_info */ | |
2793 if (fd_info[ fd ].cp != NULL) | |
2754 { | 2794 { |
2755 cp->fd = fd; | 2795 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd)); |
2756 cp->status = STATUS_READ_ACKNOWLEDGED; | 2796 abort (); |
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 | |
2767 /* success! */ | |
2768 winsock_inuse++; /* count open sockets */ | |
2769 return fd; | |
2770 } | 2797 } |
2771 | 2798 |
2772 /* clean up */ | 2799 fd_info[ fd ].cp = cp; |
2773 _close (fd); | 2800 |
2774 } | 2801 /* success! */ |
2775 pfn_closesocket (s); | 2802 winsock_inuse++; /* count open sockets */ |
2776 h_errno = EMFILE; | 2803 return fd; |
2777 } | 2804 } |
2778 set_errno (); | 2805 |
2779 | 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 |
2783 | 2814 |
2784 int | 2815 int |
2905 | 2936 |
2906 check_errno (); | 2937 check_errno (); |
2907 if (fd_info[s].flags & FILE_SOCKET) | 2938 if (fd_info[s].flags & FILE_SOCKET) |
2908 { | 2939 { |
2909 int rc = pfn_shutdown (SOCK_HANDLE (s), how); | 2940 int rc = pfn_shutdown (SOCK_HANDLE (s), how); |
2941 if (rc == SOCKET_ERROR) | |
2942 set_errno (); | |
2943 return rc; | |
2944 } | |
2945 h_errno = ENOTSOCK; | |
2946 return SOCKET_ERROR; | |
2947 } | |
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); | |
2910 if (rc == SOCKET_ERROR) | 3072 if (rc == SOCKET_ERROR) |
2911 set_errno (); | 3073 set_errno (); |
2912 return rc; | 3074 return rc; |
2913 } | 3075 } |
2914 h_errno = ENOTSOCK; | 3076 h_errno = ENOTSOCK; |