Example #1
0
gboolean
TransmitFile (guint32 socket, gpointer file, guint32 bytes_to_write, guint32 bytes_per_send, WapiOverlapped *ol,
		WapiTransmitFileBuffers *buffers, guint32 flags)
{
	gpointer sock = GUINT_TO_POINTER (socket);
	gint ret;

	if (mono_w32handle_get_type (sock) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return FALSE;
	}

	/* Write the header */
	if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
		ret = _wapi_send (socket, buffers->Head, buffers->HeadLength, 0);
		if (ret == SOCKET_ERROR)
			return FALSE;
	}

	ret = wapi_sendfile (socket, file, bytes_to_write, bytes_per_send, flags);
	if (ret == SOCKET_ERROR)
		return FALSE;

	/* Write the tail */
	if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
		ret = _wapi_send (socket, buffers->Tail, buffers->TailLength, 0);
		if (ret == SOCKET_ERROR)
			return FALSE;
	}

	if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
		closesocket (socket);

	return TRUE;
}
Example #2
0
static int
_wapi_sendmsg(guint32 fd,  const struct msghdr *msg, int send_flags)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	do {
		ret = sendmsg (fd, msg, send_flags);
	} while (ret == -1 && errno == EINTR &&
		 !mono_thread_info_is_interrupt_state (info));

	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, strerror (errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	return(ret);
}
Example #3
0
int
mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking)
{
	gpointer handle;
	int ret;
	MonoThreadInfo *info;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	info = mono_thread_info_current ();

	do {
		ret = sendto (sock, buf, len, flags, to, tolen);
	} while (ret == -1 && errno == EINTR &&  !mono_thread_info_is_interrupt_state (info));

	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}
	return ret;
}
Example #4
0
gint
mono_w32socket_set_blocking (SOCKET socket, gboolean blocking)
{
#ifdef O_NONBLOCK
	gint ret;
	gpointer handle;

	handle = GINT_TO_POINTER (socket);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	/* This works better than ioctl(...FIONBIO...)
	 * on Linux (it causes connect to return
	 * EINPROGRESS, but the ioctl doesn't seem to) */
	ret = fcntl (socket, F_GETFL, 0);
	if (ret != -1)
		ret = fcntl (socket, F_SETFL, blocking ? (ret & (~O_NONBLOCK)) : (ret | (O_NONBLOCK)));

	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	return 0;
#else
	mono_w32socket_set_last_error (ERROR_NOT_SUPPORTED);
	return SOCKET_ERROR;
#endif /* O_NONBLOCK */
}
Example #5
0
MonoBoolean
ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount)
{
	MonoW32HandleType type;
	MonoW32HandleSemaphore *sem_handle;
	int thr_ret;
	MonoBoolean ret;

	if (!handle) {
		SetLastError (ERROR_INVALID_HANDLE);
		return FALSE;
	}

	switch (type = mono_w32handle_get_type (handle)) {
	case MONO_W32HANDLE_SEM:
	case MONO_W32HANDLE_NAMEDSEM:
		break;
	default:
		SetLastError (ERROR_INVALID_HANDLE);
		return FALSE;
	}

	if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
		g_warning ("%s: error looking up sem handle %p", __func__, handle);
		return FALSE;
	}

	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
		__func__, mono_w32handle_ops_typename (type), handle);

	thr_ret = mono_w32handle_lock_handle (handle);
	g_assert (thr_ret == 0);

	/* Do this before checking for count overflow, because overflowing
	 * max is a listed technique for finding the current value */
	if (prevcount)
		*prevcount = sem_handle->val;

	/* No idea why max is signed, but thats the spec :-( */
	if (sem_handle->val + releaseCount > (guint32)sem_handle->max) {
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
			__func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);

		ret = FALSE;
	} else {
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
			__func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);

		sem_handle->val += releaseCount;
		mono_w32handle_set_signal_state (handle, TRUE, TRUE);

		ret = TRUE;
	}

	thr_ret = mono_w32handle_unlock_handle (handle);
	g_assert (thr_ret == 0);

	return ret;
}
Example #6
0
static gboolean
cleanup_close (gpointer handle, gpointer data, gpointer user_data)
{
	if (mono_w32handle_get_type (handle) == MONO_W32HANDLE_SOCKET)
		mono_w32handle_force_close (handle, data);

	return FALSE;
}
Example #7
0
int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
		   struct sockaddr *from, socklen_t *fromlen)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	struct _WapiHandle_socket *socket_handle;
	gboolean ok;
	int ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	do {
		ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
	} while (ret == -1 && errno == EINTR &&
		 !mono_thread_info_is_interrupt_state (info));

	if (ret == 0 && len > 0) {
		/* According to the Linux man page, recvfrom only
		 * returns 0 when the socket has been shut down
		 * cleanly.  Turn this into an EINTR to simulate win32
		 * behaviour of returning EINTR when a socket is
		 * closed while the recvfrom is blocking (we use a
		 * shutdown() in socket_close() to trigger this.) See
		 * bug 75705.
		 */
		/* Distinguish between the socket being shut down at
		 * the local or remote ends, and reads that request 0
		 * bytes to be read
		 */

		/* If this returns FALSE, it means the socket has been
		 * closed locally.  If it returns TRUE, but
		 * still_readable != 1 then shutdown
		 * (SHUT_RD|SHUT_RDWR) has been called locally.
		 */
		ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
					  (gpointer *)&socket_handle);
		if (ok == FALSE || socket_handle->still_readable != 1) {
			ret = -1;
			errno = EINTR;
		}
	}
	
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, strerror(errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	return(ret);
}
Example #8
0
int closesocket(guint32 fd)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(0);
	}
	
	mono_w32handle_unref (handle);
	return(0);
}
Example #9
0
void _wapi_FD_SET(guint32 fd, fd_set *set)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	
	if (fd >= FD_SETSIZE) {
		WSASetLastError (WSAEINVAL);
		return;
	}

	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return;
	}

	FD_SET (fd, set);
}
Example #10
0
static gboolean
search_callback (gpointer handle, gpointer handle_specific, gpointer user_data)
{
	SearchData *search_data = (SearchData*) user_data;

	if (search_data->type != mono_w32handle_get_type (handle))
		return FALSE;

	if (!search_data->search_user_callback (handle, search_data->search_user_data))
		return FALSE;

	mono_w32handle_ref (handle);
	search_data->handle = handle;
	search_data->handle_specific = handle_specific;
	return TRUE;
}
Example #11
0
static gboolean
mono_w32handle_namespace_search_handle_callback (gpointer handle, gpointer data, gpointer user_data)
{
	NamespaceSearchHandleData *search_data;
	MonoW32HandleType type;
	MonoW32HandleNamespace *sharedns;

	type = mono_w32handle_get_type (handle);
	if (!has_namespace (type))
		return FALSE;

	search_data = (NamespaceSearchHandleData*) user_data;

	switch (type) {
	case MONO_W32HANDLE_NAMEDMUTEX: sharedns = mono_w32mutex_get_namespace ((MonoW32HandleNamedMutex*) data); break;
	case MONO_W32HANDLE_NAMEDSEM:   sharedns = mono_w32semaphore_get_namespace ((MonoW32HandleNamedSemaphore*) data); break;
	case MONO_W32HANDLE_NAMEDEVENT: sharedns = mono_w32event_get_namespace ((MonoW32HandleNamedEvent*) data); break;
	default:
		g_assert_not_reached ();
	}

	if (strcmp (sharedns->name, search_data->name) == 0) {
		if (type != search_data->type) {
			/* Its the wrong type, so fail now */
			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
				__func__, handle, mono_w32handle_get_typename (type));
			search_data->ret = INVALID_HANDLE_VALUE;
		} else {
			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
				__func__, handle);

			/* we do not want the handle to be destroyed before we return it  */
			mono_w32handle_ref (handle);

			search_data->ret = handle;
		}

		return TRUE;
	}

	return FALSE;
}
Example #12
0
int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	ret = bind (fd, my_addr, addrlen);
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: bind error: %s", __func__, strerror(errno));
		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	return(ret);
}
Example #13
0
static int
_wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	struct _WapiHandle_socket *socket_handle;
	gboolean ok;
	int ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	do {
		ret = recvmsg (fd, msg, recv_flags);
	} while (ret == -1 && errno == EINTR &&
		 !mono_thread_info_is_interrupt_state (info));

	if (ret == 0) {
		/* see _wapi_recvfrom */
		ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
					  (gpointer *)&socket_handle);
		if (ok == FALSE || socket_handle->still_readable != 1) {
			ret = -1;
			errno = EINTR;
		}
	}
	
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, strerror(errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	return(ret);
}
Example #14
0
int _wapi_shutdown(guint32 fd, int how)
{
	struct _WapiHandle_socket *socket_handle;
	gboolean ok;
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;

	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}

	if (how == SHUT_RD ||
	    how == SHUT_RDWR) {
		ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
					  (gpointer *)&socket_handle);
		if (ok == FALSE) {
			g_warning ("%s: error looking up socket handle %p",
				   __func__, handle);
			WSASetLastError (WSAENOTSOCK);
			return(SOCKET_ERROR);
		}
		
		socket_handle->still_readable = 0;
	}
	
	ret = shutdown (fd, how);
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__,
			   strerror (errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	
	return(ret);
}
Example #15
0
gint
mono_w32socket_getsockname (SOCKET sock, struct sockaddr *name, socklen_t *namelen)
{
	gpointer handle;
	gint ret;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	ret = getsockname (sock, name, namelen);
	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockname error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	return 0;
}
Example #16
0
gint
mono_w32socket_listen (SOCKET sock, gint backlog)
{
	gpointer handle;
	gint ret;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	ret = listen (sock, backlog);
	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	return 0;
}
Example #17
0
gint
mono_w32socket_get_available (SOCKET socket, guint64 *amount)
{
	gint ret;
	gpointer handle;

	handle = GINT_TO_POINTER (socket);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

#if defined (PLATFORM_MACOSX)
	// ioctl (socket, FIONREAD, XXX) returns the size of
	// the UDP header as well on Darwin.
	//
	// Use getsockopt SO_NREAD instead to get the
	// right values for TCP and UDP.
	//
	// ai_canonname can be null in some cases on darwin,
	// where the runtime assumes it will be the value of
	// the ip buffer.

	socklen_t optlen = sizeof (int);
	ret = getsockopt (socket, SOL_SOCKET, SO_NREAD, (gulong*) amount, &optlen);
#else
	ret = ioctl (socket, FIONREAD, (gulong*) amount);
#endif

	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	return 0;
}
Example #18
0
int _wapi_listen(guint32 fd, int backlog)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	ret = listen (fd, backlog);
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: listen error: %s", __func__, strerror (errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);

		return(SOCKET_ERROR);
	}

	return(0);
}
Example #19
0
int
mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking)
{
	struct msghdr hdr;
	MonoThreadInfo *info;
	gpointer handle;
	gint ret;

	g_assert (overlapped == NULL);
	g_assert (complete == NULL);

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	info = mono_thread_info_current ();

	wsabuf_to_msghdr (buffers, count, &hdr);

	do {
		ret = sendmsg (sock, &hdr, flags);
	} while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));

	msghdr_iov_free (&hdr);

	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	*sent = ret;
	return 0;
}
Example #20
0
int
mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking)
{
	gpointer handle;
	int ret;
	MonoThreadInfo *info;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	info = mono_thread_info_current ();

	do {
		ret = send (sock, buf, len, flags);
	} while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));

	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno));

