2489 |
2492 |
2490 CleanupStack::PopAndDestroy(7); //conn1, conn2, sock1, sock2, sendBuf, recvBuf, recvBuf2 |
2493 CleanupStack::PopAndDestroy(7); //conn1, conn2, sock1, sock2, sendBuf, recvBuf, recvBuf2 |
2491 |
2494 |
2492 return EPass; |
2495 return EPass; |
2493 } |
2496 } |
|
2497 |
|
2498 |
|
2499 enum TVerdict CRawIpMBufExhaustionRx::RunTestStepL() |
|
2500 { |
|
2501 /* |
|
2502 * This test checks that the PDP flow can handle the scenario when it receives a packet but finds that |
|
2503 * the MBuf pool is exhausted. |
|
2504 * |
|
2505 * The test has the following form: |
|
2506 * |
|
2507 * 1) Initialisation |
|
2508 * 1.1) Connections conn1 and conn2 are started. |
|
2509 * 1.2) Socket sock1 is opened against conn1 and socket sock2 is opened against conn2; |
|
2510 * The sockets are logically joined by the packet loopback csy; data which is written by |
|
2511 * sock1 is read by sock2. |
|
2512 * 1.3) Connection conn3 is started. It creates a stack within ESOCK which contains the MBufGobbler layer; |
|
2513 * this is a layer which contains a publish and subscribe function which allows the ESOCK client to control the |
|
2514 * number of MBufs that are available in the MBuf pool. |
|
2515 * |
|
2516 * 2) Test Scenario |
|
2517 * 2.1) The client writes data to sock1 successfully; the packetloopback csy delays forwarding the data to sock2. |
|
2518 * 2.2) The client configures a publish and subscribe attribute which exhausts ESOCK's MBuf pool. |
|
2519 * It uses the MBufGobbler publish / subscribe function contained in the MBufGobbler layer started by conn3. |
|
2520 * 2.3) The packet loopback csy forwards the data to the flow associated with sock2. |
|
2521 * 2.4) The flow is unable to obtain a MBuf from the MBuf pool as the pool is exhausted, so it discards the packet |
|
2522 * and posts a request to receive the next packet. |
|
2523 * 2.5) The client cancels the read request from sock2. |
|
2524 * 2.6) The client configures a publish and subscribe attribute to replenish ESocks's MBuf pool. |
|
2525 * 2.7) The client writes data to sock1 successfully and reads data from sock2 successfully. |
|
2526 * |
|
2527 */ |
|
2528 |
|
2529 //Start 1st context |
|
2530 RConnection* conn1 = new (ELeave) RConnection(); |
|
2531 CleanupClosePushL<RConnection>(*conn1); |
|
2532 |
|
2533 TInt primaryIapId; |
|
2534 if (!GetIntFromConfig(ConfigSection(), _L("PrimaryIapId1"), primaryIapId)) |
|
2535 { |
|
2536 User::Leave(KErrNotFound); |
|
2537 } |
|
2538 |
|
2539 TCommDbConnPref conn1Pref; |
|
2540 conn1Pref.SetIapId(primaryIapId); |
|
2541 |
|
2542 INFO_PRINTF2(_L("Test starting Interface IAP ID == %d"), primaryIapId); |
|
2543 TestL(conn1->Open(iEsock), _L("RConnection::Open the interface")); |
|
2544 TestL(conn1->Start(conn1Pref), _L("RConnection::Start the interface")); |
|
2545 |
|
2546 //Start 2nd context |
|
2547 RConnection* conn2 = new (ELeave) RConnection(); |
|
2548 CleanupClosePushL<RConnection>(*conn2); |
|
2549 |
|
2550 if (!GetIntFromConfig(ConfigSection(), _L("PrimaryIapId2"), primaryIapId)) |
|
2551 { |
|
2552 User::Leave(KErrNotFound); |
|
2553 } |
|
2554 |
|
2555 TCommDbConnPref conn2Pref; |
|
2556 conn2Pref.SetIapId(primaryIapId); |
|
2557 |
|
2558 INFO_PRINTF2(_L("Test starting Interface IAP ID == %d"), primaryIapId); |
|
2559 TestL(conn2->Open(iEsock), _L("RConnection::Open the interface")); |
|
2560 TestL(conn2->Start(conn2Pref), _L("RConnection::Start the interface")); |
|
2561 |
|
2562 TRequestStatus status; |
|
2563 RConnection* conn3 = new (ELeave) RConnection(); |
|
2564 CleanupClosePushL<RConnection>(*conn3); |
|
2565 TestL(conn3->Open(iEsock), _L("RConnection::Open the interface")); |
|
2566 conn3->Start(status); |
|
2567 User::WaitForRequest(status); |
|
2568 TestL(status.Int(), _L("RConnection::Start - start connection containing MBuf Gobbler layer")); |
|
2569 |
|
2570 //Open & Connect 1st Socket |
|
2571 RSocket sock1; |
|
2572 TestL(sock1.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, *conn1), _L("RSocket::Open")); |
|
2573 CleanupClosePushL<RSocket>(sock1); |
|
2574 TInetAddr localAddr; |
|
2575 localAddr.SetPort(KConfiguredTftFilter1DestPort); |
|
2576 TestL(sock1.Bind(localAddr), _L("Binding the local Socket")); |
|
2577 |
|
2578 TInetAddr dstAddr; |
|
2579 dstAddr.SetPort(KConfiguredTftFilter1SrcPort); |
|
2580 dstAddr.Input(KConfiguredTftFilter1SrcAddr); |
|
2581 sock1.Connect(dstAddr, status); |
|
2582 User::WaitForRequest(status); |
|
2583 TestL(status.Int(), _L("RSocket::Connect status opening 1st socket")); |
|
2584 |
|
2585 //Open & Bind 2nd Socket |
|
2586 RSocket sock2; |
|
2587 TestL(sock2.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, *conn2), _L("RSocket::Open")); |
|
2588 CleanupClosePushL<RSocket>(sock2); |
|
2589 localAddr.SetPort(KConfiguredTftFilter1SrcPort); |
|
2590 TestL(sock2.Bind(localAddr), _L("Binding the local Socket")); |
|
2591 |
|
2592 //then send & receive data. |
|
2593 const TInt KMaxMMU = 4000; |
|
2594 TBuf8<KMaxMMU> *sendBuf = new(ELeave) TBuf8<KMaxMMU>(); |
|
2595 CleanupStack::PushL(sendBuf); |
|
2596 |
|
2597 TBuf8<KMaxMMU> *recvBuf = new(ELeave) TBuf8<KMaxMMU>(); |
|
2598 CleanupStack::PushL(recvBuf); |
|
2599 |
|
2600 TBuf8<KMaxMMU> *recvBuf2 = new(ELeave) TBuf8<KMaxMMU>(); |
|
2601 CleanupStack::PushL(recvBuf2); |
|
2602 |
|
2603 TRequestStatus readStatus; |
|
2604 |
|
2605 const TInt KOneSecond = 1000000; |
|
2606 const TInt KOneUs = 1; |
|
2607 |
|
2608 sendBuf->Zero(); |
|
2609 sendBuf->Append(Math::Random() & 0x7f); // add a token character |
|
2610 |
|
2611 sock1.Write(*sendBuf, status); // Allow packet to be sent |
|
2612 User::After( KOneSecond ); // Wait for a second to allow time for server/protocol to send |
|
2613 |
|
2614 sock1.CancelSend(); |
|
2615 |
|
2616 User::WaitForRequest(status); |
|
2617 |
|
2618 TInt result = RProperty::Set(TUid::Uid(EMBufGobbler ), EAdjustNumberOfMBufsRemainingInPool , EGobbleAllMBufs); // Allocate all MBuffs |
|
2619 if (result != KErrNone) |
|
2620 { |
|
2621 INFO_PRINTF2(_L("Unable to set gobber publish/subscribe %d"), result); |
|
2622 User::Leave(result); |
|
2623 } |
|
2624 User::After(KOneUs); // Relinquish CPU, to give time for |
|
2625 |
|
2626 sock2.Read(*recvBuf, readStatus); |
|
2627 User::After( KOneSecond ); |
|
2628 |
|
2629 sock2.CancelRecv(); |
|
2630 |
|
2631 User::WaitForRequest( readStatus ); |
|
2632 |
|
2633 if ((status != KErrNone) && (readStatus != KErrCancel)) |
|
2634 { |
|
2635 INFO_PRINTF3(_L("Unexpected error status tx= %d, rx = %d"), status.Int(), readStatus.Int()); |
|
2636 User::Leave(readStatus.Int()); |
|
2637 } |
|
2638 |
|
2639 result = RProperty::Set(TUid::Uid(EMBufGobbler), EAdjustNumberOfMBufsRemainingInPool, EReleaseAllMBufs); // Free all buffers |
|
2640 if (result != KErrNone) |
|
2641 { |
|
2642 INFO_PRINTF2(_L("Unable to set gobber publish/subscribe %d"), result); |
|
2643 User::Leave(result); |
|
2644 } |
|
2645 User::After(KOneUs); // Relinquish CPU to allow time for MBufs to be returned to the pool. |
|
2646 |
|
2647 sock1.Write(*sendBuf, status); |
|
2648 |
|
2649 User::After( KOneSecond ); // Wait for a second to allow time for server/protocol to send |
|
2650 |
|
2651 sock1.CancelSend(); |
|
2652 |
|
2653 User::WaitForRequest(status); |
|
2654 |
|
2655 sock2.Read(*recvBuf, readStatus); |
|
2656 User::After( KOneSecond ); |
|
2657 |
|
2658 sock2.CancelRecv(); |
|
2659 |
|
2660 User::WaitForRequest( readStatus ); |
|
2661 |
|
2662 if ((status != KErrNone) && (readStatus != KErrNone)) |
|
2663 { |
|
2664 INFO_PRINTF3(_L("Unexpected error status tx = %d rx = %d"), status.Int(), readStatus.Int()); |
|
2665 User::Leave(readStatus.Int()); |
|
2666 } |
|
2667 |
|
2668 CleanupStack::PopAndDestroy(8); //conn1, conn2, conn3, sock1, sock2, sendBuf, recvBuf, recvBuf2 |
|
2669 |
|
2670 return EPass; |
|
2671 } |