diff options
Diffstat (limited to 'media/mtransport/transportlayerprsock.cpp')
-rw-r--r-- | media/mtransport/transportlayerprsock.cpp | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/media/mtransport/transportlayerprsock.cpp b/media/mtransport/transportlayerprsock.cpp new file mode 100644 index 000000000..ccaff32d1 --- /dev/null +++ b/media/mtransport/transportlayerprsock.cpp @@ -0,0 +1,116 @@ +/* -*- 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 + +#include "logging.h" +#include "nspr.h" +#include "prerror.h" +#include "prio.h" + +#include "nsCOMPtr.h" +#include "nsASocketHandler.h" +#include "nsISocketTransportService.h" +#include "nsNetCID.h" +#include "nsServiceManagerUtils.h" +#include "nsXPCOM.h" + +#include "transportflow.h" +#include "transportlayerprsock.h" + +namespace mozilla { + +MOZ_MTLOG_MODULE("mtransport") + +nsresult TransportLayerPrsock::InitInternal() { + // Get the transport service as a transport service + nsresult rv; + stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); + + if (!NS_SUCCEEDED(rv)) { + MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service"); + return rv; + } + + return NS_OK; +} + +void TransportLayerPrsock::Import(PRFileDesc *fd, nsresult *result) { + if (state_ != TS_INIT) { + *result = NS_ERROR_NOT_INITIALIZED; + return; + } + + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Importing()"); + fd_ = fd; + handler_ = new SocketHandler(this, fd); + + nsresult rv = stservice_->AttachSocket(fd_, handler_); + if (!NS_SUCCEEDED(rv)) { + *result = rv; + return; + } + + TL_SET_STATE(TS_OPEN); + + *result = NS_OK; +} + +int TransportLayerPrsock::SendPacket(const unsigned char *data, size_t len) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")"); + if (state_ != TS_OPEN) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Can't send packet on closed interface"); + return TE_INTERNAL; + } + + int32_t status; + status = PR_Write(fd_, data, len); + if (status >= 0) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << len << " bytes"); + return status; + } + + PRErrorCode err = PR_GetError(); + if (err == PR_WOULD_BLOCK_ERROR) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write blocked"); + return TE_WOULDBLOCK; + } + + + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write error; channel closed"); + TL_SET_STATE(TS_ERROR); + return TE_ERROR; +} + +void TransportLayerPrsock::OnSocketReady(PRFileDesc *fd, int16_t outflags) { + if (!(outflags & PR_POLL_READ)) { + return; + } + + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "OnSocketReady(flags=" << outflags << ")"); + + unsigned char buf[1600]; + int32_t rv = PR_Read(fd, buf, sizeof(buf)); + + if (rv > 0) { + // Successful read + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes"); + SignalPacketReceived(this, buf, rv); + } else if (rv == 0) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read 0 bytes; channel closed"); + TL_SET_STATE(TS_CLOSED); + } else { + PRErrorCode err = PR_GetError(); + + if (err != PR_WOULD_BLOCK_ERROR) { + MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read error; channel closed"); + TL_SET_STATE(TS_ERROR); + } + } +} + +NS_IMPL_ISUPPORTS0(TransportLayerPrsock::SocketHandler) +} // close namespace |