libjingle Important Concepts

Important Concepts

You should understand the following important concepts about libjingle:

Signals

libjingle uses the sigslot library to facilitate communication between objects. sigslot is a generic framework that enables you to connect a calling member to a receiving function in any class (including the same class) very simply. The way it works is this:

  1. The sending class declares a member variable, called a signal, using a special template-like syntax. This signal defines the parameters of the listening function.
  2. The listening class implements a function with the same number, type, and sequence of parameters as the signal. This is sometimes called the receiver or the slot. (Note: this can even be the same class as the one that declared the signal.) This function cannot return a value (e.g., returns void). The receiver must inheritsigslot::has_slots<>.
  3. The listener connects to the signal by calling the signal's connect method, passing in a pointer to the instance of the listening object, and the address of the implementing class function.
  4. The sender calls its signal member as if it were a function, passing in the appropriate parameter types as declared. It can pass parameters by either value or reference.

You can connect as many signals as you like to a common slot. libjingle sometimes assigns multiple signals to a single slot in order to consolidate its message handling. Conversely, several objects declare a signal object in order to broadcast commonly needed messages from a single point (for example, alerts sent when a connection state changes). sigslot takes care of disconnecting callbacks and dereferencing when objects are destroyed.

The following code demonstrates using sigslot:

// Class that sends the notification.
class Sender  {

  // The signal declaration.
  // The '2' in the name indicates the number of parameters. Parameter types
  // are declared in the template parameter list.
  sigslot::signal2<string message, std::time_t time> SignalDanger;

  // When anyone calls Panic(), we will send the SignalDanger signal.
  void Panic(){
    SignalDanger("Help!", std::time(0));
  }

 // Listening class. It must inherit sigslot.
class Receiver : public sigslot::has_slots<>{

  // Receiver registers to get SignalDanger signals.
  // When SignalDanger is sent, it is caught by OnDanger().
  // Second parameter gives address of the listener function class definition.
  // First parameter points to instance of this class to receive notifications.
  Receiver(Sender sender){
        sender->SignalDanger.connect(this, &Receiver.OnDanger);
  }

  // When anyone calls Panic(), Receiver::OnDanger gets the message.
  // Notice that the number and type of parameters match
  // those in Sender::SignalDanger, and that it doesn't return a value.
  void OnDanger(string message, std::time_t time){
    if(message == "Help!")
    {
      // Call the police
      ...
    }
  }
...
}

Many classes in the code send signals to notify listeners of important events. For example, Call::SignalSessionState sends notifications when you send or receive a connection attempt. Your application must connect to these signals and act appropriately.

The general convention in libjingle code is to prefix the name of a signal with Signal: e.g., SignalStateChange, SignalSessionState, SignalSessionCreate. Listener methods intended to connect to signals are typically prefixed with On, e.g., OnPortDestroyed(), OnOutgoingMessage(), OnSendPacket().

See the sigslot documentation for more details.

Threads

libjingle supports multithreading in order to improve the performance of your application. libjingle components use one or two globally available threads:

  • The signaling thread is the thread used to create all the basic components, such as the Session Management and Control and XMPP Messaging components.
  • The worker thread (sometimes called the channel thread in the code) is used by the Peer to Peer component objects to handle more resource intensive processes, such as data streaming. Putting these on a separate thread prevents data flow from blocking or being blocked by XMPP or user interface components. Classes using the worker thread include ChannelManagerSocketMonitorP2PTransportChannel, and the Port objects. To enable a second thread, you must create and pass a new Threadobject to the SessionManager constructor. (If no thread is passed in, the thread in which SessionManager was created will be used as the worker thread).CallClient::InitPhone demonstrates creating a worker thread for the low-level components.

Additionally, libjingle now provides a base class called SignalThread. Extend this class to enable an object that exists on its own thread, and which can be instantiated, started, and left alone to complete and delete itself when done. See signalthread.h/.cc for more information.

Note:   Although libjingle supports multiple threads, only certain methods support thread safety by verifying the calling thread, and very few methods do any locking. The following snippet demonstrates how a method verifies which thread it is being called on:

// Check that we're being called from the channel (e.g., worker) thread.
ASSERT(talk_base::Thread::Current() == channel_thread_);
channel_thread_->Clear(this);

libjingle wraps all threads, the signaling thread, the worker thread, and any other threads, with the talk_base::Thread object (or a derived object). All Thread objects are managed by ThreadManager, which retrieves them on request. SessionManager calls ThreadManager::CurrentThread to provide it with a signaling thread (and a worker thread, if none is provided) when it is instantiated; XmppPump uses the current thread for its signaling thread. Therefore, you must create a Thread object (or derived object) for the signaling thread and push it into ThreadManager's thread pool before creating a SessionManager object, or before expecting the XmppPump to start working. (See Signing In to a Serverfor example code.) There are two ways to create a Thread:

