<commit_before>/* Copyright (C) 2002 <NAME> */

#include "common.h"
#include "hash.h"
#include "ioloop.h"
#include "network.h"
#include "istream.h"
#include "ostream.h"
#include "auth-connection.h"

#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>

/* Maximum size for an auth reply. 50kB should be more than enough. */
#define MAX_INBUF_SIZE (1024*50)

#define MAX_OUTBUF_SIZE \
	(sizeof(struct auth_login_request_continue) + \
	 AUTH_LOGIN_MAX_REQUEST_DATA_SIZE)

enum auth_mech available_auth_mechs;

static int auth_reconnect;
static unsigned int request_id_counter;
static struct auth_connection *auth_connections;
static struct timeout *to;
static unsigned int auth_waiting_handshake_count;

static void auth_connection_destroy(struct auth_connection *conn);
static void auth_connection_unref(struct auth_connection *conn);

static void auth_input(void *context);
static void auth_connect_missing(void);

static struct auth_connection *auth_connection_find(const char *path)
{
	struct auth_connection *conn;

	for (conn = auth_connections; conn != NULL; conn = conn->next) {
		if (strcmp(conn->path, path) == 0)
			return conn;
	}

	return NULL;
}

static struct auth_connection *auth_connection_new(const char *path)
{
	struct auth_connection *conn;
        struct auth_login_handshake_input handshake;
	int fd;

	fd = net_connect_unix(path);
	if (fd == -1) {
		i_error("Can't connect to auth process at %s: %m", path);
                auth_reconnect = TRUE;
		return NULL;
	}

	/* we depend on auth process - if it's slow, just wait */
        net_set_nonblock(fd, FALSE);

	conn = i_new(struct auth_connection, 1);
	conn->refcount = 1;
	conn->path = i_strdup(path);
	conn->fd = fd;
	conn->io = io_add(fd, IO_READ, auth_input, conn);
	conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
					   FALSE);
	conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
					    IO_PRIORITY_DEFAULT, FALSE);
	conn->requests = hash_create(default_pool, default_pool, 100,
				     NULL, NULL);

	conn->next = auth_connections;
	auth_connections = conn;

	/* send our handshake */
        auth_waiting_handshake_count++;
	memset(&handshake, 0, sizeof(handshake));
	handshake.pid = login_process_uid;
	if (o_stream_send(conn->output, &handshake, sizeof(handshake)) < 0) {
		errno = conn->output->stream_errno;
		i_warning("Error sending handshake to auth process: %m");
		auth_connection_destroy(conn);
		return NULL;
	}
	return conn;
}

static void request_hash_remove(void *key __attr_unused__, void *value,
				void *context __attr_unused__)
{
	struct auth_request *request = value;

	request->callback(request, NULL, NULL, request->context);
}

static void request_hash_destroy(void *key __attr_unused__, void *value,
				 void *context __attr_unused__)
{
	struct auth_request *request = value;

	i_free(request);
}

static void auth_connection_destroy(struct auth_connection *conn)
{
	struct auth_connection **pos;

	if (conn->fd == -1)
		return;

	for (pos = &auth_connections; *pos != NULL; pos = &(*pos)->next) {
		if (*pos == conn) {
			*pos = conn->next;
			break;
		}
	}

        auth_waiting_handshake_count--;

	if (close(conn->fd) < 0)
		i_error("close(auth) failed: %m");
	io_remove(conn->io);
	conn->fd = -1;

	hash_foreach(conn->requests, request_hash_remove, NULL);

        auth_connection_unref(conn);
}

