gpointer _wapi_stdhandle_create (int fd, const gchar *name) { struct _WapiHandle_file file_handle = {0}; gpointer handle; int flags; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd); #if !defined(__native_client__) /* Check if fd is valid */ do { flags=fcntl(fd, F_GETFL); } while (flags == -1 && errno == EINTR); if(flags==-1) { /* Invalid fd. Not really much point checking for EBADF * specifically */ MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, strerror(errno)); SetLastError (_wapi_get_win32_file_error (errno)); return(INVALID_HANDLE_VALUE); } file_handle.fileaccess=convert_from_flags(flags); #else /* * fcntl will return -1 in nacl, as there is no real file system API. * Yet, standard streams are available. */ file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE; #endif file_handle.fd = fd; file_handle.filename = g_strdup(name); /* some default security attributes might be needed */ file_handle.security_attributes=0; /* Apparently input handles can't be written to. (I don't * know if output or error handles can't be read from.) */ if (fd == 0) { file_handle.fileaccess &= ~GENERIC_WRITE; } file_handle.sharemode=0; file_handle.attrs=0; handle = _wapi_handle_new_fd (WAPI_HANDLE_CONSOLE, fd, &file_handle); if (handle == _WAPI_HANDLE_INVALID) { g_warning ("%s: error creating file handle", __func__); SetLastError (ERROR_GEN_FAILURE); return(INVALID_HANDLE_VALUE); } MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle); return(handle); }
guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3) { struct _WapiHandle_socket socket_handle = {0}; gpointer handle; int fd; socket_handle.domain = domain; socket_handle.type = type; socket_handle.protocol = protocol; socket_handle.still_readable = 1; fd = socket (domain, type, protocol); if (fd == -1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) { /* Retry with protocol == 4 (see bug #54565) */ // https://bugzilla.novell.com/show_bug.cgi?id=MONO54565 socket_handle.protocol = 4; fd = socket (AF_INET, SOCK_RAW, 4); } if (fd == -1) { gint errnum = errno; DEBUG ("%s: socket error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(INVALID_SOCKET); } if (fd >= _wapi_fd_reserve) { DEBUG ("%s: File descriptor is too big (%d >= %d)", __func__, fd, _wapi_fd_reserve); WSASetLastError (WSASYSCALLFAILURE); close (fd); return(INVALID_SOCKET); } /* .net seems to set this by default for SOCK_STREAM, not for * SOCK_DGRAM (see bug #36322) * https://bugzilla.novell.com/show_bug.cgi?id=MONO36322 * * It seems winsock has a rather different idea of what * SO_REUSEADDR means. If it's set, then a new socket can be * bound over an existing listening socket. There's a new * windows-specific option called SO_EXCLUSIVEADDRUSE but * using that means the socket MUST be closed properly, or a * denial of service can occur. Luckily for us, winsock * behaves as though any other system would when SO_REUSEADDR * is true, so we don't need to do anything else here. See * bug 53992. * https://bugzilla.novell.com/show_bug.cgi?id=MONO53992 */ { int ret, true = 1; ret = setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &true, sizeof (true)); if (ret == -1) { int errnum = errno; DEBUG ("%s: Error setting SO_REUSEADDR", __func__); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); close (fd); return(INVALID_SOCKET); } } mono_once (&socket_ops_once, socket_ops_init); handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, &socket_handle); if (handle == _WAPI_HANDLE_INVALID) { g_warning ("%s: error creating socket handle", __func__); WSASetLastError (WSASYSCALLFAILURE); close (fd); return(INVALID_SOCKET); } DEBUG ("%s: returning socket handle %p", __func__, handle); return(fd); }
guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) { gpointer handle = GUINT_TO_POINTER (fd); gpointer new_handle; struct _WapiHandle_socket *socket_handle; struct _WapiHandle_socket new_socket_handle = {0}; gboolean ok; int new_fd; if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { WSASetLastError (WSAEFAULT); return(INVALID_SOCKET); } if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(INVALID_SOCKET); } ok = _wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", __func__, handle); WSASetLastError (WSAENOTSOCK); return(INVALID_SOCKET); } do { new_fd = accept (fd, addr, addrlen); } while (new_fd == -1 && errno == EINTR && !_wapi_thread_cur_apc_pending()); if (new_fd == -1) { gint errnum = errno; DEBUG ("%s: accept error: %s", __func__, strerror(errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(INVALID_SOCKET); } if (new_fd >= _wapi_fd_reserve) { DEBUG ("%s: File descriptor is too big", __func__); WSASetLastError (WSASYSCALLFAILURE); close (new_fd); return(INVALID_SOCKET); } new_socket_handle.domain = socket_handle->domain; new_socket_handle.type = socket_handle->type; new_socket_handle.protocol = socket_handle->protocol; new_socket_handle.still_readable = 1; new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, &new_socket_handle); if(new_handle == _WAPI_HANDLE_INVALID) { g_warning ("%s: error creating socket handle", __func__); WSASetLastError (ERROR_GEN_FAILURE); return(INVALID_SOCKET); } DEBUG ("%s: returning newly accepted socket handle %p with", __func__, new_handle); return(new_fd); }