void client_idle_add(struct client *client, unsigned flags) { if (client_is_expired(client)) return; client->idle_flags |= flags; if (client->idle_waiting && (client->idle_flags & client->idle_subscriptions)) { client_idle_notify(client); client_write_output(client); } }
static void client_idle_callback(gpointer data, gpointer user_data) { struct client *client = data; unsigned flags = GPOINTER_TO_UINT(user_data); if (client_is_expired(client)) return; client->idle_flags |= flags; if (client->idle_waiting && (client->idle_flags & client->idle_subscriptions)) { client_idle_notify(client); client_write_output(client); } }
/** * Write a block of data to the client. */ static void client_write(struct client *client, const char *buffer, size_t buflen) { /* if the client is going to be closed, do nothing */ if (client_is_expired(client)) return; while (buflen > 0 && !client_is_expired(client)) { size_t copylen; assert(client->send_buf_used < sizeof(client->send_buf)); copylen = sizeof(client->send_buf) - client->send_buf_used; if (copylen > buflen) copylen = buflen; memcpy(client->send_buf + client->send_buf_used, buffer, copylen); buflen -= copylen; client->send_buf_used += copylen; buffer += copylen; if (client->send_buf_used >= sizeof(client->send_buf)) client_write_output(client); } }
enum command_return client_process_line(struct client *client, char *line) { enum command_return ret; if (strcmp(line, "noidle") == 0) { if (client->idle_waiting) { /* send empty idle response and leave idle mode */ client->idle_waiting = false; command_success(client); client_write_output(client); } /* do nothing if the client wasn't idling: the client has already received the full idle response from client_idle_notify(), which he can now evaluate */ return COMMAND_RETURN_OK; } else if (client->idle_waiting) { /* during idle mode, clients must not send anything except "noidle" */ g_warning("[%u] command \"%s\" during idle", client->num, line); return COMMAND_RETURN_CLOSE; } if (client->cmd_list_OK >= 0) { if (strcmp(line, CLIENT_LIST_MODE_END) == 0) { g_debug("[%u] process command list", client->num); /* for scalability reasons, we have prepended each new command; now we have to reverse it to restore the correct order */ client->cmd_list = g_slist_reverse(client->cmd_list); ret = client_process_command_list(client, client->cmd_list_OK, client->cmd_list); g_debug("[%u] process command " "list returned %i", client->num, ret); if (ret == COMMAND_RETURN_CLOSE || client_is_expired(client)) return COMMAND_RETURN_CLOSE; if (ret == COMMAND_RETURN_OK) command_success(client); client_write_output(client); free_cmd_list(client->cmd_list); client->cmd_list = NULL; client->cmd_list_OK = -1; } else { size_t len = strlen(line) + 1; client->cmd_list_size += len; if (client->cmd_list_size > client_max_command_list_size) { g_warning("[%u] command list size (%lu) " "is larger than the max (%lu)", client->num, (unsigned long)client->cmd_list_size, (unsigned long)client_max_command_list_size); return COMMAND_RETURN_CLOSE; } new_cmd_list_ptr(client, line); ret = COMMAND_RETURN_OK; } } else { if (strcmp(line, CLIENT_LIST_MODE_BEGIN) == 0) { client->cmd_list_OK = 0; ret = COMMAND_RETURN_OK; } else if (strcmp(line, CLIENT_LIST_OK_MODE_BEGIN) == 0) { client->cmd_list_OK = 1; ret = COMMAND_RETURN_OK; } else { g_debug("[%u] process command \"%s\"", client->num, line); ret = command_process(client, 0, line); g_debug("[%u] command returned %i", client->num, ret); if (ret == COMMAND_RETURN_CLOSE || client_is_expired(client)) return COMMAND_RETURN_CLOSE; if (ret == COMMAND_RETURN_OK) command_success(client); client_write_output(client); } } return ret; }