aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2002-03-20 20:38:44 +0000
committerJason Rumney2002-03-20 20:38:44 +0000
commit962955c57422af811b70efda580a4236c72e4056 (patch)
treefb162148f8dd2b32a92b3f052393a033e34c4d00 /src
parent3635ecad99b30100ec673c93d6a496df68ad4f9d (diff)
downloademacs-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.c336
1 files changed, 249 insertions, 87 deletions
diff --git a/src/w32.c b/src/w32.c
index f6e9f765500..6162c342db9 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -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);
2421int (PASCAL *pfn_gethostname) (char * name, int namelen); 2427int (PASCAL *pfn_gethostname) (char * name, int namelen);
2422struct hostent * (PASCAL *pfn_gethostbyname) (const char * name); 2428struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2423struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto); 2429struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2424 2430
2431int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2432 const char * optval, int optlen);
2433int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2434int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2435 int * namelen);
2436SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2437int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2438 struct sockaddr * from, int * fromlen);
2439int (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. */
2426BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags); 2443BOOL (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
2687int socket_to_fd (SOCKET s);
2688
2665int 2689int
2666sys_socket(int af, int type, int protocol) 2690sys_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. */
2713int
2714socket_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
2949int
2950sys_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
2971int
2972sys_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
2992int
2993sys_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
3013int
3014sys_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
3036int
3037sys_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
3058int
3059sys_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