void	CISO8583AcquirerGatewayFEServerSession::OnNetworkManagementRequest(CMultiXAppMsg &Msg)
{
	CISO8583Msg	ISOMsg;
	CISO8583Msg::TValidationError	Error	=	ISOMsg.FromISO((const	byte_t	*)Msg.AppData(),Msg.AppDataSize());
	if(Error	!=	CISO8583Msg::NoError)
	{
		Msg.Reply(Error);
		return;
	}

	/*
		Since Network Management messages include the destination gateway ID, we use it to find the link associated with this gateway.
	*/
	int	ReplyError	=	ErrUnableToForwardMsg;
	CISO8583AcquirerGatewayFELink	*Link	=	Owner()->FindReadyLink(ISOMsg.TransactionDestinationInstitutionIdentificationCode());
	if(Link)
	{
		std::string	MsgKey	=	ISOMsg.STAN() + ISOMsg.DateTimeLocal() + ISOMsg.TransactionOriginatorInstitutionIdentificationCode();
		ReplyError	=	Link->Forward(Msg,MsgKey);
	}
	if(ReplyError	==	0)
	{
		Msg.Keep();
	}	else
	{
		Msg.Reply(ReplyError);
	}
}
예제 #2
0
void CMultiXProcess::OnGetListeningAddressFailed(CMultiXAppMsg &OriginalMsg)
{
    CMultiXMsg	Msg(*Owner());
    Msg.Append(OriginalMsg.AppData(),OriginalMsg.AppDataSize());
    TMultiXProcID	ProcID	=	0;

    Msg.GetItemData(ProcID);
    Owner()->OnConnectProcessFailed(ProcID);
}
//!	see CMultiXSession::OnDataReplyReceived
void	CISO8583BackEndServerSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &ForwardedMsg)
{
	DebugPrint(3,"Data Reply Received\n");
	/*
		We get here when we receive a response for a message we forwarded before. In this case we will forward the response back to
		the originator, we do not care for the content, we forward it back almost AS IS except for few fields that
		we need to restore because changed them before we forwarded the message, the fields are:
		MTI - Convert it to 1993 version.
		BMP 7 - Set Transmission time
		BMP 11 - restore sender STAN
		BMP 12	-	Restore sender Date and Time Local
		BMP 32 - Restore senders Acquiring Institution Identification Code
	*/
	/*
		In order to restore old values, we need to restore the message we received originaly from the acquirer or from the pos terminal.
		this message is saved in the SaveContext() of the ForwardedMsg.
	*/
	CMultiXAppMsg	*AcquirerMsg	=	(CMultiXAppMsg	*)ForwardedMsg.SavedContext();

	CISO8583Msg	AcquirerISO;
	CISO8583Msg	ReplyISO;
	AcquirerISO.FromISO((const	byte_t	*)AcquirerMsg->AppData(),AcquirerMsg->AppDataSize());
	ReplyISO.FromISO((const	byte_t	*)ReplyMsg.AppData(),ReplyMsg.AppDataSize());

	ReplyISO.SetTimes(time(NULL),true);
	ReplyISO.SetDateTimeLocal(AcquirerISO.DateTimeLocal());
	ReplyISO.SetSTAN(AcquirerISO.STAN());
	ReplyISO.SetAcquiringInstitutionIdentificationCode(AcquirerISO.AcquiringInstitutionIdentificationCode());
	ReplyISO.ToISO();

	AcquirerMsg->Reply(CISO8583Msg::VersionDependentMTI(CISO8583Msg::ISO8583_2_1993,ReplyMsg.MsgCode()),
		ReplyISO.ISOBuffer(),
		ReplyISO.ISOBufferSize(),0,0,0,0,0,ReplyMsg.Error());

	delete	AcquirerMsg;	//	WE MUST DELETE THE MESSAGE BECAUSE WE CALLED "Keep()" BEFORE WE FORWARDED IT.

	
	/*	
		we reply the ReplyMsg for the case that the process that replied to us expects to receive a notification that we
		received the reply, if it does not wait for the reply, no reply is sent.
	*/
	ReplyMsg.Reply();	
}
/*!
	see	CMultiXSession::OnDataReplyReceived

	this reply is for a message or an ACK previously received from the POS terminal.
*/
void	CMultiplexerClientFEClientSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &OriginalMsg)
{
	DebugPrint(2,"Data Reply Received\n");
	
		
	CMultiplexerClientFELink	*pLink	=	GetLink();
	

	if(!pLink)	//	probably the link was disconnected before the reply was received
	{
		int	Error	=	ErrLinkDisconnected;	
		//	TODO:	Set an application specific error code
		
		ReplyMsg.Reply(Error);
		return;
	}

	if(ReplyMsg.AppDataSize()	==	0)	//	an empty reply from the server application
	{
		if(ReplyMsg.Error()	!=	0)
			pLink->OnSessionSendFailed(OriginalMsg,ReplyMsg.Error());
		else
			pLink->OnSessionSendCompleted(OriginalMsg);
		ReplyMsg.Reply();	//	just reply to the received msg, in case the sender expects a reply
		return;
	}


	// forward the reply to the associated link
	CMultiXBuffer	*Buf	=	Owner()->AllocateBuffer(ReplyMsg.AppData(),ReplyMsg.AppDataSize());

	pLink->OnSessionReply(*Buf,OriginalMsg);
	Buf->ReturnBuffer();
	ReplyMsg.Reply(0);

	}