static void auth_connection_unref(struct auth_connection *conn)
{<commit_msg>handshake counter was decreased too often and could have caused hangs<commit_after>/* Copyright (C) 2002 <NAME> */

#include "common.h"
#include "hash.h"
#include "ioloop.h"
#include "network.h"
#include "istream.h"
#include "ostream.h"
#include "auth-connection.h"

#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>

/* Maximum size for an auth reply. 50kB should be more than enough. */
#define MAX_INBUF_SIZE (1024*50)

#define MAX_OUTBUF_SIZE \
	(sizeof(struct auth_login_request_continue) + \
	 AUTH_LOGIN_MAX_REQUEST_DATA_SIZE)

enum auth_mech available_auth_mechs;

static int auth_reconnect;
static unsigned int request_id_counter;
static struct auth_connection *auth_connections;
static struct timeout *to;
static unsigned int auth_waiting_handshake_count;

static void auth_connection_destroy(struct auth_connection *conn);
static void auth_connection_unref(struct auth_connection *conn);

static void auth_input(void *context);
static void auth_connect_missing(void);

static struct auth_connection *auth_connection_find(const char *path)
{
	struct auth_connection *conn;

	for (conn = auth_connections; conn != NULL; conn = conn->next) {
		if (strcmp(conn->path, path) == 0)
			return conn;
	}

	return NULL;
}

static struct auth_connection *auth_connection_new(const char *path)
{
	struct auth_connection *conn;
        struct auth_login_handshake_input handshake;
	int fd;

	fd = net_connect_unix(path);
	if (fd == -1) {
		i_error("Can't connect to auth process at %s: %m", path);
                auth_reconnect = TRUE;
		return NULL;
	}

	/* we depend on auth process - if it's slow, just wait */
        net_set_nonblock(fd, FALSE);

	conn = i_new(struct auth_connection, 1);
	conn->refcount = 1;
	conn->path = i_strdup(path);
	conn->fd = fd;
	conn->io = io_add(fd, IO_READ, auth_input, conn);
	conn->input = i_stream_create_file(fd, default_pool, MAX_INBUF_SIZE,
					   FALSE);
	conn->output = o_stream_create_file(fd, default_pool, MAX_OUTBUF_SIZE,
					    IO_PRIORITY_DEFAULT, FALSE);
	conn->requests = hash_create(default_pool, default_pool, 100,
				     NULL, NULL);

	conn->next = auth_connections;
	auth_connections = conn;

	/* send our handshake */
        auth_waiting_handshake_count++;
	memset(&handshake, 0, sizeof(handshake));
	handshake.pid = login_process_uid;
	if (o_stream_send(conn->output, &handshake, sizeof(handshake)) < 0) {
		errno = conn->output->stream_errno;
		i_warning("Error sending handshake to auth process: %m");
		auth_connection_destroy(conn);
		return NULL;
	}
	return conn;
}

static void request_hash_remove(void *key __attr_unused__, void *value,
				void *context __attr_unused__)
{
	struct auth_request *request = value;

	request->callback(request, NULL, NULL, request->context);
}

static void request_hash_destroy(void *key __attr_unused__, void *value,
				 void *context __attr_unused__)
{
	struct auth_request *request = value;

	i_free(request);
}

static void auth_connection_destroy(struct auth_connection *conn)
{
	struct auth_connection **pos;

	if (conn->fd == -1)
		return;

	for (pos = &auth_connections; *pos != NULL; pos = &(*pos)->next) {
		if (*pos == conn) {
			*pos = conn->next;
			break;
		}
	}

	if (!conn->handshake_received)
		auth_waiting_handshake_count--;

	if (close(conn->fd) < 0)
		i_error("close(auth) failed: %m");
	io_remove(conn->io);
	conn->fd = -1;

	hash_foreach(conn->requests, request_hash_remove, NULL);

        auth_connection_unref(conn);
}

static void auth_connection_unref(struct auth_connection *conn)
{
{'fraction_non_alphanumeric': 0.11843238587424634, 'fraction_numerical': 0.0068906115417743325, 'mean_word_length': 4.7721623860811935, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3849392', 'n_tokens_mistral': 2511, 'n_tokens_neox': 2350, 'n_words': 598}