/// <summary>
 /// Connect to a server.
 /// </summary>
 /// <param name="ConnectionInfo">ConnectionInfo object containing connection information</param>
 /// <param name="ConnectionMode">Mode describing the type of connection</param>
 /// <param name="Params">Optional params to be passed to the ServerInfo object</param>
 public static void ConnectToServer(ConnectionInfo ConnectionInfo, ConnectionMode ConnectionMode, String[] Params)
 {
     if ((ConnectionMode != ConnectionMode.FirstConnect) && (ConnectionMode != ConnectionMode.SongRequest)) {
         Forms.MainFrm.UpdateStatusLabel("Connecting to \"" + ConnectionInfo.Description + "\" (" + ConnectionMode.ToString() + " mode).");
     }
     Log.AddStatusText("Connecting to server (" + ConnectionMode.ToString() + " mode): " + ConnectionInfo.Description);
     if (ConnectionInfo.Hostname != "") {
         Log.AddStatusText("Attempting to resolve hostname: " + ConnectionInfo.Hostname);
         IPHostEntry hostInfo = Dns.GetHostEntry(ConnectionInfo.Hostname);
         if (hostInfo.AddressList.Length > 0) {
             ConnectionInfo.IPAddress = hostInfo.AddressList[0].ToString();
             Log.AddStatusText("Hostname (" + ConnectionInfo.Hostname + ") resolved to " + ConnectionInfo.IPAddress + ".");
         }
     }
     serverConnection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
     IPEndPoint connectionEndpoint = new IPEndPoint(IPAddress.Parse(ConnectionInfo.IPAddress), ConnectionInfo.InfoPort);
     try {
         serverConnection.Connect(connectionEndpoint);
     } catch (SocketException Se) {
         if (Se.ErrorCode == 10061) {
             ServerManager.SetOffline(ConnectionInfo.InternalGUID);
             Log.AddStatusText("Info server @ " + ConnectionInfo.IPAddress + ":" + ConnectionInfo.InfoPort + " refused connection.");
             if ((ConnectionMode != ConnectionMode.FirstConnect) && (ConnectionMode != ConnectionMode.OnlineTest) && (ConnectionMode != ConnectionMode.SongRequest)) {
                 MessageBox.Show("The Info Server refused connection. Is the server running? Are ports forwarded?");
             }
             if (ConnectionMode == ConnectionMode.OnlineTest) {
                 Forms.MainFrm.UpdateStatusLabel("Server \"" + ConnectionInfo.Description + "\" is offline. Song skipped.");
             }
         }
     }
     if (serverConnection.Connected) {
         ServerInfo tempServerInfo = new ServerInfo(serverConnection, SocketCounter, ConnectionInfo, ConnectionMode);
         if (Params.Length > 0) { tempServerInfo.ConnectionParams = Params; }
         ServerInfoList.Add(tempServerInfo);
         WaitForData(tempServerInfo);
         Interlocked.Increment(ref SocketCounter);
     } else {
         Forms.MainFrm.UpdateStatusLabel("Ready");
     }
 }
 /// <summary>
 /// Constructor which starts a SocketPacket based on a Server object.
 /// </summary>
 /// <param name="iServer">Associated Server object</param>
 public SocketPacket(ServerInfo iServer)
 {
     Socket = iServer.Socket;
     ServerInfoIndex = iServer.Index;
     ServerInfo = iServer;
     Forms.MainFrm.UpdateStatusProgressBar("Increment", DataBuffer.Length);
 }
 /// <summary>
 /// An always-active function that waits for the server to send data to the client. Eventually trigers OnDataReceived().
 /// </summary>
 /// <param name="waitServerInfo">Associated Server object</param>
 private static void WaitForData(ServerInfo waitServerInfo)
 {
     if (asyncCallBack == null) { asyncCallBack = new AsyncCallback(OnDataReceived); }
     if (waitServerInfo != null) {
         SocketPacket SocketPacket = new SocketPacket(waitServerInfo);
         asyncResult = SocketPacket.Socket.BeginReceive(
             SocketPacket.DataBuffer,
             0, SocketPacket.DataBuffer.Length,
             SocketFlags.None,
             asyncCallBack,
             SocketPacket
         );
     }
 }