Esempio n. 1
0
/**
	requires MSG_DATA_REPLY -  reply for one piece:
		MSG_DATA_REPLY|piece_index|data_length|data

	@param msg Message to parse
	@param buf Memory to store data

	@return piece_index
*/
int messageParseDataReply(Message *msg, char *buf)
{
	assert(msg);
	assert(buf);

	messageDump(msg, "messageParseDataReply.txt");

	int piece_index = 0;
	int data_length = 0;
	int pos = 0;
	pos += 4;   // skip MessageType

	piece_index = READ_INT(msg->data + pos);
	verbose1("messageParseDataReply::piece_index = %d\n", piece_index);
	pos += 4;

	data_length = READ_INT(msg->data + pos);
	verbose1("messageParseDataReply::data_length = %d\n", data_length);
	pos += 4;

	memcpy(buf, msg->data + pos, data_length);
	pos += data_length;

	assert(pos == msg->length);

	return piece_index;
}
Esempio n. 2
0
/**
	creates MSG_DATA_REQUEST -  request for one piece:
		MSG_DATA_REQUEST|count|piece_index1|...

	@param piece_index Array of pieces' indices
	@param count Number of indices in piece_index

	@return NULL     on error
	        Message* on success, dynamicaly allocated
*/
Message *messageCreateDataRequest(int count, int *piece_index)
{
	assert(count > 0);
	assert(piece_index);

	// allocate space
	int len = (2 + count) * sizeof(int);
	Message *msg = calloc(len + sizeof(Message), 1);
	assert(msg);

	verbose1("messageCreateDataRequest::copying indices to message\n");

	msg->length = len;

	int pos = 0;
	int tmp = MSG_DATA_REQUEST;
	memcpy(msg->data + pos, &tmp, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &count, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, piece_index, count * sizeof(int));
	pos += count * sizeof(int);

	assert(pos == msg->length);

	verbose1("messageCreateDataRequest::msg created\n");
	messageDump(msg, "messageCreateDataRequest.txt");

	return msg;
}
Esempio n. 3
0
/**
	creates MSG_PACKAGE_INFO - basic version:
		MSG_PACKAGE_INFO|msg->length|file_size|piece_size|file_name|author_name

	@return NULL     on error
	        Message* on success, dynamicaly allocated
*/
Message *messageCreatePackage(PackageInfo *package)
{
	int tmp;

	assert(package != NULL);
	assert(package->file_size > 0);
	assert(package->piece_size > 0);

	// calculate required space for data
	int len = 0;
	if (package->file_name) len += strlen(package->file_name) +1;
	if (package->author_name) len += strlen(package->author_name) +1;
	len += sizeof(int);    // enum MessageType
	len += sizeof(int);    // total message length
	len += sizeof(int);    // package->piece_size
	len += sizeof(int);    // package->file_size

	verbose1("messageCreatePackage::len = %d\n", len);

	Message *msg = calloc(len + sizeof(Message), 1);
	assert(msg != NULL);

	// copy package to message
	verbose1("messageCreatePackage::copying package to message\n");

	msg->length = len;

	int pos = 0;
	tmp = MSG_PACKAGE_INFO;
	memcpy(msg->data + pos, &tmp, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &len, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &package->file_size, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &package->piece_size, sizeof(int));
	pos += sizeof(int);

	tmp = strlen(package->file_name) +1;
	memcpy(msg->data + pos, package->file_name, tmp);
	pos += tmp;

	tmp = strlen(package->author_name) +1;
	memcpy(msg->data + pos, package->author_name, tmp);
	pos += tmp;

	verbose1("messageCreatePackage::pos = %d\n", pos);

	// debug msg to file
	messageDump(msg, "messageCreatePackage.txt");

	return msg;
}
Esempio n. 4
0
void messageDump(Message *msg, char *file_name)
{
	FILE *fd = fopen(file_name, "wb");
	assert(fd);
	fwrite(msg->data, msg->length, 1, fd);
	fclose(fd);
	verbose1("messageDump -> %s\n", file_name);
}
Esempio n. 5
0
/**
	creates MSG_DATA_REPLY -  reply for one piece:
		MSG_DATA_REPLY|piece_index|data_length|data

	@param piece_index
	@param data_length
	@param data Bytes to send

	@return NULL     on error
	        Message* on success, dynamicaly allocated
*/
Message *messageCreateDataReply(int piece_index, const char *data, int data_length)
{
	assert(piece_index >= 0);
	assert(data);
	assert(data_length > 0);

	// allocate space
	int len = 3 * sizeof(int) + data_length;
	Message *msg = calloc(len + sizeof(Message), 1);
	assert(msg);

	verbose1("messageCreateDataReply::piece_index = %d\n", piece_index);
	verbose1("messageCreateDataReply::data_length = %d\n", data_length);
	verbose1("messageCreateDataReply::copying items to msg\n");

	msg->length = len;

	int pos = 0;
	int tmp = MSG_DATA_REPLY;
	memcpy(msg->data + pos, &tmp, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &piece_index, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, &data_length, sizeof(int));
	pos += sizeof(int);

	memcpy(msg->data + pos, data, data_length);
	pos += data_length;

	verbose1("messageCreateDataReply::pos, msg->length = %d, %d\n", pos, msg->length);
	assert(pos == msg->length);

	verbose1("messageCreateDataReply::msg created\n");
	messageDump(msg, "messageCreateDataReply.txt");

	return msg;
}
Esempio n. 6
0
/**
	requires MSG_DATA_REQUEST -  request for one piece:
		MSG_DATA_REQUEST|count|piece_index1|...

	@param msg Message to parse
	@param piece_index Array to store pieces' indices

	@return count Number of indices in piece_index
*/
int messageParseDataRequest(Message *msg, int *piece_index)
{
	assert(msg);
	assert(piece_index);

	int count = 0;
	int pos = 0;
	pos += 4;   // skip MessageType

	count = READ_INT(msg->data + pos);
	verbose1("messageParseDataRequest::count = %d\n", count);
	pos += 4;

	for (int i = 0; i < count; ++i) {
		piece_index[i] = READ_INT(msg->data + pos);
		verbose1("messageParseDataRequest::piece = %d\n", piece_index[i]);
		pos += 4;
	}

	assert(pos == msg->length);

	return count;
}
Esempio n. 7
0
/**
	requires MSG_PACKAGE_INFO - basic version:
		MSG_PACKAGE_INFO|msg->length|file_size|piece_size|file_name|author_name

	@return NULL     on error
	        Message* on success, dynamicaly allocated
*/
PackageInfo *messageParsePackage(Message *msg)
{
	assert(msg);
	messageDump(msg, "messageParsePackage.txt");

	// allocate package
	PackageInfo *pkg = calloc(sizeof(PackageInfo), 1);
	assert(pkg);

	// read items from message
	int pos = 0;
	pos += 4;   // skip MessageType
	pos += 4;   // skip message length

	pkg->file_size = READ_INT(msg->data + pos);
	verbose1("messageParsePackage::file_size = %d\n", pkg->file_size);
	pos += 4;

	pkg->piece_size = READ_INT(msg->data + pos);
	verbose1("messageParsePackage::piece_size = %d\n", pkg->piece_size);
	pos += 4;

	int len;
	len = strlen(msg->data + pos);
	verbose1("messageParsePackage::file_name::len = %d\n", len);
	pkg->file_name = calloc(len + 1, 1);
	assert(pkg->file_name);
	strcpy(pkg->file_name, msg->data + pos);
	verbose1("messageParsePackage::file_name = %s\n", pkg->file_name);
	pos += len + 1;

	len = strlen(msg->data + pos);
	verbose1("messageParsePackage::author_name::len = %d\n", len);
	pkg->author_name = calloc(len + 1, 1);
	assert(pkg->author_name);
	strcpy(pkg->author_name, msg->data + pos);
	verbose1("messageParsePackage::author_name = %s\n", pkg->author_name);
	pos += len + 1;

	assert(pos == msg->length);

	return pkg;
}
Esempio n. 8
0
Message *networkReceiveMessage(TCPsocket sock)
{
	int result;
	int msg_type = 0;
	Message *msg = NULL;

	//  receive MessageType
	result = SDLNet_TCP_Recv(sock, &msg_type, sizeof(int));
	if(result <= 0) {
		puts("thaat");
		error();
	}

	verbose1("networkReceiveMessage::msg_type = %x\n", msg_type);

	assert(msg_type == MSG_PACKAGE_INFO
		|| msg_type == MSG_DATA_REQUEST
		|| msg_type == MSG_DATA_REPLY);

	// package info message
	if (msg_type == MSG_PACKAGE_INFO) {
		verbose1("networkReceiveMessage::MSG_PACKAGE_INFO\n");

		// receive total length
		int msg_len = 0;
		result = SDLNet_TCP_Recv(sock, &msg_len, sizeof(int));
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::msg_len = %d\n", msg_len);

		// receive the rest of message
		msg = calloc(msg_len + sizeof(Message), 1);
		assert(msg);
		msg->length = msg_len;
		//msg->data[0] = msg_type;
		//msg->data[4] = msg_len;
		WRITE_INT(msg->data + 0, msg_type);
		WRITE_INT(msg->data + 4, msg_len);

		result = SDLNet_TCP_Recv(sock, msg->data + 8, msg_len - 2*sizeof(int));
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::package received\n");
	} else if (msg_type == MSG_DATA_REQUEST) {
		verbose1("networkReceiveMessage::MSG_DATA_REQUEST\n");

		// receive count of following items
		int count = 0;
		int msg_len = 0;
		result = SDLNet_TCP_Recv(sock, &count, sizeof(int));
		verbose1("result = %d\n", result);
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::count = %d\n", count);

		// receive the rest of message
		msg_len = (count+2) * sizeof(int);
		msg = calloc(msg_len + sizeof(Message), 1);
		assert(msg);
		msg->length = msg_len;
		verbose1("networkReceiveMessage::msg->length = %d\n", msg->length);

		//msg->data[0] = msg_type;
		//msg->data[4] = count;
		WRITE_INT(msg->data + 0, msg_type);
		WRITE_INT(msg->data + 4, count);

		result = SDLNet_TCP_Recv(sock, msg->data + 8, count * sizeof(int));
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::package received\n");

		messageDump(msg, "networkReceiveMessage_MSG_DATA_REQUEST.txt");
	} else if (msg_type == MSG_DATA_REPLY) {
		verbose1("networkReceiveMessage::MSG_DATA_REPLY\n");

		// receive piece_index
		int piece_index = -1;

		result = SDLNet_TCP_Recv(sock, &piece_index, sizeof(int));
		verbose1("result = %d\n", result);
		if (result <= 0) {
			puts("_381_");
			error();
		}

		verbose1("networkReceiveMessage::piece_index = %d\n", piece_index);

		// receive length of data
		int data_len = 0;
		result = SDLNet_TCP_Recv(sock, &data_len, sizeof(int));
		verbose1("result = %d\n", result);
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::data_len = %d\n", data_len);

		// alloc struct for data
		int msg_len = 3 * sizeof(int) + data_len;
		msg = calloc(msg_len + sizeof(Message), 1);
		assert(msg);
		msg->length = msg_len;
		verbose1("networkReceiveMessage::msg->length = %d\n", msg->length);

		//msg->data[0] = msg_type; // zly typ
		//msg->data[4] = piece_index;
		//msg->data[8] = data_len;
		WRITE_INT(msg->data + 0, msg_type);
		WRITE_INT(msg->data + 4, piece_index);
		WRITE_INT(msg->data + 8, data_len);

		// receive data
		result = SDLNet_TCP_Recv(sock, msg->data + 12, data_len);
		if (result <= 0)
			error();

		verbose1("networkReceiveMessage::package received\n");

		messageDump(msg, "networkReceiveMessage_MSG_DATA_REPLY.txt");
	}

	return msg;
}
Esempio n. 9
0
int main(int argc, char *argv[])
{
	int out_fd = -1, use_splice = 1, truncate = O_TRUNC, verboseness = 0;
	char *buf = NULL, *dev_path = DEV_PATH, *out_path = NULL;
	int restart_requested, dev_fd, pipe_in, pipe_out, pipe_fd[2];
	ssize_t n, m;
	unsigned int snaplen = 0, buflen = 8192;
	ssize_t (*read_dev)(void);
	ssize_t (*write_out)(void);
	
	struct argp_option options[] = {
		{"append", 'a', 0, 0, "append new records instead of overwriting"},
		{"device", 'd', "DEVICE", 0, "read events from DEVICE (default: " DEV_PATH ")"},
		{"buflen", 'l', "BYTES", 0, "set buffer length; implies -n (default: 8192)"},
		{"no-splice", 'n', 0, 0, "use read()/write() instead of splice"},
		{"quiet", 'q', 0, 0, "decrease verboseness of debug output"},
		{"snaplen", 's', "BYTES", 0, "set maximum packet capture size to BYTES bytes"},
		{"verbose", 'v', 0, 0, "increase verboseness of debug output"},
		{0},
	};

	error_t parse_opt(int key, char *arg, struct argp_state *state)
	{
		switch (key) {
		case 'a':
			truncate = 0;
			break;
		case 'd':
			dev_path = arg;
			break;
		case 'l':
			if (parse_unsigned_int(&buflen, arg))
				argp_error(state, "invalid buflen: %s\n", arg);
			use_splice = 0;
			break;
		case 'n':
			use_splice = 0;
			break;
		case 'q':
			verboseness--;
			break;
		case 's':
			if (parse_unsigned_int(&snaplen, arg))
				argp_error(state, "invalid snaplen: %s\n", arg);
			break;
		case 'v':
			verboseness++;
			break;
		case ARGP_KEY_ARG:
			if (!state->arg_num)
				out_path = arg;
			else
				return ARGP_ERR_UNKNOWN;
			break;
		default:
			return ARGP_ERR_UNKNOWN;
		}
		return 0;
	}

	struct argp argp = {options, parse_opt, "[OUTPUT_FILE]",
			"Read Hone events and write to a file or standard output.",
			NULL, NULL, NULL};

	if (argp_parse(&argp, argc, argv, 0, NULL, NULL))
		err(EX_OSERR, "argp_parse() failed");

	if (verboseness > 0)
		verbose1 = log_stderr;
	if (verboseness > 1)
		verbose2 = log_stderr;
	if (verboseness > 2)
		verbose3 = log_stderr;

	verbose2("Options:\n");
	verbose2("   buffer size: ");
	if (use_splice)
		verbose2("unused\n");
	else
		verbose2("%u\n", buflen);
	verbose2("   input device: %s\n", dev_path);
	verbose2("   output file: %s\n", out_path ?: "<standard output>");
	verbose2("   snaplen: %u\n", snaplen);
	verbose2("   use splice: %s\n", use_splice ? "yes" : "no");
	verbose2("   verbosity level: %d\n", verboseness);

	if (verboseness > 3)
		err(EX_USAGE, "verboseness limit exceeded");

	signal(SIGHUP, sighandler);
	signal(SIGINT, sighandler);
	signal(SIGTERM, sighandler);

	ssize_t splice_read(void)
	{
		return splice(dev_fd, NULL, pipe_in, NULL, 65536, 0);
	}

	ssize_t splice_write(void)
	{
		return splice(pipe_out, NULL, out_fd, NULL, n, 0);
	}

	ssize_t conventional_read(void)
	{
		return read(dev_fd, buf, buflen);
	}

	ssize_t conventional_write(void)
	{
		return write(out_fd, buf, n);
	}

	if (use_splice) {
		if (pipe(pipe_fd))
			err(EX_OSERR, "pipe() failed");
		pipe_out = pipe_fd[0];
		pipe_in = pipe_fd[1];
		read_dev = splice_read;
		write_out = splice_write;
	} else {
		if (!(buf = (typeof(buf)) malloc(buflen)))
			err(EX_OSERR, "malloc() failed");
		read_dev = conventional_read;
		write_out = conventional_write;
	}

	if ((dev_fd = open(dev_path, O_RDONLY, 0)) == -1)
		err(EX_NOINPUT, "open() failed on %s", dev_path);
	if (snaplen && ioctl(dev_fd, HEIO_SET_SNAPLEN, snaplen) == -1)
		err(EX_IOERR, "set snaplen ioctl() failed");

	void close_out(void)
	{
		if (close(out_fd))
			err(EX_OSERR, "close() failed on %s", out_path);
		out_fd = -1;
	}

restart:
	restart = 0;
	restart_requested = 0;

	if (out_fd != -1)
		close_out();
	if (!out_path || !strcmp(out_path, "-")) {
		if ((out_fd = dup(STDOUT_FILENO)) == -1)
			err(EX_CANTCREAT, "dup() failed on stdout");
	} else {
		if ((out_fd = open(out_path,
					O_WRONLY | O_CREAT | O_LARGEFILE | truncate, 00664)) == -1)
			err(EX_CANTCREAT, "open() failed on %s", out_path);
		if (!truncate && lseek(out_fd, 0, SEEK_END) == (off_t) -1)
			err(EX_OSERR, "error seeking to end of output file");
	}

	if (use_splice) {
		int is_fifo = 0;
		struct stat st;

		if (fstat(out_fd, &st))
			warn("fstat() failed");
		else
			is_fifo = S_ISFIFO(st.st_mode);
		pipe_in = is_fifo ? out_fd : pipe_fd[1];

		verbose2("output file is%s a FIFO\n", is_fifo ? "" : " not");
	}

	for (;;) {
		if ((restart || done) && !restart_requested) {
			if (ioctl(dev_fd, HEIO_RESTART) == -1)
				err(EX_OSERR, "reset ioctl() failed");
			verbose1("Requesting device restart.\n");
			restart_requested = 1;
		}

		if ((n = read_dev()) == -1) {
			if (errno != EINTR && errno != EAGAIN)
				err(EX_OSERR, "reading from device failed");
			continue;
		}

		if (!n) {
			verbose1("Device restarted.\n");
			if (done || ioctl(dev_fd, HEIO_GET_AT_HEAD) <= 0)
				break;
			verbose1("Reopening output file.\n");
			goto restart;
		}

		verbose3("Read %ld bytes\n", n);
		if (out_fd == pipe_in)  /* spliced directly to FIFO */
			continue;

		while (n > 0) {
			if ((m = write_out()) == -1) {
				if (errno != EINTR && errno != EAGAIN)
					err(EX_OSERR, "writing to output failed");
				continue;
			}
			verbose3("Wrote %ld bytes\n", m);
			n -= m;
		}
	}

	close_out();
	close(dev_fd);
	close(pipe_fd[0]);
	close(pipe_fd[1]);
	free(buf);

	exit(EX_OK);
}