Hybrid ICN (hICN) plugin  v21.06-rc0-4-g18fa668
socket_producer.h
1 /*
2  * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #include <hicn/transport/auth/signer.h>
19 #include <hicn/transport/utils/event_thread.h>
20 #include <implementation/socket.h>
21 #include <protocols/prod_protocol_bytestream.h>
22 #include <protocols/prod_protocol_rtc.h>
23 #include <utils/content_store.h>
24 #include <utils/suffix_strategy.h>
25 
26 #include <atomic>
27 #include <cmath>
28 #include <condition_variable>
29 #include <mutex>
30 #include <queue>
31 #include <thread>
32 
33 #define REGISTRATION_NOT_ATTEMPTED 0
34 #define REGISTRATION_SUCCESS 1
35 #define REGISTRATION_FAILURE 2
36 #define REGISTRATION_IN_PROGRESS 3
37 
38 namespace transport {
39 namespace implementation {
40 
41 using namespace core;
42 using namespace interface;
43 
44 class ProducerSocket : public Socket {
45  private:
46  ProducerSocket(interface::ProducerSocket *producer_socket, int protocol,
47  std::shared_ptr<core::Portal> &&portal)
48  : Socket(std::move(portal)),
49  producer_interface_(producer_socket),
50  data_packet_size_(default_values::content_object_packet_size),
51  content_object_expiry_time_(default_values::content_object_expiry_time),
52  async_thread_(),
53  making_manifest_(false),
54  hash_algorithm_(auth::CryptoHashType::SHA256),
55  suffix_strategy_(core::NextSegmentCalculationStrategy::INCREMENTAL),
56  on_interest_input_(VOID_HANDLER),
57  on_interest_dropped_input_buffer_(VOID_HANDLER),
58  on_interest_inserted_input_buffer_(VOID_HANDLER),
59  on_interest_satisfied_output_buffer_(VOID_HANDLER),
60  on_interest_process_(VOID_HANDLER),
61  on_new_segment_(VOID_HANDLER),
62  on_content_object_to_sign_(VOID_HANDLER),
63  on_content_object_in_output_buffer_(VOID_HANDLER),
64  on_content_object_output_(VOID_HANDLER),
65  on_content_object_evicted_from_output_buffer_(VOID_HANDLER),
66  on_content_produced_(VOID_HANDLER) {
67  switch (protocol) {
68  case ProductionProtocolAlgorithms::RTC_PROD:
69  production_protocol_ =
70  std::make_unique<protocol::RTCProductionProtocol>(this);
71  break;
72  case ProductionProtocolAlgorithms::BYTE_STREAM:
73  default:
74  production_protocol_ =
75  std::make_unique<protocol::ByteStreamProductionProtocol>(this);
76  break;
77  }
78  }
79 
80  public:
81  ProducerSocket(interface::ProducerSocket *producer, int protocol)
82  : ProducerSocket(producer, protocol, std::make_shared<core::Portal>()) {}
83 
84  ProducerSocket(interface::ProducerSocket *producer, int protocol,
85  asio::io_service &io_service)
86  : ProducerSocket(producer, protocol,
87  std::make_shared<core::Portal>(io_service)) {
88  is_async_ = true;
89  }
90 
91  virtual ~ProducerSocket() {}
92 
93  interface::ProducerSocket *getInterface() {
94  return producer_interface_;
95  }
96 
97  void setInterface(interface::ProducerSocket *producer_socket) {
98  producer_interface_ = producer_socket;
99  }
100 
101  void connect() override {
102  portal_->connect(false);
103  production_protocol_->start();
104  }
105 
106  bool isRunning() override { return !production_protocol_->isRunning(); };
107 
108  virtual void asyncProduce(Name content_name,
109  std::unique_ptr<utils::MemBuf> &&buffer,
110  bool is_last, uint32_t offset,
111  uint32_t **last_segment = nullptr) {
112  if (!async_thread_.stopped()) {
113  auto a = buffer.release();
114  async_thread_.add([this, content_name, a, is_last, offset,
115  last_segment]() {
116  auto buf = std::unique_ptr<utils::MemBuf>(a);
117  if (last_segment != NULL) {
118  **last_segment = offset + produceStream(content_name, std::move(buf),
119  is_last, offset);
120  } else {
121  produceStream(content_name, std::move(buf), is_last, offset);
122  }
123  });
124  }
125  }
126 
127  virtual uint32_t produceStream(const Name &content_name,
128  std::unique_ptr<utils::MemBuf> &&buffer,
129  bool is_last = true,
130  uint32_t start_offset = 0) {
131  return production_protocol_->produceStream(content_name, std::move(buffer),
132  is_last, start_offset);
133  }
134 
135  virtual uint32_t produceStream(const Name &content_name,
136  const uint8_t *buffer, size_t buffer_size,
137  bool is_last = true,
138  uint32_t start_offset = 0) {
139  return production_protocol_->produceStream(
140  content_name, buffer, buffer_size, is_last, start_offset);
141  }
142 
143  virtual uint32_t produceDatagram(const Name &content_name,
144  std::unique_ptr<utils::MemBuf> &&buffer) {
145  return production_protocol_->produceDatagram(content_name,
146  std::move(buffer));
147  }
148 
149  virtual uint32_t produceDatagram(const Name &content_name,
150  const uint8_t *buffer, size_t buffer_size) {
151  return production_protocol_->produceDatagram(content_name, buffer,
152  buffer_size);
153  }
154 
155  void produce(ContentObject &content_object) {
156  production_protocol_->produce(content_object);
157  }
158 
159  void registerPrefix(const Prefix &producer_namespace) {
160  production_protocol_->registerNamespaceWithNetwork(producer_namespace);
161  }
162 
163  void stop() { production_protocol_->stop(); }
164 
165  virtual int setSocketOption(int socket_option_key,
166  uint32_t socket_option_value) {
167  switch (socket_option_key) {
168  case GeneralTransportOptions::DATA_PACKET_SIZE:
169  if (socket_option_value <= default_values::max_content_object_size &&
170  socket_option_value > 0) {
171  data_packet_size_ = socket_option_value;
172  }
173  break;
174 
175  case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
176  production_protocol_->setOutputBufferSize(socket_option_value);
177  break;
178 
179  case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME:
180  content_object_expiry_time_ = socket_option_value;
181  break;
182 
183  default:
184  return SOCKET_OPTION_NOT_SET;
185  }
186 
187  return SOCKET_OPTION_SET;
188  }
189 
190  virtual int setSocketOption(int socket_option_key,
191  std::nullptr_t socket_option_value) {
192  // Reschedule the function on the io_service to avoid race condition in case
193  // setSocketOption is called while the io_service is running.
194  return rescheduleOnIOService(
195  socket_option_key, socket_option_value,
196  [this](int socket_option_key,
197  ProducerContentObjectCallback socket_option_value) -> int {
198  switch (socket_option_key) {
199  case ProducerCallbacksOptions::INTEREST_INPUT:
200  if (socket_option_value == VOID_HANDLER) {
201  on_interest_input_ = VOID_HANDLER;
202  break;
203  }
204 
205  case ProducerCallbacksOptions::INTEREST_DROP:
206  if (socket_option_value == VOID_HANDLER) {
207  on_interest_dropped_input_buffer_ = VOID_HANDLER;
208  break;
209  }
210 
211  case ProducerCallbacksOptions::INTEREST_PASS:
212  if (socket_option_value == VOID_HANDLER) {
213  on_interest_inserted_input_buffer_ = VOID_HANDLER;
214  break;
215  }
216 
217  case ProducerCallbacksOptions::CACHE_HIT:
218  if (socket_option_value == VOID_HANDLER) {
219  on_interest_satisfied_output_buffer_ = VOID_HANDLER;
220  break;
221  }
222 
223  case ProducerCallbacksOptions::CACHE_MISS:
224  if (socket_option_value == VOID_HANDLER) {
225  on_interest_process_ = VOID_HANDLER;
226  break;
227  }
228 
229  case ProducerCallbacksOptions::NEW_CONTENT_OBJECT:
230  if (socket_option_value == VOID_HANDLER) {
231  on_new_segment_ = VOID_HANDLER;
232  break;
233  }
234 
235  case ProducerCallbacksOptions::CONTENT_OBJECT_READY:
236  if (socket_option_value == VOID_HANDLER) {
237  on_content_object_in_output_buffer_ = VOID_HANDLER;
238  break;
239  }
240 
241  case ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT:
242  if (socket_option_value == VOID_HANDLER) {
243  on_content_object_output_ = VOID_HANDLER;
244  break;
245  }
246 
247  case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
248  if (socket_option_value == VOID_HANDLER) {
249  on_content_object_to_sign_ = VOID_HANDLER;
250  break;
251  }
252 
253  default:
254  return SOCKET_OPTION_NOT_SET;
255  }
256 
257  return SOCKET_OPTION_SET;
258  });
259  }
260 
261  virtual int setSocketOption(int socket_option_key, bool socket_option_value) {
262  switch (socket_option_key) {
263  case GeneralTransportOptions::MAKE_MANIFEST:
264  making_manifest_ = socket_option_value;
265  break;
266 
267  default:
268  return SOCKET_OPTION_NOT_SET;
269  }
270 
271  return SOCKET_OPTION_SET;
272  }
273 
274  virtual int setSocketOption(int socket_option_key,
275  Name *socket_option_value) {
276  return SOCKET_OPTION_NOT_SET;
277  }
278 
279  virtual int setSocketOption(
280  int socket_option_key,
281  interface::ProducerContentObjectCallback socket_option_value) {
282  // Reschedule the function on the io_service to avoid race condition in case
283  // setSocketOption is called while the io_service is running.
284  return rescheduleOnIOService(
285  socket_option_key, socket_option_value,
286  [this](int socket_option_key,
287  ProducerContentObjectCallback socket_option_value) -> int {
288  switch (socket_option_key) {
289  case ProducerCallbacksOptions::NEW_CONTENT_OBJECT:
290  on_new_segment_ = socket_option_value;
291  break;
292 
293  case ProducerCallbacksOptions::CONTENT_OBJECT_READY:
294  on_content_object_in_output_buffer_ = socket_option_value;
295  break;
296 
297  case ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT:
298  on_content_object_output_ = socket_option_value;
299  break;
300 
301  case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
302  on_content_object_to_sign_ = socket_option_value;
303  break;
304 
305  default:
306  return SOCKET_OPTION_NOT_SET;
307  }
308 
309  return SOCKET_OPTION_SET;
310  });
311  }
312 
313  virtual int setSocketOption(
314  int socket_option_key,
315  interface::ProducerInterestCallback socket_option_value) {
316  // Reschedule the function on the io_service to avoid race condition in case
317  // setSocketOption is called while the io_service is running.
318  return rescheduleOnIOService(
319  socket_option_key, socket_option_value,
320  [this](int socket_option_key,
321  ProducerInterestCallback socket_option_value) -> int {
322  switch (socket_option_key) {
323  case ProducerCallbacksOptions::INTEREST_INPUT:
324  on_interest_input_ = socket_option_value;
325  break;
326 
327  case ProducerCallbacksOptions::INTEREST_DROP:
328  on_interest_dropped_input_buffer_ = socket_option_value;
329  break;
330 
331  case ProducerCallbacksOptions::INTEREST_PASS:
332  on_interest_inserted_input_buffer_ = socket_option_value;
333  break;
334 
335  case ProducerCallbacksOptions::CACHE_HIT:
336  on_interest_satisfied_output_buffer_ = socket_option_value;
337  break;
338 
339  case ProducerCallbacksOptions::CACHE_MISS:
340  on_interest_process_ = socket_option_value;
341  break;
342 
343  default:
344  return SOCKET_OPTION_NOT_SET;
345  }
346 
347  return SOCKET_OPTION_SET;
348  });
349  }
350 
351  virtual int setSocketOption(
352  int socket_option_key,
353  interface::ProducerContentCallback socket_option_value) {
354  // Reschedule the function on the io_service to avoid race condition in case
355  // setSocketOption is called while the io_service is running.
356  return rescheduleOnIOService(
357  socket_option_key, socket_option_value,
358  [this](int socket_option_key,
359  ProducerContentCallback socket_option_value) -> int {
360  switch (socket_option_key) {
361  case ProducerCallbacksOptions::CONTENT_PRODUCED:
362  on_content_produced_ = socket_option_value;
363  break;
364 
365  default:
366  return SOCKET_OPTION_NOT_SET;
367  }
368 
369  return SOCKET_OPTION_SET;
370  });
371  }
372 
373  virtual int setSocketOption(int socket_option_key,
374  auth::CryptoHashType socket_option_value) {
375  switch (socket_option_key) {
376  case GeneralTransportOptions::HASH_ALGORITHM:
377  hash_algorithm_ = socket_option_value;
378  break;
379  default:
380  return SOCKET_OPTION_NOT_SET;
381  }
382 
383  return SOCKET_OPTION_SET;
384  }
385 
386  virtual int setSocketOption(
387  int socket_option_key,
388  core::NextSegmentCalculationStrategy socket_option_value) {
389  switch (socket_option_key) {
390  case GeneralTransportOptions::SUFFIX_STRATEGY:
391  suffix_strategy_ = socket_option_value;
392  break;
393  default:
394  return SOCKET_OPTION_NOT_SET;
395  }
396 
397  return SOCKET_OPTION_SET;
398  }
399 
400  virtual int setSocketOption(
401  int socket_option_key,
402  const std::shared_ptr<auth::Signer> &socket_option_value) {
403  switch (socket_option_key) {
404  case GeneralTransportOptions::SIGNER: {
405  utils::SpinLock::Acquire locked(signer_lock_);
406  signer_.reset();
407  signer_ = socket_option_value;
408  } break;
409  default:
410  return SOCKET_OPTION_NOT_SET;
411  }
412 
413  return SOCKET_OPTION_SET;
414  }
415 
416  virtual int getSocketOption(int socket_option_key,
417  uint32_t &socket_option_value) {
418  switch (socket_option_key) {
419  case GeneralTransportOptions::OUTPUT_BUFFER_SIZE:
420  socket_option_value = production_protocol_->getOutputBufferSize();
421  break;
422 
423  case GeneralTransportOptions::DATA_PACKET_SIZE:
424  socket_option_value = (uint32_t)data_packet_size_;
425  break;
426 
427  case GeneralTransportOptions::CONTENT_OBJECT_EXPIRY_TIME:
428  socket_option_value = content_object_expiry_time_;
429  break;
430 
431  default:
432  return SOCKET_OPTION_NOT_SET;
433  }
434 
435  return SOCKET_OPTION_GET;
436  }
437 
438  virtual int getSocketOption(int socket_option_key,
439  bool &socket_option_value) {
440  switch (socket_option_key) {
441  case GeneralTransportOptions::MAKE_MANIFEST:
442  socket_option_value = making_manifest_;
443  break;
444 
445  case GeneralTransportOptions::ASYNC_MODE:
446  socket_option_value = is_async_;
447  break;
448 
449  default:
450  return SOCKET_OPTION_NOT_GET;
451  }
452 
453  return SOCKET_OPTION_GET;
454  }
455 
456  virtual int getSocketOption(
457  int socket_option_key,
458  interface::ProducerContentObjectCallback **socket_option_value) {
459  // Reschedule the function on the io_service to avoid race condition in case
460  // setSocketOption is called while the io_service is running.
461  return rescheduleOnIOService(
462  socket_option_key, socket_option_value,
463  [this](int socket_option_key,
464  ProducerContentObjectCallback **socket_option_value) -> int {
465  switch (socket_option_key) {
466  case ProducerCallbacksOptions::NEW_CONTENT_OBJECT:
467  *socket_option_value = &on_new_segment_;
468  break;
469 
470  case ProducerCallbacksOptions::CONTENT_OBJECT_READY:
471  *socket_option_value = &on_content_object_in_output_buffer_;
472  break;
473 
474  case ProducerCallbacksOptions::CONTENT_OBJECT_OUTPUT:
475  *socket_option_value = &on_content_object_output_;
476  break;
477 
478  case ProducerCallbacksOptions::CONTENT_OBJECT_TO_SIGN:
479  *socket_option_value = &on_content_object_to_sign_;
480  break;
481 
482  default:
483  return SOCKET_OPTION_NOT_GET;
484  }
485 
486  return SOCKET_OPTION_GET;
487  });
488  }
489 
490  virtual int getSocketOption(
491  int socket_option_key,
492  interface::ProducerContentCallback **socket_option_value) {
493  // Reschedule the function on the io_service to avoid race condition in case
494  // setSocketOption is called while the io_service is running.
495  return rescheduleOnIOService(
496  socket_option_key, socket_option_value,
497  [this](int socket_option_key,
498  ProducerContentCallback **socket_option_value) -> int {
499  switch (socket_option_key) {
500  case ProducerCallbacksOptions::CONTENT_PRODUCED:
501  *socket_option_value = &on_content_produced_;
502  break;
503 
504  default:
505  return SOCKET_OPTION_NOT_GET;
506  }
507 
508  return SOCKET_OPTION_GET;
509  });
510  }
511 
512  virtual int getSocketOption(
513  int socket_option_key,
514  interface::ProducerInterestCallback **socket_option_value) {
515  // Reschedule the function on the io_service to avoid race condition in case
516  // setSocketOption is called while the io_service is running.
517  return rescheduleOnIOService(
518  socket_option_key, socket_option_value,
519  [this](int socket_option_key,
520  ProducerInterestCallback **socket_option_value) -> int {
521  switch (socket_option_key) {
522  case ProducerCallbacksOptions::INTEREST_INPUT:
523  *socket_option_value = &on_interest_input_;
524  break;
525 
526  case ProducerCallbacksOptions::INTEREST_DROP:
527  *socket_option_value = &on_interest_dropped_input_buffer_;
528  break;
529 
530  case ProducerCallbacksOptions::INTEREST_PASS:
531  *socket_option_value = &on_interest_inserted_input_buffer_;
532  break;
533 
534  case ProducerCallbacksOptions::CACHE_HIT:
535  *socket_option_value = &on_interest_satisfied_output_buffer_;
536  break;
537 
538  case ProducerCallbacksOptions::CACHE_MISS:
539  *socket_option_value = &on_interest_process_;
540  break;
541 
542  default:
543  return SOCKET_OPTION_NOT_GET;
544  }
545 
546  return SOCKET_OPTION_GET;
547  });
548  }
549 
550  virtual int getSocketOption(
551  int socket_option_key,
552  std::shared_ptr<core::Portal> &socket_option_value) {
553  switch (socket_option_key) {
554  case PORTAL:
555  socket_option_value = portal_;
556  break;
557  default:
558  return SOCKET_OPTION_NOT_GET;
559  ;
560  }
561 
562  return SOCKET_OPTION_GET;
563  }
564 
565  virtual int getSocketOption(int socket_option_key,
566  auth::CryptoHashType &socket_option_value) {
567  switch (socket_option_key) {
568  case GeneralTransportOptions::HASH_ALGORITHM:
569  socket_option_value = hash_algorithm_;
570  break;
571  default:
572  return SOCKET_OPTION_NOT_GET;
573  }
574 
575  return SOCKET_OPTION_GET;
576  }
577 
578  virtual int getSocketOption(
579  int socket_option_key,
580  core::NextSegmentCalculationStrategy &socket_option_value) {
581  switch (socket_option_key) {
582  case GeneralTransportOptions::SUFFIX_STRATEGY:
583  socket_option_value = suffix_strategy_;
584  break;
585  default:
586  return SOCKET_OPTION_NOT_GET;
587  }
588  return SOCKET_OPTION_GET;
589  }
590 
591  virtual int getSocketOption(
592  int socket_option_key,
593  std::shared_ptr<auth::Signer> &socket_option_value) {
594  switch (socket_option_key) {
595  case GeneralTransportOptions::SIGNER: {
596  utils::SpinLock::Acquire locked(signer_lock_);
597  socket_option_value = signer_;
598  } break;
599  default:
600  return SOCKET_OPTION_NOT_GET;
601  }
602 
603  return SOCKET_OPTION_GET;
604  }
605 
606  virtual int setSocketOption(int socket_option_key,
607  const std::string &socket_option_value) {
608  return SOCKET_OPTION_NOT_SET;
609  }
610 
611  // If the thread calling lambda_func is not the same of io_service, this
612  // function reschedule the function on it
613  template <typename Lambda, typename arg2>
614  int rescheduleOnIOServiceWithReference(int socket_option_key,
615  arg2 &socket_option_value,
616  Lambda lambda_func) {
617  // To enforce type check
618  std::function<int(int, arg2 &)> func = lambda_func;
619  int result = SOCKET_OPTION_SET;
620  if (production_protocol_ && production_protocol_->isRunning()) {
621  std::mutex mtx;
622  /* Condition variable for the wait */
623  std::condition_variable cv;
624 
625  bool done = false;
626  portal_->getIoService().dispatch([&socket_option_key,
627  &socket_option_value, &mtx, &cv,
628  &result, &done, &func]() {
629  std::unique_lock<std::mutex> lck(mtx);
630  done = true;
631  result = func(socket_option_key, socket_option_value);
632  cv.notify_all();
633  });
634  std::unique_lock<std::mutex> lck(mtx);
635  if (!done) {
636  cv.wait(lck);
637  }
638  } else {
639  result = func(socket_option_key, socket_option_value);
640  }
641 
642  return result;
643  }
644 
645  // If the thread calling lambda_func is not the same of io_service, this
646  // function reschedule the function on it
647  template <typename Lambda, typename arg2>
648  int rescheduleOnIOService(int socket_option_key, arg2 socket_option_value,
649  Lambda lambda_func) {
650  // To enforce type check
651  std::function<int(int, arg2)> func = lambda_func;
652  int result = SOCKET_OPTION_SET;
653  if (production_protocol_ && production_protocol_->isRunning()) {
654  std::mutex mtx;
655  /* Condition variable for the wait */
656  std::condition_variable cv;
657  bool done = false;
658  portal_->getIoService().dispatch([&socket_option_key,
659  &socket_option_value, &mtx, &cv,
660  &result, &done, &func]() {
661  std::unique_lock<std::mutex> lck(mtx);
662  done = true;
663  result = func(socket_option_key, socket_option_value);
664  cv.notify_all();
665  });
666  std::unique_lock<std::mutex> lck(mtx);
667  if (!done) {
668  cv.wait(lck);
669  }
670  } else {
671  result = func(socket_option_key, socket_option_value);
672  }
673 
674  return result;
675  }
676 
677  // Threads
678  protected:
679  interface::ProducerSocket *producer_interface_;
680  asio::io_service io_service_;
681  std::atomic<size_t> data_packet_size_;
682  std::atomic<uint32_t> content_object_expiry_time_;
683 
684  utils::EventThread async_thread_;
685 
686  std::atomic<bool> making_manifest_;
687  std::atomic<auth::CryptoHashType> hash_algorithm_;
688  std::atomic<auth::CryptoSuite> crypto_suite_;
689  utils::SpinLock signer_lock_;
690  std::shared_ptr<auth::Signer> signer_;
691  core::NextSegmentCalculationStrategy suffix_strategy_;
692 
693  std::unique_ptr<protocol::ProductionProtocol> production_protocol_;
694 
695  // callbacks
696  ProducerInterestCallback on_interest_input_;
697  ProducerInterestCallback on_interest_dropped_input_buffer_;
698  ProducerInterestCallback on_interest_inserted_input_buffer_;
699  ProducerInterestCallback on_interest_satisfied_output_buffer_;
700  ProducerInterestCallback on_interest_process_;
701 
702  ProducerContentObjectCallback on_new_segment_;
703  ProducerContentObjectCallback on_content_object_to_sign_;
704  ProducerContentObjectCallback on_content_object_in_output_buffer_;
705  ProducerContentObjectCallback on_content_object_output_;
706  ProducerContentObjectCallback on_content_object_evicted_from_output_buffer_;
707 
708  ProducerContentCallback on_content_produced_;
709 };
710 
711 } // namespace implementation
712 
713 } // namespace transport
transport::implementation::Socket
Definition: socket.h:36
transport::core::Name
Definition: name.h:45
transport::interface::ProducerSocket
Definition: socket_producer.h:37
utils::EventThread
Definition: event_thread.h:27
transport::core::ContentObject
Definition: content_object.h:29
transport
Definition: forwarder_config.h:32
utils::SpinLock
Definition: spinlock.h:22
utils::SpinLock::Acquire
Definition: spinlock.h:24
transport::core::Prefix
Definition: prefix.h:24