mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-23 13:05:46 +02:00
Add copyright header information to files that didn't have any. The info is copied from files that already had copyright information. Add info for Alessio when he last commited. Add PCSX2 Dev Team in copyright information.
367 lines
13 KiB
C#
367 lines
13 KiB
C#
/*
|
|
* Copyright (C) 2009-2011 Ferreri Alessio
|
|
* Copyright (C) 2009-2018 PCSX2 Dev Team
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Threading;
|
|
using System.IO;
|
|
using System.ComponentModel;
|
|
using System.Text;
|
|
|
|
namespace TCPLibrary.Core
|
|
{
|
|
/// <summary>
|
|
/// Base TCP server class wrapped around TcpListener.
|
|
/// </summary>
|
|
public class Server
|
|
{
|
|
/// <summary>
|
|
/// Socket maintaining the connection.
|
|
/// </summary>
|
|
private TcpListener _socket;
|
|
/// <summary>
|
|
/// Port to which the server will listen.
|
|
/// </summary>
|
|
private Int32 _port;
|
|
/// <summary>
|
|
/// Whether the server is enabled or not.
|
|
/// </summary>
|
|
private Boolean _enabled;
|
|
/// <summary>
|
|
/// List of the clients connected to the server.
|
|
/// </summary>
|
|
private List<ClientS> _clients;
|
|
/// <summary>
|
|
/// Number of connection permitted in the backlog of the server.
|
|
/// </summary>
|
|
private Int32 _connectionbacklog;
|
|
|
|
/// <summary>
|
|
/// Delegate for the event of the Enabled property change.
|
|
/// </summary>
|
|
/// <param name="sender">Sender of the event.</param>
|
|
public delegate void EnabledChangedHandler(Server sender);
|
|
/// <summary>
|
|
/// Occurs when the Enabled property is changed.
|
|
/// </summary>
|
|
public event EnabledChangedHandler OnEnabledChanged;
|
|
|
|
/// <summary>
|
|
/// Delegate for the event of receiving a line of data from a client.
|
|
/// </summary>
|
|
/// <param name="server">Server raising the event.</param>
|
|
/// <param name="client">Client involved in the communication.</param>
|
|
/// <param name="Data">Line of data received.</param>
|
|
public delegate void DataCommunicationHandler(Server server, ClientS client, Data Data);
|
|
/// <summary>
|
|
/// Occurs when a client send a line of data to the server.
|
|
/// </summary>
|
|
public event DataCommunicationHandler OnClientDataReceived;
|
|
/// <summary>
|
|
/// Occurs before the server send a line of data to a client.
|
|
/// </summary>
|
|
public event DataCommunicationHandler OnClientBeforeDataSent;
|
|
/// <summary>
|
|
/// Occurs after the server send a line of data to a client.
|
|
/// </summary>
|
|
public event DataCommunicationHandler OnClientAfterDataSent;
|
|
|
|
/// <summary>
|
|
/// Delegate for the event of a connection of a client.
|
|
/// </summary>
|
|
/// <param name="server">Server raising the event.</param>
|
|
/// <param name="sender">The new client connected.</param>
|
|
public delegate void ConnectedHandler(Server server, ClientS sender);
|
|
/// <summary>
|
|
/// Occurs after a client is connected to the server.
|
|
/// </summary>
|
|
public event ConnectedHandler OnClientAfterConnect;
|
|
|
|
/// <summary>
|
|
/// Delegate for the event of a connection of a client.
|
|
/// </summary>
|
|
/// <param name="server">Server raising the event.</param>
|
|
/// <param name="client">The new client to be connected.</param>
|
|
/// <param name="args">Specify if the client should be accepted into the server.</param>
|
|
public delegate void BeforeConnectedHandler(Server server, ClientS client, CancelArgs args);
|
|
/// <summary>
|
|
/// Occurs before a client is allowed to connect to the server.
|
|
/// </summary>
|
|
public event BeforeConnectedHandler OnClientBeforeConnect;
|
|
|
|
/// <summary>
|
|
/// Delegate for the event of disconnection of a client.
|
|
/// </summary>
|
|
/// <param name="server">Server raising the event.</param>
|
|
/// <param name="sender">The client disconnected.</param>
|
|
public delegate void DisconnectedHandler(Server server, ClientS sender);
|
|
/// <summary>
|
|
/// Occurs right after a client disconnect from the server.
|
|
/// </summary>
|
|
public event DisconnectedHandler OnClientAfterDisconnected;
|
|
/// <summary>
|
|
/// Occurs before a client disconnect from the server.
|
|
/// </summary>
|
|
public event DisconnectedHandler OnClientBeforeDisconnected;
|
|
|
|
/// <summary>
|
|
/// Get/set the port number to which the server will listen. Cannot be set while the server is active.
|
|
/// </summary>
|
|
/// <exception cref="TCPLibrary.Core.ServerAttivoException" />
|
|
public Int32 Port
|
|
{
|
|
get { return _port; }
|
|
set
|
|
{
|
|
if (Enabled == false)
|
|
_port = value;
|
|
else
|
|
throw new ArgumentException("Impossibile eseguire l'operazione a server attivo");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get/set the enabled state of the server. Setting this to true will actually activate the server.
|
|
/// </summary>
|
|
/// <exception cref="System.Net.Sockets.SocketException" />
|
|
public Boolean Enabled
|
|
{
|
|
get { return _enabled; }
|
|
set
|
|
{
|
|
if (value == true)
|
|
{
|
|
if (_enabled == false)
|
|
ActivateServer();
|
|
}
|
|
else
|
|
{
|
|
if (_enabled == true)
|
|
DeactivateServer();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get/set the number of connection permitted in the backlog of the server.
|
|
/// </summary>
|
|
/// <exception cref="TCPLibrary.Core.ServerAttivoException" />
|
|
public Int32 ConnectionBackLog
|
|
{
|
|
get { return _connectionbacklog; }
|
|
set
|
|
{
|
|
if (Enabled == false)
|
|
_connectionbacklog = value;
|
|
else
|
|
throw new ArgumentException("Impossibile eseguire l'operazione a server attivo");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the list of the clients connected to the server.
|
|
/// </summary>
|
|
public List<ClientS> Clients
|
|
{
|
|
get { return _clients; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Deactivate the server.
|
|
/// </summary>
|
|
protected virtual void DeactivateServer()
|
|
{
|
|
_enabled = false;
|
|
_socket.Stop();
|
|
_socket = null;
|
|
|
|
lock (_clients)
|
|
{
|
|
for (int i = 0; i < _clients.Count; i++)
|
|
_clients[i].Disconnect();
|
|
}
|
|
|
|
if (OnEnabledChanged != null)
|
|
OnEnabledChanged(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Activate the server.
|
|
/// </summary>
|
|
protected virtual void ActivateServer()
|
|
{
|
|
_socket = new TcpListener(IPAddress.Any, Port);
|
|
_socket.Start(ConnectionBackLog);
|
|
Thread thd = new Thread(new ThreadStart(MainThread));
|
|
thd.Name = "Server on port " + Port.ToString();
|
|
thd.IsBackground = true;
|
|
thd.Start();
|
|
_enabled = true;
|
|
if (OnEnabledChanged != null)
|
|
OnEnabledChanged(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Broadcast a line of data to all the clients connected to the server.
|
|
/// </summary>
|
|
/// <param name="Data">Line of data to be sent.</param>
|
|
/// <exception cref="TCPLibrary.Core.ServerNonAttivoException" />
|
|
public void Broadcast(Data Data)
|
|
{
|
|
if (Enabled)
|
|
{
|
|
lock (_clients)
|
|
{
|
|
foreach (var itm in _clients)
|
|
if (itm.Connected)
|
|
itm.Send(Data);
|
|
}
|
|
}
|
|
else
|
|
throw new ArgumentException("Unable to execute this operation when the server is inactive.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Base constructor of the class.
|
|
/// </summary>
|
|
public Server()
|
|
{
|
|
_clients = new List<ClientS>();
|
|
_port = 0;
|
|
_connectionbacklog = 0;
|
|
_enabled = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Thread function that actually run the server socket work.
|
|
/// </summary>
|
|
private void MainThread()
|
|
{
|
|
try
|
|
{
|
|
while (Enabled == true)
|
|
{
|
|
TcpClient client = _socket.AcceptTcpClient();
|
|
|
|
CancelArgs args = new CancelArgs(false);
|
|
ClientS cl = CreateClient(client);
|
|
if (OnClientBeforeConnect != null)
|
|
OnClientBeforeConnect(this, cl, args);
|
|
|
|
if (args.Cancel != true)
|
|
{
|
|
lock (_clients)
|
|
{
|
|
_clients.Add(cl);
|
|
}
|
|
|
|
ASCIIEncoding ae = new ASCIIEncoding();
|
|
byte[] arr = ae.GetBytes("CONNECTEDTCPSERVER");
|
|
|
|
cl.Send(new Data(arr));
|
|
|
|
if (OnClientAfterConnect != null)
|
|
OnClientAfterConnect(this, cl);
|
|
cl.Start();
|
|
}
|
|
else
|
|
{
|
|
client.GetStream().Close();
|
|
client.Close();
|
|
}
|
|
}
|
|
}
|
|
catch (SocketException)
|
|
{
|
|
Enabled = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Overridable function that create the structure to memorize the client data.
|
|
/// </summary>
|
|
/// <param name="socket">Socket of the client.</param>
|
|
/// <returns>The structure in which memorize all the information of the client.</returns>
|
|
protected virtual ClientS CreateClient(TcpClient socket)
|
|
{
|
|
ClientS cl = new ClientS(this, socket);
|
|
return cl;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raise the OnClientAfterDataSent event.
|
|
/// </summary>
|
|
/// <param name="cl">Client that raised the event.</param>
|
|
/// <param name="data">Line of data sent.</param>
|
|
internal void RaiseAfterDataSentEvent(ClientS cl, Data data)
|
|
{
|
|
if (OnClientAfterDataSent != null)
|
|
OnClientAfterDataSent(this, cl, data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raise the OnClientBeforeDataSent event.
|
|
/// </summary>
|
|
/// <param name="cl">Client that raised the event.</param>
|
|
/// <param name="data">Line of data sent.</param>
|
|
internal void RaiseBeforeDataSentEvent(ClientS cl, Data data)
|
|
{
|
|
if (OnClientBeforeDataSent != null)
|
|
OnClientBeforeDataSent(this, cl, data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raise the OnDataReceived event.
|
|
/// </summary>
|
|
/// <param name="cl">Client that raised the event.</param>
|
|
/// <param name="data">Line of data received.</param>
|
|
internal void RaiseDataReceivedEvent(ClientS cl, Data data)
|
|
{
|
|
if (OnClientDataReceived != null)
|
|
OnClientDataReceived(this, cl, data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raise the OnClientAfterDisconnected event.
|
|
/// </summary>
|
|
/// <param name="cl">Client that raised the event.</param>
|
|
internal void RaiseClientAfterDisconnectedEvent(ClientS cl)
|
|
{
|
|
if (OnClientAfterDisconnected != null)
|
|
OnClientAfterDisconnected(this, cl);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raise the OnClientBeforeDisconnected event.
|
|
/// </summary>
|
|
/// <param name="cl">Client that raised the event.</param>
|
|
internal void RaiseClientBeforeDisconnectedEvent(ClientS cl)
|
|
{
|
|
if (OnClientBeforeDisconnected != null)
|
|
OnClientBeforeDisconnected(this, cl);
|
|
}
|
|
}
|
|
}
|