Example #1
0
int
connectToUnixServer(const StaticString &filename, const char *file,
	unsigned int line)
{
	int fd = syscalls::socket(PF_UNIX, SOCK_STREAM, 0);
	if (fd == -1) {
		int e = errno;
		throw SystemException("Cannot create a Unix socket file descriptor", e);
	}

	FdGuard guard(fd, file, line, true);
	int ret;
	struct sockaddr_un addr;

	if (filename.size() > sizeof(addr.sun_path) - 1) {
		string message = "Cannot connect to Unix socket '";
		message.append(filename.data(), filename.size());
		message.append("': filename is too long.");
		throw RuntimeException(message);
	}

	addr.sun_family = AF_UNIX;
	memcpy(addr.sun_path, filename.c_str(), filename.size());
	addr.sun_path[filename.size()] = '\0';

	bool retry = true;
	int counter = 0;
	while (retry) {
		ret = syscalls::connect(fd, (const sockaddr *) &addr, sizeof(addr));
		if (ret == -1) {
			#if defined(sun) || defined(__sun)
				/* Solaris has this nice kernel bug where connecting to
				 * a newly created Unix socket which is obviously
				 * connectable can cause an ECONNREFUSED. So we retry
				 * in a loop.
				 */
				retry = errno == ECONNREFUSED;
			#else
				retry = false;
			#endif
			retry = retry && counter < 9;

			if (retry) {
				syscalls::usleep((useconds_t) (10000 * pow((double) 2, (double) counter)));
				counter++;
			} else {
				int e = errno;
				string message("Cannot connect to Unix socket '");
				message.append(filename.toString());
				message.append("'");
				throw SystemException(message, e);
			}
		} else {
			guard.clear();
			return fd;
		}
	}
	abort();   // Never reached.
	return -1; // Shut up compiler warning.
}
Example #2
0
string
lookupSystemUsernameByUid(uid_t uid, const StaticString &fallbackFormat) {
	OsUser user;
	bool result;

	try {
		result = lookupSystemUserByUid(uid, user);
	} catch (const SystemException &) {
		result = false;
	}

	if (result && user.pwd.pw_name != NULL && user.pwd.pw_name[0] != '\0') {
		return user.pwd.pw_name;
	} else {
		// Null terminate fallback format string
		DynamicBuffer fallbackFormatNt(fallbackFormat.size() + 1);
		memcpy(fallbackFormatNt.data, fallbackFormat.data(), fallbackFormat.size());
		fallbackFormatNt.data[fallbackFormat.size()] = '\0';

		char buf[512];
		snprintf(buf, sizeof(buf), fallbackFormatNt.data, (int) uid);
		buf[sizeof(buf) - 1] = '\0';
		return buf;
	}
}
Example #3
0
string
lookupSystemGroupnameByGid(gid_t gid, const StaticString &fallbackFormat) {
	OsGroup group;
	bool result;

	try {
		result = lookupSystemGroupByGid(gid, group);
	} catch (const SystemException &) {
		result = false;
	}

	if (result && group.grp.gr_name != NULL && group.grp.gr_name[0] != '\0') {
		return group.grp.gr_name;
	} else {
		// Null terminate fallback format string
		DynamicBuffer fallbackFormatNt(fallbackFormat.size() + 1);
		memcpy(fallbackFormatNt.data, fallbackFormat.data(), fallbackFormat.size());
		fallbackFormatNt.data[fallbackFormat.size()] = '\0';

		char buf[512];
		snprintf(buf, sizeof(buf), fallbackFormatNt.data, (int) gid);
		buf[sizeof(buf) - 1] = '\0';
		return buf;
	}
}
Example #4
0
static Numeric
stringToSignedNumeric(const StaticString &str) {
	Numeric result = 0;
	string::size_type i = 0;
	const char *data = str.data();
	bool minus = false;
	
	while (data[i] == ' ' && i < str.size()) {
		i++;
	}
	if (data[i] == '-') {
		minus = true;
		i++;
	}
	while (data[i] >= '0' && data[i] <= '9' && i < str.size()) {
		result *= 10;
		result += data[i] - '0';
		i++;
	}
	if (minus) {
		return -result;
	} else {
		return result;
	}
}
Example #5
0
int
createUnixServer(const StaticString &filename, unsigned int backlogSize, bool autoDelete,
	const char *file, unsigned int line)
{
	struct sockaddr_un addr;
	int fd, ret;

	if (filename.size() > sizeof(addr.sun_path) - 1) {
		string message = "Cannot create Unix socket '";
		message.append(filename.toString());
		message.append("': filename is too long.");
		throw RuntimeException(message);
	}

	fd = syscalls::socket(PF_LOCAL, SOCK_STREAM, 0);
	if (fd == -1) {
		int e = errno;
		throw SystemException("Cannot create a Unix socket file descriptor", e);
	}

	FdGuard guard(fd, file, line, true);
	addr.sun_family = AF_LOCAL;
	strncpy(addr.sun_path, filename.c_str(), filename.size());
	addr.sun_path[filename.size()] = '\0';

	if (autoDelete) {
		do {
			ret = unlink(filename.c_str());
		} while (ret == -1 && errno == EINTR);
	}

	ret = syscalls::bind(fd, (const struct sockaddr *) &addr, sizeof(addr));
	if (ret == -1) {
		int e = errno;
		string message = "Cannot bind Unix socket '";
		message.append(filename.toString());
		message.append("'");
		throw SystemException(message, e);
	}

	if (backlogSize == 0) {
		backlogSize = 1024;
	}
	ret = syscalls::listen(fd, backlogSize);
	if (ret == -1) {
		int e = errno;
		string message = "Cannot listen on Unix socket '";
		message.append(filename.toString());
		message.append("'");
		safelyClose(fd, true);
		throw SystemException(message, e);
	}

	guard.clear();
	return fd;
}
Example #6
0
void
setupNonBlockingTcpSocket(NTCP_State &state, const StaticString &hostname, int port) {
	int ret;

	memset(&state.hints, 0, sizeof(state.hints));
	state.hints.ai_family   = PF_UNSPEC;
	state.hints.ai_socktype = SOCK_STREAM;
	ret = getaddrinfo(hostname.toString().c_str(), toString(port).c_str(),
		&state.hints, &state.res);
	if (ret != 0) {
		string message = "Cannot resolve IP address '";
		message.append(hostname.data(), hostname.size());
		message.append(":");
		message.append(toString(port));
		message.append("': ");
		message.append(gai_strerror(ret));
		throw IOException(message);
	}

	state.fd = syscalls::socket(PF_INET, SOCK_STREAM, 0);
	if (state.fd == -1) {
		int e = errno;
		throw SystemException("Cannot create a TCP socket file descriptor", e);
	}

	state.hostname = hostname;
	state.port = port;
	setNonBlocking(state.fd);
}
Example #7
0
static Numeric
hexToUnsignedNumeric(const StaticString &hex) {
	const char *pos = hex.data();
	const char *end = hex.data() + hex.size();
	Numeric result = 0;
	bool done = false;
	
	while (pos < end && !done) {
		char c = *pos;
		if (c >= '0' && c <= '9') {
			result *= 16;
			result += c - '0';
		} else if (c >= 'a' && c <= 'f') {
			result *= 16;
			result += 10 + (c - 'a');
		} else if (c >= 'A' && c <= 'F') {
			result *= 16;
			result += 10 + (c - 'A');
		} else {
			done = true;
		}
		pos++;
	}
	return result;
}
Example #8
0
string
parseUnixSocketAddress(const StaticString &address) {
	if (getSocketAddressType(address) != SAT_UNIX) {
		throw ArgumentException("Not a valid Unix socket address");
	}
	return string(address.c_str() + sizeof("unix:") - 1, address.size() - sizeof("unix:") + 1);
}
Example #9
0
static Numeric
stringToUnsignedNumeric(const StaticString &str) {
	Numeric result = 0;
	string::size_type i = 0;
	const char *data = str.data();
	
	while (data[i] == ' ' && i < str.size()) {
		i++;
	}
	while (data[i] >= '0' && data[i] <= '9' && i < str.size()) {
		result *= 10;
		result += data[i] - '0';
		i++;
	}
	return result;
}
Example #10
0
string
cEscapeString(const StaticString &input) {
	string result;
	const char *current = input.c_str();
	const char *end = current + input.size();
	
	result.reserve(input.size());
	while (current < end) {
		char c = *current;
		if (c >= 32 && c <= 126) {
			// Printable ASCII.
			result.append(1, c);
		} else {
			char buf[sizeof("\\xFF")];
			
			switch (c) {
			case '\0':
				// Explicitly in hex format in order to avoid confusion
				// with any '0' characters that come after this byte.
				result.append("\\x00");
				break;
			case '\t':
				result.append("\\t");
				break;
			case '\n':
				result.append("\\n");
				break;
			case '\r':
				result.append("\\r");
				break;
			case '\e':
				result.append("\\e");
				break;
			default:
				buf[0] = '\\';
				buf[1] = 'x';
				toHex(StaticString(current, 1), buf + 2, true);
				buf[4] = '\0';
				result.append(buf, sizeof(buf) - 1);
				break;
			}
		}
		current++;
	}
	return result;
}
Example #11
0
void
toHex(const StaticString &data, char *output, bool upperCase) {
	const char *data_buf = data.c_str();
	string::size_type i;
	
	if (upperCase) {
		for (i = 0; i < data.size(); i++) {
			output[i * 2] = upcase_hex_chars[(unsigned char) data_buf[i] / 16];
			output[i * 2 + 1] = upcase_hex_chars[(unsigned char) data_buf[i] % 16];
		}
	} else {
		for (i = 0; i < data.size(); i++) {
			output[i * 2] = hex_chars[(unsigned char) data_buf[i] / 16];
			output[i * 2 + 1] = hex_chars[(unsigned char) data_buf[i] % 16];
		}
	}
}
Example #12
0
bool
constantTimeCompare(const StaticString &a, const StaticString &b) {
	// http://blog.jasonmooberry.com/2010/10/constant-time-string-comparison/
	// See also ActiveSupport::MessageVerifier#secure_compare.
	if (a.size() != b.size()) {
		return false;
	} else {
		const char *x = a.data();
		const char *y = b.data();
		const char *end = a.data() + a.size();
		int result = 0;

		while (x < end) {
			result |= *x ^ *y;
			x++;
			y++;
		}

		return result == 0;
	}
}
Example #13
0
string
strip(const StaticString &str) {
	const char *data = str.data();
	const char *end = str.data() + str.size();
	while (data < end && (*data == ' ' || *data == '\n' || *data == '\t')) {
		data++;
	}
	while (end > data && (end[-1] == ' ' || end[-1] == '\n' || end[-1] == '\t')) {
		end--;
	}
	return string(data, end - data);
}
Example #14
0
string
escapeHTML(const StaticString &input) {
	string result;
	result.reserve((int) round(input.size() * 1.25));
	
	const char *current = (const char *) input.c_str();
	const char *end     = current + input.size();
	
	while (current < end) {
		char ch = *current;
		if (ch & 128) {
			// Multibyte UTF-8 character.
			const char *prev = current;
			utf8::advance(current, 1, end);
			result.append(prev, current - prev);
			
		} else {
			// ASCII character <= 127.
			if (ch == '<') {
				result.append("&lt;");
			} else if (ch == '>') {
				result.append("&gt;");
			} else if (ch == '&') {
				result.append("&amp;");
			} else if (ch == '"') {
				result.append("&quot;");
			} else if (ch == '\'') {
				result.append("&apos;");
			} else if (ch >= 0x21 || ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') {
				result.append(1, ch);
			} else {
				result.append("&#");
				result.append(toString((int) ((unsigned char) ch)));
				result.append(";");
			}
			current++;
		}
	}
	return result;
}
Example #15
0
bool
lookupSystemGroupByName(const StaticString &name, OsGroup &result) {
	TRACE_POINT();

	// Null terminate name
	DynamicBuffer ntName(name.size() + 1);
	memcpy(ntName.data, name.data(), name.size());
	ntName.data[name.size()] = '\0';

	int code;
	struct group *output = NULL;

	do {
		code = getgrnam_r(ntName.data, &result.grp, result.buffer.data,
			result.buffer.size, &output);
	} while (code == EINTR || code == EAGAIN);
	if (code == 0) {
		return output != NULL;
	} else {
		throw SystemException("Error looking up OS group account " + name, code);
	}
}
Example #16
0
ServerAddressType
getSocketAddressType(const StaticString &address) {
	const char *data = address.c_str();
	size_t len = address.size();
	
	if (len > sizeof("unix:") - 1 && memcmp(data, "unix:", sizeof("unix:") - 1) == 0) {
		return SAT_UNIX;
	} else if (len > sizeof("tcp://") - 1 && memcmp(data, "tcp://", sizeof("tcp://") - 1) == 0) {
		return SAT_TCP;
	} else {
		return SAT_UNKNOWN;
	}
}
Example #17
0
static void
_splitIncludeSep(const StaticString &str, char sep, vector<OutputString> &output) {
	output.clear();
	if (!str.empty()) {
		string::size_type start, pos;
		start = 0;
		while ((pos = str.find(sep, start)) != string::npos) {
			output.push_back(str.substr(start, pos - start + 1));
			start = pos + 1;
		}
		if (start != str.size()) {
			output.push_back(str.substr(start));
		}
	}
}
Example #18
0
/**
 * Linux-only way to change OOM killer configuration for
 * current process. Requires root privileges, which we
 * should have.
 */
