Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/netwerk/protocol/http/TunnelUtils.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set sw=2 ts=8 et 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
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
// HttpLog.h should generally be included first
8
#include "HttpLog.h"
9
10
#include "Http2Session.h"
11
#include "nsHttp.h"
12
#include "nsHttpHandler.h"
13
#include "nsHttpRequestHead.h"
14
#include "TCPFastOpen.h"
15
#include "nsISocketProvider.h"
16
#include "nsISocketProviderService.h"
17
#include "nsISSLSocketControl.h"
18
#include "nsISocketTransport.h"
19
#include "nsISupportsPriority.h"
20
#include "nsNetAddr.h"
21
#include "prerror.h"
22
#include "prio.h"
23
#include "TunnelUtils.h"
24
#include "nsNetCID.h"
25
#include "nsServiceManagerUtils.h"
26
#include "nsComponentManagerUtils.h"
27
#include "nsSocketTransportService2.h"
28
29
namespace mozilla {
30
namespace net {
31
32
static PRDescIdentity sLayerIdentity;
33
static PRIOMethods sLayerMethods;
34
static PRIOMethods *sLayerMethodsPtr = nullptr;
35
36
TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped,
37
                                           const char *aTLSHost,
38
                                           int32_t aTLSPort,
39
                                           nsAHttpSegmentReader *aReader,
40
                                           nsAHttpSegmentWriter *aWriter)
41
  : mTransaction(aWrapped)
42
  , mEncryptedTextUsed(0)
43
  , mEncryptedTextSize(0)
44
  , mSegmentReader(aReader)
45
  , mSegmentWriter(aWriter)
46
  , mFilterReadCode(NS_ERROR_NOT_INITIALIZED)
47
  , mForce(false)
48
  , mReadSegmentBlocked(false)
49
  , mNudgeCounter(0)
50
0
{
51
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
52
0
  LOG(("TLSFilterTransaction ctor %p\n", this));
53
0
54
0
  nsCOMPtr<nsISocketProvider> provider;
55
0
  nsCOMPtr<nsISocketProviderService> spserv =
56
0
    do_GetService(NS_SOCKETPROVIDERSERVICE_CONTRACTID);
57
0
58
0
  if (spserv) {
59
0
    spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
60
0
  }
61
0
62
0
  // Install an NSPR layer to handle getpeername() with a failure. This is kind
63
0
  // of silly, but the default one used by the pipe asserts when called and the
64
0
  // nss code calls it to see if we are connected to a real socket or not.
65
0
  if (!sLayerMethodsPtr) {
66
0
    // one time initialization
67
0
    sLayerIdentity = PR_GetUniqueIdentity("TLSFilterTransaction Layer");
68
0
    sLayerMethods = *PR_GetDefaultIOMethods();
69
0
    sLayerMethods.getpeername = GetPeerName;
70
0
    sLayerMethods.getsocketoption = GetSocketOption;
71
0
    sLayerMethods.setsocketoption = SetSocketOption;
72
0
    sLayerMethods.read = FilterRead;
73
0
    sLayerMethods.write = FilterWrite;
74
0
    sLayerMethods.send = FilterSend;
75
0
    sLayerMethods.recv = FilterRecv;
76
0
    sLayerMethods.close = FilterClose;
77
0
    sLayerMethodsPtr = &sLayerMethods;
78
0
  }
79
0
80
0
  mFD = PR_CreateIOLayerStub(sLayerIdentity, &sLayerMethods);
81
0
82
0
  if (provider && mFD) {
83
0
    mFD->secret = reinterpret_cast<PRFilePrivate *>(this);
84
0
    provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
85
0
                          OriginAttributes(), 0, 0, mFD,
86
0
                          getter_AddRefs(mSecInfo));
87
0
  }
88
0
89
0
  if (mTransaction) {
90
0
    nsCOMPtr<nsIInterfaceRequestor> callbacks;
91
0
    mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
92
0
    nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(mSecInfo));
93
0
    if (secCtrl) {
94
0
      secCtrl->SetNotificationCallbacks(callbacks);
95
0
    }
96
0
  }
97
0
}
98
99
TLSFilterTransaction::~TLSFilterTransaction()
100
0
{
101
0
  LOG(("TLSFilterTransaction dtor %p\n", this));
102
0
  Cleanup();
103
0
}
104
105
void
106
TLSFilterTransaction::Cleanup()
107
0
{
108
0
  if (mTransaction) {
109
0
    mTransaction->Close(NS_ERROR_ABORT);
110
0
    mTransaction = nullptr;
111
0
  }
112
0
113
0
  if (mFD) {
114
0
    PR_Close(mFD);
115
0
    mFD = nullptr;
116
0
  }
117
0
  mSecInfo = nullptr;
118
0
  if (mTimer) {
119
0
    mTimer->Cancel();
120
0
    mTimer = nullptr;
121
0
  }
122
0
}
123
124
void
125
TLSFilterTransaction::Close(nsresult aReason)
126
0
{
127
0
  if (!mTransaction) {
128
0
    return;
129
0
  }
130
0
131
0
  if (mTimer) {
132
0
    mTimer->Cancel();
133
0
    mTimer = nullptr;
134
0
  }
135
0
  mTransaction->Close(aReason);
136
0
  mTransaction = nullptr;
137
0
}
138
139
nsresult
140
TLSFilterTransaction::OnReadSegment(const char *aData,
141
                                    uint32_t aCount,
142
                                    uint32_t *outCountRead)
143
0
{
144
0
  LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n",
145
0
       this, aCount, mEncryptedTextUsed));
146
0
147
0
  mReadSegmentBlocked = false;
148
0
  MOZ_ASSERT(mSegmentReader);
149
0
  if (!mSecInfo) {
150
0
    return NS_ERROR_FAILURE;
151
0
  }
152
0
153
0
  nsresult rv;
154
0
  *outCountRead = 0;
155
0
156
0
    // get rid of buffer first
157
0
  if (mEncryptedTextUsed) {
158
0
    rv = mSegmentReader->CommitToSegmentSize(mEncryptedTextUsed, mForce);
159
0
    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
160
0
      return rv;
161
0
    }
162
0
163
0
    uint32_t amt;
164
0
    rv = mSegmentReader->OnReadSegment(mEncryptedText.get(), mEncryptedTextUsed, &amt);
165
0
    if (NS_FAILED(rv)) {
166
0
      return rv;
167
0
    }
168
0
169
0
    mEncryptedTextUsed -= amt;
170
0
    if (mEncryptedTextUsed) {
171
0
      memmove(mEncryptedText.get(), &mEncryptedText[amt], mEncryptedTextUsed);
172
0
      return NS_OK;
173
0
    }
174
0
  }
175
0
176
0
  // encrypt for network write
177
0
  // write aData down the SSL layer into the FilterWrite() method where it will
178
0
  // be queued into mEncryptedText. We need to copy it like this in order to
179
0
  // guarantee atomic writes
180
0
181
0
  EnsureBuffer(mEncryptedText, aCount + 4096,
182
0
               0, mEncryptedTextSize);
183
0
184
0
  while (aCount > 0) {
185
0
    int32_t written = PR_Write(mFD, aData, aCount);
186
0
    LOG(("TLSFilterTransaction %p OnReadSegment PRWrite(%d) = %d %d\n",
187
0
         this, aCount, written,
188
0
         PR_GetError() == PR_WOULD_BLOCK_ERROR));
189
0
190
0
    if (written < 1) {
191
0
      if (*outCountRead) {
192
0
        return NS_OK;
193
0
      }
194
0
      // mTransaction ReadSegments actually obscures this code, so
195
0
      // keep it in a member var for this::ReadSegments to insepct. Similar
196
0
      // to nsHttpConnection::mSocketOutCondition
197
0
      mReadSegmentBlocked = (PR_GetError() == PR_WOULD_BLOCK_ERROR);
198
0
      return mReadSegmentBlocked ? NS_BASE_STREAM_WOULD_BLOCK : NS_ERROR_FAILURE;
199
0
    }
200
0
    aCount -= written;
201
0
    aData += written;
202
0
    *outCountRead += written;
203
0
    mNudgeCounter = 0;
204
0
  }
205
0
206
0
  LOG(("TLSFilterTransaction %p OnReadSegment2 (buffered %d)\n",
207
0
       this, mEncryptedTextUsed));
208
0
209
0
  uint32_t amt = 0;
210
0
  if (mEncryptedTextUsed) {
211
0
    // If we are tunneled on spdy CommitToSegmentSize will prevent partial
212
0
    // writes that could interfere with multiplexing. H1 is fine with
213
0
    // partial writes.
214
0
    rv = mSegmentReader->CommitToSegmentSize(mEncryptedTextUsed, mForce);
215
0
    if (rv != NS_BASE_STREAM_WOULD_BLOCK) {
216
0
      rv = mSegmentReader->OnReadSegment(mEncryptedText.get(), mEncryptedTextUsed, &amt);
217
0
    }
218
0
219
0
    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
220
0
      // return OK because all the data was consumed and stored in this buffer
221
0
      Connection()->TransactionHasDataToWrite(this);
222
0
      return NS_OK;
223
0
    } else if (NS_FAILED(rv)) {
224
0
      return rv;
225
0
    }
