transportlayerloopback.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. // Original author: ekr@rtfm.com
  6. #include "logging.h"
  7. #include "nspr.h"
  8. #include "prlock.h"
  9. #include "nsNetCID.h"
  10. #include "nsIComponentManager.h"
  11. #include "nsComponentManagerUtils.h"
  12. #include "nsIComponentRegistrar.h"
  13. #include "nsIEventTarget.h"
  14. #include "nsIIOService.h"
  15. #include "nsIServiceManager.h"
  16. #include "nsISocketTransportService.h"
  17. #include "nsServiceManagerUtils.h"
  18. #include "transportflow.h"
  19. #include "transportlayerloopback.h"
  20. namespace mozilla {
  21. MOZ_MTLOG_MODULE("mtransport")
  22. nsresult TransportLayerLoopback::Init() {
  23. timer_ = do_CreateInstance(NS_TIMER_CONTRACTID);
  24. MOZ_ASSERT(timer_);
  25. if (!timer_)
  26. return NS_ERROR_FAILURE;
  27. nsresult rv;
  28. target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
  29. MOZ_ASSERT(NS_SUCCEEDED(rv));
  30. if (!NS_SUCCEEDED(rv))
  31. return rv;
  32. timer_->SetTarget(target_);
  33. packets_lock_ = PR_NewLock();
  34. MOZ_ASSERT(packets_lock_);
  35. if (!packets_lock_)
  36. return NS_ERROR_FAILURE;
  37. deliverer_ = new Deliverer(this);
  38. timer_->InitWithCallback(deliverer_, 100, nsITimer::TYPE_REPEATING_SLACK);
  39. return NS_OK;
  40. }
  41. // Connect to the other side
  42. void TransportLayerLoopback::Connect(TransportLayerLoopback* peer) {
  43. peer_ = peer;
  44. TL_SET_STATE(TS_OPEN);
  45. }
  46. TransportResult
  47. TransportLayerLoopback::SendPacket(const unsigned char *data, size_t len) {
  48. MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")");
  49. if (!peer_) {
  50. MOZ_MTLOG(ML_ERROR, "Discarding packet because peer not attached");
  51. return TE_ERROR;
  52. }
  53. nsresult res = peer_->QueuePacket(data, len);
  54. if (!NS_SUCCEEDED(res))
  55. return TE_ERROR;
  56. return static_cast<TransportResult>(len);
  57. }
  58. nsresult TransportLayerLoopback::QueuePacket(const unsigned char *data,
  59. size_t len) {
  60. MOZ_ASSERT(packets_lock_);
  61. PR_Lock(packets_lock_);
  62. if (combinePackets_ && !packets_.empty()) {
  63. QueuedPacket *packet = packets_.front();
  64. packets_.pop();
  65. MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length " << packet->len() << " and " << len);
  66. packets_.push(new QueuedPacket());
  67. packets_.back()->Assign(packet->data(), packet->len(),
  68. data, len);
  69. } else {
  70. MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing packet of length " << len);
  71. packets_.push(new QueuedPacket());
  72. packets_.back()->Assign(data, len);
  73. }
  74. PRStatus r = PR_Unlock(packets_lock_);
  75. MOZ_ASSERT(r == PR_SUCCESS);
  76. if (r != PR_SUCCESS)
  77. return NS_ERROR_FAILURE;
  78. return NS_OK;
  79. }
  80. void TransportLayerLoopback::DeliverPackets() {
  81. while (!packets_.empty()) {
  82. QueuedPacket *packet = packets_.front();
  83. packets_.pop();
  84. MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Delivering packet of length " <<
  85. packet->len());
  86. SignalPacketReceived(this, packet->data(), packet->len());
  87. delete packet;
  88. }
  89. }
  90. NS_IMPL_ISUPPORTS(TransportLayerLoopback::Deliverer, nsITimerCallback)
  91. NS_IMETHODIMP TransportLayerLoopback::Deliverer::Notify(nsITimer *timer) {
  92. if (!layer_)
  93. return NS_OK;
  94. layer_->DeliverPackets();
  95. return NS_OK;
  96. }
  97. } // close namespace