Index: channels/chan_agent.c =================================================================== --- channels/chan_agent.c (revision 46648) +++ channels/chan_agent.c (working copy) @@ -196,6 +196,7 @@ char loginchan[80]; /**< channel they logged in from */ char logincallerid[80]; /**< Caller ID they had when they logged in */ struct ast_channel *chan; /**< Channel we use */ + int realtime; /*!< Realtime backed agent? */ AST_LIST_ENTRY(agent_pvt) list; /**< Next Agent in the linked list. */ }; @@ -344,6 +345,7 @@ ast_copy_string(p->moh, moh, sizeof(p->moh)); p->ackcall = ackcall; p->autologoff = autologoff; + p->realtime = 0; /* By default, we are not realtime. */ /* If someone reduces the wrapuptime and reloads, we want it * to change the wrapuptime immediately on all calls */ @@ -376,17 +378,19 @@ { struct ast_channel *chan = p->owner; p->owner = NULL; - chan->tech_pvt = NULL; + /* XXX:realtime chan->tech_pvt = NULL; */ p->app_sleep_cond = 1; /* Release ownership of the agent to other threads (presumably running the login app). */ ast_mutex_unlock(&p->app_lock); - if (chan) + if (chan) { + chan->tech_pvt = NULL; ast_channel_free(chan); + } if (p->dead) { ast_mutex_destroy(&p->lock); ast_mutex_destroy(&p->app_lock); free(p); - } + } return 0; } @@ -1152,6 +1156,105 @@ return 1; } +/* + * Find an agent in the list based on the username. + * + * @param username Username of the agent to find. + * @returns A pointer to the structure of the found agent, or NULL + */ +static struct agent_pvt *find_agent(char *username) +{ + struct agent_pvt *p; /* Pointer to first agent */ + + AST_LIST_LOCK(&agents); + AST_LIST_TRAVERSE(&agents, p, list) { + if (p->realtime && !ast_load_realtime("agents", "user", p->agent, NULL)) { + p->dead = 1; /* Mark this agent for destruction */ + /* agent_unlink(p); */ /* Remove from list */ + AST_LIST_REMOVE(&agents, p, list); + agent_cleanup(p); /* Destroy it */ + continue; + } + + /* + * Compare usernames, verify non-pending + * FIXME: shouldn't we also avoid 'dead' agents? + */ + if (!strcmp(p->agent, username) && !p->pending) { + if (p->realtime) { /* Realtime agent? */ + ast_mutex_lock(&p->lock); + + struct ast_variable *rtagent = ast_load_realtime("agents", "user", username, NULL); + /* Update agent pass and name. */ + while (rtagent) { + /* ast_log(LOG_WARNING, "DB: %s (update pre-loop)\n", rtagent->value); */ + + if (!strcasecmp(rtagent->name, "pass")) { + ast_copy_string(p->password, rtagent->value, sizeof(p->password)); + } else if (!strcasecmp(rtagent->name, "name")) { + ast_copy_string(p->name, rtagent->value, sizeof(p->name)); + } + + /* ast_log(LOG_WARNING, "DB: %s (update post-loop)\n", rtagent->value); */ + rtagent = rtagent->next; + } + ast_mutex_unlock(&p->lock); + } + break; + } + } + + if (!p) { + /* If no agent was found in agents.conf, try realtime */ + struct ast_variable *rtagent = ast_load_realtime("agents", "user", username, NULL); + /* struct ast_variable *rtagentptr; */ + + if (rtagent) { + /* Space for 3 ID strings + 2 commas */ + int maxcombo = AST_MAX_AGENT * 3 + 2; + + char user[AST_MAX_AGENT], pass[AST_MAX_AGENT], name[AST_MAX_AGENT]; + char user_pass_name[maxcombo]; + + AST_LIST_LOCK(&agents); + /* AST_LIST_TRAVERSE(&rtagent, rtagentptr, list) { */ + while (rtagent) { + if (!strcasecmp(rtagent->name, "user")) { + ast_copy_string(user, rtagent->value, sizeof(user)); + } else if (!strcasecmp(rtagent->name, "pass")) { + ast_copy_string(pass, rtagent->value, sizeof(pass)); + } else if (!strcasecmp(rtagent->name, "name")) { + ast_copy_string(name, rtagent->value, sizeof(name)); + } + + /* ast_log(LOG_WARNING, "DB: %s (read loop)\n", rtagent->value); */ + rtagent = rtagent->next; + } + + /* ast_log(LOG_WARNING, "USER: %s\n", username); */ + AST_LIST_UNLOCK(&agents); + + /* + * Build a string similar to the one that is found in the config file. + * This is needed because build_agent() expects it, but this shouldn't be + * considered more than a hack, build_agent()'s API should be fixed. + */ + snprintf(user_pass_name, maxcombo, "%s,%s,%s", user, pass, name); + + /* TODO: Grab pending-ness from the table. */ + p = add_agent(user_pass_name, 0); + p->realtime = 1; /* This is a realtime agent. */ + } + } + + AST_LIST_UNLOCK(&agents); + + if (!p) /* for debugging only */ + ast_log(LOG_WARNING, "AGENT NOT FOUND: %s\n", username); + + return p; /* Return the agent; if no agent found, should be NULL (?) */ +} + static int check_availability(struct agent_pvt *newlyavailable, int needlock) { struct ast_channel *chan=NULL, *parent=NULL; @@ -1437,7 +1540,10 @@ } else if (p->chan) { loginChan = ast_strdupa(p->chan->name); if (p->owner && p->owner->_bridge) { - talkingtoChan = p->chan->cid.cid_num; +/* Change talkingtoChan to be the name of the channel*/ +/* talkingtoChan = p->chan->cid.cid_num;*/ + talkingtoChan = (char *)ast_bridged_channel(p->chan)->name; + status = "AGENT_ONCALL"; } else { talkingtoChan = "n/a"; @@ -1848,12 +1954,21 @@ while (!res && (max_login_tries==0 || tries < max_login_tries)) { tries++; /* Check for password */ + + p = find_agent(user); + + if (p) { + ast_copy_string(xpass, p->password, sizeof(xpass)); + } + +/* FIXME: The following block is questionably irrelevant? Testing necessary. AST_LIST_LOCK(&agents); AST_LIST_TRAVERSE(&agents, p, list) { if (!strcmp(p->agent, user) && !p->pending) ast_copy_string(xpass, p->password, sizeof(xpass)); } AST_LIST_UNLOCK(&agents); +*/ if (!res) { if (!ast_strlen_zero(xpass)) res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); @@ -2419,12 +2534,8 @@ AST_LIST_LOCK(&agents); for (entry = db_tree; entry; entry = entry->next) { agent_num = entry->key + strlen(pa_family) + 2; - AST_LIST_TRAVERSE(&agents, cur_agent, list) { - ast_mutex_lock(&cur_agent->lock); - if (strcmp(agent_num, cur_agent->agent) == 0) - break; - ast_mutex_unlock(&cur_agent->lock); - } + cur_agent = find_agent(agent_num); + if (!cur_agent) { ast_db_del(pa_family, agent_num); continue; @@ -2501,18 +2612,6 @@ return res; } -static struct agent_pvt *find_agent(char *agentid) -{ - struct agent_pvt *cur; - - AST_LIST_TRAVERSE(&agents, cur, list) { - if (!strcmp(cur->agent, agentid)) - break; - } - - return cur; -} - static int function_agent(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { char *parse;