2909 If blocking is false, this call will return immediately, if there is no connection pending." |
2914 If blocking is false, this call will return immediately, if there is no connection pending." |
2910 |
2915 |
2911 |serverSocketHandle addr domainClass newHandle| |
2916 |serverSocketHandle addr domainClass newHandle| |
2912 |
2917 |
2913 handle notNil ifTrue:[ |
2918 handle notNil ifTrue:[ |
2914 ^ self errorAlreadyOpen |
2919 ^ self errorAlreadyOpen |
2915 ]. |
2920 ]. |
2916 |
2921 |
2917 domain := aServerSocket domain. |
2922 domain := aServerSocket domain. |
2918 socketType := aServerSocket type. |
2923 socketType := aServerSocket type. |
2919 handleType := aServerSocket handleType. |
2924 handleType := aServerSocket handleType. |
2920 serverSocketHandle := aServerSocket fileHandle. |
2925 serverSocketHandle := aServerSocket fileHandle. |
2921 serverSocketHandle isNil ifTrue:[ |
2926 serverSocketHandle isNil ifTrue:[ |
2922 ^ self error:'invalid server socket' |
2927 ^ self error:'invalid server socket' |
2923 ]. |
2928 ]. |
2924 "unix domain sockets do not return a valid peer name on accept" |
2929 "unix domain sockets do not return a valid peer name on accept" |
2925 domainClass := self class socketAddressClassForDomain:domain. |
2930 domainClass := self class socketAddressClassForDomain:domain. |
2926 domainClass isNil ifTrue:[ |
2931 domainClass isNil ifTrue:[ |
2927 ^ self error:'invalid (unsupported) domain'. |
2932 ^ self error:'invalid (unsupported) domain'. |
2928 ]. |
2933 ]. |
2929 addr := domainClass new. |
2934 addr := domainClass new. |
2930 newHandle := OperatingSystem socketAccessor new. |
2935 newHandle := OperatingSystem socketAccessor new. |
2931 |
2936 |
2932 %{ /* STACK: 100000 */ |
2937 %{ /* STACK: 100000 */ |
2944 serverSocket = __intVal(serverSocketHandle); |
2949 serverSocket = __intVal(serverSocketHandle); |
2945 #endif |
2950 #endif |
2946 |
2951 |
2947 # if defined(O_NONBLOCK) && defined(SET_NDELAY) |
2952 # if defined(O_NONBLOCK) && defined(SET_NDELAY) |
2948 if (blocking == false) { |
2953 if (blocking == false) { |
2949 flags = fcntl(serverSocket, F_GETFL); |
2954 flags = fcntl(serverSocket, F_GETFL); |
2950 fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK); |
2955 fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK); |
2951 } |
2956 } |
2952 # endif |
2957 # endif |
2953 |
2958 |
2954 # ifdef DO_WRAP_CALLS |
2959 # ifdef DO_WRAP_CALLS |
2955 do { |
2960 do { |
2956 __threadErrno = 0; |
2961 __threadErrno = 0; |
2957 alen = sizeof(sa); |
2962 alen = sizeof(sa); |
2958 newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen); |
2963 newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen); |
2959 } while ((newSock < 0) && (__threadErrno == EINTR)); |
2964 } while ((newSock < 0) && (__threadErrno == EINTR)); |
2960 if (newSock < 0) { |
2965 if (newSock < 0) { |
2961 errno = __threadErrno; |
2966 errno = __threadErrno; |
2962 } |
2967 } |
2963 # else |
2968 # else |
2964 __BEGIN_INTERRUPTABLE__ |
2969 __BEGIN_INTERRUPTABLE__ |
2965 do { |
2970 do { |
2966 alen = sizeof(sa); |
2971 alen = sizeof(sa); |
2967 newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen); |
2972 newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen); |
2968 } while ((newSock < 0) && (errno == EINTR)); |
2973 } while ((newSock < 0) && (errno == EINTR)); |
2969 __END_INTERRUPTABLE__ |
2974 __END_INTERRUPTABLE__ |
2970 # endif |
2975 # endif |
2971 DBGFPRINTF((stderr, "SOCKET: accept newSock=%d\n", newSock)); |
2976 DBGFPRINTF((stderr, "SOCKET: accept newSock=%d\n", newSock)); |
2972 |
2977 |
2973 # if defined(O_NDELAY) && defined(SET_NDELAY) |
2978 # if defined(O_NDELAY) && defined(SET_NDELAY) |
2974 if (blocking == false) { |
2979 if (blocking == false) { |
2975 fcntl(serverSocket, F_SETFL, flags); |
2980 fcntl(serverSocket, F_SETFL, flags); |
2976 } |
2981 } |
2977 # endif |
2982 # endif |
2978 |
2983 |
2979 if (newSock == -1) { |
2984 if (newSock == -1) { |
2980 DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno)); |
2985 DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno)); |
2981 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2986 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
2982 RETURN (false); |
2987 RETURN (false); |
2983 } |
2988 } |
2984 |
2989 |
2985 if (__isNonNilObject(addr)) { |
2990 if (__isNonNilObject(addr)) { |
2986 OBJ oClass = __qClass(addr); |
2991 OBJ oClass = __qClass(addr); |
2987 int nInstVars, nInstBytes, objSize; |
2992 int nInstVars, nInstBytes, objSize; |
2988 char *addrP; |
2993 char *addrP; |
2989 |
2994 |
2990 if (! __isBytes(addr) ) { |
2995 if (! __isBytes(addr) ) { |
2991 DBGPRINTF(("SOCKET: bad addr\n")); |
2996 DBGPRINTF(("SOCKET: bad addr\n")); |
2992 closesocket(newSock); |
2997 closesocket(newSock); |
2993 RETURN (false); |
2998 RETURN (false); |
2994 } |
2999 } |
2995 |
3000 |
2996 nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
3001 nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); |
2997 nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); |
3002 nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); |
2998 objSize = __qSize(addr) - nInstBytes; |
3003 objSize = __qSize(addr) - nInstBytes; |
2999 addrP = (char *)__InstPtr(addr) + nInstBytes; |
3004 addrP = (char *)__InstPtr(addr) + nInstBytes; |
3000 if (objSize < alen) { |
3005 if (objSize < alen) { |
3001 DBGPRINTF(("SOCKET: bad addr\n")); |
3006 DBGPRINTF(("SOCKET: bad addr\n")); |
3002 closesocket(newSock); |
3007 closesocket(newSock); |
3003 RETURN (false); |
3008 RETURN (false); |
3004 } |
3009 } |
3005 |
3010 |
3006 /* |
3011 /* |
3007 * extract the partners address |
3012 * extract the partners address |
3008 */ |
3013 */ |
3009 memcpy(addrP, (char *)&sa, alen); |
3014 memcpy(addrP, (char *)&sa, alen); |
3010 } |
3015 } |
3011 |
3016 |
3012 /* |
3017 /* |
3013 * make it a FILE * |
3018 * make it a FILE * |
3014 */ |
3019 */ |
3022 _fd = (int)newSock; |
3027 _fd = (int)newSock; |
3023 # endif |
3028 # endif |
3024 # else // ! WIN32 |
3029 # else // ! WIN32 |
3025 fp = fdopen(newSock, "r+"); |
3030 fp = fdopen(newSock, "r+"); |
3026 if (! fp) { |
3031 if (! fp) { |
3027 DBGPRINTF(("SOCKET: fdopen call failed\n")); |
3032 DBGPRINTF(("SOCKET: fdopen call failed\n")); |
3028 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
3033 __INST(lastErrorNumber) = __MKSMALLINT(errno); |
3029 closesocket(newSock); |
3034 closesocket(newSock); |
3030 DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock)); |
3035 DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock)); |
3031 RETURN (false); |
3036 RETURN (false); |
3032 } |
3037 } |
3033 # endif // ! WIN32 |
3038 # endif // ! WIN32 |
3034 |
3039 |
3035 if ((@global(FileOpenTrace) == true) || __debugging__) { |
3040 if ((@global(FileOpenTrace) == true) || __debugging__) { |
3036 # ifdef WIN32 |
3041 # ifdef WIN32 |
3037 console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock); |
3042 console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock); |
3038 # else |
3043 # else |
3039 console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock); |
3044 console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock); |
3040 # endif |
3045 # endif |
3041 } |
3046 } |
3042 |
3047 |
3043 # ifdef WIN32 |
3048 # ifdef WIN32 |
3044 __externalAddressVal(newHandle) = _fd; |
3049 __externalAddressVal(newHandle) = _fd; |
3688 typ = __intVal(typeCode); |
3693 typ = __intVal(typeCode); |
3689 |
3694 |
3690 # ifdef WIN32 |
3695 # ifdef WIN32 |
3691 sock = WSASocket(dom, typ, proto, 0, 0, noInheritFlag); |
3696 sock = WSASocket(dom, typ, proto, 0, 0, noInheritFlag); |
3692 if (sock == INVALID_SOCKET && noInheritFlag) { |
3697 if (sock == INVALID_SOCKET && noInheritFlag) { |
3693 // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT |
3698 // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT |
3694 // This fails on older windows versions, e.g. Windows XP |
3699 // This fails on older windows versions, e.g. Windows XP |
3695 sock = WSASocket(dom, typ, proto, 0, 0, 0); |
3700 sock = WSASocket(dom, typ, proto, 0, 0, 0); |
3696 if (sock != INVALID_SOCKET) { |
3701 if (sock != INVALID_SOCKET) { |
3697 // no error without WSA_FLAG_NO_HANDLE_INHERIT, |
3702 // no error without WSA_FLAG_NO_HANDLE_INHERIT, |
3698 // never use this flag again! |
3703 // never use this flag again! |
3699 noInheritFlag = 0; |
3704 noInheritFlag = 0; |
3700 } |
3705 } |
3701 } |
3706 } |
3702 if (sock == INVALID_SOCKET) { |
3707 if (sock == INVALID_SOCKET) { |
3703 errno = WSAGetLastError(); |
3708 errno = WSAGetLastError(); |
3704 |
3709 |
3705 # else // !WIN32 |
3710 # else // !WIN32 |
3706 |
3711 |
3707 sock = socket(dom, typ, proto); |
3712 sock = socket(dom, typ, proto); |
3708 # if defined(EPROTONOSUPPORT) /* for SGI */ |
3713 # if defined(EPROTONOSUPPORT) /* for SGI */ |
3709 if ((sock < 0) && (proto != 0) && (errno == EPROTONOSUPPORT)) { |
3714 if ((sock < 0) && (proto != 0) && (errno == EPROTONOSUPPORT)) { |
3710 DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n")); |
3715 DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n")); |
3711 proto = 0; |
3716 proto = 0; |
3712 sock = socket(dom, typ, 0); |
3717 sock = socket(dom, typ, 0); |
3713 } |
3718 } |
3714 # endif |
3719 # endif |
3715 if (sock < 0) { |
3720 if (sock < 0) { |
3716 # endif // !WIN32 |
3721 # endif // !WIN32 |
3717 |
3722 |
3718 DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno)); |
3723 DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno)); |
3719 error = __MKSMALLINT(errno); |
3724 error = __MKSMALLINT(errno); |
3720 } else { |
3725 } else { |
3721 # if defined(SET_LINGER_WHEN_CREATING_SOCKET) && defined(SO_LINGER) |
3726 # if defined(SET_LINGER_WHEN_CREATING_SOCKET) && defined(SO_LINGER) |
3722 { |
3727 { |
3723 struct linger l; |
3728 struct linger l; |
3724 |
3729 |
3725 l.l_onoff = 1; |
3730 l.l_onoff = 1; |
3726 l.l_linger = 30; |
3731 l.l_linger = 30; |
3727 setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); |
3732 setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); |
3728 } |
3733 } |
3729 # endif |
3734 # endif |
3730 # ifdef WIN32 |
3735 # ifdef WIN32 |
3731 /* |
3736 /* |
3732 * make it blocking |
3737 * make it blocking |
3733 */ |
3738 */ |
3734 { |
3739 { |
3735 unsigned long zero = 0; |
3740 unsigned long zero = 0; |
3736 ioctlsocket(sock, FIONBIO, &zero); |
3741 ioctlsocket(sock, FIONBIO, &zero); |
3737 } |
3742 } |
3738 { |
3743 { |
3739 # if 0 && (defined( __BORLANDC__ ) || defined( __MINGW__ )) |
3744 # if 0 && (defined( __BORLANDC__ ) || defined( __MINGW__ )) |
3740 /* |
3745 /* |
3741 * make it a FILE * |
3746 * make it a FILE * |
3742 */ |
3747 */ |
3743 __stxWrapApiEnterCritical(); |
3748 __stxWrapApiEnterCritical(); |
3744 _fd = _open_osfhandle((long)sock, 0); |
3749 _fd = _open_osfhandle((long)sock, 0); |
3745 __stxWrapApiLeaveCritical(); |
3750 __stxWrapApiLeaveCritical(); |
3746 # else |
3751 # else |
3747 _fd = (int)sock; |
3752 _fd = (int)sock; |
3748 # endif |
3753 # endif |
3749 DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd)); |
3754 DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd)); |
3750 } |
3755 } |
3751 # else // !WIN32 |
3756 # else // !WIN32 |
3752 fp = fdopen(sock, "r+"); |
3757 fp = fdopen(sock, "r+"); |
3753 if (! fp) { |
3758 if (! fp) { |
3754 DBGPRINTF(("SOCKET: fdopen call failed\n")); |
3759 DBGPRINTF(("SOCKET: fdopen call failed\n")); |
3755 error = __MKSMALLINT(errno); |
3760 error = __MKSMALLINT(errno); |
3756 __BEGIN_INTERRUPTABLE__ |
3761 __BEGIN_INTERRUPTABLE__ |
3757 closesocket(sock); |
3762 closesocket(sock); |
3758 DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock)); |
3763 DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock)); |
3759 __END_INTERRUPTABLE__ |
3764 __END_INTERRUPTABLE__ |
3760 goto out; |
3765 goto out; |
3761 } |
3766 } |
3762 # endif // !WIN32 |
3767 # endif // !WIN32 |
3763 |
3768 |
3764 if (@global(FileOpenTrace) == true) { |
3769 if (@global(FileOpenTrace) == true) { |
3765 # ifdef WIN32 |
3770 # ifdef WIN32 |
3766 console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock); |
3771 console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock); |
3767 # else |
3772 # else |
3768 console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock); |
3773 console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock); |
3769 # endif |
3774 # endif |
3770 } |
3775 } |
3771 |
3776 |
3772 # ifdef WIN32 |
3777 # ifdef WIN32 |
3773 __externalAddressVal(newHandle) = _fd; |
3778 __externalAddressVal(newHandle) = _fd; |
3774 __INST(handleType) = @symbol(socketHandle); |
3779 __INST(handleType) = @symbol(socketHandle); |
3775 # else |
3780 # else |
3776 __externalAddressVal(newHandle) = fp; |
3781 __externalAddressVal(newHandle) = fp; |
3777 __INST(handleType) = @symbol(socketFilePointer); |
3782 __INST(handleType) = @symbol(socketFilePointer); |
3778 # endif |
3783 # endif |
3779 } |
3784 } |
3780 #endif |
3785 #endif |
3781 out:; |
3786 out:; |
3782 %}. |
3787 %}. |
3783 |
3788 |
3784 "all ok?" |
3789 "all ok?" |
3785 handleType notNil ifTrue:[ |
3790 handleType notNil ifTrue:[ |
3786 handle := newHandle. |
3791 handle := newHandle. |
3787 domain := domainArg. |
3792 domain := domainArg. |
3788 socketType := typeArg. |
3793 socketType := typeArg. |
3789 Lobby register:self. |
3794 self registerForFinalization. |
3790 ^ self. |
3795 ^ self. |
3791 ]. |
3796 ]. |
3792 error isInteger ifTrue:[ |
3797 error isInteger ifTrue:[ |
3793 lastErrorNumber := error. |
3798 lastErrorNumber := error. |
3794 ^ self openError:error. |
3799 ^ self openError:error. |
3795 ]. |
3800 ]. |
3796 ^ self primitiveFailed:error. |
3801 ^ self primitiveFailed:error. |
3797 |
3802 |
3798 " |
3803 " |
3799 Socket new domain:#AF_INET type:#stream |
3804 Socket new domain:#AF_INET type:#stream |