예제 #5
0
void CMultiXProcess::OnPrepareForShutdown(CMultiXAppMsg &AppMsg)
{

    CMultiXMsg	Msg(*Owner());
    Msg.Append(AppMsg.AppData(),AppMsg.AppDataSize());

    int32_t	GracePeriod	=	0;

    while(Msg.Next())
    {
        switch(Msg.GetItemCode())
        {

        case	CMultiXTpmCtrlMsg::GracePeriodItemCode	:
            Msg.GetItemData(GracePeriod);
            break;
        }
    }
    AppMsg.Reply(MultiXNoError);
    Owner()->OnPrepareForShutdown(GracePeriod);
}
void	CISO8583AcquirerGatewayFEServerSession::OnTransactionRequest(CMultiXAppMsg &Msg)
{
	CISO8583Msg	ISOMsg;
	CISO8583Msg::TValidationError	Error	=	ISOMsg.FromISO((const	byte_t	*)Msg.AppData(),Msg.AppDataSize());
	if(Error	!=	CISO8583Msg::NoError)
	{
		Msg.Reply(Error);
		return;
	}

	if(Owner()->DebugLevel()	>=	5)
	{
		std::string	S;
		ISOMsg.Dump(S);
		DebugPrint(2,"New ISO 8583 Message\n%s\n",S.c_str());
	}

	/*
		When we receive a transaction for forwarding, we have no indication within the message, to which gateway we should forward the message.
		It is assumed that there is some mechanism to use the PAN and/or Track2 in order to decide to which gateway we should forward the request.
		In this application, we do not use any logic to derive the Gateway ID from these details. We just use a stub routine that gets PAN
		as input and returns the gateway ID of the issuer. Using the gateway ID, we look for a link that its RemoteGatewayID() is equal to
		the value returned. If we find one and it is signed in, we forward the request to it, otherwise we reply with an error.
	*/
	int	ReplyError	=	ErrUnableToForwardMsg;
	std::string	RemoteGatewayID	=	PANToGatewayID(ISOMsg.PAN());
	CISO8583AcquirerGatewayFELink	*Link	=	Owner()->FindReadyLink(RemoteGatewayID);
	if(Link)
	{
		std::string	MsgKey	=	ISOMsg.STAN() + ISOMsg.DateTimeLocal() + ISOMsg.AcquiringInstitutionIdentificationCode();
		ReplyError	=	Link->Forward(Msg,MsgKey);
	}
	if(ReplyError	==	0)
	{
		Msg.Keep();
	}	else
	{
		Msg.Reply(ReplyError);
	}
}
예제 #7
0
void CMultiXProcess::OnListeningAddressReceived(CMultiXAppMsg &AppMsg)
{
    CMultiXMsg	Msg(*Owner());
    Msg.Append(AppMsg.AppData(),AppMsg.AppDataSize());
    TMultiXProcID	ProcID	=	0;
    std::string	Address;
    std::string	Port;

    while(Msg.Next())
    {
        switch(Msg.GetItemCode())
        {
        case	CMultiXTpmCtrlMsg::ProcessIDItemCode	:
            Msg.GetItemData(ProcID);
            break;
        case	CMultiXTpmCtrlMsg::LocalAddressItemCode	:
            Msg.GetItemData(Address);
            break;
        case	CMultiXTpmCtrlMsg::LocalPortItemCode	:
            Msg.GetItemData(Port);
            break;
        }
    }

    if(ProcID	==	0)
        return;
    CMultiXProcess	*Process	=	Owner()->FindProcess(ProcID);
    if(Process	!=	NULL	&&	Process->Connected())
        return;
    if(Address.empty()	||Port.empty())
    {
        if(Process)
            Process->ConnectRetries()++;
        return;
    }
    TTpmConfigParams	Params;
    CMultiXTpmLink	*Link	=	new	CMultiXTpmLink(Params,false,MultiXOpenModeClient);
    Owner()->AddLink(Link);
    Link->Connect(Address,Port);
}
void	CISO8583BackEndServerSession::OnNewMsg(CMultiXAppMsg &Msg)
{

	DebugPrint(1,"New Message Received\n");


	switch(CISO8583Msg::VersionIndependentMTI(Msg.MsgCode()))	//	we check the ISO8583 Version independent MTI value
	{
		case	CISO8583Msg::MTIAuthorizationMessageRequest	:
		case	CISO8583Msg::MTIReversalMessageAdvice	:
		case	CISO8583Msg::MTIReversalMessageAdviceRepeat	:
		case	CISO8583Msg::MTINetworkManagementMessageRequestOther	:
		case	CISO8583Msg::MTINetworkManagementMessageRequestAcquirer	:
		case	CISO8583Msg::MTINetworkManagementMessageRequestAcquirerRepeat	:
			{
				//	If  we have an ISO 8583 Msg Code, we try to parse the msg to make sure that
				//	we have a valid ISO 8583

				CISO8583Msg	ISOMsg;
				CISO8583Msg::TValidationError	Error	=	ISOMsg.FromISO((const	byte_t	*)Msg.AppData(),Msg.AppDataSize());
				if(Error	!=	CISO8583Msg::NoError)
				{
					Msg.Reply(Error);
				}	else	if(ISOMsg.Version()	!=	CISO8583Msg::ISO8583_2_1993)	//	we	Support only 1993 version
				{
					Msg.Reply(CISO8583Msg::VersionNotSupported);
				}	else
				{
					OnISO8583Msg(Msg,ISOMsg);
				}
			}
			break;
		default	:
			//	We	do not know this message, reply with error
			Msg.Reply(CISO8583Msg::MTINotSupported);
			break;

	}
}
//!	see CMultiXSession::OnDataReplyReceived
void	CISO8583AuthorizerServerSession::OnDataReplyReceived(CMultiXAppMsg &ReplyMsg,CMultiXAppMsg &ForwardedMsg)
{
	DebugPrint(3,"Data Reply Received\n");

	switch(CISO8583Msg::VersionIndependentMTI(ForwardedMsg.MsgCode()))	//	this will give us version independent MTI
	{
	case	CISO8583Msg::MTIAuthorizationMessageRequest	:
	case	CISO8583Msg::MTIFinancialMessageRequest	:
		{
			CMultiXAppMsg	*AcquirerMsg	=	(CMultiXAppMsg	*)ForwardedMsg.SavedContext();
			if(ReplyMsg.AppDataSize()	==	0)
			{
				AcquirerMsg->Reply(ReplyMsg.Error());
				delete	AcquirerMsg;
				break;
			}

			CISO8583Msg	AcquirerISO;
			CISO8583Msg	ReplyISO;
			AcquirerISO.FromISO((const	byte_t	*)AcquirerMsg->AppData(),AcquirerMsg->AppDataSize());
			ReplyISO.FromISO((const	byte_t	*)ReplyMsg.AppData(),ReplyMsg.AppDataSize());


			/*
				before we send the reply, we need to check if it is MTI 200 and if the response is positive, if so	:
				1. we debit the issuer account for the sales amount + commission. in this sample we derive the issuer account from the PAN.
				2. we credit our own account for these amounts
				3. we write transactions log.
			*/

			if(CISO8583Msg::VersionIndependentMTI(AcquirerMsg->MsgCode())	==	CISO8583Msg::MTIFinancialMessageRequest)
			{
				if(CISO8583Utilities::ToInt64(ReplyISO.ActionCode())	==	0)
				{
					double	Amount	=	(double)CISO8583Utilities::ToInt64(ReplyISO.TransactionAmount())/100;
					int	IssuerAccount	=	PANToIssuerAccount(AcquirerISO.PAN());
					int	MerchantAccount	=	(int)CISO8583Utilities::ToInt64(AcquirerISO.CardAcceptorIdentificationCode().StringData());
					if(!UpdateAuthorizedSale(IssuerAccount,MerchantAccount,AcquirerISO.PAN(),Amount))
					{
						AcquirerMsg->Reply(CISO8583Msg::RequestRejected);
		//				SendReversalToIssuer(ReplyISO); not implemented
						delete	AcquirerMsg;
						return;
					}
				}
			}	else	if(CISO8583Msg::VersionIndependentMTI(AcquirerMsg->MsgCode())	==	CISO8583Msg::MTIAuthorizationMessageRequest)
			{
				int	IssuerAccount	=	PANToIssuerAccount(AcquirerISO.PAN());
				double	Amount	=	(double)CISO8583Utilities::ToInt64(AcquirerISO.TransactionAmount())/100;

				mysqlpp::Transaction	Tran(Owner()->DBConn());
				mysqlpp::Query Query = Owner()->DBConn().query();
				transactions_log	Log;
				Log.Time			=	TomysqlppDateTime(time(NULL));
				Log.AccountNumber	=	IssuerAccount;
				Log.CardNumber		=	AcquirerISO.PAN();
				Log.Action				=	11;	//	Query
				Log.Amount				=	Amount;
				Log.NewBalance		=	0;
				Query.insert(Log);
				Query.execute();
				Tran.commit();
			}

			/*
				We get here when we receive a response for a message we forwarded before. In this case we will forward the response back to
				the originator, we do not care for the content, we forward it back almost AS IS except for few fields that
				we need to restore because changed them before we forwarded the message, the fields are:

				BMP 7 - Set Transmission time
				BMP 11 - restore sender STAN
				BMP 12	-	Restore sender Date and Time Local
				BMP 32 - Restore senders Acquiring Institution Identification Code
			*/
			/*
				In order to restore old values, we need to restore the message we received originaly from the acquirer or from the pos terminal.
				this message is saved in the SaveContext() of the ForwardedMsg.
			*/



			ReplyISO.SetTimes(time(NULL),true);
			ReplyISO.SetSTAN(AcquirerISO.STAN());
			ReplyISO.SetDateTimeLocal(AcquirerISO.DateTimeLocal());
			ReplyISO.SetAcquiringInstitutionIdentificationCode(AcquirerISO.AcquiringInstitutionIdentificationCode());
			ReplyISO.ToISO();


			AcquirerMsg->Reply(AcquirerMsg->MsgCode(),
				ReplyISO.ISOBuffer(),
				ReplyISO.ISOBufferSize(),0,0,0,0,0,ReplyMsg.Error());

			delete	AcquirerMsg;	//	WE MUST DELETE THE MESSAGE BECAUSE WE CALLED "Keep()" BEFORE WE FORWARDED IT.




		}
		break;
	}



	
	/*	
		we reply the ReplyMsg for the case that the process that replied to us expects to receive a notification that we
		received the reply, if it does not wait for the reply, no reply is sent.
	*/
	ReplyMsg.Reply();	
}
예제 #10
0
void	CMultiXProcess::OnTpmConfigData(CMultiXAppMsg &AppMsg)
{
    CMultiXMsg	Msg(*Owner());
    std::string	ParamName;
    std::string	ParamValue;
    Msg.Append(AppMsg.AppData(),AppMsg.AppDataSize());

    CMultiXTpmConfiguredLink	Link;
    while(Msg.Next())
    {
        switch(Msg.GetItemCode())
        {

        case	CMultiXTpmCtrlMsg::DebugLevelItemCode	:
            Msg.GetItemData(Owner()->DebugLevel());
            break;
        case	CMultiXTpmCtrlMsg::AdditionalConfigTextItemCode	:
            Msg.GetItemData(Owner()->AdditionalConfigText());
            break;
        case	CMultiXTpmCtrlMsg::DefaultSendTimeoutItemCode	:
            Msg.GetItemData(Owner()->DefaultSendTimeout());
            break;
        case	CMultiXTpmCtrlMsg::StartLinkItemCode	:
            break;
        case	CMultiXTpmCtrlMsg::LinkIDItemCode	:
            Msg.GetItemData(Link.LinkID);
            break;
        case	CMultiXTpmCtrlMsg::LinkDescriptionItemCode	:
            Msg.GetItemData(Link.Description);
            break;
        case	CMultiXTpmCtrlMsg::LinkTypeItemCode	:
            Msg.GetItemData(Link.LinkType);
            break;
        case	CMultiXTpmCtrlMsg::OpenModeItemCode	:
            Msg.GetItemData(Link.OpenMode);
            break;
        case	CMultiXTpmCtrlMsg::IsRawItemCode	:
            Msg.GetItemData(Link.bRaw);
            break;
        case	CMultiXTpmCtrlMsg::LocalAddressItemCode	:
            Msg.GetItemData(Link.LocalAddress);
            break;
        case	CMultiXTpmCtrlMsg::LocalPortItemCode	:
            Msg.GetItemData(Link.LocalPort);
            break;
        case	CMultiXTpmCtrlMsg::RemoteAddressItemCode	:
            Msg.GetItemData(Link.RemoteAddress);
            break;
        case	CMultiXTpmCtrlMsg::RemotePortItemCode	:
            Msg.GetItemData(Link.RemotePort);
            break;
        case	CMultiXTpmCtrlMsg::EndLinkItemCode	:
            if(Link.LinkType	==	MultiXLinkTypeTcp	&&
                    Link.OpenMode	==	MultiXOpenModeServer	&&
                    Link.bRaw			==	false)
            {
                CMultiXTpmLink	*TpmLink	=	new	CMultiXTpmLink(Link.ConfigParams,false,MultiXOpenModeServer);
                Owner()->AddLink(TpmLink);
                TpmLink->Listen(Link.LocalPort,Link.LocalAddress);
            }	else
            {
                Owner()->OnTpmConfiguredLink(Link);
            }
            break;
        case	CMultiXTpmCtrlMsg::StartParamItemCode	:
            ParamName.clear();
            ParamValue.clear();
            break;
        case	CMultiXTpmCtrlMsg::ParamNameItemCode	:
            Msg.GetItemData(ParamName);
            break;
        case	CMultiXTpmCtrlMsg::ParamValueItemCode	:
            Msg.GetItemData(ParamValue);
            break;
        case	CMultiXTpmCtrlMsg::EndProcessParamItemCode	:
            if(ParamName.length()	>	0)
                Owner()->AddConfigParam(ParamName,ParamValue);
            break;
        case	CMultiXTpmCtrlMsg::EndLinkParamItemCode	:
            if(ParamName.length()	>	0)
                Link.ConfigParams[ParamName]	=	ParamValue;
            break;


        }
    }
    AppMsg.Reply(MultiXNoError);
    Owner()->OnTpmConfigCompleted();
}
예제 #11
0
bool CMultiXProcess::OnAppMsg(CMultiXMsg &Msg)
{
    if(!ReceiverEnabled()	||	!SenderEnabled())
        return	false;
    CMultiXAppMsg	*OrgMsg	=	NULL;
    CMultiXSession	*Session	=	NULL;
    CMultiXAppMsg	*AppMsg	=	CreateNewAppMsg(&Msg);
    //if(m_MsgCount++	==	1)
//		m_LastPrintTime	=	Owner()->GetMilliClock();
    m_LastMsgRecvMilliClock	=	Owner()->GetMilliClock();

    AddToMsgQueue(m_pInQueue,AppMsg);

    if(!AppMsg->ResponseRequired())
    {
        if(AppMsg->NotifyAny())
            AppMsg->Reply(MultiXNoError);
    }

    if(AppMsg->IsResponse())
    {
        OrgMsg	=	AppMsg->ReceiverMsgID().GetObject();
        if(OrgMsg	!=	NULL)
        {
            Session	=	Owner()->FindSession(OrgMsg->SessionID());
            OrgMsg->m_bKeep	=	false;
            OrgMsg->ID().RemoveObject();

            if(AppMsg->AppDataSize()	||	OrgMsg->ResponseRequired())
            {
                if(Session)
                {
                    if(AppMsg->IsCtrlMsgFromTpm())
                        Session->OnDataReplyFromTpmReceived(*AppMsg,*OrgMsg);
                    else
                        Session->OnDataReplyReceivedNV(*AppMsg,*OrgMsg);
                }	else
                {
                    if(AppMsg->IsCtrlMsgFromTpm())
                        OnDataReplyFromTpmReceived(*AppMsg,*OrgMsg);
                    else
                        OnDataReplyReceived(*AppMsg,*OrgMsg);
                }
            }	else if(AppMsg->Error())
            {
                if(OrgMsg->NotifyError())
                {
                    if(Session)
                    {
                        if(AppMsg->IsCtrlMsgFromTpm())
                            Session->OnSendMsgToTpmFailed(*OrgMsg);
                        else
                            Session->OnSendMsgFailedNV(*OrgMsg);
                    }	else
                    {
                        if(AppMsg->IsCtrlMsgFromTpm())
                            OnSendMsgToTpmFailed(*OrgMsg);
                        else
                            OnSendMsgFailed(*OrgMsg);
                    }
                }
            }	else
            {
                if(OrgMsg->NotifySuccess())
                {
                    if(Session)
                    {
                        if(AppMsg->IsCtrlMsgFromTpm())
                            Session->OnSendMsgToTpmCompleted(*OrgMsg);
                        else
                            Session->OnSendMsgCompletedNV(*OrgMsg);
                    }	else
                    {
                        if(AppMsg->IsCtrlMsgFromTpm())
                            OnSendMsgToTpmCompleted(*OrgMsg);
                        else
                            OnSendMsgCompleted(*OrgMsg);
                    }
                }
            }
        }	else	//	it is a response but the original does not exist
        {
            AppMsg->Reply(TpmErrUnableToForwardMsg);
        }
    }	else
    {
        Session	=	Owner()->FindSession(AppMsg->SessionID(),true);
        if(Session)
        {
            if(AppMsg->IsCtrlMsgFromTpm())
                Session->OnNewMsgFromTpm(*AppMsg);
            else
                Session->OnNewMsgNV(*AppMsg);
        }	else
        {
            if(AppMsg->IsCtrlMsgFromTpm())
                OnNewMsgFromTpm(*AppMsg);
            else
                OnNewMsg(*AppMsg);
        }
        if(AppMsg->ResponseRequired()	&&	!(AppMsg->ReplySent()	||	AppMsg->m_bKeep))
            Throw();
    }

    if(!(AppMsg->ReplySent()	||	AppMsg->m_bKeep))
    {
        if(AppMsg->ResponseRequired())
            Throw();
        else if(AppMsg->NotifyAny())
            AppMsg->Reply(MultiXNoError);
    }

    if(OrgMsg	&&	!OrgMsg->m_bKeep)
        delete	OrgMsg;
    if(!AppMsg->m_bKeep)
        delete	AppMsg;
    return	true;
}
예제 #12
0
CMultiXLayer::EventHandlerReturn	CMultiXWSStream::OnNewRequestMessage(CMultiXEvent	*Event)
{
	CMultiXWSStreamEvent	*Ev	=	(CMultiXWSStreamEvent	*)Event;
	//	if we have a valid message saved, we reply it with error - this will happen only if we have not replied to it before
	//	we will also delete the message, since we do not need it any more.
	CMultiXAppMsg	*pMsg	=	m_RequestMsgID.GetObject();
	if(pMsg	!=	NULL)
	{
		pMsg->Reply(TpmErrMsgCanceled);
		delete	pMsg;
	}

	m_RequestMsgID	=	Ev->m_MsgID;
	pMsg	=	m_RequestMsgID.GetObject();
	if(pMsg	==	NULL)
		return	CMultiXLayer::DeleteEvent;

	bool	bExit	=	false;


	while(!bExit)	//	we do a "while" here just so we can fall thru the end of function and delete the message object
	{
		bExit	=	true;
		if(!pMsg->IsWebServiceCall())
		{
			pMsg->Reply(TpmErrMsgNotSupported);
			break;
		}
		std::string	FuncName;
		std::string	DLLName;
		EXPORTABLE_STL::map<int32_t,std::string>::iterator	It	=	m_MsgCodeToFunctionMap.find(pMsg->MsgCode());
		if(It	!=	m_MsgCodeToFunctionMap.end())
		{
			DLLName	=	It->second.substr(0,It->second.find("|||"));
			FuncName	=	It->second.substr(It->second.find("|||")+3);
		}
		else
		{
			DLLName	=	pMsg->WSDllFile();
			FuncName	=	pMsg->WSDllFunction();
		}


		try
		{
			InitgSoap(DLLName);
		}	catch(...)
		{
			pMsg->Reply(WSErrgSoapDllNotFound);
			break;
		}
		TgSoapServiceFunction	Func	=	(TgSoapServiceFunction)GetProcAddress(m_pFunctions->m_pDLLHandle,FuncName.c_str());

		if(Func	==	NULL)
		{
			pMsg->Reply(WSErrServiceFunctionNotFound);
			break;
		}	else	if(It	==	m_MsgCodeToFunctionMap.end())
		{
			m_MsgCodeToFunctionMap[pMsg->MsgCode()]	=	DLLName	+	"|||"	+ pMsg->WSDllFunction();
		}

		ResetData();
		if(m_pInBuf)
			m_pInBuf->ReturnBuffer();
		m_pInBuf	=	pMsg->Owner()->Owner()->AllocateBuffer(pMsg->AppData(),pMsg->AppDataSize());
		int	Error	=	Func(gSoap());
		if(OutBuf().Length()	>	0)
		{
			pMsg->Reply(pMsg->MsgCode(),OutBuf());
		}	else
		{
			pMsg->Reply(Error);
		}
	}
	if(pMsg)
		delete	pMsg;

	m_RequestMsgID.Init();
	return	CMultiXLayer::DeleteEvent;
}