226
0
  }
227
0
228
0
  if (amt == mEncryptedTextUsed) {
229
0
    mEncryptedText = nullptr;
230
0
    mEncryptedTextUsed = 0;
231
0
    mEncryptedTextSize = 0;
232
0
  } else {
233
0
    memmove(mEncryptedText.get(), &mEncryptedText[amt], mEncryptedTextUsed - amt);
234
0
    mEncryptedTextUsed -= amt;
235
0
  }
236
0
  return NS_OK;
237
0
}
238
239
int32_t
240
TLSFilterTransaction::FilterOutput(const char *aBuf, int32_t aAmount)
241
0
{
242
0
  EnsureBuffer(mEncryptedText, mEncryptedTextUsed + aAmount,
243
0
               mEncryptedTextUsed, mEncryptedTextSize);
244
0
  memcpy(&mEncryptedText[mEncryptedTextUsed], aBuf, aAmount);
245
0
  mEncryptedTextUsed += aAmount;
246
0
  return aAmount;
247
0
}
248
249
nsresult
250
TLSFilterTransaction::CommitToSegmentSize(uint32_t size, bool forceCommitment)
251
0
{
252
0
  if (!mSegmentReader) {
253
0
      return NS_ERROR_FAILURE;
254
0
  }
255
0
256
0
  // pad the commit by a little bit to leave room for encryption overhead
257
0
  // this isn't foolproof and we may still have to buffer, but its a good start
258
0
  mForce = forceCommitment;
259
0
  return mSegmentReader->CommitToSegmentSize(size + 1024, forceCommitment);
260
0
}
261
262
nsresult
263
TLSFilterTransaction::OnWriteSegment(char *aData,
264
                                     uint32_t aCount,
265
                                     uint32_t *outCountRead)
266
0
{
267
0
268
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
269
0
  MOZ_ASSERT(mSegmentWriter);
270
0
  LOG(("TLSFilterTransaction::OnWriteSegment %p max=%d\n", this, aCount));
271
0
  if (!mSecInfo) {
272
0
    return NS_ERROR_FAILURE;
273
0
  }
274
0
275
0
  // this will call through to FilterInput to get data from the higher
276
0
  // level connection before removing the local TLS layer
277
0
  mFilterReadCode = NS_OK;
278
0
  int32_t bytesRead = PR_Read(mFD, aData, aCount);
279
0
  if (bytesRead == -1) {
280
0
    if (PR_GetError() == PR_WOULD_BLOCK_ERROR) {
281
0
      return NS_BASE_STREAM_WOULD_BLOCK;
282
0
    }
283
0
    return NS_ERROR_FAILURE;
284
0
  }
285
0
  *outCountRead = bytesRead;
286
0
287
0
  if (NS_SUCCEEDED(mFilterReadCode) && !bytesRead) {
288
0
    LOG(("TLSFilterTransaction::OnWriteSegment %p "
289
0
         "Second layer of TLS stripping results in STREAM_CLOSED\n", this));
290
0
    mFilterReadCode = NS_BASE_STREAM_CLOSED;
291
0
  }
292
0
293
0
  LOG(("TLSFilterTransaction::OnWriteSegment %p rv=%" PRIx32 " didread=%d "
294
0
       "2 layers of ssl stripped to plaintext\n",
295
0
       this, static_cast<uint32_t>(mFilterReadCode), bytesRead));
296
0
  return mFilterReadCode;
297
0
}
298
299
int32_t
300
TLSFilterTransaction::FilterInput(char *aBuf, int32_t aAmount)
301
0
{
302
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
303
0
  MOZ_ASSERT(mSegmentWriter);
304
0
  LOG(("TLSFilterTransaction::FilterInput max=%d\n", aAmount));
305
0
306
0
  uint32_t outCountRead = 0;
307
0
  mFilterReadCode = mSegmentWriter->OnWriteSegment(aBuf, aAmount, &outCountRead);
308
0
  if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) {
309
0
    LOG(("TLSFilterTransaction::FilterInput rv=%" PRIx32 " read=%d input from net "
310
0
         "1 layer stripped, 1 still on\n",
311
0
         static_cast<uint32_t>(mFilterReadCode), outCountRead));
312
0
    if (mReadSegmentBlocked) {
313
0
      mNudgeCounter = 0;
314
0
    }
315
0
  }
316
0
  if (mFilterReadCode == NS_BASE_STREAM_WOULD_BLOCK) {
317
0
    PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
318
0
    return -1;
319
0
  }
320
0
  return outCountRead;
321
0
}
322
323
nsresult
324
TLSFilterTransaction::ReadSegments(nsAHttpSegmentReader *aReader,
325
                                   uint32_t aCount, uint32_t *outCountRead)
326
0
{
327
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
328
0
  LOG(("TLSFilterTransaction::ReadSegments %p max=%d\n", this, aCount));
329
0
330
0
  if (!mTransaction) {
331
0
    return NS_ERROR_UNEXPECTED;
332
0
  }
333
0
334
0
  mReadSegmentBlocked = false;
335
0
  mSegmentReader = aReader;
336
0
  nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead);
337
0
  LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%" PRIx32 " %d\n",
338
0
       this, static_cast<uint32_t>(rv), *outCountRead));
339
0
  if (NS_SUCCEEDED(rv) && mReadSegmentBlocked) {
340
0
    rv = NS_BASE_STREAM_WOULD_BLOCK;
341
0
    LOG(("TLSFilterTransaction %p read segment blocked found rv=%" PRIx32 "\n",
342
0
         this, static_cast<uint32_t>(rv)));
343
0
    Unused << Connection()->ForceSend();
344
0
  }
345
0
346
0
  return rv;
347
0
}
348
349
nsresult
350
TLSFilterTransaction::WriteSegments(nsAHttpSegmentWriter *aWriter,
351
                                    uint32_t aCount, uint32_t *outCountWritten)
352
0
{
353
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
354
0
  LOG(("TLSFilterTransaction::WriteSegments %p max=%d\n", this, aCount));
355
0
356
0
  if (!mTransaction) {
357
0
    return NS_ERROR_UNEXPECTED;
358
0
  }
359
0
360
0
  mSegmentWriter = aWriter;
361
0
  nsresult rv = mTransaction->WriteSegments(this, aCount, outCountWritten);
362
0
  if (NS_SUCCEEDED(rv) && NS_FAILED(mFilterReadCode) && !(*outCountWritten)) {
363
0
    // nsPipe turns failures into silent OK.. undo that!
364
0
    rv = mFilterReadCode;
365
0
    if (Connection() && (mFilterReadCode == NS_BASE_STREAM_WOULD_BLOCK)) {
366
0
      Unused << Connection()->ResumeRecv();
367
0
    }
368
0
  }
369
0
  LOG(("TLSFilterTransaction %p called trans->WriteSegments rv=%" PRIx32 " %d\n",
370
0
       this, static_cast<uint32_t>(rv), *outCountWritten));
371
0
  return rv;
372
0
}
373
374
nsresult
375
TLSFilterTransaction::GetTransactionSecurityInfo(nsISupports **outSecInfo)
376
0
{
377
0
  if (!mSecInfo) {
378
0
    return NS_ERROR_FAILURE;
379
0
  }
380
0
381
0
  nsCOMPtr<nsISupports> temp(mSecInfo);
382
0
  temp.forget(outSecInfo);
383
0
  return NS_OK;
384
0
}
385
386
nsresult
387
TLSFilterTransaction::NudgeTunnel(NudgeTunnelCallback *aCallback)
388
0
{
389
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
390
0
  LOG(("TLSFilterTransaction %p NudgeTunnel\n", this));
391
0
  mNudgeCallback = nullptr;
392
0
393
0
  if (!mSecInfo) {
394
0
    return NS_ERROR_FAILURE;
395
0
  }
396
0
397
0
  nsCOMPtr<nsISSLSocketControl> ssl(do_QueryInterface(mSecInfo));
398
0
  nsresult rv = ssl ? ssl->DriveHandshake() : NS_ERROR_FAILURE;
399
0
  if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
400
0
    // fatal handshake failure
401
0
    LOG(("TLSFilterTransaction %p Fatal Handshake Failure: %d\n", this, PR_GetError()));
402
0
    return NS_ERROR_FAILURE;
403
0
  }
404
0
405
0
  uint32_t notUsed;
406
0
  Unused << OnReadSegment("", 0, &notUsed);
407
0
408
0
  // The SSL Layer does some unusual things with PR_Poll that makes it a bad
409
0
  // match for multiplexed SSL sessions. We work around this by manually polling for
410
0
  // the moment during the brief handshake phase or otherwise blocked on write.
