示例#1
0
static void remote_ieee80211_connect(ddf_fun_t *fun, void *iface,
    ipc_callid_t callid, ipc_call_t *call)
{
	ieee80211_iface_t *ieee80211_iface = (ieee80211_iface_t *) iface;
	assert(ieee80211_iface->connect);
	
	char ssid_start[MAX_STRING_SIZE];
	char password[MAX_STRING_SIZE];
	
	ipc_callid_t data_callid;
	size_t len;
	if (!async_data_write_receive(&data_callid, &len)) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	if (len > MAX_STRING_SIZE) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	int rc = async_data_write_finalize(data_callid, ssid_start, len);
	if (rc != EOK) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	if (!async_data_write_receive(&data_callid, &len)) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	if (len > MAX_STRING_SIZE) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	rc = async_data_write_finalize(data_callid, password, len);
	if (rc != EOK) {
		async_answer_0(data_callid, EINVAL);
		async_answer_0(callid, EINVAL);
		return;
	}
	
	rc = ieee80211_iface->connect(fun, ssid_start, password);
	
	async_answer_0(callid, rc);
}
示例#2
0
/** Process the write request from the remote client.
 *
 * Receive the write request's parameters from the remote client and pass them
 * to the local interface. Return the result of the operation processed by the
 * local interface to the remote client.
 *
 * @param fun		The function to which the data are written.
 * @param ops		The local ops structure.
 */
