/**
 *  Allocates a new AAAMessage.
 * @param commandCode - the command code for this message
 * @param applicationId - application id to be set
 * @param sessionId - session id to be set
 * @param request - if you want to create a response, put the request here. If you want a 
 * request, call with NULL
 * @returns the AAAMessage* or NULL on error
 * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
 */
AAAMessage *AAANewMessage(
	AAACommandCode commandCode,
	AAAApplicationId applicationId,
	AAASessionId *sessionId,
	AAAMessage *request)
{
	AAAMessage   *msg;
	AAA_AVP      *avp;
	AAA_AVP      *avp_t;
#if 0
	unsigned int code;
#endif
	str dest_host={"?",1};
	str dest_realm={"?",1};

	msg = 0;

	if (!sessionId||!sessionId->s) {
		if (request && request->sessionId){
			/* copy old session id */
			avp = request->sessionId;
			if (avp) {
				sessionId = &(avp->data);
			}
		}else{
//because of diameter base messages etc
//			LOG(L_ERR,"ERROR:AAANewMessage: param session-ID received null and it's a request!!\n");
//			goto error;
		}
	}

	/* allocated a new AAAMessage structure and set it to 0 */
	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
	if (!msg) {
		LOG(L_ERR,"ERROR:AAANewMessage: no more free memory!!\n");
		goto error;
	}
	memset(msg,0,sizeof(AAAMessage));

	/* command code */
	msg->commandCode = commandCode;
	/* application ID */
	msg->applicationId = applicationId;

	/* add session ID */
	if (sessionId){
		avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
			AVP_DUPLICATE_DATA);
		if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
			LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Session-Id avp\n");
			if (avp) AAAFreeAVP( &avp );
			goto error;
		}
		msg->sessionId = avp;
	}
	

	/* add origin host AVP */
	/* changed by cristian to comply with rfc3588: 
	 * 6.3.  Origin-Host AVP
	 *
	 *    The Origin-Host AVP (AVP Code 264) is of type
	 *    DiameterIdentity... */
	avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Host avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_host = avp;
	/* add origin realm AVP */
	avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERROR:AAANewMessage: cannot create/add Origin-Realm avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_realm = avp;

	if (!request) {
		/* it's a new request -> set the flag */
		msg->flags = 0x80;
		/* keep track of the session -> SendMessage will need it! */
		msg->sId = sessionId;
	} else {
		/* it'a an answer -> it will have the same session Id */
		msg->sId = request->sId;
		/* link the incoming peer to the answer */
		msg->in_peer = request->in_peer;
		/* set the P flag as in request */
		msg->flags |= request->flags&0x40;
		/**/
		msg->endtoendId = request->endtoendId;
		msg->hopbyhopId = request->hopbyhopId;

	/* Mirror the old originhost/realm to destinationhost/realm*/
	avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
	if (avp) dest_host = avp->data;
	/* add destination host and destination realm */
	avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
		dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
	if (!avp) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Host avp\n");
		return 0;
	}
	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
		AAAFreeAVP(&avp);
		return 0;
	}
	avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
	if (avp) dest_realm = avp->data;

	avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
		dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
	if (!avp) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed creating Destination Realm avp\n");
		return 0;
	}
	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LOG(L_ERR,"ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
		AAAFreeAVP(&avp);
		return 0;
	}		


		msg->res_code=0;
		/* mirror all the proxy-info avp in the same order */
		avp_t = request->avpList.head;
		while ( (avp_t=AAAFindMatchingAVP
		(request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
			if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
			msg->avpList.tail)!=AAA_ERR_SUCCESS )
				goto error;
		}
	}

	return msg;
error:
	LOG(L_ERR,"ERROR:AAANewMessage: failed to create a new AAA message!\n");
	AAAFreeMessage(&msg);
	return 0;
}
/**
 *  Allocates a new AAAMessage.
 * @param commandCode - the command code for this message
 * @param applicationId - application id to be set
 * @param sessionId - session id to be set
 * @param request - if you want to create a response, put the request here. If you want a 
 * request, call with NULL
 * @returns the AAAMessage* or NULL on error
 * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
 */