411
0
  // Thankfully this is a pretty unusual state. NSPR doesn't help us here -
412
0
  // asserting when polling without the NSPR IO layer on the bottom of
413
0
  // the stack. As a follow-on we can do some NSPR and maybe libssl changes
414
0
  // to make this more event driven, but this is acceptable for getting started.
415
0
416
0
  uint32_t counter = mNudgeCounter++;
417
0
  uint32_t delay;
418
0
419
0
  if (!counter) {
420
0
    delay = 0;
421
0
  } else if (counter < 8) { // up to 48ms at 6
422
0
    delay = 6;
423
0
  } else if (counter < 34) { // up to 499 ms at 17ms
424
0
    delay = 17;
425
0
  } else { // after that at 51ms (3 old windows ticks)
426
0
    delay = 51;
427
0
  }
428
0
429
0
  if(!mTimer) {
430
0
    mTimer = NS_NewTimer();
431
0
  }
432
0
433
0
  mNudgeCallback = aCallback;
434
0
  if (!mTimer ||
435
0
      NS_FAILED(mTimer->InitWithCallback(this, delay, nsITimer::TYPE_ONE_SHOT))) {
436
0
    return StartTimerCallback();
437
0
  }
438
0
439
0
  LOG(("TLSFilterTransaction %p NudgeTunnel timer started\n", this));
440
0
  return NS_OK;
441
0
}
442
443
NS_IMETHODIMP
444
TLSFilterTransaction::Notify(nsITimer *timer)
445
0
{
446
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
447
0
  LOG(("TLSFilterTransaction %p NudgeTunnel notify\n", this));
448
0
449
0
  if (timer != mTimer) {
450
0
    return NS_ERROR_UNEXPECTED;
451
0
  }
452
0
  DebugOnly<nsresult> rv = StartTimerCallback();
453
0
  MOZ_ASSERT(NS_SUCCEEDED(rv));
454
0
  return NS_OK;
455
0
}
456
457
NS_IMETHODIMP
458
TLSFilterTransaction::GetName(nsACString& aName)
459
0
{
460
0
  aName.AssignLiteral("TLSFilterTransaction");
461
0
  return NS_OK;
462
0
}
463
464
nsresult
465
TLSFilterTransaction::StartTimerCallback()
466
0
{
467
0
  LOG(("TLSFilterTransaction %p NudgeTunnel StartTimerCallback %p\n",
468
0
       this, mNudgeCallback.get()));
469
0
470
0
  if (mNudgeCallback) {
471
0
    // This class can be called re-entrantly, so cleanup m* before ->on()
472
0
    RefPtr<NudgeTunnelCallback> cb(mNudgeCallback);
473
0
    mNudgeCallback = nullptr;
474
0
    cb->OnTunnelNudged(this);
475
0
  }
476
0
  return NS_OK;
477
0
}
478
479
PRStatus
480
TLSFilterTransaction::GetPeerName(PRFileDesc *aFD, PRNetAddr*addr)
481
0
{
482
0
  NetAddr peeraddr;
483
0
  TLSFilterTransaction *self = reinterpret_cast<TLSFilterTransaction *>(aFD->secret);
484
0
485
0
  if (!self->mTransaction ||
486
0
      NS_FAILED(self->mTransaction->Connection()->Transport()->GetPeerAddr(&peeraddr))) {
487
0
    return PR_FAILURE;
488
0
  }
489
0
  NetAddrToPRNetAddr(&peeraddr, addr);
490
0
  return PR_SUCCESS;
491
0
}
492
493
PRStatus
494
TLSFilterTransaction::GetSocketOption(PRFileDesc *aFD, PRSocketOptionData *aOpt)
495
0
{
496
0
  if (aOpt->option == PR_SockOpt_Nonblocking) {
497
0
    aOpt->value.non_blocking = PR_TRUE;
498
0
    return PR_SUCCESS;
499
0
  }
500
0
  return PR_FAILURE;
501
0
}
502
503
PRStatus
504
TLSFilterTransaction::SetSocketOption(PRFileDesc *aFD, const PRSocketOptionData *aOpt)
505
0
{
506
0
  return PR_FAILURE;
507
0
}
508
509
PRStatus
510
TLSFilterTransaction::FilterClose(PRFileDesc *aFD)
511
0
{
512
0
  return PR_SUCCESS;
513
0
}
514
515
int32_t
516
TLSFilterTransaction::FilterWrite(PRFileDesc *aFD, const void *aBuf, int32_t aAmount)
517
0
{
518
0
  TLSFilterTransaction *self = reinterpret_cast<TLSFilterTransaction *>(aFD->secret);
519
0
  return self->FilterOutput(static_cast<const char *>(aBuf), aAmount);
520
0
}
521
522
int32_t
523
TLSFilterTransaction::FilterSend(PRFileDesc *aFD, const void *aBuf, int32_t aAmount,
524
                                  int , PRIntervalTime)
525
0
{
526
0
  return FilterWrite(aFD, aBuf, aAmount);
527
0
}
528
529
int32_t
530
TLSFilterTransaction::FilterRead(PRFileDesc *aFD, void *aBuf, int32_t aAmount)
531
0
{
532
0
  TLSFilterTransaction *self = reinterpret_cast<TLSFilterTransaction *>(aFD->secret);
533
0
  return self->FilterInput(static_cast<char *>(aBuf), aAmount);
534
0
}
535
536
int32_t
537
TLSFilterTransaction::FilterRecv(PRFileDesc *aFD, void *aBuf, int32_t aAmount,
538
                                  int , PRIntervalTime)
539
0
{
540
0
  return FilterRead(aFD, aBuf, aAmount);
541
0
}
542
543
/////
544
// The other methods of TLSFilterTransaction just call mTransaction->method
545
/////
546
547
void
548
TLSFilterTransaction::SetConnection(nsAHttpConnection *aConnection)
549
0
{
550
0
  if (!mTransaction) {
551
0
    return;
552
0
  }
553
0
554
0
  mTransaction->SetConnection(aConnection);
555
0
}
556
557
nsAHttpConnection *
558
TLSFilterTransaction::Connection()
559
0
{
560
0
  if (!mTransaction) {
561
0
    return nullptr;
562
0
  }
563
0
  return mTransaction->Connection();
564
0
}
565
566
void
567
TLSFilterTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
568
0
{
569
0
  if (!mTransaction) {
570
0
    return;
571
0
  }
572
0
  mTransaction->GetSecurityCallbacks(outCB);
573
0
}
574
575
void
576
TLSFilterTransaction::OnTransportStatus(nsITransport* aTransport,
577
                                        nsresult aStatus, int64_t aProgress)
578
0
{
579
0
  if (!mTransaction) {
580
0
    return;
581
0
  }
582
0
  mTransaction->OnTransportStatus(aTransport, aStatus, aProgress);
583
0
}
584
585
nsHttpConnectionInfo *
586
TLSFilterTransaction::ConnectionInfo()
587
0
{
588
0
  if (!mTransaction) {
589
0
    return nullptr;
590
0
  }
591
0
  return mTransaction->ConnectionInfo();
592
0
}
593
594
bool
595
TLSFilterTransaction::IsDone()
596
0
{
597
0
  if (!mTransaction) {
598
0
    return true;
599
0
  }
600
0
  return mTransaction->IsDone();
601
0
}
602
603
nsresult
604
TLSFilterTransaction::Status()
605
0
{
606
0
  if (!mTransaction) {
607
0
    return NS_ERROR_UNEXPECTED;
608
0
  }
609
0
610
0
  return mTransaction->Status();
611
0
}
612
613
uint32_t
614
TLSFilterTransaction::Caps()
615
0
{
616
0
  if (!mTransaction) {
617
0
    return 0;
618
0
  }
619
0
620
0
  return mTransaction->Caps();
621
0
}
622
623
void
624
TLSFilterTransaction::SetDNSWasRefreshed()
625
0
{
626
0
  if (!mTransaction) {
627
0
    return;
628
0
  }
629
0
630
0
  mTransaction->SetDNSWasRefreshed();
631
0
}
632
633
void
634
TLSFilterTransaction::SetProxyConnectFailed()
635
0
{
636
0
  if (!mTransaction) {
637
0
    return;
638
0
  }
639
0
640
0
  mTransaction->SetProxyConnectFailed();
641
0
}
642
643
nsHttpRequestHead *
644
TLSFilterTransaction::RequestHead()
645
0
{
646
0
  if (!mTransaction) {
647
0
    return nullptr;
648
0
  }
649
0
650
0
  return mTransaction->RequestHead();
651
0
}
652
653
uint32_t
654
TLSFilterTransaction::Http1xTransactionCount()
655
0
{
656
0
  if (!mTransaction) {
657
0
    return 0;
658
0
  }
659
0
660
0
  return mTransaction->Http1xTransactionCount();
661
0
}
662
663
nsresult
664
TLSFilterTransaction::TakeSubTransactions(
665
  nsTArray<RefPtr<nsAHttpTransaction> > &outTransactions)
