static bool caerOutputFileInit(caerModuleData moduleData) { // First, always create all needed setting nodes, set their default values // and add their listeners. char *userHomeDir = getUserHomeDirectory(moduleData); if (userHomeDir == NULL) { // caerModuleLog() called inside getUserHomeDirectory(). return (false); } sshsNodeCreateString(moduleData->moduleNode, "directory", userHomeDir, 1, (PATH_MAX - MAX_PREFIX_LENGTH), SSHS_FLAGS_NORMAL, "Directory to write output data files in."); free(userHomeDir); // Support file-chooser in GUI, select any directory. sshsNodeCreateAttributeFileChooser(moduleData->moduleNode, "directory", "DIRECTORY"); sshsNodeCreateString(moduleData->moduleNode, "prefix", DEFAULT_PREFIX, 1, MAX_PREFIX_LENGTH, SSHS_FLAGS_NORMAL, "Output data files name prefix."); // Generate current file name and open it. char *directory = sshsNodeGetString(moduleData->moduleNode, "directory"); char *prefix = sshsNodeGetString(moduleData->moduleNode, "prefix"); char *filePath = getFullFilePath(moduleData, directory, prefix); free(directory); free(prefix); if (filePath == NULL) { // caerModuleLog() called inside getFullFilePath(). return (false); } int fileFd = open(filePath, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP); if (fileFd < 0) { caerModuleLog(moduleData, CAER_LOG_CRITICAL, "Could not create or open output file '%s' for writing. Error: %d.", filePath, errno); free(filePath); return (false); } caerModuleLog(moduleData, CAER_LOG_INFO, "Opened output file '%s' successfully for writing.", filePath); free(filePath); if (!caerOutputCommonInit(moduleData, fileFd, NULL)) { close(fileFd); return (false); } return (true); }
static bool caerOutputUnixSocketServerInit(caerModuleData moduleData) { // First, always create all needed setting nodes, set their default values // and add their listeners. sshsNodeCreateString(moduleData->moduleNode, "socketPath", "/tmp/caer.sock", 2, PATH_MAX, SSHS_FLAGS_NORMAL, "Unix Socket path for writing output data (server mode, create new socket)."); sshsNodeCreateInt( moduleData->moduleNode, "backlogSize", 5, 1, 32, SSHS_FLAGS_NORMAL, "Maximum number of pending connections."); sshsNodeCreateInt(moduleData->moduleNode, "concurrentConnections", 10, 1, 128, SSHS_FLAGS_NORMAL, "Maximum number of concurrent active connections."); // Allocate memory. size_t numClients = (size_t) sshsNodeGetInt(moduleData->moduleNode, "concurrentConnections"); outputCommonNetIO streams = malloc(sizeof(*streams) + (numClients * sizeof(uv_stream_t *))); if (streams == NULL) { caerModuleLog(moduleData, CAER_LOG_ERROR, "Failed to allocate memory for streams structure."); return (false); } streams->server = malloc(sizeof(uv_pipe_t)); if (streams->server == NULL) { free(streams); caerModuleLog(moduleData, CAER_LOG_ERROR, "Failed to allocate memory for network server."); return (false); } // Initialize common info. streams->isTCP = false; streams->isUDP = false; streams->isPipe = true; streams->activeClients = 0; streams->clientsSize = numClients; for (size_t i = 0; i < streams->clientsSize; i++) { streams->clients[i] = NULL; } // Remember address. streams->address = sshsNodeGetString(moduleData->moduleNode, "socketPath"); streams->server->data = streams; // Initialize loop and network handles. int retVal = uv_loop_init(&streams->loop); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_loop_init", free(streams->server); free(streams->address); free(streams); return (false)); retVal = uv_pipe_init(&streams->loop, (uv_pipe_t *) streams->server, false); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_pipe_init", uv_loop_close(&streams->loop); free(streams->server); free(streams->address); free(streams); return (false)); retVal = uv_pipe_bind((uv_pipe_t *) streams->server, streams->address); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_pipe_bind", libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false)); retVal = uv_listen( streams->server, sshsNodeGetInt(moduleData->moduleNode, "backlogSize"), &caerOutputCommonOnServerConnection); UV_RET_CHECK(retVal, moduleData->moduleSubSystemString, "uv_listen", libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false)); // Start. if (!caerOutputCommonInit(moduleData, -1, streams)) { libuvCloseLoopHandles(&streams->loop); uv_loop_close(&streams->loop); free(streams->address); free(streams); return (false); } return (true); }
static bool caerOutputUnixSocketServerInit(caerModuleData moduleData) { // First, always create all needed setting nodes, set their default values // and add their listeners. sshsNodePutStringIfAbsent(moduleData->moduleNode, "socketPath", "/tmp/caer.sock"); sshsNodePutShortIfAbsent(moduleData->moduleNode, "backlogSize", 5); sshsNodePutShortIfAbsent(moduleData->moduleNode, "concurrentConnections", 10); // Open a Unix local socket on a known path, to be accessed by other processes (server-like mode). int serverSockFd = socket(AF_UNIX, SOCK_STREAM, 0); if (serverSockFd < 0) { caerLog(CAER_LOG_CRITICAL, moduleData->moduleSubSystemString, "Could not create local Unix socket. Error: %d.", errno); return (false); } struct sockaddr_un unixSocketAddr; memset(&unixSocketAddr, 0, sizeof(struct sockaddr_un)); unixSocketAddr.sun_family = AF_UNIX; char *socketPath = sshsNodeGetString(moduleData->moduleNode, "socketPath"); strncpy(unixSocketAddr.sun_path, socketPath, sizeof(unixSocketAddr.sun_path) - 1); unixSocketAddr.sun_path[sizeof(unixSocketAddr.sun_path) - 1] = '\0'; // Ensure NUL terminated string. free(socketPath); // Bind socket to above address. if (bind(serverSockFd, (struct sockaddr *) &unixSocketAddr, sizeof(struct sockaddr_un)) < 0) { close(serverSockFd); caerLog(CAER_LOG_CRITICAL, moduleData->moduleSubSystemString, "Could not bind local Unix socket. Error: %d.", errno); return (false); } // Listen to new connections on the socket. if (listen(serverSockFd, sshsNodeGetShort(moduleData->moduleNode, "backlogSize")) < 0) { close(serverSockFd); caerLog(CAER_LOG_CRITICAL, moduleData->moduleSubSystemString, "Could not listen on local Unix socket. Error: %d.", errno); return (false); } outputCommonFDs fileDescriptors = caerOutputCommonAllocateFdArray( (size_t) sshsNodeGetShort(moduleData->moduleNode, "concurrentConnections")); if (fileDescriptors == NULL) { close(serverSockFd); caerLog(CAER_LOG_CRITICAL, moduleData->moduleSubSystemString, "Unable to allocate memory for file descriptors."); return (false); } fileDescriptors->serverFd = serverSockFd; if (!caerOutputCommonInit(moduleData, fileDescriptors, true, false)) { close(serverSockFd); free(fileDescriptors); return (false); } caerLog(CAER_LOG_INFO, moduleData->moduleSubSystemString, "Local Unix socket ready at '%s'.", unixSocketAddr.sun_path); return (true); }