#ifdef O_NONBLOCK
		/* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
		 * a blocking socket. See bug #599488 */
		if (errnum == EAGAIN) {
			ret = fcntl (sock, F_GETFL, 0);
			if (ret != -1 && (ret & O_NONBLOCK) == 0)
				errnum = ETIMEDOUT;
		}
#endif /* O_NONBLOCK */
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}
	return ret;
}
Example #21
0
int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	MonoThreadInfo *info = mono_thread_info_current ();
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}

	do {
		ret = send (fd, msg, len, send_flags);
	} while (ret == -1 && errno == EINTR &&
		 !mono_thread_info_is_interrupt_state (info));

	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno));

#ifdef O_NONBLOCK
		/* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on
		 * a blocking socket. See bug #599488 */
		if (errnum == EAGAIN) {
			ret = fcntl (fd, F_GETFL, 0);
			if (ret != -1 && (ret & O_NONBLOCK) == 0)
				errnum = ETIMEDOUT;
		}
#endif /* O_NONBLOCK */
		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	return(ret);
}
Example #22
0
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;
	MonoThreadInfo *info = mono_thread_info_current ();

	if (addr != NULL && *addrlen < sizeof(struct sockaddr)) {
		WSASetLastError (WSAEFAULT);
		return(INVALID_SOCKET);
	}
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(INVALID_SOCKET);
	}
	
	ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_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 &&
		 !mono_thread_info_is_interrupt_state (info));

	if (new_fd == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, strerror(errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(INVALID_SOCKET);
	}

	if (new_fd >= mono_w32handle_fd_reserve) {
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%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 = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd,
					  &new_socket_handle);
	if(new_handle == INVALID_HANDLE_VALUE) {
		g_warning ("%s: error creating socket handle", __func__);
		WSASetLastError (ERROR_GEN_FAILURE);
		return(INVALID_SOCKET);
	}

	MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with",
		   __func__, new_handle);
	
	return(new_fd);
}
Example #23
0
gint
mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written)
{
	gpointer handle;
	gint ret;
	gchar *buffer;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	if (command == 0xC8000006 /* SIO_GET_EXTENSION_FUNCTION_POINTER */) {
		gint i;
		GUID *guid;

		if (inputlen < sizeof(GUID)) {
			/* As far as I can tell, windows doesn't
			 * actually set an error here...
			 */
			mono_w32socket_set_last_error (WSAEINVAL);
			return SOCKET_ERROR;
		}

		if (outputlen < sizeof(gpointer)) {
			/* Or here... */
			mono_w32socket_set_last_error (WSAEINVAL);
			return SOCKET_ERROR;
		}

		if (output == NULL) {
			/* Or here */
			mono_w32socket_set_last_error (WSAEINVAL);
			return SOCKET_ERROR;
		}

		guid = (GUID*) input;
		for (i = 0; extension_functions[i].func; i++) {
			if (memcmp (guid, &extension_functions[i].guid, sizeof(GUID)) == 0) {
				memcpy (output, &extension_functions[i].func, sizeof(gpointer));
				*written = sizeof(gpointer);
				return 0;
			}
		}

		mono_w32socket_set_last_error (WSAEINVAL);
		return SOCKET_ERROR;
	}

	if (command == 0x98000004 /* SIO_KEEPALIVE_VALS */) {
		guint32 onoff;

		if (inputlen < 3 * sizeof (guint32)) {
			mono_w32socket_set_last_error (WSAEINVAL);
			return SOCKET_ERROR;
		}

		onoff = *((guint32*) input);

		ret = setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &onoff, sizeof (guint32));
		if (ret < 0) {
			mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
			return SOCKET_ERROR;
		}

#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
		if (onoff != 0) {
			/* Values are in ms, but we need s */
			guint32 keepalivetime, keepaliveinterval, rem;

			keepalivetime = *(((guint32*) input) + 1);
			keepaliveinterval = *(((guint32*) input) + 2);

			/* keepalivetime and keepaliveinterval are > 0 (checked in managed code) */
			rem = keepalivetime % 1000;
			keepalivetime /= 1000;
			if (keepalivetime == 0 || rem >= 500)
				keepalivetime++;
			ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepalivetime, sizeof (guint32));
			if (ret == 0) {
				rem = keepaliveinterval % 1000;
				keepaliveinterval /= 1000;
				if (keepaliveinterval == 0 || rem >= 500)
					keepaliveinterval++;
				ret = setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepaliveinterval, sizeof (guint32));
			}
			if (ret != 0) {
				mono_w32socket_set_last_error (mono_w32socket_convert_error (errno));
				return SOCKET_ERROR;
			}

			return 0;
		}