  • AutoThread   This wraps the existing operating system thread with a libjingle Thread object and makes it the current thread in the ThreadManager object's thread pool (that is, will return the thread if Thread::CurrentThread is called).
  • Thread   This creates and wraps a new thread to use, typically for a worker thread. In order to use this thread, you have to create a new Thread object, callThreadManager::Add or ThreadManager::SetCurrent to add it to the pool, and call Run to start it in a blocking loop, or Start to start the thread listening.

Threads provide a conduit for messages between (or within) objects. For instance, SocketManager sends a message to itself on another thread to destroy a socket, or toSessionManager when connection candidates have been generated. The Thread object inherits MessageQueue, and together they expose SendPost, and other methods for sending messages synchronously and asynchronously. An object that will receive messages sent using MessageQueue must inherit and implement MessageHandler.MessageHandler defines the OnMessage method, which is called with the MessageQueue messages.

You can send messages to any object that inherits talk_base::MessageHandler over any thread. However, if sending a message to perform a resource-intensive thread, you should send the message over the worker thread. You can get a handle to the worker thread by calling SessionManager::worker_thread(). You can get a handle to the signaling thread by calling SessionManager::signaling_thread().

An object has several ways to access a specific thread: it can request and store a thread pointer as an input parameter; it can assume that the current thread when it is created (accessed by ThreadManager::CurrentThread in its constructor) is a particular thread and cache a member pointer to it; it can call SessionManger::signal_thread() orSessionManager::worker_thread() to retrieve threads. All three techniques are used in libjingle.

Because an object can be called on any thread, an object may need to verify which thread a method is being called from. To do this, call Thread::Current (which retrieves the current thread) and compare that value against a known thread--this can be one of the threads exposed by SessionManager, or the object can store a pointer to its initial thread in the constructor. Here is a more extended example of calling a method in the same object on another thread.

// Note that worker_thread_ is not initialized until someone
// calls PseudoTcpChannel::Connect
// Also note that this method *is* thread-safe.
bool PseudoTcpChannel::Connect(const std::string& channel_name) {
  ASSERT(signal_thread_->IsCurrent());
  CritScope lock(&cs_);
    if (channel_)
      return false;
    ASSERT(session_ != NULL);
    worker_thread_ = session_->session_manager()->worker_thread();
...
}

void PseudoTcpChannel::SomeFunction(){
  ...
  // Post a message to yourself over the worker thread.
  worker_thread_->Post(this, MSG_PING); // <- Goes in here....
  ...
}

// Handle queued requests.
void PseudoTcpChannel::OnMessage(Message *pmsg) {
  if (pmsg->message_id == MSG_SORT)
    OnSort();
  else if (pmsg->message_id == MSG_PING) // -> And comes out here!
    // Check that we're in the worker thread before proceding.
    ASSERT(worker_thread_->IsCurrent());
    OnPing();
  else if (pmsg->message_id == MSG_ALLOCATE)
    OnAllocate();
  else
    assert(false);
}

Naming Conventions

libjingle has some naming conventions that it is useful to be aware of:

  • OnSomeMethod   Methods beginning with "On" are often connected to a signal, either from this or another object. If called from the same object, it is probably called on a different thread.
  • SomeMethod_w   Methods ending with "_w" exist in the "worker thread" and are called from another thread
  • SignalSomeName   These are the signals that send messages to callback methods.

SSL Support

libjingle supports two types of SSL:

  • OpenSSL (for UNIX)
  • SChannel (for Windows)

To use SSL, you must perform the following steps:

  1. #define FEATURE_ENABLE_SSL (in the Visual Studio project, this value is defined in the project settings, not in the code).
  2. Ensure that either SSL_USE_OPENSSL or SSL_USE_SCHANNEL are #defined in ssladapter.cc. One of these should be defined by default, depending on the build settings for your operating system.
  3. Call InitializeSSL to initialize required components. This function is defined in ssladapter.cc. When the application closes down, call CleanupSSL. You do not need to call InitializeSSLThread (it is used internally by InitializeSSL).

Connections

A libjingle peer-to-peer connection actually consists of two channels:

