Esempio n. 1
0
struct link *link_accept(struct link *master, time_t stoptime)
{
	struct link *link = 0;

	link = link_create();
	if(!link)
		goto failure;

	while(1) {
		if(!link_sleep(master, stoptime, 1, 0))
			goto failure;
		link->fd = accept(master->fd, 0, 0);
		break;
	}

	if(!link_nonblocking(link, 1))
		goto failure;
	if(!link_address_remote(link, link->raddr, &link->rport))
		goto failure;
	link_squelch();

	debug(D_TCP, "got connection from %s:%d", link->raddr, link->rport);

	return link;

      failure:
	if(link)
		link_close(link);
	return 0;
}
Esempio n. 2
0
struct link *link_serve_address(const char *addr, int port)
{
	struct link *link = 0;
	struct sockaddr_in address;
	int success;
	int value;

	link = link_create();
	if(!link)
		goto failure;

	link->fd = socket(AF_INET, SOCK_STREAM, 0);
	if(link->fd < 0)
		goto failure;

	value = 1;
	setsockopt(link->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof(value));

	link_window_configure(link);

	if(addr != 0 || port != LINK_PORT_ANY) {

		memset(&address, 0, sizeof(address));
#if defined(CCTOOLS_OPSYS_DARWIN)
		address.sin_len = sizeof(address);
#endif
		address.sin_family = AF_INET;
		address.sin_port = htons(port);

		if(addr) {
			string_to_ip_address(addr, (unsigned char *) &address.sin_addr.s_addr);
		} else {
			address.sin_addr.s_addr = htonl(INADDR_ANY);
		}

		success = bind(link->fd, (struct sockaddr *) &address, sizeof(address));
		if(success < 0)
			goto failure;
	}

	success = listen(link->fd, 5);
	if(success < 0)
		goto failure;

	if(!link_nonblocking(link, 1))
		goto failure;

	debug(D_TCP, "listening on port %d", port);
	return link;

      failure:
	if(link)
		link_close(link);
	return 0;
}
Esempio n. 3
0
struct link *link_connect(const char *addr, int port, time_t stoptime)
{
	struct sockaddr_in address;
	struct link *link = 0;
	int result;
	int save_errno;

	link = link_create();
	if(!link)
		goto failure;

	link_squelch();

	memset(&address, 0, sizeof(address));
#if defined(CCTOOLS_OPSYS_DARWIN)
	address.sin_len = sizeof(address);
#endif
	address.sin_family = AF_INET;
	address.sin_port = htons(port);

	if(!string_to_ip_address(addr, (unsigned char *) &address.sin_addr))
		goto failure;

	link->fd = socket(AF_INET, SOCK_STREAM, 0);
	if(link->fd < 0)
		goto failure;

	link_window_configure(link);

	/* sadly, cygwin does not do non-blocking connect correctly */
#ifdef CCTOOLS_OPSYS_CYGWIN
	if(!link_nonblocking(link, 0))
		goto failure;
#else
	if(!link_nonblocking(link, 1))
		goto failure;
#endif

	debug(D_TCP, "connecting to %s:%d", addr, port);

	do {
		result = connect(link->fd, (struct sockaddr *) &address, sizeof(address));

		/* On some platforms, errno is not set correctly. */
		/* If the remote address can be found, then we are really connected. */
		/* Also, on bsd-derived systems, failure to connect is indicated by a second connect returning EINVAL. */

		if(result < 0 && !errno_is_temporary(errno)) {
			if(errno == EINVAL)
				errno = ECONNREFUSED;
			break;
		}

		if(link_address_remote(link, link->raddr, &link->rport)) {

			debug(D_TCP, "made connection to %s:%d", link->raddr, link->rport);

#ifdef CCTOOLS_OPSYS_CYGWIN
			link_nonblocking(link, 1);
#endif
			return link;
		}
	} while(link_sleep(link, stoptime, 0, 1));

