Example #1
0
bool command_exec(struct client_command_context *cmd)
{
	const struct command_hook *hook;
	long long diff;
	bool finished;

	if (cmd->last_ioloop_time.tv_sec != 0) {
		diff = timeval_diff_usecs(&ioloop_timeval, &cmd->last_ioloop_time);
		if (diff > 0)
			cmd->usecs_in_ioloop += diff;
	}

	array_foreach(&command_hooks, hook)
		hook->pre(cmd);
	finished = cmd->func(cmd);
	array_foreach(&command_hooks, hook)
		hook->post(cmd);
	if (cmd->state == CLIENT_COMMAND_STATE_DONE)
		finished = TRUE;
	if (!finished) {
		io_loop_time_refresh();
		cmd->last_ioloop_time = ioloop_timeval;
	}
	return finished;
}
Example #2
0
void client_send_tagline(struct client_command_context *cmd, const char *data)
{
	struct client *client = cmd->client;
	const char *tag = cmd->tag;
	int time_msecs;

	if (client->output->closed || cmd->cancel)
		return;

	i_assert(!cmd->tagline_sent);
	cmd->tagline_sent = TRUE;

	if (tag == NULL || *tag == '\0')
		tag = "*";

	T_BEGIN {
		string_t *str = t_str_new(256);
		str_printfa(str, "%s %s", tag, data);
		if (cmd->start_time.tv_sec != 0) {
			if (str_data(str)[str_len(str)-1] == '.')
				str_truncate(str, str_len(str)-1);
			io_loop_time_refresh();
			time_msecs = timeval_diff_msecs(&ioloop_timeval,
							&cmd->start_time);
			time_msecs -= cmd->usecs_in_ioloop/1000;
			if (time_msecs >= 0) {
				str_printfa(str, " (%d.%03d secs).",
					    time_msecs/1000, time_msecs%1000);
			}
		}
		str_append(str, "\r\n");
		o_stream_nsend(client->output, str_data(str), str_len(str));
	} T_END;

	client->last_output = ioloop_time;
}
Example #3
0
static int driver_mysql_connect(struct sql_db *_db)
{
	struct mysql_db *db = (struct mysql_db *)_db;
	const char *unix_socket, *host;
	unsigned long client_flags = db->client_flags;
	unsigned int secs_used;
	bool failed;

	i_assert(db->api.state == SQL_DB_STATE_DISCONNECTED);

	sql_db_set_state(&db->api, SQL_DB_STATE_CONNECTING);

	if (*db->host == '/') {
		unix_socket = db->host;
		host = NULL;
	} else {
		unix_socket = NULL;
		host = db->host;
	}

	if (db->option_file != NULL) {
		mysql_options(db->mysql, MYSQL_READ_DEFAULT_FILE,
			      db->option_file);
	}

	mysql_options(db->mysql, MYSQL_READ_DEFAULT_GROUP,
		      db->option_group != NULL ? db->option_group : "client");

	if (!db->ssl_set && (db->ssl_ca != NULL || db->ssl_ca_path != NULL)) {
#ifdef HAVE_MYSQL_SSL
		mysql_ssl_set(db->mysql, db->ssl_key, db->ssl_cert,
			      db->ssl_ca, db->ssl_ca_path
#ifdef HAVE_MYSQL_SSL_CIPHER
			      , db->ssl_cipher
#endif
			     );
		db->ssl_set = TRUE;
#else
		i_fatal("mysql: SSL support not compiled in "
			"(remove ssl_ca and ssl_ca_path settings)");
#endif
	}

	alarm(SQL_CONNECT_TIMEOUT_SECS);
#ifdef CLIENT_MULTI_RESULTS
	client_flags |= CLIENT_MULTI_RESULTS;
#endif
	/* CLIENT_MULTI_RESULTS allows the use of stored procedures */
	failed = mysql_real_connect(db->mysql, host, db->user, db->password,
				    db->dbname, db->port, unix_socket,
				    client_flags) == NULL;
	secs_used = SQL_CONNECT_TIMEOUT_SECS - alarm(0);
	if (failed) {
		/* connecting could have taken a while. make sure that any
		   timeouts that get added soon will get a refreshed
		   timestamp. */
		io_loop_time_refresh();

		if (db->api.connect_delay < secs_used)
			db->api.connect_delay = secs_used;
		sql_db_set_state(&db->api, SQL_DB_STATE_DISCONNECTED);
		i_error("%s: Connect failed to database (%s): %s - "
			"waiting for %u seconds before retry",
			mysql_prefix(db), db->dbname,
			mysql_error(db->mysql), db->api.connect_delay);
		return -1;
	} else {
		db->last_success = ioloop_time;
		sql_db_set_state(&db->api, SQL_DB_STATE_IDLE);
		return 1;
	}
}
Example #4
0
static int lmtp_client_send_data(struct lmtp_client *client)
{
	const unsigned char *data;
	unsigned char add;
	size_t i, size;
	bool sent_bytes = FALSE;
	int ret;

	if (client->output_finished)
		return 0;

	while ((ret = i_stream_read_more(client->data_input, &data, &size)) > 0) {
		add = '\0';
		for (i = 0; i < size; i++) {
			if (data[i] == '\n') {
				if ((i == 0 && client->output_last != '\r') ||
				    (i > 0 && data[i-1] != '\r')) {
					/* missing CR */
					add = '\r';
					break;
				}
			} else if (data[i] == '.' &&
				   ((i == 0 && client->output_last == '\n') ||
				    (i > 0 && data[i-1] == '\n'))) {
				/* escape the dot */
				add = '.';
				break;
			}
		}

		if (i > 0) {
			if (o_stream_send(client->output, data, i) < 0)
				break;
			client->output_last = data[i-1];
			i_stream_skip(client->data_input, i);
			sent_bytes = TRUE;
		}

		if (o_stream_get_buffer_used_size(client->output) >= 4096) {
			if ((ret = o_stream_flush(client->output)) < 0)
				break;
			if (ret == 0) {
				/* continue later */
				o_stream_set_flush_pending(client->output, TRUE);
				return 0;
			}
		}

		if (add != '\0') {
			if (o_stream_send(client->output, &add, 1) < 0)
				break;

			client->output_last = add;
		}
	}
	if (client->data_input->stream_errno != 0) {
		i_error("lmtp client: read(%s) failed: %s",
			i_stream_get_name(client->data_input),
			i_stream_get_error(client->data_input));
		lmtp_client_fail(client,
			"451 4.3.0 Internal failure while reading DATA input");
		return -1;
	}
	if (sent_bytes && client->data_output_callback != NULL)
		client->data_output_callback(client->data_output_context);

	if (ret == 0 || ret == -2) {
		/* -2 can happen with tee istreams */
		return 0;
	}

	if (client->output_last != '\n') {
		/* didn't end with CRLF */
		o_stream_nsend(client->output, "\r\n", 2);
	}
	o_stream_nsend(client->output, ".\r\n", 3);
	client->output_finished = TRUE;
	io_loop_time_refresh();
	client->times.data_sent = ioloop_timeval;
	return 0;
}