private void RTSPMessageReceived(RTSPConnection rtspConnection, IPEndPoint remoteEndPoint, byte[] buffer) { if (RTSPClientMessageReceived != null) { RTSPClientMessageReceived(rtspConnection, remoteEndPoint, buffer); } }
/// <summary> /// Sends data to the RTSP client listening on the destination end point. /// </summary> /// <param name="destinationEndPoint">The destination to send the message to.</param> /// <param name="buffer">The data to send.</param> public void Send(IPEndPoint dstEndPoint, byte[] buffer) { try { if (buffer == null) { throw new ApplicationException("An empty buffer was specified to Send in SIPTCPChannel."); } else if (m_localIPEndPoint.ToString() == dstEndPoint.ToString()) { Logger.Logger.Error("The RTSPServer blocked Send to " + dstEndPoint.ToString() + " as it was identified as a locally hosted TCP socket.->" + Encoding.UTF8.GetString(buffer)); throw new ApplicationException( "A Send call was made in RTSPServer to send to another local TCP socket."); } else { // Lookup a client socket that is connected to the destination. if (m_connectedSockets.ContainsKey(dstEndPoint.ToString())) { RTSPConnection rtspClientConnection = m_connectedSockets[dstEndPoint.ToString()]; try { rtspClientConnection.Stream.BeginWrite(buffer, 0, buffer.Length, new AsyncCallback(EndSend), rtspClientConnection); rtspClientConnection.LastTransmission = DateTime.Now; } catch (SocketException) { Logger.Logger.Error("RTSPServer could not send to TCP socket " + dstEndPoint + ", closing and removing."); rtspClientConnection.Stream.Close(); m_connectedSockets.Remove(dstEndPoint.ToString()); } } else { Logger.Logger.Warn("Could not send RTSP packet to TCP " + dstEndPoint + " as there was no current connection to the client, dropping message."); } } } catch (ApplicationException appExcp) { Logger.Logger.Error("ApplicationException RTSPServer Send (sendto=>" + dstEndPoint + "). ->" + appExcp.Message); throw; } catch (Exception excp) { Logger.Logger.Error("Exception (" + excp.GetType().ToString() + ") RTSPServer Send (sendto=>" + dstEndPoint + "). ->" + excp.Message); throw; } }
private void EndSend(IAsyncResult ar) { try { RTSPConnection rtspConnection = (RTSPConnection)ar.AsyncState; rtspConnection.Stream.EndWrite(ar); } catch (Exception excp) { logger.Error("Exception RTSPServer EndSend. " + excp.Message); } }
private void AcceptConnections(string threadName) { try { Thread.CurrentThread.Name = threadName; Logger.Logger.Debug( "RTSP server socket on " + m_localIPEndPoint + " accept connections thread started."); while (!Closed) { try { TcpClient tcpClient = m_tcpServerListener.AcceptTcpClient(); tcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); IPEndPoint remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint; Logger.Logger.Debug("RTSP server accepted connection from " + remoteEndPoint + "."); RTSPConnection rtspClientConnection = new RTSPConnection(this, tcpClient.GetStream(), remoteEndPoint); lock (m_connectedSockets) { m_connectedSockets.Add(remoteEndPoint.ToString(), rtspClientConnection); } rtspClientConnection.RTSPSocketDisconnected += RTSPClientDisconnected; rtspClientConnection.RTSPMessageReceived += RTSPMessageReceived; rtspClientConnection.Stream.BeginRead(rtspClientConnection.SocketBuffer, 0, MaxMessageSize, new AsyncCallback(ReceiveCallback), rtspClientConnection); } catch (Exception acceptExcp) { // This exception gets thrown if the remote end disconnects during the socket accept. Logger.Logger.Error("Exception RTSPServer accepting socket (" + acceptExcp.GetType() + "). ->" + acceptExcp.Message); } } Logger.Logger.Debug("RTSP server socket on " + m_localIPEndPoint + " listening halted."); } catch (Exception excp) { Logger.Logger.Error("Exception RTSPServer Listen. ->" + excp.Message); } }
private void ReceiveCallback(IAsyncResult ar) { RTSPConnection rtspConnection = (RTSPConnection)ar.AsyncState; try { int bytesRead = rtspConnection.Stream.EndRead(ar); if (rtspConnection.SocketReadCompleted(bytesRead)) { rtspConnection.Stream.BeginRead(rtspConnection.SocketBuffer, rtspConnection.SocketBufferEndPosition, MaxMessageSize - rtspConnection.SocketBufferEndPosition, new AsyncCallback(ReceiveCallback), rtspConnection); } } catch (SocketException) // Occurs if the remote end gets disconnected. { } catch (Exception excp) { logger.Warn("Exception RTSPServer ReceiveCallback. " + excp.Message); RTSPClientSocketDisconnected(rtspConnection.RemoteEndPoint); } }
/// <summary> /// Periodically checks the established connections and closes any that have not had a transmission for a specified /// period or where the number of connections allowed per IP address has been exceeded. /// </summary> private void PruneConnections(string threadName) { try { Thread.CurrentThread.Name = threadName; Thread.Sleep(INITIALPRUNE_CONNECTIONS_DELAY); while (!Closed) { // Check the TCP connections established by RTSP clients for any inactive ones. try { RTSPConnection inactiveConnection = null; lock (m_connectedSockets) { var inactiveConnectionQuery = from connection in m_connectedSockets where connection.Value.LastTransmission < DateTime.Now.AddMinutes(PRUNE_NOTRANSMISSION_MINUTES * -1) select connection.Key; var inactiveConnectionKey = inactiveConnectionQuery.FirstOrDefault(); while (inactiveConnectionKey != null) { if (inactiveConnectionKey != null) { inactiveConnection = m_connectedSockets[inactiveConnectionKey]; m_connectedSockets.Remove(inactiveConnectionKey); logger.Debug("Pruning inactive RTSP connection on to remote end point " + inactiveConnection.RemoteEndPoint + "."); inactiveConnection.Close(); } inactiveConnectionKey = inactiveConnectionQuery.FirstOrDefault(); } } } catch (SocketException) { // Will be thrown if the socket is already closed. } catch (Exception pruneExcp) { logger.Error("Exception RTSPServer PruneConnections (pruning). " + pruneExcp.Message); } // Check the list of active RTSP sessions for any that have stopped communicating or that have closed. try { RTSPSession inactiveSession = null; lock (m_rtspSessions) { var inactiveSessionQuery = from session in m_rtspSessions where (session.Value.DontTimeout == false && session.Value.RTPLastActivityAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) && session.Value.ControlLastActivityAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) && session.Value.StartedAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1) && session.Value.CreatedAt < DateTime.Now.AddSeconds(CLOSE_RTSP_SESSION_NO_DATA_SECONDS * -1)) || session.Value.IsClosed select session.Key; var inactiveSessionKey = inactiveSessionQuery.FirstOrDefault(); while (inactiveSessionKey != null) { inactiveSession = m_rtspSessions[inactiveSessionKey]; m_rtspSessions.Remove(inactiveSessionKey); if (!inactiveSession.IsClosed) { logger.Debug("Closing inactive RTSP session for session ID " + inactiveSession.SessionID + " established from RTSP client on " + inactiveSession.RemoteEndPoint + " (started at " + inactiveSession.StartedAt + ", RTP last activity at " + inactiveSession.RTPLastActivityAt + ", control last activity at " + inactiveSession.ControlLastActivityAt + ", is closed " + inactiveSession.IsClosed + ")."); inactiveSession.Close(); } inactiveSessionKey = inactiveSessionQuery.FirstOrDefault(); } } } catch (Exception rtspSessExcp) { logger.Error("Exception RTSPServer checking for inactive RTSP sessions. " + rtspSessExcp); } Thread.Sleep(PRUNE_CONNECTIONS_INTERVAL * 1000); } logger.Debug("RTSPServer socket on " + m_localIPEndPoint.ToString() + " pruning connections halted."); } catch (Exception excp) { logger.Error("Exception RTSPServer PruneConnections. " + excp.Message); } }