#endif

		return 0;
	}

	buffer = inputlen > 0 ? (gchar*) g_memdup (input, inputlen) : NULL;

	ret = ioctl (sock, command, buffer);
	if (ret == -1) {
		g_free (buffer);

		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: WSAIoctl error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	if (!buffer) {
		*written = 0;
		return 0;
	}

	/* We just copy the buffer to the output. Some ioctls
	 * don't even output any data, but, well...
	 *
	 * NB windows returns WSAEFAULT if outputlen is too small */
	inputlen = (inputlen > outputlen) ? outputlen : inputlen;

	if (inputlen > 0 && output != NULL)
		memcpy (output, buffer, inputlen);

	g_free (buffer);
	*written = inputlen;

	return 0;
}
Example #24
0
gint
mono_w32socket_setsockopt (SOCKET sock, gint level, gint optname, const gpointer optval, socklen_t optlen)
{
	gpointer handle;
	gint ret;
	gpointer tmp_val;
#if defined (__linux__)
	/* This has its address taken so it cannot be moved to the if block which uses it */
	gint bufsize = 0;
#endif
	struct timeval tv;

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return SOCKET_ERROR;
	}

	tmp_val = optval;
	if (level == SOL_SOCKET &&
	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
		int ms = *((int *) optval);
		tv.tv_sec = ms / 1000;
		tv.tv_usec = (ms % 1000) * 1000;	// micro from milli
		tmp_val = &tv;
		optlen = sizeof (tv);
	}
