michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original author: ekr@rtfm.com michael@0: michael@0: #include "logging.h" michael@0: #include "nspr.h" michael@0: #include "prerror.h" michael@0: #include "prio.h" michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsASocketHandler.h" michael@0: #include "nsISocketTransportService.h" michael@0: #include "nsNetCID.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsXPCOM.h" michael@0: michael@0: #include "transportflow.h" michael@0: #include "transportlayerprsock.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: MOZ_MTLOG_MODULE("mtransport") michael@0: michael@0: nsresult TransportLayerPrsock::InitInternal() { michael@0: // Get the transport service as a transport service michael@0: nsresult rv; michael@0: stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); michael@0: michael@0: if (!NS_SUCCEEDED(rv)) { michael@0: MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service"); michael@0: return rv; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void TransportLayerPrsock::Import(PRFileDesc *fd, nsresult *result) { michael@0: if (state_ != TS_INIT) { michael@0: *result = NS_ERROR_NOT_INITIALIZED; michael@0: return; michael@0: } michael@0: michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Importing()"); michael@0: fd_ = fd; michael@0: handler_ = new SocketHandler(this, fd); michael@0: michael@0: nsresult rv = stservice_->AttachSocket(fd_, handler_); michael@0: if (!NS_SUCCEEDED(rv)) { michael@0: *result = rv; michael@0: return; michael@0: } michael@0: michael@0: TL_SET_STATE(TS_OPEN); michael@0: michael@0: *result = NS_OK; michael@0: } michael@0: michael@0: int TransportLayerPrsock::SendPacket(const unsigned char *data, size_t len) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")"); michael@0: if (state_ != TS_OPEN) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Can't send packet on closed interface"); michael@0: return TE_INTERNAL; michael@0: } michael@0: michael@0: int32_t status; michael@0: status = PR_Write(fd_, data, len); michael@0: if (status >= 0) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << len << " bytes"); michael@0: return status; michael@0: } michael@0: michael@0: PRErrorCode err = PR_GetError(); michael@0: if (err == PR_WOULD_BLOCK_ERROR) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write blocked"); michael@0: return TE_WOULDBLOCK; michael@0: } michael@0: michael@0: michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write error; channel closed"); michael@0: TL_SET_STATE(TS_ERROR); michael@0: return TE_ERROR; michael@0: } michael@0: michael@0: void TransportLayerPrsock::OnSocketReady(PRFileDesc *fd, int16_t outflags) { michael@0: if (!(outflags & PR_POLL_READ)) { michael@0: return; michael@0: } michael@0: michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "OnSocketReady(flags=" << outflags << ")"); michael@0: michael@0: unsigned char buf[1600]; michael@0: int32_t rv = PR_Read(fd, buf, sizeof(buf)); michael@0: michael@0: if (rv > 0) { michael@0: // Successful read michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes"); michael@0: SignalPacketReceived(this, buf, rv); michael@0: } else if (rv == 0) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read 0 bytes; channel closed"); michael@0: TL_SET_STATE(TS_CLOSED); michael@0: } else { michael@0: PRErrorCode err = PR_GetError(); michael@0: michael@0: if (err != PR_WOULD_BLOCK_ERROR) { michael@0: MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read error; channel closed"); michael@0: TL_SET_STATE(TS_ERROR); michael@0: } michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS0(TransportLayerPrsock::SocketHandler) michael@0: } // close namespace