示例#1
0
/**
 * 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);
	
}
示例#2
0
/**
 * Handler for incoming Diameter requests.
 * @param request - the received request
 * @param param - generic pointer
 * @returns the answer to this request
 */
AAAMessage* callback_cdp_request(AAAMessage *request, void *param) {
    if (is_req(request)) {

        switch (request->applicationId) {
            case IMS_Cx:
            //case IMS_Dx:  IMS_Cx is same as IMS_Dx 16777216
                switch (request->commandCode) {
                    case IMS_RTR:
                        LM_INFO("Cx/Dx request handler():- Received an IMS_RTR \n");
                        return cxdx_process_rtr(request);
                        break;
                    default:
                        LM_ERR("Cx/Dx request handler(): - Received unknown request for Cx/Dx command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId);
                        return 0;
                        break;
                }
                break;
            default:
                LM_ERR("Cx/Dx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
                return 0;
                break;
        }
    }
    return 0;
}
示例#3
0
/**
 * Handler for incoming Diameter requests.
 * @param request - the received request
 * @param param - generic pointer
 * @returns the answer to this request
 */
AAAMessage* callback_cdp_request(AAAMessage *request, void *param) {
    if (is_req(request)) {

        switch (request->applicationId) {
            case IMS_Rx:
            case IMS_Gq:
                switch (request->commandCode) {
                    case IMS_RAR:
                        LM_INFO("Rx request handler():- Received an IMS_RAR \n");
                        /* TODO: Add support for Re-Auth Requests */
                        return 0;
                        break;
                    case IMS_ASR:
                        LM_INFO("Rx request handler(): - Received an IMS_ASR \n");
                        return rx_process_asr(request);
                        break;
                    default:
                        LM_ERR("Rx request handler(): - Received unknown request for Rx/Gq command %d, flags %#1x endtoend %u hopbyhop %u\n", request->commandCode, request->flags, request->endtoendId, request->hopbyhopId);
                        return 0;
                        break;
                }
                break;
            default:
                LM_ERR("Rx request handler(): - Received unknown request for app %d command %d\n", request->applicationId, request->commandCode);
                return 0;
                break;
        }
    }
    return 0;
}
示例#4
0
/**
 * Handler for incoming Diameter requests.
 * @param request - the received request
 * @param param - generic pointer
 * @returns the answer to this request
 * but we wont/should not recieve any request here
 */
AAAMessage* RfRequestHandler(AAAMessage *request,void *param)
{
	if (is_req(request)){		
		LOG(L_INFO,"INFO: RfRequestHandler(): We have received a request!!!\n");
		#ifdef WITH_IMS_PM
			ims_pm_diameter_request(request);
		#endif		
		switch(request->applicationId){
        	case IMS_Rf:
				switch(request->commandCode){				
					
					default :
						LOG(L_ERR,"ERR: RfRequestHandler(): - Received unknown request for Rf command %d\n",request->commandCode);
						break;	
				}
				break;
			default:
				LOG(L_ERR,"ERR: RfRequestHandler(): - Received unknown request for app %d command %d\n",
					request->applicationId,
					request->commandCode);
				break;				
		}					
	}
	return 0;		
}
示例#5
0
	/**
	 * This is an executor for tasks from shm. Should do the same as what is the middle of the worker_process() loop,
	 * but this should be used when the messages will be processed by an external to cdp worker-pool.
	 * @param ptr - the tast_t* into shm
	 */
	int worker_execute(void* ptr)
	{
		task_t *t=ptr;
		int r;
		cdp_cb_t *cb;
	
		if (!t) return -1;
		if (!t->msg) goto error;
		if (shutdownx&&(*shutdownx)) goto error;
		LOG(L_DBG,"Executing task for cdp: Message [%d] from Peer [%.*s]\n",
				t->msg->commandCode,t->p?t->p->fqdn.len:0,t->p?t->p->fqdn.s:0);
		r = is_req(t->msg);
		for(cb = callbacks->head;cb;cb = cb->next)
			(*(cb->cb))(t->p,t->msg,*(cb->ptr));
			
		if (r){
			AAAFreeMessage(&(t->msg));
		}else{
			/* will be freed by the user in upper api */
			/*AAAFreeMessage(&(t.msg));*/
		}
		shm_free(t);
		return -1;
	error:
		if (t->msg) AAAFreeMessage(&(t->msg));
		shm_free(t);
		return -1;
	}
示例#6
0
/**
 * Handler for incoming Diameter requests.
 * @param request - the received request
 * @param param - generic pointer
 * @returns the answer to this request
 */
AAAMessage* CxRequestHandler(AAAMessage *request,void *param)
{
	if (is_req(request)){		
		LOG(L_INFO,"INFO:"M_NAME":CxRequestHandler(): We have received a request\n");
		#ifdef WITH_IMS_PM
			ims_pm_diameter_request(request);
		#endif		
		switch(request->applicationId){
        	case IMS_Cx:
				switch(request->commandCode){				
					case IMS_RTR:
						LOG(L_INFO,"INFO:"M_NAME":CxRequestHandler():- Received an IMS_RTR \n");
						return Cx_RTA(request);
						break;
					case IMS_PPR:
						LOG(L_INFO,"INFO:"M_NAME":CxRequestHandler(): - Received an IMS_PPR \n");
						return Cx_PPA(request);
						break;
					default :
						LOG(L_ERR,"ERR:"M_NAME":CxRequestHandler(): - Received unknown request for Cx command %d\n",request->commandCode);
						break;	
				}
				break;
			default:
				LOG(L_ERR,"ERR:"M_NAME":CxRequestHandler(): - Received unknown request for app %d command %d\n",
					request->applicationId,
					request->commandCode);
				break;				
		}					
	}
	return 0;		
}
示例#7
0
/**
 * Send a AAAMessage asynchronously.
 * When the response is received, the callback_f(callback_param,...) is called.
 * @param message - the request to be sent
 * @param peer_id - FQDN of the peer to send
 * @param callback_f - callback to be called on transactional response or transaction timeout
 * @param callback_param - generic parameter to call the transactional callback function with
 * @returns 1 on success, 0 on failure 
 * \todo remove peer_id and add Realm routing
 */
AAAReturnCode AAASendMessageToPeer(	
		AAAMessage *message,
		str *peer_id, 
		AAATransactionCallback_f *callback_f,
		void *callback_param)
{
	peer *p;
	p = get_peer_by_fqdn(peer_id);
	if (!p) {
		LOG(L_ERR,"ERROR:AAASendMessageToPeer(): Peer unknown %.*s\n",peer_id->len,peer_id->s);
		goto error;
	}
	if (p->state!=I_Open && p->state!=R_Open){
		LOG(L_ERR,"ERROR:AAASendMessageToPeer(): Peer not connected to %.*s\n",peer_id->len,peer_id->s);
		goto error;
	}
	/* only add transaction following when required */
	if (callback_f){
		if (is_req(message))
			cdp_add_trans(message,callback_f,callback_param,config->transaction_timeout,1);
		else
			LOG(L_ERR,"ERROR:AAASendMessageToPeer(): can't add transaction callback for answer.\n");
	}
		
//	if (!peer_send_msg(p,message))
	if (!sm_process(p,Send_Message,message,0,0))	
		goto error;
		
	return 1;
error:	
	AAAFreeMessage(&message);
	return 0;
}
/** 
 * Authorization Client State-Machine - Stateless
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param s
 * @param event
 * @param msg
 */
inline void auth_client_stateless_sm_process(cdp_session_t* s, int event, AAAMessage *msg)
{
	cdp_auth_session_t *x;
	int rc;
	if (!s) return;
	x = &(s->u.auth);
	switch(x->state){
		case AUTH_ST_IDLE:
			switch(event){
				case AUTH_EV_SEND_REQ:
					x->state = AUTH_ST_PENDING;
					break;
				default:
					LOG(L_ERR,"ERR:auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
						event,auth_states[x->state]);				
			}
			break;
			
		case AUTH_ST_PENDING:
			if (!is_req(msg)){
				rc = get_result_code(msg);
				if (rc>=2000 && rc<3000 && get_auth_session_state(msg)==NO_STATE_MAINTAINED) 
					event = AUTH_EV_RECV_ANS_SUCCESS;
				else
					event = AUTH_EV_RECV_ANS_UNSUCCESS;
			}
			switch(event){
				case AUTH_EV_RECV_ANS_SUCCESS:
					x->state = AUTH_ST_OPEN;
					break;
				case AUTH_EV_RECV_ANS_UNSUCCESS:
					x->state = AUTH_ST_IDLE;
					break;					
				default:
					LOG(L_ERR,"ERR:auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
						event,auth_states[x->state]);				
			}
			break;
			
		case AUTH_ST_OPEN:
			switch(event){
				case AUTH_EV_SESSION_TIMEOUT:
					x->state = AUTH_ST_IDLE;
					break;
				case AUTH_EV_SERVICE_TERMINATED:
					x->state = AUTH_ST_IDLE;
					break;					
				default:
					LOG(L_ERR,"ERR:auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
						event,auth_states[x->state]);				
			}
			break;
			
		default:
			LOG(L_ERR,"ERR:auth_client_stateless_sm_process(): Received event %d while in invalid state %d!\n",
				event,x->state);
	}	
	if (s) AAASessionsUnlock(s->hash);
}
示例#9
0
/* Sets the proper result_code into the Result-Code AVP; thus avp must already
 * exists into the reply message */
AAAReturnCode  AAASetMessageResultCode(
				       AAAMessage *message,
				       AAAResultCode resultCode)
{
  if ( !is_req(message) && message->res_code) {
    *((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
    return AAA_ERR_SUCCESS;
  }
  return AAA_ERR_FAILURE;
}
示例#10
0
/**
 * Send a AAAMessage synchronously.
 * This blocks until a response is received or a transactional time-out happens. 
 * @param message - the request to be sent
 * @param peer_id - FQDN of the peer to send
 * @returns 1 on success, 0 on failure 
 * \todo remove peer_id and add Realm routing
 * \todo replace the busy-waiting lock in here with one that does not consume CPU
 */
AAAMessage* AAASendRecvMessageToPeer(AAAMessage *message, str *peer_id)
{
	peer *p;
	gen_sem_t *sem;
	cdp_trans_t *t;
	AAAMessage *ans;
	
	p = get_peer_by_fqdn(peer_id);
	if (!p) {
		LOG(L_ERR,"ERROR:AAASendRecvMessageToPeer(): Peer unknown %.*s\n",peer_id->len,peer_id->s);
		goto error;
	}
	if (p->state!=I_Open && p->state!=R_Open){
		LOG(L_ERR,"ERROR:AAASendRecvMessageToPeer(): Peer not connected to %.*s\n",peer_id->len,peer_id->s);
		goto error;
	}
	
	
	if (is_req(message)){
		sem_new(sem,0);
		t = cdp_add_trans(message,sendrecv_cb,(void*)sem,config->transaction_timeout,0);

//		if (!peer_send_msg(p,message)) {
		if (!sm_process(p,Send_Message,message,0,0)){	
			sem_free(sem);				
			goto error;
		}

		/* block until callback is executed */
		while(sem_get(sem)<0){
			if (shutdownx&&(*shutdownx)) goto error;
			LOG(L_WARN,"WARN:AAASendRecvMessageToPeer(): interrupted by signal or something > %s\n",strerror(errno));
		}
		sem_free(sem);		
		ans = t->ans;
		cdp_free_trans(t);
		return ans;
	} else {
		LOG(L_ERR,"ERROR:AAASendRecvMessageToPeer(): can't add wait for answer to answer.\n");
		goto error;
	}

		
error:	
out_of_memory:
	AAAFreeMessage(&message);
	return 0;
}
示例#11
0
/**
 * This is the main worker process.
 * Takes tasks from the queue in a loop and processes them by calling the registered callbacks.
 * @param id - id of the worker
 * @returns never, exits on shutdown.
 */
void worker_process(int id) {
    task_t t;
    cdp_cb_t *cb;
    int r;
    LM_INFO("[%d] Worker process started...\n", id);
    /* init the application level for this child */
    while (1) {
        if (shutdownx && (*shutdownx)) break;
	cfg_update();
        t = take_task();
        if (!t.msg) {
            if (shutdownx && (*shutdownx)) break;
            LM_INFO("[%d] got empty task Q(%d/%d)\n", id, tasks->start, tasks->end);
            continue;
        }
        LM_DBG("worker_process(): [%d] got task Q(%d/%d)\n", id, tasks->start, tasks->end);
        r = is_req(t.msg);
        for (cb = callbacks->head; cb; cb = cb->next)
            (*(cb->cb))(t.p, t.msg, *(cb->ptr));

        if (r) {
            AAAFreeMessage(&(t.msg));
        } else {
            /* will be freed by the user in upper api */
            /*AAAFreeMessage(&(t.msg));*/
        }
    }
    worker_poison_queue();
    LM_INFO("[%d]... Worker process finished\n", id);
#ifdef CDP_FOR_SER
#else
#ifdef PKG_MALLOC
    LM_DBG("Worker[%d] Memory status (pkg):\n", id);
    //pkg_status();
#ifdef pkg_sums
    pkg_sums();
#endif
#endif
    dp_del_pid(getpid());
#endif
    exit(0);
}
示例#12
0
文件: e2.c 项目: asyn/openvims
/**
 * Handler for incoming Diameter requests.
 * @param request - the received request
 * @param param - generic pointer
 * @returns the answer to this request
 */
AAAMessage* e2RequestHandler(AAAMessage *request,void *param)
{
	if (is_req(request)){		
		LOG(L_INFO,"INFO:"M_NAME":e2RequestHandler(): We have received a request\n");
		switch(request->applicationId){
        	case IMS_e2:
				switch(request->commandCode){				
					default :
						LOG(L_ERR,"ERR:"M_NAME":e2RequestHandler(): - Received unknown request for e2 command %d\n",request->commandCode);
						break;	
				}
				break;
			default:
				LOG(L_ERR,"ERR:"M_NAME":e2RequestHandler(): - Received unknown request for app %d command %d\n",
					request->applicationId,
					request->commandCode);
				break;				
		}					
	}
	return 0;		
}
示例#13
0
void ServerConnection::receive() {
  int res = tcp_recv_msg(conn.dia_conn, &conn.rb,
			 0, CONN_WAIT_USECS);


  if (res < 0) {
    if (res == AAA_CONN_SHUTDOWN) {
      INFO( M_NAME "receive(): shutdown - closing connection.\n");
      closeConnection(true);
    } else {
      closeConnection();
      ERROR( M_NAME "receive(): tcp_recv_reply() failed.\n");
    }
    return;
  }

  if (!res) // nothing received
    return;

  /* obtain the structure corresponding to the message */
  AAAMessage* msg = AAATranslateMessage(conn.rb.buf, conn.rb.buf_len, 0);	
  if(!msg) {
    ERROR( M_NAME "receive(): message structure not obtained from message.\n");	
    closeConnection();
    return;
  }
    
#ifdef EXTRA_DEBUG 
  AAAPrintMessage(msg);
#endif
  
  if (is_req(msg)) 
    handleRequest(msg);
  else 
    handleReply(msg);
  
  AAAFreeMessage(&msg);  
}
示例#14
0
文件: receiver.c 项目: 2pac/kamailio
/**
 * Receives a message and does basic processing or call the sm_process().
 * This gets called from the do_receive() for every message that is received.
 * Basic processing, before the state machine, is done here.
 * @param msg - the message received
 * @param sp - the serviced peer that it was receiver on
 */
void receive_message(AAAMessage *msg,serviced_peer_t *sp)
{
	AAA_AVP *avp1,*avp2;
	LM_DBG("receive_message(): [%.*s] Recv msg %d\n",
			sp->p?sp->p->fqdn.len:0,
			sp->p?sp->p->fqdn.s:0,
			msg->commandCode);

	if (!sp->p){
		switch (msg->commandCode){
			case Code_CE:
				if (is_req(msg)){
					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
					if (avp1&&avp2){
						sp->p = get_peer_from_fqdn(avp1->data,avp2->data);
					}
					if (!sp->p) {
						LM_ERR("receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
							config->accept_unknown_peers);
						AAAFreeMessage(&msg);
					}else{
						LM_DBG("receive_message(): [%.*s] This receiver has no peer associated\n",
								sp->p?sp->p->fqdn.len:0,
								sp->p?sp->p->fqdn.s:0	);
						//set_peer_pipe();
						make_send_pipe(sp);
						sm_process(sp->p,R_Conn_CER,msg,0,sp->tcp_socket);
					}
				}
				else{
					LM_ERR("receive_msg(): Received CEA from an unknown peer -ignored\n");
					AAAFreeMessage(&msg);
				}
				break;
			default:
				LM_ERR("receive_msg(): Received non-CE from an unknown peer -ignored\n");
				AAAFreeMessage(&msg);
		}
	}else{
		touch_peer(sp->p);
		switch (sp->p->state){
			case Wait_I_CEA:
				if (msg->commandCode!=Code_CE||is_req(msg)){
					sm_process(sp->p,I_Rcv_Non_CEA,msg,0,sp->tcp_socket);
				}else
					sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
				break;
			case I_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_CER,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DWR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,I_Rcv_DPR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,I_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,I_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			case R_Open:
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_CER,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_CEA,msg,0,sp->tcp_socket);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DWR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_DWA,msg,0,sp->tcp_socket);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(sp->p,R_Rcv_DPR,msg,0,sp->tcp_socket);
									else sm_process(sp->p,R_Rcv_DPA,msg,0,sp->tcp_socket);
						break;
					default:
						sm_process(sp->p,R_Rcv_Message,msg,0,sp->tcp_socket);
				}
				break;
			default:
				LM_ERR("receive_msg(): [%.*s] Received msg while peer in state %d -ignored\n",
						sp->p->fqdn.len,
						sp->p->fqdn.s,
						sp->p->state);
				AAAFreeMessage(&msg);
		}
	}
}
示例#15
0
文件: receiver.c 项目: asyn/openvims
/**
 * Receives a mesasge and does basic processing or call the sm_process().
 * This gets called from the receive_loop for every message that is received.
 * @param msg - the message received
 * @param sock - socket received on
 */
void receive_message(AAAMessage *msg,int sock)
{
	AAA_AVP *avp1,*avp2;
	LOG(L_DBG,"DBG:receive_message(): [%d] Recv msg %d\n",sock,msg->commandCode);

	if (!this_peer) {
		this_peer = get_peer_from_sock(sock);
		set_peer_pipe();
	}
	
	if (!this_peer){
		switch (msg->commandCode){
			case Code_CE:
				if (is_req(msg)){
					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
					if (avp1&&avp2){
						this_peer = get_peer_from_fqdn(avp1->data,avp2->data);
					}
					if (!this_peer) {
						LOG(L_ERR,"ERROR:receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
							config->accept_unknown_peers);
						AAAFreeMessage(&msg);
					}else{
						set_peer_pipe();						
						sm_process(this_peer,R_Conn_CER,msg,0,sock);
					}
				}
				else{
					LOG(L_ERR,"ERROR:receive_msg(): Received CEA from an unknown peer -ignored\n");
					AAAFreeMessage(&msg);
				}
				break;
			default:
				LOG(L_ERR,"ERROR:receive_msg(): Received non-CE from an unknown peer -ignored\n");
				AAAFreeMessage(&msg);				
		}
	}else{
		touch_peer(this_peer);
		switch (this_peer->state){
			case Wait_I_CEA:
				if (msg->commandCode!=Code_CE||is_req(msg)){
					sm_process(this_peer,I_Rcv_Non_CEA,msg,0,sock);
				}else
					sm_process(this_peer,I_Rcv_CEA,msg,0,sock);
				break;
			case I_Open:			
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_CER,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_CEA,msg,0,sock);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_DWR,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_DWA,msg,0,sock);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(this_peer,I_Rcv_DPR,msg,0,sock);	
									else sm_process(this_peer,I_Rcv_DPA,msg,0,sock);
						break;
					default:
						sm_process(this_peer,I_Rcv_Message,msg,0,sock);
				}				
				break;				
			case R_Open:			
				switch (msg->commandCode){
					case Code_CE:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_CER,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_CEA,msg,0,sock);
						break;
					case Code_DW:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_DWR,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_DWA,msg,0,sock);
						break;
					case Code_DP:
						if (is_req(msg)) sm_process(this_peer,R_Rcv_DPR,msg,0,sock);	
									else sm_process(this_peer,R_Rcv_DPA,msg,0,sock);
						break;
					default:
						sm_process(this_peer,R_Rcv_Message,msg,0,sock);
				}				
				break;				
			default:
				LOG(L_ERR,"ERROR:receive_msg(): Received msg while peer in state %d -ignored\n",this_peer->state);
				AAAFreeMessage(&msg);								
		}
	}
}
示例#16
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);
	
}
示例#17
0
/**
 * stateful client state machine
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param cc_acc - AAACCAccSession which uses this state machine
 * @param ev   - Event
 * @param msg  - AAAMessage
 * @returns 0 if msg should be given to the upper layer 1 if not
 */
