Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : // Original author: ekr@rtfm.com
8 :
9 : #include "logging.h"
10 : #include "nspr.h"
11 : #include "prerror.h"
12 : #include "prio.h"
13 :
14 : #include "nsCOMPtr.h"
15 : #include "nsASocketHandler.h"
16 : #include "nsISocketTransportService.h"
17 : #include "nsNetCID.h"
18 : #include "nsServiceManagerUtils.h"
19 : #include "nsXPCOM.h"
20 :
21 : #include "transportflow.h"
22 : #include "transportlayerprsock.h"
23 :
24 : namespace mozilla {
25 :
26 0 : MOZ_MTLOG_MODULE("mtransport")
27 :
28 0 : nsresult TransportLayerPrsock::InitInternal() {
29 : // Get the transport service as a transport service
30 : nsresult rv;
31 0 : stservice_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
32 :
33 0 : if (!NS_SUCCEEDED(rv)) {
34 0 : MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service");
35 0 : return rv;
36 : }
37 :
38 0 : return NS_OK;
39 : }
40 :
41 0 : void TransportLayerPrsock::Import(PRFileDesc *fd, nsresult *result) {
42 0 : if (state_ != TS_INIT) {
43 0 : *result = NS_ERROR_NOT_INITIALIZED;
44 0 : return;
45 : }
46 :
47 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Importing()");
48 0 : fd_ = fd;
49 0 : handler_ = new SocketHandler(this, fd);
50 :
51 0 : nsresult rv = stservice_->AttachSocket(fd_, handler_);
52 0 : if (!NS_SUCCEEDED(rv)) {
53 0 : *result = rv;
54 0 : return;
55 : }
56 :
57 0 : TL_SET_STATE(TS_OPEN);
58 :
59 0 : *result = NS_OK;
60 : }
61 :
62 0 : int TransportLayerPrsock::SendPacket(const unsigned char *data, size_t len) {
63 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << len << ")");
64 0 : if (state_ != TS_OPEN) {
65 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Can't send packet on closed interface");
66 0 : return TE_INTERNAL;
67 : }
68 :
69 : int32_t status;
70 0 : status = PR_Write(fd_, data, len);
71 0 : if (status >= 0) {
72 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << len << " bytes");
73 0 : return status;
74 : }
75 :
76 0 : PRErrorCode err = PR_GetError();
77 0 : if (err == PR_WOULD_BLOCK_ERROR) {
78 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write blocked");
79 0 : return TE_WOULDBLOCK;
80 : }
81 :
82 :
83 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Write error; channel closed");
84 0 : TL_SET_STATE(TS_ERROR);
85 0 : return TE_ERROR;
86 : }
87 :
88 0 : void TransportLayerPrsock::OnSocketReady(PRFileDesc *fd, int16_t outflags) {
89 0 : if (!(outflags & PR_POLL_READ)) {
90 0 : return;
91 : }
92 :
93 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "OnSocketReady(flags=" << outflags << ")");
94 :
95 : unsigned char buf[1600];
96 0 : int32_t rv = PR_Read(fd, buf, sizeof(buf));
97 :
98 0 : if (rv > 0) {
99 : // Successful read
100 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes");
101 0 : SignalPacketReceived(this, buf, rv);
102 0 : } else if (rv == 0) {
103 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read 0 bytes; channel closed");
104 0 : TL_SET_STATE(TS_CLOSED);
105 : } else {
106 0 : PRErrorCode err = PR_GetError();
107 :
108 0 : if (err != PR_WOULD_BLOCK_ERROR) {
109 0 : MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read error; channel closed");
110 0 : TL_SET_STATE(TS_ERROR);
111 : }
112 : }
113 : }
114 :
115 0 : NS_IMPL_ISUPPORTS0(TransportLayerPrsock::SocketHandler)
116 : } // close namespace
|