protected ISMVMC GetVMCNoSync(int i_iKey) { ISMVMC vRet = null; StringBuilder sbTmp = null; if (i_iKey > (m_VMCs.Count - 1)) { //Console.Error.WriteLine("ERROR: ResourceMgr_local.GetVMCNoSync() invalid index '{0}'.", i_iKey.ToString()); sbTmp = new StringBuilder(); sbTmp.AppendFormat("ResourceMgr_local.GetVMCNoSync() invalid index '{0}'.", i_iKey.ToString()); m_Logger.Log(Level.Exception, sbTmp.ToString()); } else { vRet = (ISMVMC)(m_VMCs[i_iKey]); if (i_iKey != vRet.m_iKey) { //Console.Error.WriteLine("WARNING: ResourceMgr_local.GetVMCNoSync() VMC index '{0}' doesn't match key passed in '{1}'.", vRet.m_iKey.ToString(), i_iKey.ToString()); sbTmp = new StringBuilder(); sbTmp.AppendFormat("ResourceMgr_local.GetVMCNoSync() VMC index '{0}' doesn't match key passed in '{1}'.", vRet.m_iKey.ToString(), i_iKey.ToString()); m_Logger.Log(Level.Warning, sbTmp.ToString()); } } return(vRet); }
} // GetVMCBySessionid /// <summary> /// /// </summary> /// <param name="i_iKey"></param> /// <returns></returns> public virtual string GetSessionId(int i_iKey) { string sRet = ""; ISMVMC vmcTmp = null; try { if (i_iKey == -1) // Catch if an invalid key was passed in { vmcTmp = new ISMVMC(); vmcTmp.Clear(); } else { Monitor.Enter(m_Lock); vmcTmp = GetVMCInfoByKey_NoSync(i_iKey).m_VMC; sRet = vmcTmp.m_sSessionId; } } catch (Exception exc) { m_Logger.Log(Level.Exception, "RMl GetSessionId(key=" + i_iKey.ToString() + ") caught exception: " + exc.ToString()); } finally { Monitor.Exit(m_Lock); } return(sRet); } // GetSessionId
public ResourceMgr_local(ILegacyLogger i_Logger) { int ii; ISMVMC vmc; try { m_Logger = i_Logger; m_iMaxSessions = ConfigParams.GetNumExt(); m_VMCs = new VMCList(); Monitor.Enter(m_Lock); for (ii = 0; ii < m_iMaxSessions; ii++) { vmc = new ISMVMC(); vmc.Clear(); m_VMCs.Add(new VMCInfo(ref vmc)); } } catch (Exception exc) { m_Logger.Log(Level.Exception, "RMl ctor caught exception: " + exc.ToString()); } finally { Monitor.Exit(m_Lock); } } // ctor
} // ReleaseSession /* * /// <summary> * /// * /// </summary> * /// <param name="i_sSessionId"></param> * /// <returns></returns> * public virtual bool ReleaseSession(string i_sSessionId) * { * bool bRet = true; * ISMVMC vRes; * * try * { * Monitor.Enter(m_Lock); * * vRes = GetVMCNoSync(i_sSessionId); * vRes.Clear(); * } * catch(Exception exc) * { * //Console.Error.WriteLine("ResourceMgr_local.RemoveSession('{0}') Caught exception: '{1}'.", i_sSessionId, e.ToString()); * m_Logger.Log(Level.Exception, "RMl ReleaseSession(id=" + i_sSessionId + ") caught exception: " + exc.ToString()); * } * finally * { * Monitor.Exit(m_Lock); * } * * return(bRet); * } // ReleaseSession */ protected ISMVMC GetVMCBySrc_NoSync(string i_sSrc) { ISMVMC vRet = null; int ii, iLen; string sTmp; iLen = m_VMCs.Count; for (ii = 0; ((ii < iLen) && (vRet == null)); ii++) { sTmp = ((ISMVMC)(m_VMCs[ii].m_VMC)).m_sDescription; if (i_sSrc == sTmp) { vRet = (ISMVMC)m_VMCs[ii].m_VMC; } } if (vRet == null) // VMC wasn't found { // Allocate new VMC so we don't return null vRet = new ISMVMC(); vRet.Clear(); } return(vRet); } // GetVMCBySrc_NoSync
} // GetVMCInfoByKey_NoSync protected ISMVMC GetVMCBySessionid_NoSync(string i_sSessionid) { ISMVMC vRet = null; vRet = m_VMCs.Find(vmc => vmc.m_VMC.m_sSessionId == i_sSessionid).m_VMC; return(vRet); } // GetVMCBySessionid_NoSync
/// <summary> /// NOTE: This is NOT thread safe, it is assumed that the caller will be performing /// any necessary syncronization. /// </summary> /// <returns></returns> protected ISMVMC GetFreeVMC() { int ii; ISMVMC vRet = null; for (ii = 0; ((ii < m_iMaxSessions) && (vRet == null)); ii++) { if (((ISMVMC)(m_VMCs[ii])).m_iKey == -1) { vRet = (ISMVMC)m_VMCs[ii]; vRet.m_iKey = ii; } } return(vRet); }
protected ISMVMC GetVMCNoSync(string i_sSessionId) { ISMVMC vRet = null; int ii, iLen; string sTmp; iLen = m_VMCs.Count; for (ii = 0; ((ii < iLen) && (vRet == null)); ii++) { sTmp = ((ISMVMC)(m_VMCs[ii])).m_sDescription; if (i_sSessionId == sTmp) { vRet = (ISMVMC)m_VMCs[ii]; } } return(vRet); }
} // GetVMCByKey public virtual ISMVMC GetVMCBySessionid(string i_sSessionid) { ISMVMC vRet = null; try { Monitor.Enter(m_Lock); vRet = GetVMCBySessionid_NoSync(i_sSessionid); } catch (Exception exc) { m_Logger.Log(Level.Exception, "RMl GetVMCBySessionid(key=" + i_sSessionid + ") caught exception: " + exc.ToString()); } finally { Monitor.Exit(m_Lock); } return(vRet); } // GetVMCBySessionid
} // GetVMCBySessionid_NoSync /// <summary> /// This is dangerous IF it is possible for the src to be reused (for example, if a call from a AR hasn't completely cleared AM before a new call comes in.) /// </summary> /// <param name="i_sSrc"></param> /// <returns></returns> /* * protected virtual ISMVMC GetVMCBySrc(string i_sSrc) * { * ISMVMC vRet = null; * * try * { * Monitor.Enter(m_Lock); * vRet = GetVMCBySrc_NoSync(i_sSrc); * } * catch(Exception exc) * { * m_Logger.Log(Level.Exception, "RMl GetVMCBySrc(id=" + i_sSrc + ") caught exception: " + exc.ToString()); * } * finally * { * Monitor.Exit(m_Lock); * } * * return(vRet); * } // GetVMCBySrc */ /// <summary> /// /// </summary> /// <param name="i_iKey"></param> /// <returns>VMC, or null if not found.</returns> public virtual ISMVMC GetVMCByKey(int i_iKey) { ISMVMC vRet = null; try { Monitor.Enter(m_Lock); vRet = GetVMCInfoByKey_NoSync(i_iKey).m_VMC; } catch (Exception exc) { m_Logger.Log(Level.Exception, "RMl GetVMCByKey(key=" + i_iKey.ToString() + ") caught exception: " + exc.ToString()); } finally { Monitor.Exit(m_Lock); } return(vRet); } // GetVMCByKey
/// <summary> /// /// </summary> /// <param name="i_iKey"></param> /// <returns>VMC, or null if not found.</returns> public virtual ISMVMC GetVMC(int i_iKey) { ISMVMC vRet = null; try { m_Lock.WaitOne(); vRet = GetVMCNoSync(i_iKey); } catch (Exception e) { //Console.Error.WriteLine("ResourceMgr_local.GetVMC('{0}') Caught exception: '{1}'.", i_iKey.ToString(), e.ToString()); m_Logger.Log(e); } finally { m_Lock.ReleaseMutex(); } return(vRet); }
/// <summary> /// NOTE: This is NOT thread safe, it is assumed that the caller will be performing /// any necessary syncronization. /// </summary> /// <returns></returns> protected ISMVMC GetFreeVMC(int i_iThreadIndex, string i_sSrc) { int ii; ISMVMC vRet = null; for (ii = 0; ((ii < m_iMaxSessions) && (vRet == null)); ii++) { //if(((ISMVMC)(m_VMCs[ii].m_VMC)).m_iKey == -1) if (m_VMCs[ii].m_State == VMCInfo.VMCState.Unused) { m_VMCs[ii].m_State = VMCInfo.VMCState.InUse; vRet = (ISMVMC)m_VMCs[ii].m_VMC; vRet.m_iKey = ii; vRet.m_sDescription = i_sSrc; vRet.m_sSessionId = CreateSessionId(i_iThreadIndex, ii); } } return(vRet); } // GetFreeVMC
public ResourceMgr_local(Logger i_Logger) { int ii; ISMVMC vmc; m_Logger = i_Logger; m_iMaxSessions = int.Parse(ConfigurationSettings.AppSettings["MaxSessions"]); m_Lock.WaitOne(); if (m_VMCs == null) { m_VMCs = new ArrayList(); for (ii = 0; ii < m_iMaxSessions; ii++) { vmc = new ISMVMC(); m_VMCs.Add(vmc); } } m_Lock.ReleaseMutex(); }
/// <summary> /// /// </summary> public void ThreadProc() { bool bCont = true; int iSockBytes = 0; int iMsgBytes = 0; int iArrayIndex = 0; int iVmcIndex = -1; byte[] baMsg; // Buffer received from socket. AMSockData amsData; // Message extraced from socket buffer. byte[] baAudio; // Audio extracted from socket msg. ISMessaging.ISAppEndpoint mSrc; // Indicates where msg came from. ISMessaging.ISMVMC mVMC; // VMC string sSessionId = ""; string sMsgType = ""; m_Logger.Init("", "", Thread.CurrentThread.Name, "", "", ""); Log(Level.Verbose, "[TI:" + m_iThreadIndex.ToString() + "]" + "ARMsgListenerThread started."); // Initialize session-id collection - Should be the same size as the number of VMCs. // FIX - This may be more than this particular system handles. for (int ii = 0; ii < m_aqAudioIn.Length; ii++) { m_asSessionIds.Add(""); } m_SockConn.m_sockARRead = m_SockConn.m_listenARRead.AcceptSocket(); if (m_SockConn.m_sockARRead != null) { baMsg = new Byte[AMSockData.SIZEOPPACKET]; // Make sure that baAudio size is such as to hold an integer number of audio data packets that collectively are at least 250 ms worth of audio. baAudio = new Byte[AMSockData.SIZE025SECAUDIO + (AMSockData.SIZE025SECAUDIO % AMSockData.SIZEAUDIODATA)]; amsData = new AMSockData(ref m_Logger); iArrayIndex = 0; ISMessaging.Audio.ISMRawData.MuClear(baAudio); while (bCont) // FIX - use failure counter (to prevent infinite looping) { try { // Receive data from socket and extract the message. iSockBytes = m_SockConn.m_sockARRead.Receive(baMsg, 0, baMsg.Length, SocketFlags.None); if (iSockBytes > 0) { amsData.Extract(baMsg); if (baMsg == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "] ARMLT Extract returned null message!"); } else { // If this is a new session coming in, make sure to grab a new VMC, otherwise reuse the one already open. sMsgType = amsData.m_Msg.GetType().ToString(); if (sMsgType == "ISMessaging.Session.ISMSessionBegin") { iVmcIndex = m_RM.AddSession(m_iThreadIndex, amsData.m_sMsgSrc); //iVmcIndex = m_RM.AddSession(m_iThreadIndex, amsData.m_sMsgSrc, 4, 250); if (iVmcIndex == -1) { sSessionId = ""; // The error will get logged after the check below } else { sSessionId = m_RM.GetSessionId(iVmcIndex); } } else { sSessionId = m_RM.GetSessionId(iVmcIndex); if ((sSessionId == null) || (sSessionId.Length == 0)) { iVmcIndex = -1; } else { mVMC = m_RM.GetVMCBySessionid(sSessionId); iVmcIndex = mVMC.m_iKey; } } if (iVmcIndex == -1) { if (sMsgType != "ISMessaging.Audio.ISMRawData") { Log(Level.Exception, string.Format("[TI:{0}] ARMLT got invalid VMC index: {1} on msg: '{2}'.", iVmcIndex.ToString(), iVmcIndex.ToString(), sMsgType)); } } else { m_SockConn.m_VMC = m_RM.GetVMCByKey(iVmcIndex); if (m_SockConn.m_VMC == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "] ARMLT.ThreadProc() returned VMC was null on VMC index: " + iVmcIndex.ToString() + "on msg: " + amsData.m_Msg.GetType().ToString()); } else if (m_SockConn.m_VMC.m_iKey != iVmcIndex) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "] ARMLT.ThreadProc() returned VMC key: " + m_SockConn.m_VMC.m_iKey + " didn't match VMC index: " + iVmcIndex.ToString() + "on msg: " + amsData.m_Msg.GetType().ToString()); } else { switch (sMsgType) { case "ISMessaging.Audio.ISMRawData": { // Grab the session id amsData.m_Msg.m_sSessionId = m_asSessionIds[m_iThreadIndex]; // Should also be the same as sSessionId // Copy audio data from message, if the 1sec buffer is full, forward it on. iMsgBytes = amsData.m_abData.Length; // Do we have enough audio data to pass it to AudioInThread? If not then just save it until we do. if ((iArrayIndex + iMsgBytes) <= baAudio.Length) { Array.Copy(amsData.m_abData, 0, baAudio, iArrayIndex, iMsgBytes); iArrayIndex += iMsgBytes; } else { // Forward audio data mSrc = new ISAppEndpoint(); mVMC = new ISMVMC(); mVMC.Init(iVmcIndex, m_SockConn.m_VMC.m_sDescription, m_SockConn.m_VMC.m_sSessionId); mSrc.Init(mVMC, amsData.m_sMsgSrc, EApplication.eAudioMgr, "Raw data"); ((ISMessaging.Audio.ISMRawData)(amsData.m_Msg)).Init(mSrc, null, ISMessaging.Audio.SOUND_FORMAT.ULAW_8KHZ, baAudio, iArrayIndex); // NOTE - i_Dest is currently null, we're assuming that it isn't used. m_aqAudioIn[iVmcIndex].Push(amsData.m_Msg); // FIX - get array index from message. // Reset index, clear data iArrayIndex = 0; ISMessaging.Audio.ISMRawData.MuClear(baAudio); // Save the audio data that triggered the sending of audio data to AudioInThread but wasn't included in the actual message sent. Array.Copy(amsData.m_abData, 0, baAudio, iArrayIndex, iMsgBytes); iArrayIndex += iMsgBytes; } } break; case "ISMessaging.Audio.ISMDtmf": { // Grab the session id amsData.m_Msg.m_sSessionId = m_asSessionIds[m_iThreadIndex]; // Should also be the same as sSessionId m_aqAudioIn[iVmcIndex].Push(amsData.m_Msg); } break; case "ISMessaging.Session.ISMSessionBegin": { // Store the session-id in the local array and the message m_asSessionIds[m_iThreadIndex] = sSessionId; amsData.m_Msg.m_sSessionId = sSessionId; // Set IpAddress, SessionId in Logger so all subsequent calls to Log() will be identified. (Need-to/should do this in every thread once the ISMSessionBegin comes in.) m_Logger.UpdateValue(Thread.CurrentThread.Name, LoggerCore.eRequiredParams.IpAddress.ToString(), Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(oAddr => oAddr.AddressFamily == AddressFamily.InterNetwork).ToString() ?? ""); m_Logger.UpdateValue(Thread.CurrentThread.Name, LoggerCore.eRequiredParams.SessionId.ToString(), sSessionId); m_Logger.Log(Level.Info, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] <<<ARMLT ISMessaging.Session.ISMSessionBegin(F:'" + ((ISMessaging.Session.ISMSessionBegin)amsData.m_Msg).m_sFromAddr + "', T:'" + ((ISMessaging.Session.ISMSessionBegin)amsData.m_Msg).m_sToAddr + "')>>>"); // m_aqAudioOut[iVmcIndex].Clear(); // FIX: Is this clear causing messages we want to receive to be deleted? Or is it helping us by clearing out residual messages that are meaningless to the new session? m_aqAudioOut[iVmcIndex].Push(amsData.m_Msg); // Push to qAudioOut first, so that socket handling gets done first //m_aqAudioIn[iVmcIndex].Clear(); // Moved this to Begin handler in AudioOut to ensure proper delivery order. //m_aqAudioIn[iVmcIndex].Push((ISMessaging.ISMsg)((ISMessaging.Session.ISMSessionBegin)(amsData.m_Msg)).Clone()); // Clone, just in case Mono is not properly ref-counting. If it isn't, will this cause a leak? } break; case "ISMessaging.Session.ISMSessionEnd": { // Grab the session id amsData.m_Msg.m_sSessionId = m_asSessionIds[m_iThreadIndex]; // Should also be the same as sSessionId // FIX - What happens if there is a socket exception caught in AOT? It will forward an ISMSessionEnd to AIT, but we'll never get here and clear baAudio. m_Logger.Log(Level.Info, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] <<<ARMLT ISMessaging.Session.ISMSessionEnd>>>"); m_aqAudioOut[iVmcIndex].Push(amsData.m_Msg); // Moved the Push to audio-in thread below to AudioOut's End to ensure no overlap //m_aqAudioIn[iVmcIndex].Push((ISMessaging.ISMsg)((ISMessaging.Session.ISMSessionEnd)(amsData.m_Msg)).Clone()); // Pass 'end' on to AudioOut so it can reset socket. // FIX - get array index from message. SEE CLONE COMMENT ABOVE // Reset index, clear data iArrayIndex = 0; ISMessaging.Audio.ISMRawData.MuClear(baAudio); } break; default: { //Console.Error.WriteLine("AudioMgr.AudioEngine_srv.ARMsgListenerThread() Got unknown message from AudioRouter: '{0}'.", amsData.m_Msg.GetType().ToString()); Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT Got unknown message from AudioRouter: " + amsData.m_Msg.GetType().ToString()); } break; } // switch } // if(!iVmcIndex) //Console.Write("*"); } // else vmcindex != -1 } // else msg != null } // if else { // Receive returned 0 bytes, socket has probably been closed down by other side. // Close socket and wait for new connection. m_SockConn.m_VMC = null; //m_RM.ReleaseSession(iVmcIndex); // Fix - Here or ProcessSessionEnd()? try { if (m_SockConn.m_sockARRead.Connected) { m_SockConn.m_sockARRead.Shutdown(SocketShutdown.Both); } } catch (SocketException exc2) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT caught exception when calling Shutdown: " + exc2.ErrorCode.ToString()); } try { m_SockConn.m_sockARRead.Close(); } catch (SocketException exc2) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT caught exception when calling Close: " + exc2.ErrorCode.ToString()); } m_SockConn.m_sockARRead = m_SockConn.m_listenARRead.AcceptSocket(); } } catch (SocketException exc) { // Most likely, the AudioRtr dropped out. // Close socket and wait for new connection. m_SockConn.m_VMC = null; //m_RM.ReleaseSession(iVmcIndex); // Fix - Here or ProcessSessionEnd()? try { // WSAENOTSOCK == 10038, WSAEINTR == 10004 if (exc.ErrorCode == 10038) { // Do nothing here, the socket will get nulled below. Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket NOTSOCK."); } else if (exc.ErrorCode == 10004) { // Do nothing here, the socket will get nulled below. Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket INTR."); } else { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: " + exc.ToString()); if (m_SockConn == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: m_SockConn was null!!! 1"); } else if (m_SockConn.m_sockARRead == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: m_SockConn.m_sockARRead was null."); } else if (!m_SockConn.m_sockARRead.Connected) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: Socket was not connected."); } else { if (m_SockConn.m_sockARRead.Connected) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket.Shutdown..."); m_SockConn.m_sockARRead.Shutdown(SocketShutdown.Both); } Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket.Close..."); m_SockConn.m_sockARRead.Close(); Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket.Closed."); } } } catch (SocketException exc2) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "] ARMLT socket error in cleanup: " + exc2.ErrorCode.ToString()); } catch (Exception exc2) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "] ARMLT Exception in cleanup: " + exc2.ToString()); } if (m_SockConn == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: m_SockConn was null!!! Nothing more we can do, exiting..."); break; } else { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: socket.AcceptSocket..."); m_SockConn.m_sockARRead = m_SockConn.m_listenARRead.AcceptSocket(); } Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: Socket exception handling complete."); } catch (Exception exc) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: " + exc.ToString()); } } // while } if (m_SockConn == null) { Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: m_SockConn was null!!! 3"); } else { if (m_SockConn.m_sockARRead != null) { m_SockConn.m_sockARRead.Shutdown(SocketShutdown.Both); m_SockConn.m_sockARRead.Close(); } if (m_SockConn.m_listenARRead != null) { m_SockConn.m_listenARRead.Stop(); } } Log(Level.Exception, "[TI:" + m_iThreadIndex.ToString() + "][VMC:" + iVmcIndex + "] ARMLT: Exiting thread now."); } // ThreadProc()
public VMCInfo(ref ISMVMC i_VMC) { m_State = VMCState.Unused; m_VMC = i_VMC; } // VMCInfo ctor
public VMCInfo() { m_State = VMCState.Unused; m_VMC = new ISMVMC(); m_VMC.Clear(); }