Example #1
0
UByte PancakeNetworkActivate() {
	UInt16 i;

	if(!numListenSockets) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "No network interfaces configured");
		return 0;
	}

	for(i = 0; i < numListenSockets; i++) {
		PancakeSocket *sock = listenSockets[i];

		// Start listening on socket
		if(listen(sock->fd, (Int32) (UNative) sock->data) == -1) {
			Byte *name = PancakeNetworkGetInterfaceName(sock->localAddress);

			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Can't listen on %s: %s", name, strerror(errno));

			PancakeFree(name);
			return 0;
		}

		sock->data = NULL;
	}

	return 1;
}
Example #2
0
STATIC UByte PancakeAuthenticationBackendConfiguration(UByte step, config_setting_t *setting, PancakeConfigurationScope **scope) {
	PancakeAuthenticationConfiguration *config = (PancakeAuthenticationConfiguration*) setting->parent->hook;

	if(step == PANCAKE_CONFIGURATION_INIT) {
		UInt32 length = strlen(setting->value.sval);

		HASH_FIND(hh, PancakeAuthenticationBackends, setting->value.sval, length, config->backend);

		if(config->backend == NULL) {
			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Unknown authentication backend %s", setting->value.sval);
			return 0;
		}

		// Call onConfiguration handler
		if(config->backend->onConfiguration) {
			config->backend->onConfiguration(config);
		}

		// Save some memory
		free(setting->value.sval);
		setting->type = CONFIG_TYPE_NONE;
	}

	return 1;
}
STATIC UByte PancakeHTTPRewriteSetHTTPVersion(PancakeSocket *sock, PancakeHTTPRewriteVariable *var, PancakeHTTPRewriteValue *value) {
	PancakeHTTPRequest *request = (PancakeHTTPRequest*) sock->data;

	if(UNEXPECTED(value->intv < 10 || value->intv > 11)) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Bad value for $HTTPVersion: must be 10 or 11");
		return 0;
	}

	if(UNEXPECTED(value->intv == 11 && request->HTTPVersion < PANCAKE_HTTP_11)) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Can't set $HTTPVersion to higher value than supported by client");
		return 0;
	}

	request->HTTPVersion = value->intv == 10 ? PANCAKE_HTTP_10 : PANCAKE_HTTP_11;

	return 1;
}
STATIC UByte PancakeHTTPRewriteSetHTTPAnswerCode(PancakeSocket *sock, PancakeHTTPRewriteVariable *var, PancakeHTTPRewriteValue *value) {
	PancakeHTTPRequest *request = (PancakeHTTPRequest*) sock->data;

	if(UNEXPECTED(value->intv < 100 || value->intv > 599)) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Value for $HTTPAnswerCode is out of range (100 - 599)");
		return 0;
	}

	request->answerCode = (UInt16) value->intv;
	return 1;
}
Example #5
0
STATIC UByte PancakeNetworkInterfaceNetworkConfiguration(UByte step, config_setting_t *setting, PancakeConfigurationScope **scope) {
	if(step == PANCAKE_CONFIGURATION_INIT) {
		PancakeSocket *sock = (PancakeSocket*) setting->parent->hook;
		Int32 value = 1;

		// Check family
		if(!strcmp(setting->value.sval, "ip4")) {
			struct sockaddr_in *addr = (struct sockaddr_in*) sock->localAddress;

			sock->localAddress->sa_family = AF_INET;
			addr->sin_family = AF_INET;
		} else if(!strcmp(setting->value.sval, "ip6")) {
			struct sockaddr_in6 *addr = (struct sockaddr_in6*) sock->localAddress;

			sock->localAddress->sa_family = AF_INET6;
			addr->sin6_family = AF_INET6;
		} else if(!strcmp(setting->value.sval, "unix")) {
			struct sockaddr_un *addr = (struct sockaddr_un*) sock->localAddress;

			sock->localAddress->sa_family = AF_UNIX;
			addr->sun_family = AF_UNIX;
		} else {
			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Invalid network family %s", setting->value.sval);
			return 0;
		}

		sock->fd = socket(sock->localAddress->sa_family, SOCK_STREAM, sock->localAddress->sa_family == AF_UNIX ? 0 : SOL_TCP);

		if(sock->fd == -1) {
			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Can't create socket: %s", strerror(errno));
			return 0;
		}

		// Set SO_REUSEADDR
		setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(Int32));
	}

	return 1;
}
Example #6
0
STATIC UByte PancakeLinuxPollServerInitialize() {
	// Just test epoll here, to make sure everything will work
	// The actual epoll instance must be created in the workers as it can't be shared

	// Initialize with size 32 on old kernels
	PancakeLinuxPollFD = epoll_create(32);

	if(PancakeLinuxPollFD == -1) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Can't create epoll instance: %s", strerror(errno));
		return 0;
	}

	close(PancakeLinuxPollFD);
	PancakeLinuxPollFD = -1;

	return 1;
}
Example #7
0
STATIC UByte PancakeAuthenticationConfigurationConfiguration(UByte step, config_setting_t *setting, PancakeConfigurationScope **scope) {
	PancakeAuthenticationConfiguration *config = NULL;

	if(step == PANCAKE_CONFIGURATION_INIT) {
		UInt32 length = strlen(setting->value.sval);

		HASH_FIND(hh, PancakeAuthenticationConfigurations, setting->value.sval, length, config);

		if(config == NULL) {
			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Unknown authentication configuration %s", setting->value.sval);
			return 0;
		}

		free(setting->value.sval);
		setting->type = CONFIG_TYPE_SPECIAL;
		setting->value.sval = (void*) config;
	} else {
		// Make library happy
		setting->type = CONFIG_TYPE_NONE;
	}

	return 1;
}
Example #8
0
STATIC void PancakeLinuxPollWait() {
	// Initialize with size 32 on old kernels
	PancakeLinuxPollFD = epoll_create(32);

	if(PancakeLinuxPollFD == -1) {
		PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "Can't create epoll instance: %s", strerror(errno));
		return;
	}

	// Activate listen sockets
	PancakeNetworkActivateListenSockets();

	while(1) {
		struct epoll_event events[32];
		Int32 numEvents, i;

		numEvents = epoll_wait(PancakeLinuxPollFD, events, 32, PancakeSchedulerGetNextExecutionTimeOffset() * 1000);

		if(UNEXPECTED(numEvents == -1)) {
			if(PancakeDoShutdown) {
				return;
			}

			if(errno == EINTR) {
				continue;
			}

			PancakeLoggerFormat(PANCAKE_LOGGER_ERROR, 0, "epoll_wait failed: %s", strerror(errno));
			return;
		}

		// Network events first
		for(i = 0; i < numEvents; i++) {
			PancakeSocket *sock = (PancakeSocket*) events[i].data.ptr;

			if(((events[i].events & EPOLLHUP) && !(events[i].events & EPOLLRDHUP)) || (events[i].events & EPOLLERR)) {
				sock->onRemoteHangup(sock);
				PancakeCheckHeap();
				continue;
			}

			currentSocket = sock;

			if(events[i].events & EPOLLIN) {
				sock->onRead(sock);
				PancakeCheckHeap();
			}

			if(events[i].events & EPOLLOUT) {
				// Socket has been closed in onRead()
				if(!currentSocket) {
					continue;
				}

				sock->onWrite(sock);
				PancakeCheckHeap();
			}

			if(events[i].events & EPOLLRDHUP) {
				// Socket has been closed in onWrite()
				if(!currentSocket) {
					continue;
				}

				sock->onRemoteHangup(sock);
				PancakeCheckHeap();
			}
		}

		// Scheduler events second
		PancakeSchedulerRun();

		if(UNEXPECTED(PancakeDoShutdown)) {
			return;
		}
	}
}