666
0
{
667
0
  LOG(("TLSFilterTransaction::TakeSubTransactions [this=%p] mTransaction %p\n",
668
0
       this, mTransaction.get()));
669
0
670
0
  if (!mTransaction) {
671
0
    return NS_ERROR_UNEXPECTED;
672
0
  }
673
0
674
0
  if (mTransaction->TakeSubTransactions(outTransactions) == NS_ERROR_NOT_IMPLEMENTED) {
675
0
    outTransactions.AppendElement(mTransaction);
676
0
  }
677
0
  mTransaction = nullptr;
678
0
679
0
  return NS_OK;
680
0
}
681
682
nsresult
683
TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans)
684
0
{
685
0
  LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p\n",
686
0
       this, aTrans));
687
0
688
0
  mTransaction = aTrans;
689
0
  nsCOMPtr<nsIInterfaceRequestor> callbacks;
690
0
  mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
691
0
  nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(mSecInfo));
692
0
  if (secCtrl && callbacks) {
693
0
    secCtrl->SetNotificationCallbacks(callbacks);
694
0
  }
695
0
696
0
  return NS_OK;
697
0
}
698
699
bool
700
TLSFilterTransaction::IsNullTransaction()
701
0
{
702
0
  if (!mTransaction) {
703
0
    return false;
704
0
  }
705
0
  return mTransaction->IsNullTransaction();
706
0
}
707
708
NullHttpTransaction *
709
TLSFilterTransaction::QueryNullTransaction()
710
0
{
711
0
  if (!mTransaction) {
712
0
    return nullptr;
713
0
  }
714
0
  return mTransaction->QueryNullTransaction();
715
0
}
716
717
nsHttpTransaction *
718
TLSFilterTransaction::QueryHttpTransaction()
719
0
{
720
0
  if (!mTransaction) {
721
0
    return nullptr;
722
0
  }
723
0
  return mTransaction->QueryHttpTransaction();
724
0
}
725
726
727
class SocketInWrapper : public nsIAsyncInputStream
728
                      , public nsAHttpSegmentWriter
729
{
730
  NS_DECL_THREADSAFE_ISUPPORTS
731
  NS_FORWARD_NSIASYNCINPUTSTREAM(mStream->)
732
733
  SocketInWrapper(nsIAsyncInputStream *aWrapped, TLSFilterTransaction *aFilter)
734
    : mStream(aWrapped)
735
    , mTLSFilter(aFilter)
736
0
  { }
737
738
  NS_IMETHOD Close() override
739
0
  {
740
0
    mTLSFilter = nullptr;
741
0
    return mStream->Close();
742
0
  }
743
744
  NS_IMETHOD Available(uint64_t *_retval) override
745
0
  {
746
0
    return mStream->Available(_retval);
747
0
  }
748
749
  NS_IMETHOD IsNonBlocking(bool *_retval) override
750
0
  {
751
0
    return mStream->IsNonBlocking(_retval);
752
0
  }
753
754
  NS_IMETHOD ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) override
755
0
  {
756
0
    return mStream->ReadSegments(aWriter, aClosure, aCount, _retval);
757
0
  }
758
759
  // finally, ones that don't get forwarded :)
760
  NS_IMETHOD Read(char *aBuf, uint32_t aCount, uint32_t *_retval) override;
761
  virtual nsresult OnWriteSegment(char *segment, uint32_t count, uint32_t *countWritten) override;
762
763
private:
764
0
  virtual ~SocketInWrapper() = default;;
765
766
  nsCOMPtr<nsIAsyncInputStream> mStream;
767
  RefPtr<TLSFilterTransaction> mTLSFilter;
768
};
769
770
nsresult
771
SocketInWrapper::OnWriteSegment(char *segment, uint32_t count, uint32_t *countWritten)
772
0
{
773
0
  LOG(("SocketInWrapper OnWriteSegment %d %p filter=%p\n", count, this, mTLSFilter.get()));
774
0
775
0
  nsresult rv = mStream->Read(segment, count, countWritten);
776
0
  LOG(("SocketInWrapper OnWriteSegment %p wrapped read %" PRIx32 " %d\n",
777
0
       this, static_cast<uint32_t>(rv), *countWritten));
778
0
  return rv;
779
0
}
780
781
NS_IMETHODIMP
782
SocketInWrapper::Read(char *aBuf, uint32_t aCount, uint32_t *_retval)
783
0
{
784
0
  LOG(("SocketInWrapper Read %d %p filter=%p\n", aCount, this, mTLSFilter.get()));
785
0
786
0
  if (!mTLSFilter) {
787
0
    return NS_ERROR_UNEXPECTED; // protect potentially dangling mTLSFilter
788
0
  }
789
0
790
0
  // mTLSFilter->mSegmentWriter MUST be this at ctor time
791
0
  return mTLSFilter->OnWriteSegment(aBuf, aCount, _retval);
792
0
}
793
794
class SocketOutWrapper : public nsIAsyncOutputStream
795
                       , public nsAHttpSegmentReader
796
{
797
  NS_DECL_THREADSAFE_ISUPPORTS
798
  NS_FORWARD_NSIASYNCOUTPUTSTREAM(mStream->)
799
800
  SocketOutWrapper(nsIAsyncOutputStream *aWrapped, TLSFilterTransaction *aFilter)
801
    : mStream(aWrapped)
802
    , mTLSFilter(aFilter)
803
0
  { }
804
805
  NS_IMETHOD Close() override
806
0
  {
807
0
    mTLSFilter = nullptr;
808
0
    return mStream->Close();
809
0
  }
810
811
  NS_IMETHOD Flush() override
812
0
  {
813
0
    return mStream->Flush();
814
0
  }
815
816
  NS_IMETHOD IsNonBlocking(bool *_retval) override
817
0
  {
818
0
    return mStream->IsNonBlocking(_retval);
819
0
  }
820
821
  NS_IMETHOD WriteSegments(nsReadSegmentFun aReader, void *aClosure, uint32_t aCount, uint32_t *_retval) override
822
0
  {
823
0
    return mStream->WriteSegments(aReader, aClosure, aCount, _retval);
824
0
  }
825
826
  NS_IMETHOD WriteFrom(nsIInputStream *aFromStream, uint32_t aCount, uint32_t *_retval) override
827
0
  {
828
0
    return mStream->WriteFrom(aFromStream, aCount, _retval);
829
0
  }
830
831
  // finally, ones that don't get forwarded :)
832
  NS_IMETHOD Write(const char *aBuf, uint32_t aCount, uint32_t *_retval) override;
833
  virtual nsresult OnReadSegment(const char *segment, uint32_t count, uint32_t *countRead) override;
834
835
private:
836
0
  virtual ~SocketOutWrapper() = default;;
837
838
  nsCOMPtr<nsIAsyncOutputStream> mStream;
839
  RefPtr<TLSFilterTransaction> mTLSFilter;
840
};
841
842
nsresult
843
SocketOutWrapper::OnReadSegment(const char *segment, uint32_t count, uint32_t *countWritten)
844
0
{
845
0
  return mStream->Write(segment, count, countWritten);
846
0
}
847
848
NS_IMETHODIMP
849
SocketOutWrapper::Write(const char *aBuf, uint32_t aCount, uint32_t *_retval)
850
0
{
851
0
  LOG(("SocketOutWrapper Write %d %p filter=%p\n", aCount, this, mTLSFilter.get()));
852
0
853
0
  // mTLSFilter->mSegmentReader MUST be this at ctor time
854
0
  if (!mTLSFilter) {
855
0
    return NS_ERROR_UNEXPECTED; // protect potentially dangling mTLSFilter
856
0
  }
857
0
858
0
  return mTLSFilter->OnReadSegment(aBuf, aCount, _retval);
859
0
}
860
861
void
862
TLSFilterTransaction::newIODriver(nsIAsyncInputStream *aSocketIn,
863
                                  nsIAsyncOutputStream *aSocketOut,
864
                                  nsIAsyncInputStream **outSocketIn,
865
                                  nsIAsyncOutputStream **outSocketOut)
