rem: if (p->tl.timer_list==wait_cer_timer) rmv_from_timer_list( &(p->tl) );
add: rmv_from_timer_list( &(p->tl), wait_cer_timer );
context: int peer_state_machine( struct peer *p, enum AAA_PEER_EVENT event, void *ptr){	struct tcp_params *info;	static char     *err_msg[]= {		"no error",		"event - state mismatch",		"unknown type event",		"unknown peer state"	};	int error_code=0;	int res;	if (!p) {		LOG(L_ERR,"ERROR:peer_state_machine: addressed peer is 0!!\n");		return -1;	}	DBG("DEBUG:peer_state_machine: peer %p, state = %d, event=%d\n",		p,p->state,event);	switch (event) {		case TCP_ACCEPT:			lock_get( p->mutex );			switch (p->state) {				case PEER_UNCONN:					DBG("DEBUG:peer_state_machine: accepting connection\n");					/* if peer in reconn timer list-> take it out*/					if (p->tl.timer_list==reconn_timer)						rmv_from_timer_list( &(p->tl) );					else if (p->flags&PEER_CONN_IN_PROG) {						tcp_close( p );					}					/* update the peer */					p->conn_cnt++;					info = (struct tcp_params*)ptr;					p->sock = info->sock;					memcpy( &p->local_ip, info->local, sizeof(struct ip_addr));					/* put the peer in wait_cer timer list */					add_to_timer_list( &(p->tl), wait_cer_timer,						get_ticks()+WAIT_CER_TIMEOUT);					/* the new state */					p->state = PEER_WAIT_CER;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case TCP_CONNECTED:			lock_get( p->mutex );			switch (p->state) {				case PEER_UNCONN:					DBG("DEBUG:peer_state_machine: connect finished ->"						" send CER\n");					/* update the peer */					p->conn_cnt++;					p->flags &= !PEER_CONN_IN_PROG;					info = (struct tcp_params*)ptr;					p->sock = info->sock;					memcpy( &p->local_ip, info->local, sizeof(struct ip_addr));					/* send cer */					if (send_cer( p )!=-1) {						/* new state */						p->state = PEER_WAIT_CEA;					} else {						tcp_close( p );						reset_peer( p );					}					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case TCP_CONN_IN_PROG:			lock_get( p->mutex );			switch (p->state) {				case PEER_UNCONN:					DBG("DEBUG:peer_state_machine: connect in progress\n");					/* update the peer */					info = (struct tcp_params*)ptr;					p->sock = info->sock;					p->flags |= PEER_CONN_IN_PROG;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case TCP_CONN_FAILED:			lock_get( p->mutex );			switch (p->state) {				case PEER_UNCONN:					DBG("DEBUG:peer_state_machine: connect failed\n");					reset_peer( p );					p->state = PEER_UNCONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case TCP_CONN_CLOSE:			lock_get( p->mutex );			if (p->state!=PEER_UNCONN || p->flags&PEER_CONN_IN_PROG) {				DBG("DEBUG:peer_state_machine: closing TCP connection "					"and reseting peer\n");				tcp_close( p );				reset_peer( p );				/* new state */				p->state = PEER_UNCONN;			}			lock_release( p->mutex );			break;		case PEER_CER_TIMEOUT:			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_CER:					DBG("DEBUG:peer_state_machine: CER not received!\n");					tcp_close( p );					reset_peer( p );					p->state = PEER_UNCONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case PEER_RECONN_TIMEOUT:			lock_get( p->mutex );			switch (p->state) {				case PEER_UNCONN:					DBG("DEBUG:peer_state_machine: reconnecting peer\n");					if (p->flags&PEER_CONN_IN_PROG)						tcp_close( p );					write_command( p->fd, CONNECT_CMD, 0, p, 0);					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					DBG("DEBUG:peer_state_machine: no reason to reconnect\n");			}			break;		case PEER_TR_TIMEOUT:			if ((unsigned int)ptr!=p->conn_cnt) {				LOG(L_WARN,"WARNING:peer_state_machine: transaction generated"					" from a prev. connection gave TIMEOUT -> ignoring!\n");				break;			}			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_DWA:					list_del_safe( &p->lh , &activ_peers );				case PEER_WAIT_CEA:				case PEER_WAIT_DPA:					DBG("DEBUG:peer_state_machine: transaction timeout\n");					tcp_close( p );					reset_peer( p );					p->state = PEER_UNCONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case CEA_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_CEA:					DBG("DEBUG:peer_state_machine: CEA received\n");					if ( process_ce( p, (str*)ptr, 0 )!=AAA_SUCCESS ) {						tcp_close( p );						reset_peer( p );						p->state = PEER_UNCONN;					} else {						list_add_tail_safe( &p->lh, &activ_peers );						p->state = PEER_CONN;					}					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case CER_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_CER:					/* if peer in wait_cer timer list-> take it out */					if (p->tl.timer_list==wait_cer_timer)						rmv_from_timer_list( &(p->tl) );				case PEER_WAIT_CEA:					DBG("DEBUG:peer_state_machine: CER received -> "						"sending CEA\n");					res = process_ce( p, (str*)ptr, 1 );					/* send the response */					if(send_cea( (str*)ptr, res, p)==-1 || res!=AAA_SUCCESS){						tcp_close( p );						reset_peer( p );						p->state = PEER_UNCONN;					} else {						list_add_tail_safe( &p->lh, &activ_peers );						p->state = PEER_CONN;					}					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case DWR_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_CONN:				case PEER_WAIT_DWA:				case PEER_WAIT_DPA:					DBG("DEBUG:peer_state_machine: DWR received -> "						"sending DWA\n");					res = AAA_SUCCESS;					if (process_dw( p, (str*)ptr, 1 )==-1)						res = AAA_MISSING_AVP;					/* send the response */					if(send_dwa( (str*)ptr, res, p)==-1 || res!=AAA_SUCCESS){						tcp_close( p );						reset_peer( p );						p->state = PEER_UNCONN;					}					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case PEER_IS_INACTIV:			lock_get( p->mutex );			switch (p->state) {				case PEER_CONN:					if (p->last_activ_time+SEND_DWR_TIMEOUT<=get_ticks()) {						if (send_dwr( p )==-1) {							LOG(L_ERR,"ERROR:peer_state_machine: cannot send"								" DWR -> trying later\n");						} else {							p->state = PEER_WAIT_DWA;						}					} else {						DBG("DEBUG:peer_state_machine: sending DWR - false "							"alarm -> cancel sending\n");						list_add_tail_safe( &p->lh, &activ_peers );					}					lock_release( p->mutex );					break;				default:					LOG(L_CRIT,"BUG:peer_state_machine: peer_is_inactiv "						"triggered outside PEER_CONN state!\n");					list_add_tail_safe( &p->lh, &activ_peers );					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case DWA_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_DWA:					process_dw( p, (str*)ptr, 0 );					list_add_tail_safe( &p->lh, &activ_peers );					p->state = PEER_CONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case DPR_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_CONN:				case PEER_WAIT_DWA:				case PEER_WAIT_DPA:					list_del_safe( &p->lh , &activ_peers );					DBG("DEBUG:peer_state_machine: DPR received -> "						"sending DPA\n");					res = AAA_SUCCESS;					if (process_dp( p, (str*)ptr, 1 )==-1)						res = AAA_MISSING_AVP;					/* send the response */					send_dpa( (str*)ptr, res, p);					tcp_close( p );					reset_peer( p );					p->state = PEER_UNCONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case DPA_RECEIVED:			lock_get( p->mutex );			switch (p->state) {				case PEER_WAIT_DPA:					tcp_close( p );					reset_peer( p );					p->state = PEER_UNCONN;					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		case PEER_HANGUP:			lock_get( p->mutex );			switch (p->state) {				case PEER_CONN:					list_del_safe( &p->lh , &activ_peers );					if (send_dpr( p ,(unsigned int)ptr )==-1) {						LOG(L_ERR,"ERROR:peer_state_machine: cannot send"							" DPR : closing tcp directly\n");						tcp_close( p );						reset_peer( p );						p->state = PEER_UNCONN;					} else {						p->state = PEER_WAIT_DPA;					}					lock_release( p->mutex );					break;				default:					lock_release( p->mutex );					error_code = 1;					goto error;			}			break;		default:			error_code = 2;			goto error;	}	DBG("DEBUG:peer_state_machine: peer %p, new state = %d\n",		p,p->state);	return 1;error:	LOG(L_ERR,"ERROR:peer_state_machine: %s : peer=%p, state=%d, event=%d\n",		err_msg[error_code],p,p->state,event);	return -1;}