#if defined (__linux__)
	else if (level == SOL_SOCKET &&
		   (optname == SO_SNDBUF || optname == SO_RCVBUF)) {
		/* According to socket(7) the Linux kernel doubles the
		 * buffer sizes "to allow space for bookkeeping
		 * overhead."
		 */
		bufsize = *((int *) optval);

		bufsize /= 2;
		tmp_val = &bufsize;
	}
#endif

	ret = setsockopt (sock, level, optname, tmp_val, optlen);
	if (ret == -1) {
		gint errnum = errno;
		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setsockopt error: %s", __func__, g_strerror (errno));
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

#if defined (SO_REUSEPORT)
	/* BSD's and MacOS X multicast sockets also need SO_REUSEPORT when SO_REUSEADDR is requested.  */
	if (level == SOL_SOCKET && optname == SO_REUSEADDR) {
		int type;
		socklen_t type_len = sizeof (type);

		if (!getsockopt (sock, level, SO_TYPE, &type, &type_len)) {
			if (type == SOCK_DGRAM || type == SOCK_STREAM)
				setsockopt (sock, level, SO_REUSEPORT, tmp_val, optlen);
		}
	}
#endif

	return ret;
}
Example #25
0
int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
		     socklen_t *optlen)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	struct timeval tv;
	void *tmp_val;
	struct _WapiHandle_socket *socket_handle;
	gboolean ok;
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}

	tmp_val = optval;
	if (level == SOL_SOCKET &&
	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
		tmp_val = &tv;
		*optlen = sizeof (tv);
	}

	ret = getsockopt (fd, level, optname, tmp_val, optlen);
	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__,
			   strerror (errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}

	if (level == SOL_SOCKET &&
	    (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) {
		*((int *) optval)  = tv.tv_sec * 1000 + (tv.tv_usec / 1000);	// milli from micro
		*optlen = sizeof (int);
	}

	if (optname == SO_ERROR) {
		ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
					  (gpointer *)&socket_handle);
		if (ok == FALSE) {
			g_warning ("%s: error looking up socket handle %p",
				   __func__, handle);

			/* can't extract the last error */
			*((int *) optval) = errno_to_WSA (*((int *)optval),
							  __func__);
		} else {
			if (*((int *)optval) != 0) {
				*((int *) optval) = errno_to_WSA (*((int *)optval),
								  __func__);
				socket_handle->saved_error = *((int *)optval);
			} else {
				*((int *)optval) = socket_handle->saved_error;
			}
		}
	}
	
	return(ret);
}
Example #26
0
BOOL
mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking)
{
	MonoThreadInfo *info;
	gpointer handle;
	gint file;
	gssize ret;
#if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
	struct stat statbuf;
#else
	gchar *buffer;
#endif

	handle = GUINT_TO_POINTER (sock);
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		mono_w32socket_set_last_error (WSAENOTSOCK);
		return FALSE;
	}

	/* Write the header */
	if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) {
		ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE);
		if (ret == SOCKET_ERROR)
			return FALSE;
	}

	info = mono_thread_info_current ();

	file = GPOINTER_TO_INT (file_handle);

