/*
Media File XStream, Network file stream server supporting XBMSP
Copyright (C) 2004 j3g
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This project can be found on SourceForge.
http://sourceforge.net/projects/mfxstream
*/
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace MediaStream{
/// <summary>
///
/// </summary>
public class CIPConnection
{
// Socket event handlers
public delegate void CLOSE_HANDLER(CIPConnection pConnection);
public delegate void ERROR_HANDLER(CIPConnection pConnection, Exception pException);
public delegate void MESSAGE_HANDLER(CIPConnection pConnection, Int32 nBytesRead);
// Public properties
public Byte [] GetMessage { get { return(this._pbMessageBuffer); } }
public Object GetStateObject { get { return(this._pStateObject); } set { this._pStateObject = value; }}
public String GetIPAddress { get { return(this._pConnectionSocket.RemoteEndPoint.ToString().Split(':')[0]); } }
// Private attributes
private CLOSE_HANDLER _pfnCloseHandler;
private ERROR_HANDLER _pfnErrorHandler;
private MESSAGE_HANDLER _pfnMessageHandler;
private Int32 _nMessageBufferSize;
private Byte [] _pbMessageBuffer;
private Object _pStateObject;
private Boolean _blnDisposed;
private AsyncCallback _pfnCallbackRead;
private AsyncCallback _pfnCallbackWrite;
private CIPListener _pListener;
private Socket _pConnectionSocket;
// private String _strIPAddress;
// private Int16 _nPort;
private NetworkStream _pNetworkStream;
public CIPConnection(CIPListener pListener, Socket pConnectionSocket,
Int32 nMessageBufferSize, MESSAGE_HANDLER pfnMessageHandler,
CLOSE_HANDLER pfnCloseHandler, ERROR_HANDLER pfnErrorHandler)
{
this._nMessageBufferSize = nMessageBufferSize;
this._pbMessageBuffer = new Byte[this._nMessageBufferSize];
this._pfnMessageHandler = pfnMessageHandler;
this._pfnCloseHandler = pfnCloseHandler;
this._pfnErrorHandler = pfnErrorHandler;
this._pfnCallbackRead = new AsyncCallback(ReadComplete);
this._pfnCallbackWrite = new AsyncCallback(SendComplete);
this._blnDisposed = false;
this._pListener = pListener;
this._pConnectionSocket = pConnectionSocket;
// Connection socket option
this._pConnectionSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.ReceiveBuffer, 1024 * CSettings.GetClientBufferSize);
this._pConnectionSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.SendBuffer, 1024 * CSettings.GetClientBufferSize);
this._pConnectionSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, System.Net.Sockets.SocketOptionName.DontLinger, 1);
this._pConnectionSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Tcp, System.Net.Sockets.SocketOptionName.NoDelay, 1);
this._pNetworkStream = new NetworkStream(this._pConnectionSocket, System.IO.FileAccess.ReadWrite);
Read();
}
~CIPConnection()
{
if (!this._blnDisposed)
Dispose();
}
public void Disconnect()
{
if (null != this._pNetworkStream)
this._pNetworkStream.Close();
if (null != this._pConnectionSocket)
this._pConnectionSocket.Close();
this._pConnectionSocket = null;
this._pNetworkStream = null;
}
public void Dispose()
{
try
{
this._blnDisposed = true;
Disconnect();
}
catch
{
}
if (null != this._pListener)
this._pListener.RemoveConnection(this);
}
private void Read()
{
try
{
this._pNetworkStream.BeginRead(this._pbMessageBuffer, 0,
this._nMessageBufferSize , this._pfnCallbackRead, null);
}
catch
{
throw new Exception("Socket Closed");
}
}
private void ReadComplete(IAsyncResult ar)
{
try
{
if (this._pNetworkStream.CanRead)
{
Int32 nBytesRead = this._pNetworkStream.EndRead(ar);
if (0 < nBytesRead)
{
try
{
Monitor.Enter(_pfnMessageHandler);
_pfnMessageHandler(this, nBytesRead);
Monitor.Exit(_pfnMessageHandler);
}
catch(Exception ex)
{
string str = ex.Message;
}
Read();
}
else
throw new Exception("Shut Down");
}
else
throw new Exception("Shut Down");
}
catch
{
try
{
_pfnCloseHandler(this);
}
catch
{
}
Dispose();
}
}
public void Send(Byte [] pbMessage)
{
try
{
this._pNetworkStream.BeginWrite(pbMessage, 0, pbMessage.Length, _pfnCallbackWrite, null);
}
catch
{
throw new Exception("Socket Closed");
}
}
private void SendComplete(IAsyncResult ar)
{
try
{
this._pNetworkStream.EndWrite(ar);
}
catch
{
}
}
}
/// <summary>
///
/// </summary>
public class CIPListener
{
// Socket event handlers
public delegate void ACCEPT_HANDLER(CIPConnection pConn);
public delegate void CLOSE_HANDLER(CIPConnection pConn);
public delegate void ERROR_HANDLER(CIPConnection pConn, Exception pException);
public delegate void MESSAGE_HANDLER(CIPConnection pConn, Int32 nBytesRead);
// Public properties
private Boolean _blnIsStarted;
public Boolean IsStarted { get { return(_blnIsStarted); } }
// Private attributes
private ACCEPT_HANDLER _pfnAcceptHandler;
private CLOSE_HANDLER _pfnCloseHandler;
private ERROR_HANDLER _pfnErrorHandler;
private MESSAGE_HANDLER _pfnMessageHandler;
public ACCEPT_HANDLER GetAcceptHandler { set { _pfnAcceptHandler = value; } }
public CLOSE_HANDLER GetCloseHandler { set { _pfnCloseHandler = value;}}
public ERROR_HANDLER GetErrorHandler { set { _pfnErrorHandler = value;}}
public MESSAGE_HANDLER GetMessageHandler { set { _pfnMessageHandler = value;}}
private Int32 _nMaxConnections;
private IPAddress _IPAddress;
private Int16 _nPort;
// private System.Collections.Hashtable _pConnectionList;
// private System.Collections.IDictionaryEnumerator _pConnectionListEnumerator;
// private Int32 _nConnectionList;
private int _nConnectionList
{
get
{
Monitor.Enter(this._ConnectionList);
int nCount = this._ConnectionList.Count;
Monitor.Exit(this._ConnectionList);
return(nCount);
}
}
private ArrayList _ConnectionList;
private Int32 _nMessageBufferSize;
private Boolean _blnDisposed;
private Boolean _blnClosing;
private Thread _pListenerThread;
private ProtocolType _ProtocolType;
private ManualResetEvent _mreWait = new ManualResetEvent(false);
public CIPListener()
{
this._blnIsStarted = false;
this._blnClosing = false;
this._blnDisposed = false;
}
~CIPListener()
{
if (!this._blnDisposed)
Dispose();
}
public void Start(String strIPAddress, Int16 nPort, Int32 nMaxConnections, Int32 nMessageBufferSize, ProtocolType ptProtocolType)
{
if (null != this._pListenerThread) return;
if (this._blnIsStarted) return;
this._ProtocolType = ptProtocolType;
this._nMaxConnections = nMaxConnections;
this._ConnectionList = new ArrayList(nMaxConnections);
this._IPAddress = IPAddress.Parse(strIPAddress);
this._nPort = nPort;
this._nMessageBufferSize = nMessageBufferSize;
// Start listener thread
this._pListenerThread = new Thread(new ThreadStart(ListenerThread));
this._pListenerThread.Name = "Listener";
this._pListenerThread.Start();
this._blnIsStarted = true;
}
virtual public void Stop()
{
Exception ex = null;
try
{
Monitor.Enter(this._ConnectionList);
if (null != this._pListenerThread)
{
this._blnClosing = true;
this._mreWait.Set();
this._pListenerThread = null;
}
if (null != this._ConnectionList)
{
foreach (CIPConnection pConn in this._ConnectionList)
{
pConn.Disconnect();
}
this._ConnectionList.Clear();
}
// Wait for socket to close all connections
GC.Collect();
GC.WaitForPendingFinalizers();
this._nMessageBufferSize = 0;
this._blnIsStarted = false;
}
catch (Exception e) { ex = e; }
finally
{
Monitor.Exit(this._ConnectionList);
if (null != ex)
HandleError(null, ex);
}
}
public void Dispose()
{
try
{
this._blnDisposed = true;
if (null != this._pListenerThread)
Stop();
}
catch (Exception e)
{
HandleError(null, e);
}
}
private void HandleError(CIPConnection pConn, Exception ex)
{
Monitor.Enter(this._pfnErrorHandler);
this._pfnErrorHandler(pConn, ex);
Monitor.Exit(this._pfnErrorHandler);
}
public void AddConnection(CIPConnection pConn)
{
Exception ex = null;
try
{
Monitor.Enter(this._ConnectionList);
this._ConnectionList.Add(pConn);
}
catch (Exception e) { ex = e; }
finally
{
Monitor.Exit(this._ConnectionList);
if (null != ex)
HandleError(pConn, ex);
}
}
public void RemoveConnection(CIPConnection pConn)
{
Exception ex = null;
try
{
Monitor.Enter(this._ConnectionList);
this._ConnectionList.Remove(pConn);
}
catch (Exception e) { ex = e; }
finally
{
Monitor.Exit(this._ConnectionList);
if (null != ex)
HandleError(pConn, ex);
}
}
// public void RemoveConnection1(CIPConnection pConnection)
// {
// Monitor.Enter(this._pConnectionList);
// try
// {
// this._pConnectionList.Remove(pConnection.GetHashCode());
// this._nConnectionList--;
// }
// catch (Exception e)
// {
// Monitor.Enter(_pfnErrorHandler);
// this._pfnErrorHandler(pConnection, e);
// Monitor.Exit(_pfnErrorHandler);
// }
// Monitor.Exit(this._pConnectionList);
// }
private void ListenerThread()
{
try
{
IPEndPoint localEndPoint = new IPEndPoint(this._IPAddress, this._nPort);
Socket psListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, this._ProtocolType);
this._blnClosing = false;
psListener.Bind(localEndPoint);
psListener.Listen(CSettings.GetMaxClientConnections + 10);
while (!this._blnClosing)
{
this._mreWait.Reset();
psListener.BeginAccept(new AsyncCallback(AcceptComplete), psListener);
this._mreWait.WaitOne();
}
psListener.Close();
}
catch (Exception e)
{
HandleError(null, e);
}
}
private void AcceptComplete(IAsyncResult ar)
{
this._mreWait.Set();
Socket psListener = (Socket) ar.AsyncState;
// if Listner socket is closed...
if (-1 == psListener.Handle.ToInt32()) return;
Socket psConnection = psListener.EndAccept(ar);
try
{
if (this._nConnectionList < this._nMaxConnections)
{
CIPConnection pConnection = null;
if (ProtocolType.Tcp == _ProtocolType)
{
pConnection = new CIPConnection(this,
psConnection, this._nMessageBufferSize,
new CIPConnection.MESSAGE_HANDLER(_pfnMessageHandler),
new CIPConnection.CLOSE_HANDLER(_pfnCloseHandler),
new CIPConnection.ERROR_HANDLER(_pfnErrorHandler));
}
AddConnection(pConnection);
Monitor.Enter(this._pfnAcceptHandler);
this._pfnAcceptHandler(pConnection);
Monitor.Exit(this._pfnAcceptHandler);
}
else
{
HandleError(null, new Exception("Client connection failed, too many connections!"));
psConnection.Close();
}
}
catch (Exception e)
{
HandleError(null, e);
}
}
}
// public class CTCPListener : CIPListener
// {
// public void Start(String strIPAddress, Int16 nPort, Int32 nMaxConnections, Int32 nMessageBufferSize)
// {
// base.Start(strIPAddress, nPort, nMaxConnections, nMessageBufferSize, ProtocolType.Tcp);
// }
// }
public class CConvertUtility
{
public Byte [] StringToByteArray(String Text)
{
Byte [] pbResult = new Byte[Text.Length];
for (Int32 i = 0; i < Text.Length; i++)
pbResult[i] = (Byte) Text[i];
return (pbResult);
}
public String ByteArrayToString(Byte [] pbBuffer, Int32 nStart, Int32 nLength)
{
String strResult = "";
for (Int32 i = 0; i < nLength; i++)
strResult += (char) pbBuffer[i + nStart];
return (strResult);
}
public Int32 BufferToInt32_(Byte [] pbBuffer, Int32 nPos)
{
Int32 nRet = (Int32)(pbBuffer[nPos]);
for (Int16 i = 1; i < 4; i++)
{
nRet <<= 8;
nRet |= (Int32)(pbBuffer[i + nPos]);
}
return nRet;
}
public Int32 BufferToInt32(Byte [] pbBuffer, Int32 nPos)
{
Int32 nRet = (Int32)(pbBuffer[0 + nPos]);
nRet <<= 8;
nRet |= (Int32)(pbBuffer[1 + nPos]);
nRet <<= 8;
nRet |= (Int32)(pbBuffer[2 + nPos]);
nRet <<= 8;
nRet |= (Int32)(pbBuffer[3 + nPos]);
return nRet;
}
public long BufferToLong(Byte [] pbBuffer, Int32 nPos)
{
long nRet = (long)(pbBuffer[0 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[1 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[2 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[3 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[4 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[5 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[6 + nPos]);
nRet <<= 8;
nRet |= (long)(pbBuffer[7 + nPos]);
return nRet;
}
public void Int32ToBuffer(Byte [] pbBuffer, Int32 n, Int32 nPos)
{
pbBuffer[3 + nPos] = (Byte)(n & 0xff);
n >>= 8;
pbBuffer[2 + nPos] = (Byte)(n & 0xff);
n >>= 8;
pbBuffer[1 + nPos] = (Byte)(n & 0xff);
n >>= 8;
pbBuffer[0 + nPos] = (Byte)(n & 0xff);
}
public Byte [] GetByteArray(Byte [] pbBuffer, Int32 nStart, Int32 nLength)
{
Byte [] pbRet = new Byte[nLength];
for (Int32 i = 0; i < nLength; i++)
pbRet[i] = pbBuffer[i + nStart];
return pbRet;
}
}
}
|