static void
remote_char_write(ddf_fun_t *fun, void *ops, ipc_callid_t callid,
    ipc_call_t *call)
{
	char_dev_ops_t *char_dev_ops = (char_dev_ops_t *) ops;
	ipc_callid_t cid;
	size_t len;
	
	if (!async_data_write_receive(&cid, &len)) {
		/* TODO handle protocol error. */
		async_answer_0(callid, EINVAL);
		return;
	}
	
	if (!char_dev_ops->write) {
		async_data_write_finalize(cid, NULL, 0);
		async_answer_0(callid, ENOTSUP);
		return;
	}
	
	if (len > MAX_CHAR_RW_COUNT)
		len = MAX_CHAR_RW_COUNT;
	
	char buf[MAX_CHAR_RW_COUNT];
	
	async_data_write_finalize(cid, buf, len);
	
	int ret = (*char_dev_ops->write)(fun, buf, len);
	if (ret < 0) {
		/* Some error occured. */
		async_answer_0(callid, ret);
	} else {
		/*
		 * The operation was successful, return the number of data
		 * written.
		 */
		async_answer_1(callid, EOK, ret);
	}
}
示例#3
0
static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
{
	int socket_id;
	int fragments;
	int index;
	socket_core_t *sock_core;
	tcp_sockdata_t *socket;
	ipc_call_t answer;
	ipc_callid_t wcallid;
	size_t length;
	uint8_t buffer[TCP_SOCK_FRAGMENT_SIZE];
	tcp_error_t trc;
	int rc;

	log_msg(LVL_DEBUG, "tcp_sock_send()");
	socket_id = SOCKET_GET_SOCKET_ID(call);
	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
	SOCKET_GET_FLAGS(call);

	sock_core = socket_cores_find(&client->sockets, socket_id);
	if (sock_core == NULL) {
		async_answer_0(callid, ENOTSOCK);
		return;
	}

	socket = (tcp_sockdata_t *)sock_core->specific_data;
	fibril_mutex_lock(&socket->lock);

	if (socket->conn == NULL) {
		fibril_mutex_unlock(&socket->lock);
		async_answer_0(callid, ENOTCONN);
		return;
	}

	for (index = 0; index < fragments; index++) {
		if (!async_data_write_receive(&wcallid, &length)) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, EINVAL);
			return;
		}

		if (length > TCP_SOCK_FRAGMENT_SIZE)
			length = TCP_SOCK_FRAGMENT_SIZE;

		rc = async_data_write_finalize(wcallid, buffer, length);
		if (rc != EOK) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, rc);
			return;
		}

		trc = tcp_uc_send(socket->conn, buffer, length, 0);

		switch (trc) {
		case TCP_EOK:
			rc = EOK;
			break;
		case TCP_ENOTEXIST:
			rc = ENOTCONN;
			break;
		case TCP_ECLOSING:
			rc = ENOTCONN;
			break;
		case TCP_ERESET:
			rc = ECONNABORTED;
			break;
		default:
			assert(false);
		}

		if (rc != EOK) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, rc);
			return;
		}
	}

	IPC_SET_ARG1(answer, 0);
	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, TCP_SOCK_FRAGMENT_SIZE);
	async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
	    IPC_GET_ARG2(answer));
	fibril_mutex_unlock(&socket->lock);
}
示例#4
0
static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
{
	int socket_id;
	int fragments;
	int index;
	struct sockaddr_in *addr;
	size_t addr_size;
	socket_core_t *sock_core;
	udp_sockdata_t *socket;
	udp_sock_t fsock, *fsockp;
	ipc_call_t answer;
	ipc_callid_t wcallid;
	size_t length;
	uint8_t buffer[UDP_FRAGMENT_SIZE];
	udp_error_t urc;
	int rc;

	log_msg(LVL_DEBUG, "udp_sock_send()");

	addr = NULL;

	if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
		rc = async_data_write_accept((void **) &addr, false,
		    0, 0, 0, &addr_size);
		if (rc != EOK) {
			async_answer_0(callid, rc);
			goto out;
		}

		if (addr_size != sizeof(struct sockaddr_in)) {
			async_answer_0(callid, EINVAL);
			goto out;
		}

		fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
		fsock.port = uint16_t_be2host(addr->sin_port);
		fsockp = &fsock;
	} else {
		fsockp = NULL;
	}

	socket_id = SOCKET_GET_SOCKET_ID(call);
	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
	SOCKET_GET_FLAGS(call);

	sock_core = socket_cores_find(&client->sockets, socket_id);
	if (sock_core == NULL) {
		async_answer_0(callid, ENOTSOCK);
		goto out;
	}

	if (sock_core->port == 0) {
		/* Implicitly bind socket to port */
		rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
		    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
		    last_used_port);
		if (rc != EOK) {
			async_answer_0(callid, rc);
			goto out;
		}
	}

	socket = (udp_sockdata_t *)sock_core->specific_data;
	fibril_mutex_lock(&socket->lock);

	if (socket->assoc->ident.local.addr.ipv4 == UDP_IPV4_ANY) {
		/* Determine local IP address */
		inet_addr_t loc_addr, rem_addr;

		rem_addr.ipv4 = fsockp ? fsock.addr.ipv4 :
		    socket->assoc->ident.foreign.addr.ipv4;

		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
		if (rc != EOK) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, rc);
			log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
			    "determine local address.");
			return;
		}

		socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
		log_msg(LVL_DEBUG, "Local IP address is %x",
		    socket->assoc->ident.local.addr.ipv4);
	}


	assert(socket->assoc != NULL);

	for (index = 0; index < fragments; index++) {
		if (!async_data_write_receive(&wcallid, &length)) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, EINVAL);
			goto out;
		}

		if (length > UDP_FRAGMENT_SIZE)
			length = UDP_FRAGMENT_SIZE;

		rc = async_data_write_finalize(wcallid, buffer, length);
		if (rc != EOK) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, rc);
			goto out;
		}

		urc = udp_uc_send(socket->assoc, fsockp, buffer, length, 0);

		switch (urc) {
		case UDP_EOK:
			rc = EOK;
			break;
/*		case TCP_ENOTEXIST:
			rc = ENOTCONN;
			break;
		case TCP_ECLOSING:
			rc = ENOTCONN;
			break;
		case TCP_ERESET:
			rc = ECONNABORTED;
			break;*/
		default:
			assert(false);
		}

		if (rc != EOK) {
			fibril_mutex_unlock(&socket->lock);
			async_answer_0(callid, rc);
			goto out;
		}
	}
	
	IPC_SET_ARG1(answer, 0);
	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, UDP_FRAGMENT_SIZE);
	async_answer_2(callid, EOK, IPC_GET_ARG1(answer),
	    IPC_GET_ARG2(answer));
	fibril_mutex_unlock(&socket->lock);
	
out:
	if (addr != NULL)
		free(addr);
}