	debug(D_TCP, "connection to %s:%d failed (%s)", addr, port, strerror(errno));

      failure:
	save_errno = errno;
	if(link)
		link_close(link);
	errno = save_errno;
	return 0;
}
Esempio n. 4
0
File: link.c Progetto: mcast/cctools
struct link *link_connect(const char *addr, int port, time_t stoptime)
{
	struct sockaddr_in address;
	struct link *link = 0;
	int result;
	int save_errno;

	link = link_create();
	if(!link)
		goto failure;

	link_squelch();

	memset(&address, 0, sizeof(address));
#if defined(CCTOOLS_OPSYS_DARWIN)
	address.sin_len = sizeof(address);
#endif
	address.sin_family = AF_INET;
	address.sin_port = htons(port);

	if(!string_to_ip_address(addr, (unsigned char *) &address.sin_addr))
		goto failure;

	link->fd = socket(AF_INET, SOCK_STREAM, 0);
	if(link->fd < 0)
		goto failure;

	link_window_configure(link);

	/* sadly, cygwin does not do non-blocking connect correctly */
#ifdef CCTOOLS_OPSYS_CYGWIN
	if(!link_nonblocking(link, 0))
		goto failure;
#else
	if(!link_nonblocking(link, 1))
		goto failure;
#endif

	debug(D_TCP, "connecting to %s:%d", addr, port);

	while(1) {
		// First attempt a non-blocking connect
		result = connect(link->fd, (struct sockaddr *) &address, sizeof(address));

		// On many platforms, non-blocking connect sets errno in unexpected ways:

		// On OSX, result=-1 and errno==EISCONN indicates a successful connection.
		if(result<0 && errno==EISCONN) result=0;

		// On BSD-derived systems, failure to connect is indicated by errno = EINVAL.
		// Set it to something more explanatory.
		if(result<0 && errno==EINVAL) errno=ECONNREFUSED;

		// Otherwise, a non-temporary errno should cause us to bail out.
		if(result<0 && !errno_is_temporary(errno)) break;

		// If the remote address is valid, we are connected no matter what.
		if(link_address_remote(link, link->raddr, &link->rport)) {
			debug(D_TCP, "made connection to %s:%d", link->raddr, link->rport);
#ifdef CCTOOLS_OPSYS_CYGWIN
			link_nonblocking(link, 1);
#endif
			return link;
		}

		// if the time has expired, bail out
		if( time(0) >= stoptime ) {
			errno = ETIMEDOUT;
			break;
		}

		// wait for some activity on the socket.
		link_sleep(link, stoptime, 0, 1);

		// No matter how the sleep ends, we want to go back to the top
		// and call connect again to get a proper errno.
	}


	debug(D_TCP, "connection to %s:%d failed (%s)", addr, port, strerror(errno));

failure:
	save_errno = errno;
	if(link)
		link_close(link);
	errno = save_errno;
	return 0;
}
Esempio n. 5
0
File: link.c Progetto: mcast/cctools
struct link *link_serve_address(const char *addr, int port)
{
	struct link *link = 0;
	struct sockaddr_in address;
	int success;
	int value;

	link = link_create();
	if(!link)
		goto failure;

	link->fd = socket(AF_INET, SOCK_STREAM, 0);
	if(link->fd < 0)
		goto failure;

	value = fcntl(link->fd, F_GETFD);
	if (value == -1)
		goto failure;
	value |= FD_CLOEXEC;
	if (fcntl(link->fd, F_SETFD, value) == -1)
		goto failure;

	value = 1;
	setsockopt(link->fd, SOL_SOCKET, SO_REUSEADDR, (void *) &value, sizeof(value));

	link_window_configure(link);

	memset(&address, 0, sizeof(address));
#if defined(CCTOOLS_OPSYS_DARWIN)
	address.sin_len = sizeof(address);
#endif
	address.sin_family = AF_INET;