866
0
{
867
0
  SocketInWrapper *inputWrapper = new SocketInWrapper(aSocketIn, this);
868
0
  mSegmentWriter = inputWrapper;
869
0
  nsCOMPtr<nsIAsyncInputStream> newIn(inputWrapper);
870
0
  newIn.forget(outSocketIn);
871
0
872
0
  SocketOutWrapper *outputWrapper = new SocketOutWrapper(aSocketOut, this);
873
0
  mSegmentReader = outputWrapper;
874
0
  nsCOMPtr<nsIAsyncOutputStream> newOut(outputWrapper);
875
0
  newOut.forget(outSocketOut);
876
0
}
877
878
SpdyConnectTransaction *
879
TLSFilterTransaction::QuerySpdyConnectTransaction()
880
0
{
881
0
  if (!mTransaction) {
882
0
    return nullptr;
883
0
  }
884
0
  return mTransaction->QuerySpdyConnectTransaction();
885
0
}
886
887
class SocketTransportShim : public nsISocketTransport
888
{
889
public:
890
  NS_DECL_THREADSAFE_ISUPPORTS
891
  NS_DECL_NSITRANSPORT
892
  NS_DECL_NSISOCKETTRANSPORT
893
894
  explicit SocketTransportShim(nsISocketTransport *aWrapped)
895
    : mWrapped(aWrapped)
896
0
  {};
897
898
private:
899
0
  virtual ~SocketTransportShim() = default;;
900
901
  nsCOMPtr<nsISocketTransport> mWrapped;
902
};
903
904
class OutputStreamShim : public nsIAsyncOutputStream
905
{
906
public:
907
  NS_DECL_THREADSAFE_ISUPPORTS
908
  NS_DECL_NSIOUTPUTSTREAM
909
  NS_DECL_NSIASYNCOUTPUTSTREAM
910
911
  friend class SpdyConnectTransaction;
912
913
  explicit OutputStreamShim(SpdyConnectTransaction *aTrans)
914
    : mCallback(nullptr)
915
    , mStatus(NS_OK)
916
0
  {
917
0
    mWeakTrans = do_GetWeakReference(aTrans);
918
0
  }
919
920
private:
921
0
  virtual ~OutputStreamShim() = default;;
922
923
  nsWeakPtr mWeakTrans; // SpdyConnectTransaction *
924
  nsIOutputStreamCallback *mCallback;
925
  nsresult mStatus;
926
};
927
928
class InputStreamShim : public nsIAsyncInputStream
929
{
930
public:
931
  NS_DECL_THREADSAFE_ISUPPORTS
932
  NS_DECL_NSIINPUTSTREAM
933
  NS_DECL_NSIASYNCINPUTSTREAM
934
935
  friend class SpdyConnectTransaction;
936
937
  explicit InputStreamShim(SpdyConnectTransaction *aTrans)
938
    : mCallback(nullptr)
939
    , mStatus(NS_OK)
940
0
  {
941
0
    mWeakTrans = do_GetWeakReference(aTrans);
942
0
  }
943
944
private:
945
0
  virtual ~InputStreamShim() = default;;
946
947
  nsWeakPtr mWeakTrans; // SpdyConnectTransaction *
948
  nsIInputStreamCallback *mCallback;
949
  nsresult mStatus;
950
};
951
952
SpdyConnectTransaction::SpdyConnectTransaction(nsHttpConnectionInfo *ci,
953
                                               nsIInterfaceRequestor *callbacks,
954
                                               uint32_t caps,
955
                                               nsHttpTransaction *trans,
956
                                               nsAHttpConnection *session)
957
  : NullHttpTransaction(ci, callbacks, caps | NS_HTTP_ALLOW_KEEPALIVE)
958
  , mConnectStringOffset(0)
959
  , mSession(session)
960
  , mSegmentReader(nullptr)
961
  , mInputDataSize(0)
962
  , mInputDataUsed(0)
963
  , mInputDataOffset(0)
964
  , mOutputDataSize(0)
965
  , mOutputDataUsed(0)
966
  , mOutputDataOffset(0)
967
  , mForcePlainText(false)
968
0
{
969
0
  LOG(("SpdyConnectTransaction ctor %p\n", this));
970
0
971
0
  mTimestampSyn = TimeStamp::Now();
972
0
  mRequestHead = new nsHttpRequestHead();
973
0
  DebugOnly<nsresult> rv =
974
0
    nsHttpConnection::MakeConnectString(trans, mRequestHead, mConnectString);
975
0
  MOZ_ASSERT(NS_SUCCEEDED(rv));
976
0
  mDrivingTransaction = trans;
977
0
}
978
979
SpdyConnectTransaction::~SpdyConnectTransaction()
980
0
{
981
0
  LOG(("SpdyConnectTransaction dtor %p\n", this));
982
0
983
0
  if (mDrivingTransaction) {
984
0
    // requeue it I guess. This should be gone.
985
0
    Unused << gHttpHandler->InitiateTransaction(mDrivingTransaction,
986
0
                                                mDrivingTransaction->Priority());
987
0
  }
988
0
}
989
990
void
991
SpdyConnectTransaction::ForcePlainText()
992
0
{
993
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
994
0
  MOZ_ASSERT(!mInputDataUsed && !mInputDataSize && !mInputDataOffset);
995
0
  MOZ_ASSERT(!mForcePlainText);
996
0
  MOZ_ASSERT(!mTunnelTransport, "call before mapstreamtohttpconnection");
997
0
998
0
  mForcePlainText = true;
999
0
}
1000
1001
void
1002
SpdyConnectTransaction::MapStreamToHttpConnection(nsISocketTransport *aTransport,
1003
                                                  nsHttpConnectionInfo *aConnInfo)
1004
0
{
1005
0
  mConnInfo = aConnInfo;
1006
0
1007
0
  mTunnelTransport = new SocketTransportShim(aTransport);
1008
0
  mTunnelStreamIn = new InputStreamShim(this);
1009
0
  mTunnelStreamOut = new OutputStreamShim(this);
1010
0
  mTunneledConn = new nsHttpConnection();
1011
0
1012
0
  // this new http connection has a specific hashkey (i.e. to a particular
1013
0
  // host via the tunnel) and is associated with the tunnel streams
1014
0
  LOG(("SpdyConnectTransaction new httpconnection %p %s\n",
1015
0
       mTunneledConn.get(), aConnInfo->HashKey().get()));
1016
0
1017
0
  nsCOMPtr<nsIInterfaceRequestor> callbacks;
1018
0
  GetSecurityCallbacks(getter_AddRefs(callbacks));
1019
0
  mTunneledConn->SetTransactionCaps(Caps());
1020
0
  MOZ_ASSERT(aConnInfo->UsingHttpsProxy());
1021
0
  TimeDuration rtt = TimeStamp::Now() - mTimestampSyn;
1022
0
  DebugOnly<nsresult> rv =
1023
0
    mTunneledConn->Init(aConnInfo,
1024
0
                        gHttpHandler->ConnMgr()->MaxRequestDelay(),
1025
0
                        mTunnelTransport, mTunnelStreamIn, mTunnelStreamOut,
1026
0
                        true, callbacks,
1027
0
                        PR_MillisecondsToInterval(
1028
0
                          static_cast<uint32_t>(rtt.ToMilliseconds())));
1029
0
  MOZ_ASSERT(NS_SUCCEEDED(rv));
1030
0
  if (mForcePlainText) {
1031
0
      mTunneledConn->ForcePlainText();
1032
0
  } else {
1033
0
    mTunneledConn->SetupSecondaryTLS();
1034
0
    mTunneledConn->SetInSpdyTunnel(true);
1035
0
  }
1036
0
1037
0
  // make the originating transaction stick to the tunneled conn
1038
0
  RefPtr<nsAHttpConnection> wrappedConn =
1039
0
    gHttpHandler->ConnMgr()->MakeConnectionHandle(mTunneledConn);
1040
0
  mDrivingTransaction->SetConnection(wrappedConn);
1041
0
  mDrivingTransaction->MakeSticky();
1042
0
1043
0
  // jump the priority and start the dispatcher
1044
0
  Unused << gHttpHandler->InitiateTransaction(
1045
0
    mDrivingTransaction, nsISupportsPriority::PRIORITY_HIGHEST - 60);
1046
0
  mDrivingTransaction = nullptr;
1047
0
}
1048
1049
nsresult
1050
SpdyConnectTransaction::Flush(uint32_t count, uint32_t *countRead)
1051
0
{
1052
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1053
0
  LOG(("SpdyConnectTransaction::Flush %p count %d avail %d\n",
1054
0
       this, count, mOutputDataUsed - mOutputDataOffset));
1055
0
1056
0
  if (!mSegmentReader) {
1057
0
    return NS_ERROR_UNEXPECTED;
1058
0
  }
1059
0
1060
0
  *countRead = 0;
1061
0
  count = std::min(count, (mOutputDataUsed - mOutputDataOffset));
1062
0
  if (count) {
1063
0
    nsresult rv;
1064
0
    rv = mSegmentReader->OnReadSegment(&mOutputData[mOutputDataOffset],
1065
0
                                       count, countRead);
1066
0
    if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
1067
0
      LOG(("SpdyConnectTransaction::Flush %p Error %" PRIx32 "\n",
1068
0
           this, static_cast<uint32_t>(rv)));
1069
0
      CreateShimError(rv);
1070
0
      return rv;
1071
0
    }
1072
0
  }
1073
0
1074
0
  mOutputDataOffset += *countRead;
1075
0
  if (mOutputDataOffset == mOutputDataUsed) {
1076
0
    mOutputDataOffset = mOutputDataUsed = 0;
1077
0
  }
1078
0
  if (!(*countRead)) {
1079
0
    return NS_BASE_STREAM_WOULD_BLOCK;
1080
0
  }
