DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (5b81998bb7ab)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

// Original author: ekr@rtfm.com

#ifndef transportlayer_h__
#define transportlayer_h__

#include "sigslot.h"

#include "mozilla/DebugOnly.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsIEventTarget.h"
#include "nsThreadUtils.h"

#include "m_cpp_utils.h"

namespace mozilla {

class TransportFlow;

typedef int TransportResult;

enum {
  TE_WOULDBLOCK = -1, TE_ERROR = -2, TE_INTERNAL = -3
};

#define TRANSPORT_LAYER_ID(name) \
  virtual const std::string id() { return name; } \
  static std::string ID() { return name; }

// Abstract base class for network transport layers.
class TransportLayer : public sigslot::has_slots<> {
 public:
  // The state of the transport flow
  // We can't use "ERROR" because Windows has a macro named "ERROR"
  enum State { TS_NONE, TS_INIT, TS_CONNECTING, TS_OPEN, TS_CLOSED, TS_ERROR };
  enum Mode { STREAM, DGRAM };

  // Is this a stream or datagram flow
  TransportLayer(Mode mode = STREAM) :
    mode_(mode),
    state_(TS_NONE),
    flow_id_(),
    downward_(nullptr) {}

  virtual ~TransportLayer() {}

  // Called to initialize
  nsresult Init();  // Called by Insert() to set up -- do not override
  virtual nsresult InitInternal() { return NS_OK; } // Called by Init

  // Called when inserted into a flow
  virtual void Inserted(TransportFlow *flow, TransportLayer *downward);

  // Downward interface
  TransportLayer *downward() { return downward_; }

  // Dispatch a call onto our thread (or run on the same thread if
  // thread is not set). This is always synchronous.
  nsresult RunOnThread(nsIRunnable *event) {
    if (target_) {
      nsIThread *thr;

      DebugOnly<nsresult> rv = NS_GetCurrentThread(&thr);
      MOZ_ASSERT(NS_SUCCEEDED(rv));

      if (target_ != thr) {
        return target_->Dispatch(event, NS_DISPATCH_SYNC);
      }
    }

    return event->Run();
  }

  // Get the state
  State state() const { return state_; }
  // Must be implemented by derived classes
  virtual TransportResult SendPacket(const unsigned char *data, size_t len) = 0;

  // Get the thread.
  const nsCOMPtr<nsIEventTarget> GetThread() const {
    return target_;
  }

  // Event definitions that one can register for
  // State has changed
  sigslot::signal2<TransportLayer*, State> SignalStateChange;
  // Data received on the flow
  sigslot::signal3<TransportLayer*, const unsigned char *, size_t>
                         SignalPacketReceived;

  // Return the layer id for this layer
  virtual const std::string id() = 0;

  // The id of the flow
  const std::string& flow_id() {
    return flow_id_;
  }

 protected:
  virtual void WasInserted() {}
  virtual void SetState(State state);
  // Check if we are on the right thread
  void CheckThread() {
    NS_ABORT_IF_FALSE(CheckThreadInt(), "Wrong thread");
  }

  Mode mode_;
  State state_;
  std::string flow_id_;
  TransportLayer *downward_; // The next layer in the stack
  nsCOMPtr<nsIEventTarget> target_;

 private:
  DISALLOW_COPY_ASSIGN(TransportLayer);

  bool CheckThreadInt() {
    bool on;

    if (!target_)  // OK if no thread set.
      return true;

    NS_ENSURE_SUCCESS(target_->IsOnCurrentThread(&on), false);
    NS_ENSURE_TRUE(on, false);

    return true;
  }
};

#define LAYER_INFO "Flow[" << flow_id() << "(none)" << "]; Layer[" << id() << "]: "

}  // close namespace
#endif