inline int cc_acc_client_stateful_sm_process(cdp_session_t* s, int event, AAAMessage* msg)
{
	cdp_cc_acc_session_t* x;
	int ret = 0;
	int rc;		//return code for responses
	int record_type;

	x = &(s->u.cc_acc);
	LM_DBG("cc_acc_client_stateful_sm_process: processing CC App in state [%d] and event [%d]\n", x->state, event);

	//first run session callbacks
	if (s->cb) (s->cb)(event, s);
	LM_DBG("finished callback of event %i\n", event);

	switch (x->state) {
		case ACC_CC_ST_IDLE:
			switch (event) {
				case ACC_CC_EV_SEND_REQ:		//were sending a message - CCR
					//assert this is an initial request. we can't move from IDLE with anything else
					record_type = get_accounting_record_type(msg);
					switch (record_type) {
						case 2 /*START RECORD*/:
							LM_DBG("sending CCR START record on session\n");
							s->application_id = msg->applicationId;
							s->u.cc_acc.state = ACC_CC_ST_PENDING_I;
							//update our reservation and its timers... if they exist in CCR
							update_gsu_request_timers(x, msg);
							break;
						default:
							LM_ERR("Sending CCR with no/incorrect accounting record type AVP. In state IDLE\n");
							break;
					}
					break;

				default:
					LM_ERR("Recevied unknown event [%d] in state [%d]\n", event, x->state);
					break;
			}
			break;
		case ACC_CC_ST_OPEN:
			switch (event) {
				case ACC_CC_EV_SEND_REQ:		//were sending a message - CCR
					//make sure it is either an update or a termination.
					record_type = get_accounting_record_type(msg);
					switch (record_type) {
						case 3 /*UPDATE RECORD*/:
							LM_DBG("sending CCR UPDATE record on session\n");
							s->u.cc_acc.state = ACC_CC_ST_PENDING_U;
							//update our reservation and its timers...
							update_gsu_request_timers(x, msg);
							break;
						case 4: /*TERMINATE RECORD*/
							LM_DBG("sending CCR TERMINATE record on session\n");
							s->u.cc_acc.state = ACC_CC_ST_PENDING_T;
							//update our reservation and its timers...
							update_gsu_request_timers(x, msg);
							break;
						default:
							LM_ERR("asked to send CCR with no/incorrect accounting record type AVP. In state IDLE\n");
							break;
					}
					break;
				case ACC_CC_EV_RSVN_WARNING:
					//nothing we can do here, we have sent callback, client needs to send CCR Update
					LM_DBG("Reservation close to expiring\n");
					break;
				default:
					LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state);
					break;
			}
			break;
		case ACC_CC_ST_PENDING_I:
			if (event == ACC_CC_EV_RECV_ANS && msg && !is_req(msg)) {
				rc = get_result_code(msg);
				if (rc >= 2000 && rc < 3000) {
					event = ACC_CC_EV_RECV_ANS_SUCCESS;
				} else {
					event = ACC_CC_EV_RECV_ANS_UNSUCCESS;
				}
			}
			switch (event) {
				case ACC_CC_EV_RECV_ANS_SUCCESS:
					x->state = ACC_CC_ST_OPEN;
					LM_DBG("received success response for CCR START\n");
					update_gsu_response_timers(x, msg);
					break;
				case ACC_CC_EV_RECV_ANS_UNSUCCESS:
					//TODO: grant/terminate service callbacks to callback clients
					LM_ERR("failed answer on CCR START\n");
					x->state = ACC_CC_ST_DISCON;
					break;
				default:
					LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state);
					break;
			}
			break;
		case ACC_CC_ST_PENDING_T:
			if (event == ACC_CC_EV_RECV_ANS && msg && !is_req(msg)) {
				rc = get_result_code(msg);
				if (rc >= 2000 && rc < 3000) {
					event = ACC_CC_EV_RECV_ANS_SUCCESS;
				} else {
					event = ACC_CC_EV_RECV_ANS_UNSUCCESS;
				}
			}
			switch (event) {
				case ACC_CC_EV_RECV_ANS_SUCCESS:
					x->state = ACC_CC_ST_DISCON;
//					update_gsu_response_timers(x, msg);
				case ACC_CC_EV_RECV_ANS_UNSUCCESS:
					x->state = ACC_CC_ST_DISCON;
				default:
					LM_DBG("Received event [%d] in state [%d] - cleaning up session regardless\n", event, x->state);
					//have to leave session alone because our client app still has to be given this msg
					x->discon_time = time(0);
//					if (msg) AAAFreeMessage(&msg);
//					cdp_session_cleanup(s, NULL);
//					s = 0;
			}
			break;
		case ACC_CC_ST_PENDING_U:
			if (event == ACC_CC_EV_RECV_ANS && msg && !is_req(msg)) {
				rc = get_result_code(msg);
				if (rc >= 2000 && rc < 3000) {
					event = ACC_CC_EV_RECV_ANS_SUCCESS;
				} else {
					event = ACC_CC_EV_RECV_ANS_UNSUCCESS;
				}
			}
			switch (event) {
				case ACC_CC_EV_RECV_ANS_SUCCESS:
					x->state = ACC_CC_ST_OPEN;
					LM_DBG("success CCA for UPDATE\n");
					update_gsu_response_timers(x, msg);
					break;
				case ACC_CC_EV_RECV_ANS_UNSUCCESS:
					//TODO: check whether we grant or terminate service to callback clients
					x->state = ACC_CC_ST_DISCON;
					LM_ERR("update failed... going back to IDLE/DISCON\n");
					break;
				default:
					LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state);
				break;
			}
			break;
		case ACC_CC_ST_DISCON:
			switch (event) {
				case ACC_CC_EV_SESSION_STALE:
					LM_DBG("stale session about to be cleared\n");
					cdp_session_cleanup(s, msg);
					s = 0;
					break;
				default:
					LM_ERR("Received unknown event [%d] in state [%d]\n", event, x->state);
					break;
			}
			break;
	}

	if (s) {
		AAASessionsUnlock(s->hash);
	}

	return ret;
}
示例#18
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;
	int nput=0;
	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);

	if (session){
		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);
					session = 0;
				}else {
					if (msg->commandCode==IMS_STA)
						nput=auth_client_statefull_sm_process(session,AUTH_EV_RECV_STA,msg);
					else
						auth_client_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg);
					session = 0;
				}
				break;
			 case AUTH_SERVER_STATEFULL:
			 	if (is_req(msg))
			 	{
			 		if (msg->commandCode==IMS_STR)
			 		{
			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_STR,msg);
			 		} else {
			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg);
			 		}
					session = 0;			 		
			 	}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);
					session = 0;			 		
			 	}
			 	break;
			default:
				AAASessionsUnlock(session->hash);
				session =0;
				break;			 
		}
	}else{
		if (msg->sessionId){
			if (msg->commandCode == IMS_ASR) 
				auth_client_statefull_sm_process(0,AUTH_EV_RECV_ASR,msg);
		} 
				 
	}
	if (!nput && !put_task(p,msg)){
		LM_ERR("Rcv_Process(): Queue refused task\n");
		if (msg) AAAFreeMessage(&msg); 
	}
	//if (msg) LM_ERR("Rcv_Process(): task added to queue command %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId);
	