AAAMessage *AAANewMessage(
	AAACommandCode commandCode,
	AAAApplicationId applicationId,
	AAASession *session,
	AAAMessage *request)
{
	AAAMessage   *msg;
	AAA_AVP      *avp;
	AAA_AVP      *avp_t;
	str *sessionId=0;
#if 0
	unsigned int code;
#endif
	// str dest_host={"?",1};
	str dest_realm={"?",1};

	msg = 0;
	if (!session||!session->id.s) {
		if (request){
			/* copy old session id from AVP */
			if (request->sessionId) 
				sessionId = &(request->sessionId->data);
		}else{
			if (commandCode!=Code_DW)
				LM_DBG("AAANewMessage: param session received null and it's a request!!\n");
		}
	}else{
		sessionId = &(session->id);
	}

	/* allocated a new AAAMessage structure and set it to 0 */
	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
	if (!msg) {
		LM_ERR("AAANewMessage: no more free memory!!\n");
		goto error;
	}
	memset(msg,0,sizeof(AAAMessage));

	/* command code */
	msg->commandCode = commandCode;
	/* application ID */
	msg->applicationId = applicationId;

	/*add session ID */
	if (sessionId){
		avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
			AVP_DUPLICATE_DATA);
		if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
			LM_ERR("AAANewMessage: cannot create/add Session-Id avp\n");
			if (avp) AAAFreeAVP( &avp );
			goto error;
		}
		msg->sessionId = avp;
	}

	/* add origin host AVP */
	/* changed by cristian to comply with rfc3588: 
	 * 6.3.  Origin-Host AVP
	 *
	 *    The Origin-Host AVP (AVP Code 264) is of type
	 *    DiameterIdentity... */
	avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LM_ERR("AAANewMessage: cannot create/add Origin-Host avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_host = avp;
	/* add origin realm AVP */
	avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
		AVP_DUPLICATE_DATA);
	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		LM_ERR("AAANewMessage: cannot create/add Origin-Realm avp\n");
		if (avp) AAAFreeAVP( &avp );
		goto error;
	}
	msg->orig_realm = avp;

	if (!request) {
		/* it's a new request -> set the flag */
		msg->flags = 0x80;
	} else {
		/* link the incoming peer to the answer */
		msg->in_peer = request->in_peer;
		/* set the P flag as in request */
		msg->flags |= request->flags&0x40;
		/**/
		msg->endtoendId = request->endtoendId;
		msg->hopbyhopId = request->hopbyhopId;

		
		//TODO: aon:move this information in the AAASession structure, do not add these fields for
		
	    if (msg->commandCode==Code_CE||msg->commandCode==Code_DP||msg->commandCode==Code_DW ||
			    msg->commandCode==Diameter_CCR || msg->commandCode==Diameter_RAR){
	    	// Don't add Destination Host/Realm because some stacks are way to picky and will just refuse it
	    }else{

			/* Mirror the old originhost/realm to destinationhost/realm*/
			//avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
			//if (avp) dest_host = avp->data;
			/* add destination host and destination realm */
			//avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
			//	dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
			//if (!avp) {
		//		LM_ERR("ERR:AAANewMessage: Failed creating Destination Host avp\n");
		//		goto error;
		//	}
		//	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
		//		LM_ERR("ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
		//		AAAFreeAVP(&avp);
		//		goto error;
		//	}
	
			avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
			if (avp) dest_realm = avp->data;
			avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
				dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
			if (!avp) {
				LM_ERR("ERR:AAANewMessage: Failed creating Destination Realm avp\n");
				goto error;
			}
			if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
				LM_ERR("ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
				AAAFreeAVP(&avp);
				goto error;
			}
	    }

		msg->res_code=0;
		/* mirror all the proxy-info avp in the same order */
		avp_t = request->avpList.head;
		while ( (avp_t=AAAFindMatchingAVP
		(request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
			if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
			msg->avpList.tail)!=AAA_ERR_SUCCESS )
				goto error;
		}
	}

	return msg;
error:
	LM_ERR("AAANewMessage: failed to create a new AAA message!\n");
	AAAFreeMessage(&msg);
	return 0;
}