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;