public async void Connect(CmdArg arg) { string addr = arg.Text ?? "localhost"; try { //check state switch (state) { case State.Connected: connector.RunError("already connected (" + chans.MetaAddr + ")".ArgSrc("connect")); return; case State.Connecting: connector.RunNotifySystem("connecting...".ArgSrc("connect")); return; case State.ConnectingFailed: connector.RunError("connecting failed; disconnected".ArgSrc("connect")); return; case State.Disconnected: //continue break; } //await Task.Yield(); //possibly append port if necessary if (!addr.Contains(":")) { if (settings.DefaultServerPort == -1) throw new ArgumentException("connect: requires addr:port (no default port)"); else addr += ":" + settings.DefaultServerPort; } //create uri and helpers (uri from path) var uri = new Uri("chan://" + addr + ""); Func<string,Uri> path = s => new UriBuilder(uri){ Path = s }.Uri; //run after connected (or failed) Action<State> cleanConnecting = s => { if (state == State.Connected && s == State.ConnectingFailed) //exception in afterConnected in OK connected return; state = s; //change state before getting afterC: ~cannot add anything else Action a = null; while (true) try { a = afterConnected; //get and null afterConnected afterConnected = null; if (a == null) //nothing to do or added while executing last time return; a(); } finally { //: I doubt this works... - It does, actually. //worst case scenario: something will be left in afterConnected... if (a != null) continue; } }; //actually connect state = State.Connecting; try { chans = await ConnectionChans.Connect(settings, store, path); chans.MetaAddr = addr; cleanConnecting(State.Connected); } catch (Exception) { cleanConnecting(State.ConnectingFailed); throw; } //receive messages loop var ce = ChanEvent.Listen(chans.Broadcast, ReceiveMessage); chans.MetaEvent = ce; //inform: client connected BroadcastMessage(new Message(Message.MessageType.Connected, "".ArgSrc(ClientName))); } catch (EndpointNotFoundException) { connector.RunError("no server found".ArgSrc("connect " + addr)); #if DEBUG //ex.PipeEx(connector, "connect.notFound " + addr); #endif } catch (Exception ex) { ex.PipeEx(connector, "connect " + addr); } finally { if (state != State.Connected) state = State.Disconnected; } try { if (state != State.Disconnected && chans.BsReceiver != null) await chans.BsReceiver.AfterClosed().ContinueWith(t => { connector.RunNotifySystem("channel closed".ArgSrc("disconnecting " + addr)); DisconnectCore(); });//.PipeEx(connector, "connect[after chan closed] " + addr); } catch (TaskCanceledException) { //channel closed: already processed in continuation } catch (Exception ex) { ex.PipeEx(connector, "connect[after chan closed awaiting] " + addr); } }
public Message(MessageType type, CmdArg data) { Type = type; Data = data; }
public void BroadcastMessage(CmdArg msg) { if (msg.Source == null) msg = msg.Text.ArgSrc(ClientName); BroadcastMessage(new Message(msg)); }
public Message(CmdArg msg) : this(MessageType.Message, msg) { }