1081
0
1082
0
  if (mOutputDataUsed != mOutputDataOffset) {
1083
0
    LOG(("SpdyConnectTransaction::Flush %p Incomplete %d\n",
1084
0
         this, mOutputDataUsed - mOutputDataOffset));
1085
0
    mSession->TransactionHasDataToWrite(this);
1086
0
  }
1087
0
1088
0
  return NS_OK;
1089
0
}
1090
1091
nsresult
1092
SpdyConnectTransaction::ReadSegments(nsAHttpSegmentReader *reader,
1093
                                     uint32_t count,
1094
                                     uint32_t *countRead)
1095
0
{
1096
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1097
0
  LOG(("SpdyConnectTransaction::ReadSegments %p count %d conn %p\n",
1098
0
       this, count, mTunneledConn.get()));
1099
0
1100
0
  mSegmentReader = reader;
1101
0
1102
0
  // spdy stream carrying tunnel is not setup yet.
1103
0
  if (!mTunneledConn) {
1104
0
    uint32_t toWrite = mConnectString.Length() - mConnectStringOffset;
1105
0
    toWrite = std::min(toWrite, count);
1106
0
    *countRead = toWrite;
1107
0
    if (toWrite) {
1108
0
      nsresult rv = mSegmentReader->
1109
0
        OnReadSegment(mConnectString.BeginReading() + mConnectStringOffset,
1110
0
                      toWrite, countRead);
1111
0
      if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
1112
0
        LOG(("SpdyConnectTransaction::ReadSegments %p OnReadSegmentError %" PRIx32 "\n",
1113
0
             this, static_cast<uint32_t>(rv)));
1114
0
        CreateShimError(rv);
1115
0
      } else {
1116
0
        mConnectStringOffset += toWrite;
1117
0
        if (mConnectString.Length() == mConnectStringOffset) {
1118
0
          mConnectString.Truncate();
1119
0
          mConnectStringOffset = 0;
1120
0
        }
1121
0
      }
1122
0
      return rv;
1123
0
    }
1124
0
    return NS_BASE_STREAM_WOULD_BLOCK;
1125
0
  }
1126
0
1127
0
  if (mForcePlainText) {
1128
0
    // this path just ignores sending the request so that we can
1129
0
    // send a synthetic reply in writesegments()
1130
0
    LOG(("SpdyConnectTransaciton::ReadSegments %p dropping %d output bytes "
1131
0
         "due to synthetic reply\n", this, mOutputDataUsed - mOutputDataOffset));
1132
0
    *countRead = mOutputDataUsed - mOutputDataOffset;
1133
0
    mOutputDataOffset = mOutputDataUsed = 0;
1134
0
    mTunneledConn->DontReuse();
1135
0
    return NS_OK;
1136
0
  }
1137
0
1138
0
  *countRead = 0;
1139
0
  Unused << Flush(count, countRead);
1140
0
  if (!mTunnelStreamOut->mCallback) {
1141
0
    return NS_BASE_STREAM_WOULD_BLOCK;
1142
0
  }
1143
0
1144
0
  nsresult rv =
1145
0
    mTunnelStreamOut->mCallback->OnOutputStreamReady(mTunnelStreamOut);
1146
0
  if (NS_FAILED(rv)) {
1147
0
    return rv;
1148
0
  }
1149
0
1150
0
  uint32_t subtotal;
1151
0
  count -= *countRead;
1152
0
  rv = Flush(count, &subtotal);
1153
0
  *countRead += subtotal;
1154
0
  return rv;
1155
0
}
1156
1157
void
1158
SpdyConnectTransaction::CreateShimError(nsresult code)
1159
0
{
1160
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1161
0
  MOZ_ASSERT(NS_FAILED(code));
1162
0
1163
0
  if (mTunnelStreamOut && NS_SUCCEEDED(mTunnelStreamOut->mStatus)) {
1164
0
    mTunnelStreamOut->mStatus = code;
1165
0
  }
1166
0
1167
0
  if (mTunnelStreamIn && NS_SUCCEEDED(mTunnelStreamIn->mStatus)) {
1168
0
    mTunnelStreamIn->mStatus = code;
1169
0
  }
1170
0
1171
0
  if (mTunnelStreamIn && mTunnelStreamIn->mCallback) {
1172
0
    mTunnelStreamIn->mCallback->OnInputStreamReady(mTunnelStreamIn);
1173
0
  }
1174
0
1175
0
  if (mTunnelStreamOut && mTunnelStreamOut->mCallback) {
1176
0
    mTunnelStreamOut->mCallback->OnOutputStreamReady(mTunnelStreamOut);
1177
0
  }
1178
0
}
1179
1180
nsresult
1181
SpdyConnectTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
1182
                                      uint32_t count,
1183
                                      uint32_t *countWritten)
1184
0
{
1185
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1186
0
  LOG(("SpdyConnectTransaction::WriteSegments %p max=%d cb=%p\n",
1187
0
       this, count, mTunneledConn ? mTunnelStreamIn->mCallback : nullptr));
1188
0
1189
0
  // first call into the tunnel stream to get the demux'd data out of the
1190
0
  // spdy session.
1191
0
  EnsureBuffer(mInputData, mInputDataUsed + count, mInputDataUsed, mInputDataSize);
1192
0
  nsresult rv = writer->OnWriteSegment(&mInputData[mInputDataUsed],
1193
0
                                       count, countWritten);
1194
0
  if (NS_FAILED(rv)) {
1195
0
    if (rv != NS_BASE_STREAM_WOULD_BLOCK) {
1196
0
      LOG(("SpdyConnectTransaction::WriteSegments wrapped writer %p Error %" PRIx32 "\n",
1197
0
           this, static_cast<uint32_t>(rv)));
1198
0
      CreateShimError(rv);
1199
0
    }
1200
0
    return rv;
1201
0
  }
1202
0
  mInputDataUsed += *countWritten;
1203
0
  LOG(("SpdyConnectTransaction %p %d new bytes [%d total] of ciphered data buffered\n",
1204
0
       this, *countWritten, mInputDataUsed - mInputDataOffset));
1205
0
1206
0
  if (!mTunneledConn || !mTunnelStreamIn->mCallback) {
1207
0
    return NS_BASE_STREAM_WOULD_BLOCK;
1208
0
  }
1209
0
1210
0
  rv = mTunnelStreamIn->mCallback->OnInputStreamReady(mTunnelStreamIn);
1211
0
  LOG(("SpdyConnectTransaction::WriteSegments %p "
1212
0
       "after InputStreamReady callback %d total of ciphered data buffered rv=%"
1213
0
       PRIx32 "\n",
1214
0
       this, mInputDataUsed - mInputDataOffset, static_cast<uint32_t>(rv)));
1215
0
  LOG(("SpdyConnectTransaction::WriteSegments %p "
1216
0
       "goodput %p out %" PRId64 "\n", this, mTunneledConn.get(),
1217
0
       mTunneledConn->ContentBytesWritten()));
1218
0
  if (NS_SUCCEEDED(rv) && !mTunneledConn->ContentBytesWritten()) {
1219
0
    mTunnelStreamOut->AsyncWait(mTunnelStreamOut->mCallback, 0, 0, nullptr);
1220
0
  }
1221
0
  return rv;
1222
0
}
1223
1224
bool
1225
SpdyConnectTransaction::ConnectedReadyForInput()
1226
0
{
1227
0
  return mTunneledConn && mTunnelStreamIn->mCallback;
1228
0
}
1229
1230
nsHttpRequestHead *
1231
SpdyConnectTransaction::RequestHead()
1232
0
{
1233
0
  return mRequestHead;
1234
0
}
1235
1236
void
1237
SpdyConnectTransaction::Close(nsresult code)
1238
0
{
1239
0
  LOG(("SpdyConnectTransaction close %p %" PRIx32 "\n", this, static_cast<uint32_t>(code)));
1240
0
1241
0
  NullHttpTransaction::Close(code);
1242
0
  if (NS_FAILED(code) && (code != NS_BASE_STREAM_WOULD_BLOCK)) {
1243
0
    CreateShimError(code);
1244
0
  } else {
1245
0
    CreateShimError(NS_BASE_STREAM_CLOSED);
1246
0
  }
1247
0
}
1248
1249
NS_IMETHODIMP
1250
OutputStreamShim::AsyncWait(nsIOutputStreamCallback *callback,
1251
                            unsigned int, unsigned int, nsIEventTarget *target)