	if(addr) {
		string_to_ip_address(addr, (unsigned char *) &address.sin_addr.s_addr);
	} else {
		address.sin_addr.s_addr = htonl(INADDR_ANY);
	}

	int low = TCP_LOW_PORT_DEFAULT;
	int high = TCP_HIGH_PORT_DEFAULT;
	if(port < 1) {
		const char *lowstr = getenv("TCP_LOW_PORT");
		if (lowstr)
			low = atoi(lowstr);
		const char *highstr = getenv("TCP_HIGH_PORT");
		if (highstr)
			high = atoi(highstr);
	} else {
		low = high = port;
	}

	if(high < low)
		fatal("high port %d is less than low port %d in range", high, low);

	for (port = low; port <= high; port++) {
		address.sin_port = htons(port);
		success = bind(link->fd, (struct sockaddr *) &address, sizeof(address));
		if(success == -1) {
			if(errno == EADDRINUSE) {
				//If a port is specified, fail!
				if (low == high) {
					goto failure;
				} else {
					continue;
				}
			} else {
				goto failure;
			}
		}
		break;
	}

	success = listen(link->fd, 5);
	if(success < 0)
		goto failure;

	if(!link_nonblocking(link, 1))
		goto failure;

	debug(D_TCP, "listening on port %d", port);
	return link;

