/** * Sends a message to the peer. * \note Must be called with a lock on the peer. * @param p - peer to send to * @param msg - message to send */ void Snd_Message(peer *p, AAAMessage *msg) { AAASession *session=0; int rcode; int send_message_before_session_sm=0; touch_peer(p); if (msg->sessionId) session = get_session(msg->sessionId->data); if (session){ switch (session->type){ case AUTH_CLIENT_STATEFULL: if (is_req(msg)) auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg); else { if (msg->commandCode == IMS_ASA){ if (!msg->res_code){ msg->res_code = AAAFindMatchingAVP(msg,0,AVP_Result_Code,0,0); } if (!msg->res_code) auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg); else { rcode = get_4bytes(msg->res_code->data.s); if (rcode>=2000 && rcode<3000) { peer_send_msg(p,msg); send_message_before_session_sm=1; auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_SUCCESS,msg); } else auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg); } }else auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg); } break; case AUTH_SERVER_STATEFULL: if (is_req(msg)) { if (msg->commandCode== IMS_ASR) { auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg); } else { //would be a RAR but ok! auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg); } } else { if (msg->commandCode == IMS_STR) auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg); else auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg); } break; default: break; } sessions_unlock(session->hash); } if (!send_message_before_session_sm) peer_send_msg(p,msg); }
void session_timer(time_t now, void* ptr) { int hash; cdp_session_t *x; AAASessionCallback_f *cb; LOG(L_DBG,"-------session timer --------\n"); for(hash=0;hash<sessions_hash_size;hash++){ sessions_lock(hash); for(x = sessions[hash].head;x;x=x->next) { LOG(L_DBG,"session of type [%i] with id %.*s in hash %u\n",x->type,x->id.len,x->id.s,hash); if (x->type==AUTH_CLIENT_STATEFULL) { LOG(L_DBG,"auth state [%i] timeout [%li]\n",x->u.auth.state,x->u.auth.timeout-now); } else LOG(L_INFO,"\n"); switch (x->type){ case AUTH_CLIENT_STATEFULL: if (x->u.auth.timeout!=0 && x->u.auth.timeout<=now){ //Session timeout LOG(L_CRIT,"session TIMEOUT\n"); if (x->cb) { cb = x->cb; (cb)(AUTH_EV_SESSION_TIMEOUT,x->cb_param,x); } auth_client_statefull_sm_process(x,AUTH_EV_SESSION_TIMEOUT,0); } if (x->u.auth.timeout!=0 && x->u.auth.lifetime+x->u.auth.grace_period<=now){ //lifetime + grace timeout LOG(L_CRIT,"grace TIMEOUT\n"); if (x->cb){ cb = x->cb; (cb)(AUTH_EV_SESSION_GRACE_TIMEOUT,x->cb_param,x); } auth_client_statefull_sm_process(x,AUTH_EV_SESSION_GRACE_TIMEOUT,0); } break; default: break; } } sessions_unlock(hash); } LOG(L_DBG,"-------------------------------\n"); }
/** * Adds the session to the session list. * \note If you use x after this then lock first!!! * @param x - the session to add */ void add_session(cdp_session_t *x) { // unsigned int hash; if (!x) return; // hash = get_str_hash(x->id,sessions_hash_size); // x->hash = hash; LOG(L_DBG,"adding a session with id %.*s\n",x->id.len,x->id.s); sessions_lock(x->hash); x->next = 0; x->prev = sessions[x->hash].tail; if (sessions[x->hash].tail) sessions[x->hash].tail->next = x; sessions[x->hash].tail = x; if (!sessions[x->hash].head) sessions[x->hash].head = x; sessions_unlock(x->hash); }
/** * Finds a session in the session hash table. * \note Returns with a lock on the sessions[x->hash].lock!!! * @param id - the id of the session * @returns the session if found or 0 if not */ cdp_session_t* get_session(str id) { unsigned int hash; cdp_session_t *x; hash = get_str_hash(id,sessions_hash_size); LOG(L_DBG,"calling get session with id %.*s and hash %u\n",id.len,id.s,hash); sessions_lock(hash); for(x = sessions[hash].head;x;x=x->next) { LOG(L_DBG,"looking for |%.*s| in |%.*s|\n",id.len,id.s,x->id.len,x->id.s); if (x->id.len == id.len && strncasecmp(x->id.s,id.s,id.len)==0) return x; } sessions_unlock(hash); return 0; }
/** * Processes an incoming message. * This actually just puts the message into a message queue. One worker will pick-it-up * and do the actual processing. * \note Must be called with a lock on the peer. * @param p - peer received from * @param msg - the message received */ void Rcv_Process(peer *p, AAAMessage *msg) { AAASession *session=0; unsigned int hash; // we need this here because after the sm_processing , we might end up // with no session any more if (msg->sessionId) session = get_session(msg->sessionId->data); if (session){ hash=session->hash; switch (session->type){ case AUTH_CLIENT_STATEFULL: if (is_req(msg)){ if (msg->commandCode==IMS_ASR) auth_client_statefull_sm_process(session,AUTH_EV_RECV_ASR,msg); else auth_client_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg); }else { if (msg->commandCode==IMS_STA) auth_client_statefull_sm_process(session,AUTH_EV_RECV_STA,msg); else auth_client_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg); } break; case AUTH_SERVER_STATEFULL: if (is_req(msg)) { auth_server_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg); }else{ if (msg->commandCode==IMS_ASA) auth_server_statefull_sm_process(session,AUTH_EV_RECV_ASA,msg); else auth_server_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg); } break; default: break; } sessions_unlock(hash); }else{ if (msg->sessionId){ if (msg->commandCode == IMS_ASR) auth_client_statefull_sm_process(0,AUTH_EV_RECV_ASR,msg); if (msg->commandCode == IMS_AAR) { session=AAACreateAuthSession(0,0,1,0,0); shm_str_dup(session->id,msg->sessionId->data); auth_server_statefull_sm_process(0,AUTH_EV_RECV_REQ,msg); } // Any other cases to think about? } } if (!put_task(p,msg)){ LOG(L_ERR,"ERROR:Rcv_Process(): Queue refused task\n"); AAAFreeMessage(&msg); } LOG(L_DBG,"DBG:Rcv_Process(): task added to queue\n"); // AAAPrintMessage(msg); }