private void PrimeConnection(TcpClient client) { LOG.Info(string.Format("Socket connection established to {0}, initiating session", client.Client.RemoteEndPoint)); ConnectRequest conReq = new ConnectRequest(0, lastZxid, Convert.ToInt32(conn.SessionTimeout.TotalMilliseconds), conn.SessionId, conn.SessionPassword); byte[] buffer; using (MemoryStream ms = new MemoryStream()) using (EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Big, ms, Encoding.UTF8)) { BinaryOutputArchive boa = BinaryOutputArchive.getArchive(writer); boa.WriteInt(-1, "len"); conReq.Serialize(boa, "connect"); ms.Position = 0; writer.Write(ms.ToArray().Length - 4); buffer = ms.ToArray(); } lock (outgoingQueueLock) { if (!ClientConnection.disableAutoWatchReset && (!zooKeeper.DataWatches.IsEmpty() || !zooKeeper.ExistWatches.IsEmpty() || !zooKeeper.ChildWatches.IsEmpty())) { var sw = new SetWatches(lastZxid, zooKeeper.DataWatches, zooKeeper.ExistWatches, zooKeeper.ChildWatches); var h = new RequestHeader(); h.Type = (int)OpCode.SetWatches; h.Xid = -8; Packet packet = new Packet(h, new ReplyHeader(), sw, null, null, null, null, null); outgoingQueue.AddFirst(packet); } foreach (ClientConnection.AuthData id in conn.authInfo) { outgoingQueue.AddFirst(new Packet(new RequestHeader(-4, (int)OpCode.Auth), null, new AuthPacket(0, id.scheme, id.data), null, null, null, null, null)); } outgoingQueue.AddFirst((new Packet(null, null, null, null, buffer, null, null, null))); } lock (this) { EnableWrite(); } if (LOG.IsDebugEnabled) { LOG.Debug("Session establishment request sent on " + client.Client.RemoteEndPoint); } }
/// <summary> /// Connect to a server ip address /// </summary> /// <returns>Connection success</returns> public bool Connect(string ip) { Console.WriteLine("Connecting to " + ip); UdpClient = new UdpClient(ClientPort); Endpoint = new IPEndPoint(IPAddress.Parse(ip), Server.DefaultPort); // connect to server UdpClient.Connect(Endpoint); // send connect request var connectRequest = new ConnectRequest(); var data = connectRequest.Serialize(); UdpClient.Send(data, data.Length); // wait for response byte[] responseBytes = null; try { responseBytes = UdpClient.Receive(ref Endpoint); } catch (Exception) { //Console.WriteLine(e); Console.WriteLine("Couldn't connect to server"); return(false); } ShowResponse(responseBytes); // deserialize response packet var packet = GetPacket(responseBytes); if (packet.Type == PacketType.ConnectResponse) { var responsePacket = (ConnectResponse)packet; if (responsePacket.ConnectResponseType != ConnectResponseType.Accepted || !responsePacket.Reason.Equals("ok")) { Console.WriteLine("Connection refused"); return(false); } } else if (packet.Type == PacketType.PingRequest) { var pingRequest = (PingRequest)packet; // craft a ping response with matching info // this small handshake should hopefully prevent ip spoofing / amplification // before the larger packets are sent for world state var pingResponse = new PingResponse(pingRequest); var pingResponseBytes = pingResponse.Serialize(); UdpClient.Send(pingResponseBytes, pingResponseBytes.Length); // wait for world data responseBytes = UdpClient.Receive(ref Endpoint); //ShowResponse(responseBytes); var gameState = (Packet.GameState)GetPacket(responseBytes); GameState = gameState.State; Console.WriteLine(string.Format("Connected to {0}:{1}", ip, Server.DefaultPort)); IsConnected = true; // start receiving async UdpClient.BeginReceive(ReceiveData, UdpClient); } else { Console.WriteLine("Unknown connection response: " + packet.Type); return(false); } return(true); }
/// <summary> /// Initializes a new instance of the <see cref="NamedPipeClient" /> class. /// </summary> /// <param name="description">The client description.</param> /// <param name="server">The server.</param> /// <param name="onReceive">The action to call on receipt of a message.</param> /// <param name="token">The token.</param> private NamedPipeClient( [NotNull] string description, [NotNull] NamedPipeServerInfo server, [NotNull] Action <Message> onReceive, CancellationToken token = default(CancellationToken)) { if (description == null) { throw new ArgumentNullException("description"); } if (server == null) { throw new ArgumentNullException("server"); } if (onReceive == null) { throw new ArgumentNullException("onReceive"); } _server = server; _cancellationTokenSource = new CancellationTokenSource(); CancellationToken disposeToken = _cancellationTokenSource.Token; _clientTask = Task.Run( async() => { try { using (ITokenSource tokenSource = token.CreateLinked(disposeToken)) using ( OverlappingPipeClientStream stream = new OverlappingPipeClientStream( _server.Host, _server.FullName, PipeTransmissionMode.Message)) { _state = PipeState.Open; token = tokenSource.Token; // We need to support cancelling the connect. await stream.Connect(token).ConfigureAwait(false); ConnectResponse connectResponse = null; DisconnectResponse disconnectResponse = null; if (!token.IsCancellationRequested) { // Set the stream. _stream = stream; _state = PipeState.AwaitingConnect; // Kick off a connect request, but don't wait for it's result as we're the task that will receive it! ConnectRequest connectRequest = new ConnectRequest(description); await stream.WriteAsync(connectRequest.Serialize(), token).ConfigureAwait(false); // Keep going as long as we're connected. try { while (stream.IsConnected && !disposeToken.IsCancellationRequested) { // Read data in. byte[] data = await stream.ReadAsync(disposeToken).ConfigureAwait(false); if (data == null) { break; } // Deserialize the incoming message. Message message = Message.Deserialize(data); if (connectResponse == null) { // We require a connect response to start connectResponse = message as ConnectResponse; if (connectResponse == null || connectResponse.ID != connectRequest.ID) { break; } _state = PipeState.Connected; _serviceName = connectResponse.ServiceName; Log.Add( LoggingLevel.Notification, () => ClientResources.Not_NamedPipeClient_Connection, connectResponse.ServiceName); TaskCompletionSource <NamedPipeClient> ccs = Interlocked.Exchange(ref _connectionCompletionSource, null); if (ccs != null) { ccs.TrySetResult(this); } // Observer the message. onReceive(message); continue; } // Check for disconnect, we don't observe the message until the disconnect is complete. disconnectResponse = message as DisconnectResponse; if (disconnectResponse != null) { break; } // Observe the message. onReceive(message); Response response = message as Response; if (response == null) { continue; } ConnectedCommand connectedCommand; // Check for cancellation responses. CommandCancelResponse cancelResponse = response as CommandCancelResponse; if (cancelResponse != null) { // Cancel the associated request if (_commandRequests.TryGetValue( cancelResponse.CancelledCommandId, out connectedCommand)) { // ReSharper disable once PossibleNullReferenceException connectedCommand.Cancel(cancelResponse); } } // And fall through to complete the response... // Find command the response is related to, and notify it of the response. if (!_commandRequests.TryGetValue(response.ID, out connectedCommand)) { continue; } Debug.Assert(connectedCommand != null); if (connectedCommand.Received(response)) { _commandRequests.TryRemove(response.ID, out connectedCommand); } } } catch (TaskCanceledException) { } } // If we're still connected, and we haven't received a disconnect response, try to send a disconnect request. if (stream.IsConnected && disconnectResponse == null) { CancellationTokenSource cts = token.IsCancellationRequested ? new CancellationTokenSource(500) : null; try { CancellationToken t = cts != null ? cts.Token : token; // Try to send disconnect request. // ReSharper disable once PossibleNullReferenceException await Send(new DisconnectRequest(), t) .ToTask(t) .ConfigureAwait(false); } catch (TaskCanceledException) { } finally { if (cts != null) { cts.Dispose(); } } } // Remove the stream. _stream = null; _state = PipeState.Closed; _serviceName = null; // If we had a disconnect message observe it now that the disconnect has been actioned, // this prevents the receiver thinking the connection is still active. if (disconnectResponse != null) { onReceive(disconnectResponse); ConnectedCommand connectedCommand; if (_commandRequests.TryGetValue(disconnectResponse.ID, out connectedCommand)) { Debug.Assert(connectedCommand != null); if (connectedCommand.Received(disconnectResponse)) { _commandRequests.TryRemove(disconnectResponse.ID, out connectedCommand); } } } } } catch (IOException ioe) { if (!token.IsCancellationRequested) { // Common exception caused by sudden disconnect, lower level Log.Add( ioe, LoggingLevel.Information, () => ClientResources.Err_NamedPipeClient_Failed); } } catch (Exception exception) { TaskCanceledException tce = exception as TaskCanceledException; TaskCompletionSource <NamedPipeClient> ccs = Interlocked.Exchange( ref _connectionCompletionSource, null); if (ccs != null) { if (tce != null) { ccs.TrySetCanceled(); } else { ccs.TrySetException(exception); } } // We only log if this wasn't a cancellation exception. if (tce == null && !token.IsCancellationRequested) { Log.Add( exception, LoggingLevel.Error, () => ClientResources.Err_NamedPipeClient_Failed); } } finally { Dispose(); } }, disposeToken); }