1252
0
{
1253
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1254
0
  bool currentThread;
1255
0
1256
0
  if (target &&
1257
0
      (NS_FAILED(target->IsOnCurrentThread(&currentThread)) || !currentThread)) {
1258
0
    return NS_ERROR_FAILURE;
1259
0
  }
1260
0
1261
0
  LOG(("OutputStreamShim::AsyncWait %p callback %p\n", this, callback));
1262
0
  mCallback = callback;
1263
0
1264
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1265
0
  if (!baseTrans) {
1266
0
    return NS_ERROR_FAILURE;
1267
0
  }
1268
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1269
0
  MOZ_ASSERT(trans);
1270
0
  if (!trans) {
1271
0
    return NS_ERROR_UNEXPECTED;
1272
0
  }
1273
0
1274
0
  trans->mSession->TransactionHasDataToWrite(trans);
1275
0
1276
0
  return NS_OK;
1277
0
}
1278
1279
NS_IMETHODIMP
1280
OutputStreamShim::CloseWithStatus(nsresult reason)
1281
0
{
1282
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1283
0
  if (!baseTrans) {
1284
0
    return NS_ERROR_FAILURE;
1285
0
  }
1286
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1287
0
  MOZ_ASSERT(trans);
1288
0
  if (!trans) {
1289
0
    return NS_ERROR_UNEXPECTED;
1290
0
  }
1291
0
1292
0
  trans->mSession->CloseTransaction(trans, reason);
1293
0
  return NS_OK;
1294
0
}
1295
1296
NS_IMETHODIMP
1297
OutputStreamShim::Close()
1298
0
{
1299
0
  return CloseWithStatus(NS_OK);
1300
0
}
1301
1302
NS_IMETHODIMP
1303
OutputStreamShim::Flush()
1304
0
{
1305
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1306
0
  if (!baseTrans) {
1307
0
    return NS_ERROR_FAILURE;
1308
0
  }
1309
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1310
0
  MOZ_ASSERT(trans);
1311
0
  if (!trans) {
1312
0
    return NS_ERROR_UNEXPECTED;
1313
0
  }
1314
0
1315
0
  uint32_t count = trans->mOutputDataUsed - trans->mOutputDataOffset;
1316
0
  if (!count) {
1317
0
    return NS_OK;
1318
0
  }
1319
0
1320
0
  uint32_t countRead;
1321
0
  nsresult rv = trans->Flush(count, &countRead);
1322
0
  LOG(("OutputStreamShim::Flush %p before %d after %d\n",
1323
0
       this, count, trans->mOutputDataUsed - trans->mOutputDataOffset));
1324
0
  return rv;
1325
0
}
1326
1327
NS_IMETHODIMP
1328
OutputStreamShim::Write(const char * aBuf, uint32_t aCount, uint32_t *_retval)
1329
0
{
1330
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1331
0
1332
0
  if (NS_FAILED(mStatus)) {
1333
0
    return mStatus;
1334
0
  }
1335
0
1336
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1337
0
  if (!baseTrans) {
1338
0
    return NS_ERROR_FAILURE;
1339
0
  }
1340
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1341
0
  MOZ_ASSERT(trans);
1342
0
  if (!trans) {
1343
0
    return NS_ERROR_UNEXPECTED;
1344
0
  }
1345
0
1346
0
  if ((trans->mOutputDataUsed + aCount) >= 512000) {
1347
0
    *_retval = 0;
1348
0
    // time for some flow control;
1349
0
    return NS_BASE_STREAM_WOULD_BLOCK;
1350
0
  }
1351
0
1352
0
  EnsureBuffer(trans->mOutputData, trans->mOutputDataUsed + aCount,
1353
0
               trans->mOutputDataUsed, trans->mOutputDataSize);
1354
0
  memcpy(&trans->mOutputData[trans->mOutputDataUsed], aBuf, aCount);
1355
0
  trans->mOutputDataUsed += aCount;
1356
0
  *_retval = aCount;
1357
0
  LOG(("OutputStreamShim::Write %p new %d total %d\n", this, aCount, trans->mOutputDataUsed));
1358
0
1359
0
  trans->mSession->TransactionHasDataToWrite(trans);
1360
0
1361
0
  return NS_OK;
1362
0
}
1363
1364
NS_IMETHODIMP
1365
OutputStreamShim::WriteFrom(nsIInputStream *aFromStream, uint32_t aCount, uint32_t *_retval)
1366
0
{
1367
0
  return NS_ERROR_NOT_IMPLEMENTED;
1368
0
}
1369
1370
NS_IMETHODIMP
1371
OutputStreamShim::WriteSegments(nsReadSegmentFun aReader, void *aClosure, uint32_t aCount, uint32_t *_retval)
1372
0
{
1373
0
  return NS_ERROR_NOT_IMPLEMENTED;
1374
0
}
1375
1376
NS_IMETHODIMP
1377
OutputStreamShim::IsNonBlocking(bool *_retval)
1378
0
{
1379
0
  *_retval = true;
1380
0
  return NS_OK;
1381
0
}
1382
1383
NS_IMETHODIMP
1384
InputStreamShim::AsyncWait(nsIInputStreamCallback *callback,
1385
                           unsigned int, unsigned int, nsIEventTarget *target)
1386
0
{
1387
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1388
0
  bool currentThread;
1389
0
1390
0
  if (target &&
1391
0
      (NS_FAILED(target->IsOnCurrentThread(&currentThread)) || !currentThread)) {
1392
0
    return NS_ERROR_FAILURE;
1393
0
  }
1394
0
1395
0
  LOG(("InputStreamShim::AsyncWait %p callback %p\n", this, callback));
1396
0
  mCallback = callback;
1397
0
  return NS_OK;
1398
0
}
1399
1400
NS_IMETHODIMP
1401
InputStreamShim::CloseWithStatus(nsresult reason)
1402
0
{
1403
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1404
0
  if (!baseTrans) {
1405
0
    return NS_ERROR_FAILURE;
1406
0
  }
1407
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1408
0
  MOZ_ASSERT(trans);
1409
0
  if (!trans) {
1410
0
    return NS_ERROR_UNEXPECTED;
1411
0
  }
1412
0
1413
0
  trans->mSession->CloseTransaction(trans, reason);
1414
0
  return NS_OK;
1415
0
}
1416
1417
NS_IMETHODIMP
1418
InputStreamShim::Close()
1419
0
{
1420
0
  return CloseWithStatus(NS_OK);
1421
0
}
1422
1423
NS_IMETHODIMP
1424
InputStreamShim::Available(uint64_t *_retval)
1425
0
{
1426
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1427
0
  if (!baseTrans) {
1428
0
    return NS_ERROR_FAILURE;
1429
0
  }
1430
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1431
0
  MOZ_ASSERT(trans);
1432
0
  if (!trans) {
1433
0
    return NS_ERROR_UNEXPECTED;
1434
0
  }
1435
0
1436
0
  *_retval = trans->mInputDataUsed - trans->mInputDataOffset;
1437
0
  return NS_OK;
1438
0
}
1439
1440
NS_IMETHODIMP
1441
InputStreamShim::Read(char *aBuf, uint32_t aCount, uint32_t *_retval)
1442
0
{
1443
0
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
1444
0
1445
0
  if (NS_FAILED(mStatus)) {
1446
0
    return mStatus;
1447
0
  }
1448
0
1449
0
  RefPtr<NullHttpTransaction> baseTrans(do_QueryReferent(mWeakTrans));
1450
0
  if (!baseTrans) {
1451
0
    return NS_ERROR_FAILURE;
1452
0
  }
1453
0
  SpdyConnectTransaction *trans = baseTrans->QuerySpdyConnectTransaction();
1454
0
  MOZ_ASSERT(trans);
1455
0
  if (!trans) {
1456
0
    return NS_ERROR_UNEXPECTED;
1457
0
  }
1458
0
1459
0
  uint32_t avail = trans->mInputDataUsed - trans->mInputDataOffset;
1460
0
  uint32_t tocopy = std::min(aCount, avail);
1461
0
  *_retval = tocopy;
1462
0
  memcpy(aBuf, &trans->mInputData[trans->mInputDataOffset], tocopy);
1463
0
  trans->mInputDataOffset += tocopy;
1464
0
  if (trans->mInputDataOffset == trans->mInputDataUsed) {
1465
0
    trans->mInputDataOffset = trans->mInputDataUsed = 0;
1466
0
  }
1467
0
1468
0
  return tocopy ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
1469
0
}
1470
1471
NS_IMETHODIMP
1472
InputStreamShim::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
1473
                              uint32_t aCount, uint32_t *_retval)
1474
0
{
1475
0
  return NS_ERROR_NOT_IMPLEMENTED;
1476
0
}
1477
1478
NS_IMETHODIMP
1479
InputStreamShim::IsNonBlocking(bool *_retval)
1480
0
{
1481
0
  *_retval = true;
1482
0
  return NS_OK;
1483
0
}
1484
1485
NS_IMETHODIMP
1486
SocketTransportShim::SetKeepaliveEnabled(bool aKeepaliveEnabled)
1487
0
{
1488
0
  return NS_ERROR_NOT_IMPLEMENTED;
1489
0
}
1490
1491
NS_IMETHODIMP
1492
SocketTransportShim::SetKeepaliveVals(int32_t keepaliveIdleTime, int32_t keepaliveRetryInterval)
1493
0
{
1494
0
  return NS_ERROR_NOT_IMPLEMENTED;
1495
0
}
1496
1497
NS_IMETHODIMP
1498
SocketTransportShim::SetSecurityCallbacks(nsIInterfaceRequestor *aSecurityCallbacks)
1499
0
{
1500
0
  return NS_ERROR_NOT_IMPLEMENTED;
1501
0
}
1502
1503
NS_IMETHODIMP
1504
SocketTransportShim::OpenInputStream(uint32_t aFlags, uint32_t aSegmentSize,
1505
                                     uint32_t aSegmentCount, nsIInputStream * *_retval)
