Copy the current lists of queued and waiting commands and reference each command before calling smtp_client_command_fail_reply().
Failing one command can cause other dependent commands to be aborted (in a transaction or from submission service), which could have caused trouble in this function.
Problems would likely occur at connection disconnect.
smtp_client_command_fail_reply(_cmd, &reply);
}
+void smtp_client_commands_list_fail_reply(
+ struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
+ const struct smtp_reply *reply)
+{
+ struct smtp_client_command *cmd;
+ ARRAY(struct smtp_client_command *) cmds_arr;
+ struct smtp_client_command **cmds;
+ unsigned int count, i;
+
+ if (cmds_list == NULL)
+ return;
+ i_assert(cmds_list_count > 0);
+
+ /* copy the array and reference the commands to be robust against more
+ than one command disappearing from the list */
+ t_array_init(&cmds_arr, cmds_list_count);
+ for (cmd = cmds_list; cmd != NULL; cmd = cmd->next) {
+ smtp_client_command_ref(cmd);
+ array_append(&cmds_arr, &cmd, 1);
+ }
+
+ cmds = array_get_modifiable(&cmds_arr, &count);
+ for (i = 0; i < count; i++) {
+ cmd = cmds[i];
+ /* fail the reply */
+ smtp_client_command_fail_reply(&cmds[i], reply);
+ /* drop our reference */
+ smtp_client_command_unref(&cmd);
+ }
+}
+
void smtp_client_command_set_abort_callback(struct smtp_client_command *cmd,
void (*callback)(void *context), void *context)
{
smtp_client_connection_commands_fail_reply(struct smtp_client_connection *conn,
const struct smtp_reply *reply)
{
- struct smtp_client_command *cmd, *cmd_next = NULL;
-
- cmd = conn->cmd_wait_list_head;
- while (cmd != NULL) {
- i_assert(conn->cmd_wait_list_count > 0);
- cmd_next = cmd->next;
- smtp_client_command_fail_reply(&cmd, reply);
- cmd = cmd_next;
- }
-
- cmd = conn->cmd_send_queue_head;
- while (cmd != NULL) {
- i_assert(conn->cmd_send_queue_count > 0);
- cmd_next = cmd->next;
- smtp_client_command_fail_reply(&cmd, reply);
- cmd = cmd_next;
- }
+ smtp_client_commands_list_fail_reply(conn->cmd_wait_list_head,
+ conn->cmd_wait_list_count, reply);
+ smtp_client_commands_list_fail_reply(conn->cmd_send_queue_head,
+ conn->cmd_send_queue_count, reply);
}
static void
int smtp_client_command_send_more(struct smtp_client_connection *conn);
int smtp_client_command_input_reply(struct smtp_client_command *cmd,
const struct smtp_reply *reply);
+
void smtp_client_command_fail(struct smtp_client_command **_cmd,
unsigned int status, const char *error);
void smtp_client_command_fail_reply(struct smtp_client_command **_cmd,
const struct smtp_reply *reply);
+void smtp_client_commands_list_fail_reply(
+ struct smtp_client_command *cmds_list, unsigned int cmds_list_count,
+ const struct smtp_reply *reply);
/*
* Transaction