//	AAAPrintMessage(msg);
	
}
示例#19
0
/**
 * stateful client state machine
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param auth - AAAAuthSession which uses this state machine
 * @param ev   - Event
 * @param msg  - AAAMessage
 * @returns 0 if msg should be given to the upper layer 1 if not
 */
inline int auth_client_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg) {

    cdp_auth_session_t *x;
    int rc;
    int rv = 0; //return value

    if (!s) {
        switch (event) {
            case AUTH_EV_RECV_ASR:
                Send_ASA(0, msg);
                break;
            default:
                LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d with no session!\n",
                        event);
        }
        return rv;
    }
    x = &(s->u.auth);

    if (s->cb) (s->cb)(event, s);
    LM_INFO("after callback of event %i\n", event);

    //if (x && x->state && msg) LM_ERR("auth_client_statefull_sm_process [event %i] [state %i] endtoend %u hopbyhop %u\n",event,x->state,msg->endtoendId,msg->hopbyhopId);

    switch (x->state) {
        case AUTH_ST_IDLE:
            switch (event) {
                case AUTH_EV_SEND_REQ:
                    s->application_id = msg->applicationId;
                    s->u.auth.state = AUTH_ST_PENDING;
                    update_auth_session_timers(x, msg);
                    add_auth_session_timers(x, msg);

                    //Richard add this add: add destination realm to cdp session
                    //use msg origin realm as the destination realm
                    //we do this here as this is were the state changes to open
                    //Where must we free this?
                    s->dest_realm.s = (char*) shm_malloc(msg->dest_realm->data.len);
                    memcpy(s->dest_realm.s, msg->dest_realm->data.s, msg->dest_realm->data.len);
                    s->dest_realm.len = msg->dest_realm->data.len;


                    //LM_INFO("state machine: i was in idle and i am going to pending\n");
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!(data %p)\n",
                            event, auth_states[x->state], x->generic_data);
            }
            break;

        case AUTH_ST_PENDING:
            if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)) {
                rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000 && get_auth_session_state(msg) == STATE_MAINTAINED)
                    event = AUTH_EV_RECV_ANS_SUCCESS;
                else
                    event = AUTH_EV_RECV_ANS_UNSUCCESS;
            }

            switch (event) {
                case AUTH_EV_RECV_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in pending and i am going to open\n");
                    break;
                case AUTH_EV_RECV_ANS_UNSUCCESS:
                    LM_DBG("In state AUTH_ST_PENDING and received AUTH_EV_RECV_ANS_UNSUCCESS - nothing to do but clean up session\n");
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SERVICE_TERMINATED:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    cdp_session_cleanup(s, NULL);
                    s = 0;
                    break;

                default:
                    LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_OPEN:
            if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)) {
                rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000 && get_auth_session_state(msg) == STATE_MAINTAINED)
                    event = AUTH_EV_RECV_ANS_SUCCESS;
                else
                    event = AUTH_EV_RECV_ANS_UNSUCCESS;
            }

            switch (event) {
                case AUTH_EV_SEND_REQ:
                    // if the request is STR i should move to Discon ..
                    // this is not in the state machine but I (Alberto Diez) need it
                    if (msg->commandCode == IMS_STR)
                        s->u.auth.state = AUTH_ST_DISCON;
                    else {
                        s->u.auth.state = AUTH_ST_OPEN;
                        add_auth_session_timers(x, msg);
                    }
                    break;

                case AUTH_EV_RECV_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in open and i am going to open\n");
                    break;

                case AUTH_EV_RECV_ANS_UNSUCCESS:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");
                    break;

                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SERVICE_TERMINATED:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");

                    Send_STR(s, msg);
                    break;

                case AUTH_EV_SEND_ASA_SUCCESS:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in open and i am going to discon\n");
                    Send_STR(s, msg);
                    break;

                case AUTH_EV_SEND_ASA_UNSUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    //LM_INFO("state machine: i was in open and i am going to open\n");
                    break;

                case AUTH_EV_RECV_ASR:
                    // two cases , client will comply or will not
                    // our client is very nice and always complys.. because
                    // our brain is in the PCRF... if he says to do this , we do it
                    // Alberto Diez , (again this is not Diameter RFC)
                    x->state = AUTH_ST_DISCON;
                    Send_ASA(s, msg);
                    Send_STR(s, msg);
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_DISCON:
            switch (event) {
                case AUTH_EV_RECV_ASR:
                    x->state = AUTH_ST_DISCON;
                    //LM_INFO("state machine: i was in discon and i am going to discon\n");
                    Send_ASA(s, msg);
                    break;

                    // Just added this because it might happen if the other peer doesnt
                    // send a valid STA, then the session stays open forever...
                    // We dont accept that... we have lifetime+grace_period for that
                    // This is not in the Diameter RFC ...
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    // thats the addition
                case AUTH_EV_RECV_STA:
                    x->state = AUTH_ST_IDLE;
                    LM_INFO("state machine: AUTH_EV_RECV_STA about to clean up\n");
                    if (msg) AAAFreeMessage(&msg); // if might be needed in frequency
                    // If I register a ResponseHandler then i Free the STA there not here..
                    // but i dont have interest in that now..
                    cdp_session_cleanup(s, NULL);
                    s = 0;
                    rv = 1;
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;
        default:
            LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
                    event, x->state);
    }
    if (s) {
        if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
        AAASessionsUnlock(s->hash);
    }
    return rv;
}
示例#20
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;
	int nput=0;
	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);

	if (session){
		switch (session->type){
			case ACCT_CC_CLIENT:
				if (is_req(msg)){
					LM_WARN("unhandled receive request on Credit Control Acct session\n");
					AAASessionsUnlock(session->hash);	//must be called because we dont call state machine here
					session = 0; //we dont call SM here so we mustnt set to 0
				} else {
					cc_acc_client_stateful_sm_process(session, ACC_CC_EV_RECV_ANS, msg);
					session = 0;
				}
				break;
			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);
					session = 0;
				}else {
					if (msg->commandCode==IMS_STA)
						nput=auth_client_statefull_sm_process(session,AUTH_EV_RECV_STA,msg);
					else
						auth_client_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg);
					session = 0;
				}
				break;
			case AUTH_SERVER_STATEFULL:
				if (is_req(msg))
				{
					if (msg->commandCode==IMS_STR)
					{
						auth_server_statefull_sm_process(session,AUTH_EV_RECV_STR,msg);
					} else {
						auth_server_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg);
					}
					session = 0;
				}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);
					session = 0;
				}
				break;
			default:
				AAASessionsUnlock(session->hash);
				session =0;
				break;
		}
	}else{
		if (msg->sessionId){
			if (msg->commandCode == IMS_ASR)
				auth_client_statefull_sm_process(0,AUTH_EV_RECV_ASR,msg);
		}

	}
	if (!nput && !put_task(p,msg)){
		LM_ERR("Rcv_Process(): Queue refused task\n");
		if (msg) AAAFreeMessage(&msg);
	}
	//if (msg) LM_ERR("Rcv_Process(): task added to queue command %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId);

	//	AAAPrintMessage(msg);

}
示例#21
0
/**
 * Authorization Server State-Machine - Statefull
 * \Note - should be called with a lock on the session and will unlock it - do not use it after!
 * @param s
 * @param event
 * @param msg
 */