      failure:
	if(link)
		link_close(link);
	return 0;
}
Esempio n. 6
0
static void handle_query(struct link *query_link)
{
	FILE *stream;
	char line[LINE_MAX];
	char url[LINE_MAX];
	char path[LINE_MAX];
	char action[LINE_MAX];
	char version[LINE_MAX];
	char hostport[LINE_MAX];
	char addr[LINK_ADDRESS_MAX];
	char key[LINE_MAX];
	int port;
	time_t current;

	char *hkey;
	struct nvpair *nv;
	int i, n;

	link_address_remote(query_link, addr, &port);
	debug(D_DEBUG, "www query from %s:%d", addr, port);

	if(link_readline(query_link, line, LINE_MAX, time(0) + HANDLE_QUERY_TIMEOUT)) {
		string_chomp(line);
		if(sscanf(line, "%s %s %s", action, url, version) != 3) {
			return;
		}

		// Consume the rest of the query
		while(1) {
			if(!link_readline(query_link, line, LINE_MAX, time(0) + HANDLE_QUERY_TIMEOUT)) {
				return;
			}

			if(line[0] == 0) {
				break;
			}
		}
	} else {
		return;
	}

	// Output response
	stream = fdopen(link_fd(query_link), "w");
	if(!stream) {
		return;
	}
	link_nonblocking(query_link, 0);

	current = time(0);
	fprintf(stream, "HTTP/1.1 200 OK\n");
	fprintf(stream, "Date: %s", ctime(&current));
	fprintf(stream, "Server: catalog_server\n");
	fprintf(stream, "Connection: close\n");

	if(sscanf(url, "http://%[^/]%s", hostport, path) == 2) {
		// continue on
	} else {
		strcpy(path, url);
	}

	/* load the hash table entries into one big array */

	n = 0;
	nvpair_database_firstkey(table);
	while(nvpair_database_nextkey(table, &hkey, &nv)) {
		array[n] = nv;
		n++;
	}

	/* sort the array by name before displaying */

	qsort(array, n, sizeof(struct nvpair *), compare_nvpair);

	if(!strcmp(path, "/query.text")) {
		fprintf(stream, "Content-type: text/plain\n\n");
		for(i = 0; i < n; i++)
			nvpair_print_text(array[i], stream);
	} else if(!strcmp(path, "/query.json")) {
		fprintf(stream, "Content-type: text/plain\n\n");
		fprintf(stream,"[\n");
		for(i = 0; i < n; i++) {
			nvpair_print_json(array[i], stream);
			fprintf(stream,",\n");
		}
		fprintf(stream,"]\n");
	} else if(!strcmp(path, "/query.oldclassads")) {
		fprintf(stream, "Content-type: text/plain\n\n");
		for(i = 0; i < n; i++)
			nvpair_print_old_classads(array[i], stream);
	} else if(!strcmp(path, "/query.newclassads")) {
		fprintf(stream, "Content-type: text/plain\n\n");
		for(i = 0; i < n; i++)
			nvpair_print_new_classads(array[i], stream);
	} else if(!strcmp(path, "/query.xml")) {
		fprintf(stream, "Content-type: text/xml\n\n");
		fprintf(stream, "<?xml version=\"1.0\" standalone=\"yes\"?>\n");
		fprintf(stream, "<catalog>\n");
		for(i = 0; i < n; i++)
			nvpair_print_xml(array[i], stream);
		fprintf(stream, "</catalog>\n");
	} else if(sscanf(path, "/detail/%s", key) == 1) {
		struct nvpair *nv;
		fprintf(stream, "Content-type: text/html\n\n");
		nv = nvpair_database_lookup(table, key);
		if(nv) {
			const char *name = nvpair_lookup_string(nv, "name");
			if(!name)
				name = "unknown";
			fprintf(stream, "<title>%s catalog server: %s</title>\n", preferred_hostname, name);
			fprintf(stream, "<center>\n");
			fprintf(stream, "<h1>%s catalog server</h1>\n", preferred_hostname);
			fprintf(stream, "<h2>%s</h2>\n", name);
			fprintf(stream, "<p><a href=/>return to catalog view</a><p>\n");
			nvpair_print_html_solo(nv, stream);
			fprintf(stream, "</center>\n");
		} else {
			fprintf(stream, "<title>%s catalog server</title>\n", preferred_hostname);
			fprintf(stream, "<center>\n");
			fprintf(stream, "<h1>%s catalog server</h1>\n", preferred_hostname);
			fprintf(stream, "<h2>Unknown Item!</h2>\n");
			fprintf(stream, "</center>\n");
		}
	} else {
		char avail_line[LINE_MAX];
		char total_line[LINE_MAX];
		INT64_T sum_total = 0;
		INT64_T sum_avail = 0;
		INT64_T sum_devices = 0;

		fprintf(stream, "Content-type: text/html\n\n");
		fprintf(stream, "<title>%s catalog server</title>\n", preferred_hostname);
		fprintf(stream, "<center>\n");
		fprintf(stream, "<h1>%s catalog server</h1>\n", preferred_hostname);
		fprintf(stream, "<a href=/query.text>text</a> - ");
		fprintf(stream, "<a href=/query.html>html</a> - ");
		fprintf(stream, "<a href=/query.xml>xml</a> - ");
		fprintf(stream, "<a href=/query.json>json</a> - ");
		fprintf(stream, "<a href=/query.oldclassads>oldclassads</a> - ");
		fprintf(stream, "<a href=/query.newclassads>newclassads</a>");
		fprintf(stream, "<p>\n");

		for(i = 0; i < n; i++) {
			nv = array[i];
			sum_total += nvpair_lookup_integer(nv, "total");
			sum_avail += nvpair_lookup_integer(nv, "avail");
			sum_devices++;
		}

		string_metric(sum_avail, -1, avail_line);
		string_metric(sum_total, -1, total_line);
		fprintf(stream, "<b>%sB available out of %sB on %d devices</b><p>\n", avail_line, total_line, (int) sum_devices);

		nvpair_print_html_header(stream, html_headers);
		for(i = 0; i < n; i++) {
			nv = array[i];
			make_hash_key(nv, key);
			sprintf(url, "/detail/%s", key);
			nvpair_print_html_with_link(nv, stream, html_headers, "name", url);
		}
		nvpair_print_html_footer(stream, html_headers);
		fprintf(stream, "</center>\n");
	}
	fclose(stream);
}