예제 #1
0
    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);
      }

    }
예제 #2
0
파일: Message.cs 프로젝트: Maartyl/cs-chan
 public Message(MessageType type, CmdArg data)
 {
     Type = type;
       Data = data;
 }
예제 #3
0
 public void BroadcastMessage(CmdArg msg) {
   if (msg.Source == null)
     msg = msg.Text.ArgSrc(ClientName);
   BroadcastMessage(new Message(msg));
 }
예제 #4
0
파일: Message.cs 프로젝트: Maartyl/cs-chan
 public Message(CmdArg msg)
     : this(MessageType.Message, msg)
 {
 }