示例#1
0
文件: comm.c 项目: Janesak1977/j4cDAC
/* Initialize a dac_conn_t and connect to the DAC.
 *
 * On success, return 0.
 */
int dac_connect(dac_t *d, const char *host, const char *port) {
	dac_conn_t *conn = &d->conn;
	ZeroMemory(conn, sizeof(d->conn));

	// Look up the server address
	struct addrinfo *result = NULL, *ptr = NULL, hints;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	trace(d, "Calling getaddrinfo: \"%s\", \"%s\"\n", host, port);

	int res = getaddrinfo(host, port, &hints, &result);
	if (res != 0) {
		trace(d, "getaddrinfo failed: %d\n", res);
		return -1;
	}

	// Create a SOCKET
	ptr = result;
	conn->sock = socket(ptr->ai_family, ptr->ai_socktype, 
		ptr->ai_protocol);

	if (conn->sock == INVALID_SOCKET) {
		log_socket_error(d, "socket");
		freeaddrinfo(result);
		return -1;
	}

	unsigned long nonblocking = 1;
	ioctlsocket(conn->sock, FIONBIO, &nonblocking);

	memset(&conn->udp_target, 0, sizeof(conn->udp_target));
	conn->udp_target.sin_family = AF_INET;
	conn->udp_target.sin_addr.s_addr = ((struct sockaddr_in *)(ptr->ai_addr))->sin_addr.s_addr;
	conn->udp_target.sin_port = htons(60000);

	// Connect to host. Because the socket is nonblocking, this
	// will always return WSAEWOULDBLOCK.
	connect(conn->sock, ptr->ai_addr, (int)ptr->ai_addrlen);
	freeaddrinfo(result);

	if (WSAGetLastError() != WSAEWOULDBLOCK) {
		log_socket_error(d, "connect");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	// Wait for connection.
	fd_set set;
	FD_ZERO(&set);
	FD_SET(conn->sock, &set);
	struct timeval time;
	time.tv_sec = 0;
	time.tv_usec = DEFAULT_TIMEOUT;
	res = select(0, &set, &set, &set, &time);

	if (res == SOCKET_ERROR) {
		log_socket_error(d, "select");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	} else if (res == 0) {
		trace(d, "Connection to %s timed out.\n", host);
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	// See if we have *actually* connected
	int error;
	int len = sizeof(error);
	if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) ==
			SOCKET_ERROR) {
		log_socket_error(d, "getsockopt");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	if (error) {
		WSASetLastError(error);
		log_socket_error(d, "connect");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	BOOL ndelay = 1;
	res = setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
		(char *)&ndelay, sizeof(ndelay));
	if (res == SOCKET_ERROR) {
		log_socket_error(d, "setsockopt TCP_NODELAY");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	trace(d, "Connected.\n");

	// Create socket for OSC
	conn->udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (conn->udp_sock == INVALID_SOCKET) {
		log_socket_error(d, "socket(AF_INET, SOCK_DRGAM)");
	} else {
		res = connect(conn->udp_sock, (struct sockaddr *)&conn->udp_target, sizeof(conn->udp_target));
		if (res == SOCKET_ERROR) {
			log_socket_error(d, "connect(udp_sock)");
		}
	}

	nonblocking = 1;
	ioctlsocket(conn->udp_sock, FIONBIO, &nonblocking);

	// After we connect, the host will send an initial status response. 
	dac_read_resp(d, DEFAULT_TIMEOUT);
	dac_dump_resp(d);

	char c = 'p';
	dac_sendall(d, &c, 1);
	dac_read_resp(d, DEFAULT_TIMEOUT);
	dac_dump_resp(d);

	if (d->sw_revision >= 2) {
		c = 'v';
		dac_sendall(d, &c, 1);
		res = dac_read_bytes(d, d->version, sizeof(d->version));
		if (res < 0)
			return res;

		trace(d, "DAC version: %.*s\n", sizeof(d->version), d->version);
	} else {
		memset(d->version, 0, sizeof(d->version));
		trace(d, "DAC version old!\n");
	}

	return 0;
}
示例#2
0
文件: comm.c 项目: Janesak1977/j4cDAC
int dac_send_data(dac_t *d, struct dac_point *data, int npoints, int rate) { 
	int res;
	const struct dac_status *st = &d->conn.resp.dac_status;

	/* Write the header */

	if (st->playback_state == 0) {
		trace(d, "L: Sending prepare command...\n");
		char c = 'p';
		if ((res = dac_sendall(d, &c, sizeof(c))) < 0)
			return res;

		/* Read ACK */
		d->conn.pending_meta_acks++;

		/* Block here until all ACKs received... */
		while (d->conn.pending_meta_acks)
			dac_get_acks(d, 1500);

		trace(d, "L: prepare ACKed\n");
	}

	if (st->buffer_fullness > 1600 && st->playback_state == 1 \
	    && !d->conn.begin_sent) {
		trace(d, "L: Sending begin command...\n");

		struct begin_command b;
		b.command = 'b';
		b.point_rate = rate;
		b.low_water_mark = 0;
		if ((res = dac_sendall(d, (const char *)&b, sizeof(b))) < 0)
			return res;

		d->conn.begin_sent = 1;
		d->conn.pending_meta_acks++;
	}

	d->conn.local_buffer.queue.command = 'q';
	d->conn.local_buffer.queue.point_rate = rate;

	d->conn.local_buffer.header.command = 'd';
	d->conn.local_buffer.header.npoints = npoints;

	memcpy(&d->conn.local_buffer.data[0], data,
		npoints * sizeof(struct dac_point));

	d->conn.local_buffer.data[0].control |= DAC_CTRL_RATE_CHANGE;

	ct_assert(sizeof(d->conn.local_buffer) == 18008);

	/* Write the data */
	if ((res = dac_sendall(d, (const char *)&d->conn.local_buffer,
		8 + npoints * sizeof(struct dac_point))) < 0)
		return res;

	/* Expect two ACKs */
	d->conn.pending_meta_acks++;
	d->conn.ackbuf[d->conn.ackbuf_prod] = npoints;
	d->conn.ackbuf_prod = (d->conn.ackbuf_prod + 1) % MAX_LATE_ACKS;
	d->conn.unacked_points += npoints;

	if ((res = dac_get_acks(d, 0)) < 0)
		return res;

	return npoints;
}
示例#3
0
文件: comm.c 项目: laserpic/j4cDAC
/* Initialize a dac_conn_t and connect to the DAC.
 *
 * On success, return 0.
 */
int dac_connect(dac_t *d, const char *host, const char *port) {
	dac_conn_t *conn = &d->conn;
	ZeroMemory(conn, sizeof(d->conn));

	// Look up the server address
	struct addrinfo *result = NULL, *ptr = NULL, hints;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	flogd(d, "Calling getaddrinfo: \"%s\", \"%s\"\n", host, port);

	int res = getaddrinfo(host, port, &hints, &result);
	if (res != 0) {
		flogd(d, "getaddrinfo failed: %d\n", res);
		return -1;
	}

	// Create a SOCKET
	ptr = result;
	conn->sock = socket(ptr->ai_family, ptr->ai_socktype, 
		ptr->ai_protocol);

	if (conn->sock == INVALID_SOCKET) {
		log_socket_error(d, "socket");
		freeaddrinfo(result);
		return -1;
	}

	unsigned long nonblocking = 1;
	ioctlsocket(conn->sock, FIONBIO, &nonblocking);

	// Connect to host. Because the socket is nonblocking, this
	// will always return WSAEWOULDBLOCK.
	connect(conn->sock, ptr->ai_addr, (int)ptr->ai_addrlen);
	freeaddrinfo(result);

	if (WSAGetLastError() != WSAEWOULDBLOCK) {
		log_socket_error(d, "connect");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	// Wait for connection.
	fd_set set;
	FD_ZERO(&set);
	FD_SET(conn->sock, &set);
	struct timeval time;
	time.tv_sec = 0;
	time.tv_usec = DEFAULT_TIMEOUT;
	res = select(0, &set, &set, &set, &time);

	if (res == SOCKET_ERROR) {
		log_socket_error(d, "select");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	} else if (res == 0) {
		flogd(d, "Connection to %s timed out.\n", host);
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	// See if we have *actually* connected
	int error;
	int len = sizeof(error);
	if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *)&error, &len) ==
			SOCKET_ERROR) {
		log_socket_error(d, "getsockopt");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	if (error) {
		WSASetLastError(error);
		log_socket_error(d, "connect");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	BOOL ndelay = 1;
	res = setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
		(char *)&ndelay, sizeof(ndelay));
	if (res == SOCKET_ERROR) {
		log_socket_error(d, "setsockopt");
		closesocket(conn->sock);
		conn->sock = INVALID_SOCKET;
		return -1;
	}

	flogd(d, "Connected.\n");

	// After we connect, the host will send an initial status response. 
	dac_read_resp(d, DEFAULT_TIMEOUT);
	dac_dump_resp(d);

	char c = 'p';
	dac_sendall(d, &c, 1);
	dac_read_resp(d, DEFAULT_TIMEOUT);
	dac_dump_resp(d);

	flogd(d, "Sent.\n");

	return 0;
}