inline void auth_server_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg) {
    cdp_auth_session_t *x;

    if (!s) return;
    x = &(s->u.auth);

    if (s->cb) (s->cb)(event, s);
    LM_DBG("after callback for event %i\n", event);

    switch (x->state) {
        case AUTH_ST_IDLE:
            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_RECV_REQ:
                    // The RequestHandler will generate a Send event for the answer
                    // and we will only then now if the user is authorised or not
                    // if its not authorised it will move back to idle and cleanup the session
                    // so no big deal
                    // but this is not the Diameter RFC...
                    x->state = AUTH_ST_OPEN;
                    // execute the cb here because we won't have a chance later
                    if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
                    // Don't unlock the session hash table because the session is returned to the user
                    // This can only be called from the AAACreateServerAuthSession()!
                    s = 0;
                    break;
                case AUTH_EV_SEND_STA:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;

                    /* Just in case we have some lost sessions */
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;

                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_OPEN:


            if (event == AUTH_EV_SEND_ANS && msg && !is_req(msg)) {
                int rc = get_result_code(msg);
                if (rc >= 2000 && rc < 3000)
                    event = AUTH_EV_SEND_ANS_SUCCESS;
                else
                    event = AUTH_EV_SEND_ANS_UNSUCCESS;
            }


            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_SEND_ANS_SUCCESS:
                    x->state = AUTH_ST_OPEN;
                    update_auth_session_timers(x, msg);
                    add_auth_session_timers(x, msg);
                    break;
                case AUTH_EV_SEND_ANS_UNSUCCESS:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                case AUTH_EV_SEND_ASR:
                    x->state = AUTH_ST_DISCON;
                    break;
                case AUTH_EV_SESSION_TIMEOUT:
                case AUTH_EV_SESSION_GRACE_TIMEOUT:
                    x->state = AUTH_ST_IDLE;
                    LM_DBG("before session cleanup\n");
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                case AUTH_EV_SEND_STA:
                    LM_ERR("SENDING STA!!!\n");
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        case AUTH_ST_DISCON:
            switch (event) {
                case AUTH_EV_RECV_STR:
                    break;
                case AUTH_EV_RECV_ASA:
                case AUTH_EV_RECV_ASA_SUCCESS:
                    x->state = AUTH_ST_IDLE;
                    //cdp_session_cleanup(s,msg);
                    break;
                case AUTH_EV_RECV_ASA_UNSUCCESS:
                    Send_ASR(s, msg);
                    // how many times will this be done?
                    x->state = AUTH_ST_DISCON;
                    break;
                case AUTH_EV_SEND_STA:
                    x->state = AUTH_ST_IDLE;
                    cdp_session_cleanup(s, msg);
                    s = 0;
                    break;
                default:
                    LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
                            event, auth_states[x->state]);
            }
            break;

        default:
            LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
                    event, x->state);
    }
    if (s) {
        if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED, s);
        AAASessionsUnlock(s->hash);
    }
}
示例#22
0
/**
 * 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;
	LM_DBG("Snd_Message called to peer [%.*s] for %s with code %d \n",
		p->fqdn.len,p->fqdn.s,is_req(msg)?"request":"response",msg->commandCode);
	touch_peer(p);
	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);
	
	if (session){
		LM_DBG("There is a session of type %d\n",session->type);
		switch (session->type){
			case AUTH_CLIENT_STATEFULL:
				if (is_req(msg)) {
					auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
					session = 0;
				}
				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);
							session = 0;
						}
						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);
								session = 0;
							}
							else {
								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
								session = 0;
							}
						}
						
					}else {
						auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;
			case AUTH_SERVER_STATEFULL:
				LM_DBG("this message is matched here to see what request or reply it is\n");
				if (is_req(msg))
				{
					if (msg->commandCode== IMS_ASR)
					{
						LM_DBG("ASR\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg);
						session = 0;
					} else {
						//would be a RAR but ok!
						LM_DBG("other request\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
						session = 0;
					}
				} else {
					if (msg->commandCode == IMS_STR)
					{
						LM_DBG("STA\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg);
						session = 0;
					} else {
						LM_DBG("other reply\n");
						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
						session = 0;
					}
				}
				break;				 
			default:
				break;
		}
		if (session) AAASessionsUnlock(session->hash);
	}
	if (!send_message_before_session_sm) peer_send_msg(p,msg);
	
}