#if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN))
	ret = fstat (file, &statbuf);
	if (ret == -1) {
		gint errnum = errno;
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return SOCKET_ERROR;
	}

	do {
#ifdef __linux__
		ret = sendfile (sock, file, NULL, statbuf.st_size);
#elif defined(DARWIN)
		/* TODO: header/tail could be sent in the 5th argument */
		/* TODO: Might not send the entire file for non-blocking sockets */
		ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0);
#endif
	} while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
#else
	buffer = g_malloc (SF_BUFFER_SIZE);

	do {
		do {
			ret = read (file, buffer, SF_BUFFER_SIZE);
		} while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));

		if (ret == -1 || ret == 0)
			break;

		do {
			ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */
		} while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));
	} while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info));

	g_free (buffer);
#endif

	if (ret == -1) {
		gint errnum = errno;
		mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum));
		return FALSE;
	}

	/* Write the tail */
	if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) {
		ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE);
		if (ret == SOCKET_ERROR)
			return FALSE;
	}

	if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
		mono_w32handle_close (handle);

	return TRUE;
}
Example #27
0
int ioctlsocket(guint32 fd, unsigned long command, gpointer arg)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	int ret;
	
	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}

	switch(command){
		case FIONBIO:
#ifdef O_NONBLOCK
			/* This works better than ioctl(...FIONBIO...) 
			 * on Linux (it causes connect to return
			 * EINPROGRESS, but the ioctl doesn't seem to)
			 */
			ret = fcntl(fd, F_GETFL, 0);
			if (ret != -1) {
				if (*(gboolean *)arg) {
					ret |= O_NONBLOCK;
				} else {
					ret &= ~O_NONBLOCK;
				}
				ret = fcntl(fd, F_SETFL, ret);
			}
			break;
#endif /* O_NONBLOCK */
			/* Unused in Mono */
		case SIOCATMARK:
			ret = ioctl (fd, command, arg);
			break;
			
		case FIONREAD:
		{
#if defined (PLATFORM_MACOSX)
			
			// ioctl (fd, FIONREAD, XXX) returns the size of
			// the UDP header as well on
			// Darwin.
			//
			// Use getsockopt SO_NREAD instead to get the
			// right values for TCP and UDP.
			// 
			// ai_canonname can be null in some cases on darwin, where the runtime assumes it will
			// be the value of the ip buffer.

			socklen_t optlen = sizeof (int);
			ret = getsockopt (fd, SOL_SOCKET, SO_NREAD, arg, &optlen);
#else
			ret = ioctl (fd, command, arg);
#endif
			break;
		}
		default:
			WSASetLastError (WSAEINVAL);
			return(SOCKET_ERROR);
	}

	if (ret == -1) {
		gint errnum = errno;
		MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: ioctl error: %s", __func__, strerror (errno));

		errnum = errno_to_WSA (errnum, __func__);
		WSASetLastError (errnum);
		
		return(SOCKET_ERROR);
	}
	
	return(0);
}
Example #28
0
int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
		  socklen_t addrlen)
{
	gpointer handle = GUINT_TO_POINTER (fd);
	struct _WapiHandle_socket *socket_handle;
	gboolean ok;
	gint errnum;
	MonoThreadInfo *info = mono_thread_info_current ();

	if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) {
		WSASetLastError (WSAENOTSOCK);
		return(SOCKET_ERROR);
	}
	
	if (connect (fd, serv_addr, addrlen) == -1) {
		mono_pollfd fds;
		int so_error;
		socklen_t len;
		
		errnum = errno;
		
		if (errno != EINTR) {
			MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__,
				   strerror (errnum));

			errnum = errno_to_WSA (errnum, __func__);
			if (errnum == WSAEINPROGRESS)
				errnum = WSAEWOULDBLOCK; /* see bug #73053 */

			WSASetLastError (errnum);

			/* 
			 * On solaris x86 getsockopt (SO_ERROR) is not set after 
			 * connect () fails so we need to save this error.
			 *
			 * But don't do this for EWOULDBLOCK (bug 317315)
			 */
			if (errnum != WSAEWOULDBLOCK) {
				ok = mono_w32handle_lookup (handle,
							  MONO_W32HANDLE_SOCKET,
							  (gpointer *)&socket_handle);
				if (ok == FALSE) {
					/* ECONNRESET means the socket was closed by another thread */
					/* Async close on mac raises ECONNABORTED. */
					if (errnum != WSAECONNRESET && errnum != WSAENETDOWN)
						g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum);
				} else {
					socket_handle->saved_error = errnum;
				}
			}
			return(SOCKET_ERROR);
		}

		fds.fd = fd;
		fds.events = MONO_POLLOUT;
		while (mono_poll (&fds, 1, -1) == -1 &&
		       !mono_thread_info_is_interrupt_state (info)) {
			if (errno != EINTR) {
				errnum = errno_to_WSA (errno, __func__);

				MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s",
					   __func__, strerror (errno));

				WSASetLastError (errnum);
				return(SOCKET_ERROR);
			}
		}

		len = sizeof(so_error);
		if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error,
				&len) == -1) {
			errnum = errno_to_WSA (errno, __func__);

			MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s",
				   __func__, strerror (errno));

			WSASetLastError (errnum);
			return(SOCKET_ERROR);
		}
		
		if (so_error != 0) {
			errnum = errno_to_WSA (so_error, __func__);

			/* Need to save this socket error */
			ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET,
						  (gpointer *)&socket_handle);
			if (ok == FALSE) {
				g_warning ("%s: error looking up socket handle %p", __func__, handle);
			} else {
				socket_handle->saved_error = errnum;
			}
			
			MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s",
				   __func__, strerror (so_error));

			WSASetLastError (errnum);
			return(SOCKET_ERROR);
		}
	}
		
	return(0);
}
Example #29
0
MonoBoolean
ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle)
{
	MonoW32HandleType type;
	MonoW32HandleMutex *mutex_handle;
	pthread_t tid;
	gboolean ret;

	if (handle == NULL) {
		mono_w32error_set_last (ERROR_INVALID_HANDLE);
		return FALSE;
	}

	switch (type = mono_w32handle_get_type (handle)) {
	case MONO_W32HANDLE_MUTEX:
	case MONO_W32HANDLE_NAMEDMUTEX:
		break;
	default:
		mono_w32error_set_last (ERROR_INVALID_HANDLE);
		return FALSE;
	}

	if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
		g_warning ("%s: error looking up %s handle %p",
			__func__, mono_w32handle_get_typename (type), handle);
		return FALSE;
	}

	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p, tid: %p recursion: %d",
		__func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);

	mono_w32handle_lock_handle (handle);

	tid = pthread_self ();

	if (mutex_handle->abandoned) {
		// The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes
		ret = TRUE;
	} else if (!pthread_equal (mutex_handle->tid, tid)) {
		ret = FALSE;

		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
			    __func__, mono_w32handle_get_typename (type), handle, (long)mutex_handle->tid, (long)tid);
	} else {
		ret = TRUE;

		/* OK, we own this mutex */
		mutex_handle->recursion--;

		if (mutex_handle->recursion == 0) {
			thread_disown_mutex (mono_thread_internal_current (), handle);

			mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p, tid: %p recusion : %d",
				__func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);

			mutex_handle->tid = 0;
			mono_w32handle_set_signal_state (handle, TRUE, FALSE);
		}
	}

	mono_w32handle_unlock_handle (handle);

	return ret;
}
Example #30
0
void
mono_w32mutex_abandon (void)
{
	MonoInternalThread *internal;

	g_assert (mono_thread_internal_current_is_attached ());

	internal = mono_thread_internal_current ();
	g_assert (internal);

	if (!internal->owned_mutexes)
		return;

	while (internal->owned_mutexes->len) {
		MonoW32HandleType type;
		MonoW32HandleMutex *mutex_handle;
		MonoNativeThreadId tid;
		gpointer handle;

		handle = g_ptr_array_index (internal->owned_mutexes, 0);

		switch (type = mono_w32handle_get_type (handle)) {
		case MONO_W32HANDLE_MUTEX:
		case MONO_W32HANDLE_NAMEDMUTEX:
			break;
		default:
			g_assert_not_reached ();
		}

		if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
			g_error ("%s: error looking up %s handle %p",
				__func__, mono_w32handle_get_typename (type), handle);
		}

		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoning %s handle %p",
			__func__, mono_w32handle_get_typename (type), handle);

		tid = MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid);

		if (!pthread_equal (mutex_handle->tid, tid))
			g_error ("%s: trying to release mutex %p acquired by thread %p from thread %p",
				__func__, handle, (gpointer) mutex_handle->tid, (gpointer) tid);

		mono_w32handle_lock_handle (handle);

		mutex_handle->recursion = 0;
		mutex_handle->tid = 0;
		mutex_handle->abandoned = TRUE;

		mono_w32handle_set_signal_state (handle, TRUE, FALSE);

		thread_disown_mutex (internal, handle);

		mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p",
			__func__, mono_w32handle_get_typename (type), handle);

		mono_w32handle_unlock_handle (handle);
	}

	g_ptr_array_free (internal->owned_mutexes, TRUE);
	internal->owned_mutexes = NULL;
}