  • The session negotiation channel (also called the signaling channel) is the communication link used to negotiate the data connection. This channel is used to request a connection, exchange candidates, and negotiate the details of the session (such as socket addresses, codecs needed, files to be exchanged, connection change requests, and termination requests). This is the first connection made between computers, and only after this connection is made can the data channel be established. libjingle uses a precursor to Jingle to specify the stanzas and responses needed to establish the data connection (see Jingle and libjingle) This channel sends stanzas through an intermediary XMPP server; the example code uses the Google Talk server as the intermediary.
  • The data channel carries the actual data (audio, video, files, etc) exchanged in the peer-to-peer session. Data channel data is wrapped in TCP or UDP packets, depending on the transport negotiated, and does not go through the XMPP server.

The session negotiation channel is established first, as the computers negotiate the details of the data channel; after the data connection is made, most activity occurs on the data channel, except for the occasional requests for a codec change, a new file request, a redirect request, or a termination request.

The following diagram shows these two pathways. In the diagram, two alternate data paths are shown, although only one data pathway will be active in a connection. This is because the data pathway can be either a direct connection (92% of connection attempts can take place directly) or through a relay server (8% of connection attempts require an intermediary relay server). A third data pathway, not shown, is a direct connection from computer to computer when there is no intermediary firewall.

时间: 2024-09-24 13:43:30

libjingle Important Concepts的相关文章

libjingle翻译之《Important Concepts(重要概念)之Signals (信号)》

Important Concepts(重要概念) 你应该理解libjingle中以下的重要概念: ● Signals                                          (信号) ● Threads and Messages                     (线程.消息) ● Naming Conventions                        (命名约定) ● SSL Support                              

libjingle翻译之《Important Concepts(重要概念)之Candidates(候选)》

Candidates(候选) libjingle一个主要的好处就是它可以穿透防火墙和NAT设备进行链接协商.libjingle使用ICE机制穿透防火墙.libjingle应用程序第一步要做的就是在试图协商一个链接时为其它计算机的链入创建一个潜在的本地端口地址链表.链表中的每个潜在的地址就称作一个候选.候选就是"IP地址:端口"对应对,这些对应对使应用程序和其它计算机互联(技术上,这些对应对只在本地机上监听).libjingle提供了强壮的机制在本地链接上发现候选供其它计算机进入,甚至穿

libjingle翻译之《Important Concepts(重要概念)之Transports, Channels, and Connections(传输、通道、链接)》

Transports, Channels, and Connections(传输.通道.链接) 每个p2pTransportChannel代表了本地机与远程机的数据通道.这个通道实际上包含着(隐藏着)一个设计复杂而健壮的体系.P2PTransportChannel管理着大量的不同的Connection对象,每个对象代表了一个不同种类的链接(UDP,TCP等).一个Connection对象实际上封装了一对对象:一个Port子类,代表了本地链接,和一个代表远程机的地址.如果一个链接无效,P2pTra

libjingle翻译之《Important Concepts(重要概念)之Connections(链接)》

Connections(链接) 一个p2p的链接实际上由两个通道组成. ●  session negotiation channel(也称作signaling channel),会话协商通道.是为数据链接服务的沟通通道.这个通道被用来回应取得一个链接的请求,交换候选,和协商会话的细节(比如:套接字地址,需要的编码方案,交换的文件,链接改变请求,终止请求).这个通道是两个计算机之间建立的第一个链接,也只有这个链接成功之后,两个计算机之间的数据链接才能被建立.libjingle通过发送一个指定的前导

C++内存管理学习笔记(5)

/****************************************************************/ /*            学习是合作和分享式的! /* Author:Atlas                    Email:wdzxl198@163.com  /*  转载请注明本文出处: *   http://blog.csdn.net/wdzxl198/article/details/9112123 /************************

gatling官方文档翻译

第一篇 http://gatling.io/docs/2.2.1/index.html Gatling is a highly capable load testing tool. It is designed for ease of use, maintainability and high performance. Out of the box, Gatling comes with excellent support of the HTTP protocol that makes it a

booklist for machine learning

Recommended Books Here is a list of books which I have read and feel it is worth recommending to friends who are interested in computer science. Machine Learning Pattern Recognition and Machine Learning Christopher M. Bishop A new treatment of classi

(转)Nuts and Bolts of Applying Deep Learning

Kevin Zakka's Blog About Nuts and Bolts of Applying Deep Learning Sep 26, 2016 This weekend was very hectic (catching up on courses and studying for a statistics quiz), but I managed to squeeze in some time to watch the Bay Area Deep Learning School 

Memory Access Patterns Are Important

原文地址:http://mechanical-sympathy.blogspot.com/2012/08/memory-access-patterns-are-important.html(因墙转载) In high-performance computing it is often said that the cost of a cache-miss is the largest performance penalty for an algorithm.  For many years the