1506
0
{
1507
0
  return NS_ERROR_NOT_IMPLEMENTED;
1508
0
}
1509
1510
NS_IMETHODIMP
1511
SocketTransportShim::OpenOutputStream(uint32_t aFlags, uint32_t aSegmentSize,
1512
                                      uint32_t aSegmentCount, nsIOutputStream * *_retval)
1513
0
{
1514
0
  return NS_ERROR_NOT_IMPLEMENTED;
1515
0
}
1516
1517
NS_IMETHODIMP
1518
SocketTransportShim::Close(nsresult aReason)
1519
0
{
1520
0
  return NS_ERROR_NOT_IMPLEMENTED;
1521
0
}
1522
1523
NS_IMETHODIMP
1524
SocketTransportShim::SetEventSink(nsITransportEventSink *aSink, nsIEventTarget *aEventTarget)
1525
0
{
1526
0
  return NS_ERROR_NOT_IMPLEMENTED;
1527
0
}
1528
1529
NS_IMETHODIMP
1530
SocketTransportShim::Bind(NetAddr *aLocalAddr)
1531
0
{
1532
0
  return NS_ERROR_NOT_IMPLEMENTED;
1533
0
}
1534
1535
NS_IMETHODIMP
1536
SocketTransportShim::GetFirstRetryError(nsresult *aFirstRetryError)
1537
0
{
1538
0
  return NS_ERROR_NOT_IMPLEMENTED;
1539
0
}
1540
1541
NS_IMETHODIMP
1542
SocketTransportShim::GetEsniUsed(bool *aEsniUsed)
1543
0
{
1544
0
  return NS_ERROR_NOT_IMPLEMENTED;
1545
0
}
1546
1547
1548
#define FWD_TS_PTR(fx, ts) NS_IMETHODIMP \
1549
0
SocketTransportShim::fx(ts *arg) { return mWrapped->fx(arg); }
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetKeepaliveEnabled(bool*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetSendBufferSize(unsigned int*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetPort(int*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetPeerAddr(mozilla::net::NetAddr*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetSelfAddr(mozilla::net::NetAddr*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::IsAlive(bool*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetConnectionFlags(unsigned int*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetTlsFlags(unsigned int*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetRecvBufferSize(unsigned int*)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetResetIPFamilyPreference(bool*)
1550
1551
#define FWD_TS_ADDREF(fx, ts) NS_IMETHODIMP \
1552
0
SocketTransportShim::fx(ts **arg) { return mWrapped->fx(arg); }
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetScriptablePeerAddr(nsINetAddr**)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetScriptableSelfAddr(nsINetAddr**)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetSecurityInfo(nsISupports**)
Unexecuted instantiation: mozilla::net::SocketTransportShim::GetSecurityCallbacks(nsIInterfaceRequestor**)
1553
1554
#define FWD_TS(fx, ts) NS_IMETHODIMP \
1555
0
SocketTransportShim::fx(ts arg) { return mWrapped->fx(arg); }
Unexecuted instantiation: mozilla::net::SocketTransportShim::SetSendBufferSize(unsigned int)
Unexecuted instantiation: mozilla::net::SocketTransportShim::SetConnectionFlags(unsigned int)
Unexecuted instantiation: mozilla::net::SocketTransportShim::SetTlsFlags(unsigned int)
Unexecuted instantiation: mozilla::net::SocketTransportShim::SetRecvBufferSize(unsigned int)
1556
1557
FWD_TS_PTR(GetKeepaliveEnabled, bool);
1558
FWD_TS_PTR(GetSendBufferSize, uint32_t);
1559
FWD_TS(SetSendBufferSize, uint32_t);
1560
FWD_TS_PTR(GetPort, int32_t);
1561
FWD_TS_PTR(GetPeerAddr, mozilla::net::NetAddr);
1562
FWD_TS_PTR(GetSelfAddr, mozilla::net::NetAddr);
1563
FWD_TS_ADDREF(GetScriptablePeerAddr, nsINetAddr);
1564
FWD_TS_ADDREF(GetScriptableSelfAddr, nsINetAddr);
1565
FWD_TS_ADDREF(GetSecurityInfo, nsISupports);
1566
FWD_TS_ADDREF(GetSecurityCallbacks, nsIInterfaceRequestor);
1567
FWD_TS_PTR(IsAlive, bool);
1568
FWD_TS_PTR(GetConnectionFlags, uint32_t);
1569
FWD_TS(SetConnectionFlags, uint32_t);
1570
FWD_TS_PTR(GetTlsFlags, uint32_t);
1571
FWD_TS(SetTlsFlags, uint32_t);
1572
FWD_TS_PTR(GetRecvBufferSize, uint32_t);
1573
FWD_TS(SetRecvBufferSize, uint32_t);
1574
FWD_TS_PTR(GetResetIPFamilyPreference, bool);
1575
1576
nsresult
1577
SocketTransportShim::GetOriginAttributes(mozilla::OriginAttributes* aOriginAttributes)
1578
0
{
1579
0
  return mWrapped->GetOriginAttributes(aOriginAttributes);
1580
0
}
1581
1582
nsresult
1583
SocketTransportShim::SetOriginAttributes(const mozilla::OriginAttributes& aOriginAttributes)
1584
0
{
1585
0
  return mWrapped->SetOriginAttributes(aOriginAttributes);
1586
0
}
1587
1588
NS_IMETHODIMP
1589
SocketTransportShim::GetScriptableOriginAttributes(JSContext* aCx,
1590
  JS::MutableHandle<JS::Value> aOriginAttributes)
1591
0
{
1592
0
  return mWrapped->GetScriptableOriginAttributes(aCx, aOriginAttributes);
1593
0
}
1594
1595
NS_IMETHODIMP
1596
SocketTransportShim::SetScriptableOriginAttributes(JSContext* aCx,
1597
  JS::Handle<JS::Value> aOriginAttributes)
1598
0
{
1599
0
  return mWrapped->SetScriptableOriginAttributes(aCx, aOriginAttributes);
1600
0
}
1601
1602
NS_IMETHODIMP
1603
SocketTransportShim::GetHost(nsACString & aHost)
1604
0
{
1605
0
  return mWrapped->GetHost(aHost);
1606
0
}
1607
1608
NS_IMETHODIMP
1609
SocketTransportShim::GetTimeout(uint32_t aType, uint32_t *_retval)
1610
0
{
1611
0
  return mWrapped->GetTimeout(aType, _retval);
1612
0
}
1613
1614
NS_IMETHODIMP
1615
SocketTransportShim::SetTimeout(uint32_t aType, uint32_t aValue)
1616
0
{
1617
0
  return mWrapped->SetTimeout(aType, aValue);
1618
0
}
1619
1620
NS_IMETHODIMP
1621
SocketTransportShim::SetReuseAddrPort(bool aReuseAddrPort)
1622
0
{
1623
0
  return mWrapped->SetReuseAddrPort(aReuseAddrPort);
1624
0
}
1625
1626
NS_IMETHODIMP
1627
SocketTransportShim::GetQoSBits(uint8_t *aQoSBits)
1628
0
{
1629
0
  return mWrapped->GetQoSBits(aQoSBits);
1630
0
}
1631
1632
NS_IMETHODIMP
1633
SocketTransportShim::SetQoSBits(uint8_t aQoSBits)
1634
0
{
1635
0
  return mWrapped->SetQoSBits(aQoSBits);
1636
0
}
1637
1638
NS_IMETHODIMP
1639
SocketTransportShim::SetFastOpenCallback(TCPFastOpen *aFastOpen)
1640
0
{
1641
0
  return mWrapped->SetFastOpenCallback(aFastOpen);
1642
0
}
1643
1644
NS_IMPL_ISUPPORTS(TLSFilterTransaction, nsITimerCallback, nsINamed)
1645
NS_IMPL_ISUPPORTS(SocketTransportShim, nsISocketTransport, nsITransport)
1646
NS_IMPL_ISUPPORTS(InputStreamShim, nsIInputStream, nsIAsyncInputStream)
1647
NS_IMPL_ISUPPORTS(OutputStreamShim, nsIOutputStream, nsIAsyncOutputStream)
1648
NS_IMPL_ISUPPORTS(SocketInWrapper, nsIAsyncInputStream)
1649
NS_IMPL_ISUPPORTS(SocketOutWrapper, nsIAsyncOutputStream)
1650
1651
} // namespace net
1652
} // namespace mozilla