static void
setOomScore(const StaticString &score) {
	if (score.empty()) {
		return;
	}

	FILE *f;
	OomFileType type;
	
	f = openOomAdjFile("w", type);
	if (f != NULL) {
		fwrite(score.data(), 1, score.size(), f);
		fclose(f);
	}
}
Example #19
0
void
parseTcpSocketAddress(const StaticString &address, string &host, unsigned short &port) {
	if (getSocketAddressType(address) != SAT_TCP) {
		throw ArgumentException("Not a valid TCP socket address");
	}
	
	vector<string> args;
	string begin(address.c_str() + sizeof("tcp://") - 1, address.size() - sizeof("tcp://") + 1);
	split(begin, ':', args);
	if (args.size() != 2) {
		throw ArgumentException("Not a valid TCP socket address");
	} else {
		host = args[0];
		port = atoi(args[1].c_str());
	}
}
Example #20
0
void
parseTcpSocketAddress(const StaticString &address, string &host, unsigned short &port) {
	if (getSocketAddressType(address) != SAT_TCP) {
		throw ArgumentException("Not a valid TCP socket address");
	}

	StaticString hostAndPort(address.data() + sizeof("tcp://") - 1,
		address.size() - sizeof("tcp://") + 1);
	if (hostAndPort.empty()) {
		throw ArgumentException("Not a valid TCP socket address");
	}

	if (hostAndPort[0] == '[') {
		// IPv6 address, e.g.:
		// [::1]:3000
		const char *hostEnd = (const char *) memchr(hostAndPort.data(), ']',
			hostAndPort.size());
		if (hostEnd == NULL || hostAndPort.size() <= string::size_type(hostEnd - hostAndPort.data()) + 3) {
			throw ArgumentException("Not a valid TCP socket address");
		}

		const char *sep = hostEnd + 1;
		host.assign(hostAndPort.data() + 1, hostEnd - hostAndPort.data() - 1);
		port = stringToUint(StaticString(
			sep + 1,
			hostAndPort.data() + hostAndPort.size() - sep - 1
		));

	} else {
		// IPv4 address, e.g.:
		// 127.0.0.1:3000
		const char *sep = (const char *) memchr(hostAndPort.data(), ':', hostAndPort.size());
		if (sep == NULL || hostAndPort.size() <= string::size_type(sep - hostAndPort.data()) + 2) {
			throw ArgumentException("Not a valid TCP socket address");
		}

		host.assign(hostAndPort.data(), sep - hostAndPort.data());
		port = stringToUint(StaticString(
			sep + 1,
			hostAndPort.data() + hostAndPort.size() - sep - 1
		));
	}
}
Example #21
0
unsigned long long
hexatriToULL(const StaticString &str) {
	unsigned long long result = 0;
	string::size_type i = 0;
	bool done = false;
	
	while (i < str.size() && !done) {
		char c = str[i];
		if (c >= '0' && c <= '9') {
			result *= 36;
			result += c - '0';
		} else if (c >= 'a' && c <= 'z') {
			result *= 36;
			result += 10 + (c - 'a');
		} else if (c >= 'A' && c <= 'Z') {
			result *= 36;
			result += 10 + (c - 'A');
		} else {
			done = true;
		}
		i++;
	}
	return result;
}
Example #22
0
string
toHex(const StaticString &data) {
	string result(data.size() * 2, '\0');
	toHex(data, (char *) result.data());
	return result;
}
Example #23
0
void
writeExact(int fd, const StaticString &data, unsigned long long *timeout) {
	const char * restrict data_ptr = data.data();
	writeExact(fd, data_ptr, data.size(), timeout);
}