Merge b2ginbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-06-02 18:34:21 -07:00
commit 6cbdb228c3
31 changed files with 606 additions and 368 deletions

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
@ -129,10 +129,10 @@
<!-- Emulator specific things -->
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f390788a00706c06e5248edfd8d27b365387e84a"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d2f58dbee70cba71bd3fad8cdd0fee620d10cf92"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c4d9746e5f1a3a2e6cb53d59d5d721e9888cd2e1"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="42f61f665e7a9857da8cd14b455e15bae98e6b44"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="de4bfffbbc2aabe5b5eca485e459da75e49097e2"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/>
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -19,11 +19,11 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="22664edc4c73e5fe8f5095ff1d5549db78a2bc10"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="218a5637399d023f4326e12c8a486dad95403b6c"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "6d477a7884273886605049b20f60af5c1583a150",
"git_revision": "9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "c7beef2b034d2308a85e8c866395c78245bc554f",
"revision": "d5e509fd9697316bcbc267413a30478dcd4dbca9",
"repo_path": "integration/gaia-central"
}

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="6d477a7884273886605049b20f60af5c1583a150"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b7ed13e0dee26b9f16ae5fbc076fa8bd588b256"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4a697ec692aa762eb8cdb7812f5a051c5870020f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="15a220c3e411f9606e4059e4c9fd0c57a4290c13"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -522,8 +522,7 @@ public:
gattManager->UnregisterClient(mClient->mClientIf, result);
}
DispatchReplyError(mClient->mStartLeScanRunnable,
BluetoothValue(mClient->mAppUuid));
DispatchReplyError(mClient->mStartLeScanRunnable, aStatus);
mClient->mStartLeScanRunnable = nullptr;
}

View File

@ -74,8 +74,11 @@ public:
SOCKET_IS_CONNECTED
};
DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer)
DroidSocketImpl(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
BluetoothSocket* aConsumer)
: ipc::UnixFdWatcher(aIOLoop)
, DataSocketIO(aConsumerThread)
, mConsumer(aConsumer)
, mShuttingDownOnIOThread(false)
, mConnectionStatus(SOCKET_IS_DISCONNECTED)
@ -83,7 +86,7 @@ public:
~DroidSocketImpl()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
}
void Send(UnixSocketIOBuffer* aBuffer)
@ -120,8 +123,8 @@ public:
/**
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
* directly from main thread. All non-main-thread accesses should happen with
* mImpl as container.
* directly from consumer thread. All non-consumer-thread accesses should
* happen with mImpl as container.
*/
RefPtr<BluetoothSocket> mConsumer;
@ -140,9 +143,10 @@ public:
return GetDataSocket();
}
bool IsShutdownOnMainThread() const override
bool IsShutdownOnConsumerThread() const override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
return mConsumer == nullptr;
}
@ -151,16 +155,17 @@ public:
return mShuttingDownOnIOThread;
}
void ShutdownOnMainThread() override
void ShutdownOnConsumerThread() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mConsumer = nullptr;
}
void ShutdownOnIOThread() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
@ -214,7 +219,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
MOZ_ASSERT(!IsCanceled());
GetIO()->Connect(mFd);
@ -234,7 +239,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
if (!IsCanceled()) {
GetIO()->Listen(mFd);
@ -254,7 +259,7 @@ class SocketConnectClientFdTask final
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
GetIO()->ConnectClientFd();
}
@ -314,8 +319,9 @@ DroidSocketImpl::Accept(int aFd)
SetFd(aFd);
mConnectionStatus = SOCKET_IS_CONNECTED;
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -338,7 +344,7 @@ DroidSocketImpl::OnFileCanReadWithoutBlocking(int aFd)
void
DroidSocketImpl::OnSocketCanReceiveWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
ssize_t res = ReceiveData(aFd);
@ -361,7 +367,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
MOZ_ASSERT(!IsCanceled());
GetIO()->Accept(mFd);
@ -383,11 +389,11 @@ public:
void Accept(int aFd, const nsAString& aBdAddress,
int aConnectionStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
mozilla::ScopedClose fd(aFd); // Close received socket fd on error
if (mImpl->IsShutdownOnMainThread()) {
if (mImpl->IsShutdownOnConsumerThread()) {
BT_LOGD("mConsumer is null, aborting receive!");
return;
}
@ -398,16 +404,16 @@ public:
}
mImpl->mConsumer->SetAddress(aBdAddress);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new AcceptTask(mImpl, fd.forget()));
mImpl->GetIOLoop()->PostTask(FROM_HERE,
new AcceptTask(mImpl, fd.forget()));
}
void OnError(BluetoothStatus aStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
BT_LOGR("BluetoothSocketInterface::Accept failed: %d", (int)aStatus);
if (!mImpl->IsShutdownOnMainThread()) {
if (!mImpl->IsShutdownOnConsumerThread()) {
// Instead of NotifyError(), call NotifyDisconnect() to trigger
// BluetoothOppManager::OnSocketDisconnect() as
// DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
@ -430,7 +436,7 @@ public:
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(GetIO()->IsConsumerThread());
MOZ_ASSERT(sBluetoothSocketInterface);
BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
@ -448,7 +454,7 @@ private:
void
DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
/* When a listening socket is ready for receiving data,
@ -456,8 +462,8 @@ DroidSocketImpl::OnSocketCanAcceptWithoutBlocking(int aFd)
*/
RemoveWatchers(READ_WATCHER);
nsRefPtr<AcceptRunnable> t = new AcceptRunnable(this, aFd);
NS_DispatchToMainThread(t);
GetConsumerThread()->Dispatch(new AcceptRunnable(this, aFd),
NS_DISPATCH_NORMAL);
}
void
@ -475,7 +481,7 @@ DroidSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
void
DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
MOZ_ASSERT(aFd >= 0);
@ -492,7 +498,7 @@ DroidSocketImpl::OnSocketCanSendWithoutBlocking(int aFd)
void
DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
/* We follow Posix behaviour here: Connect operations are
@ -501,8 +507,9 @@ DroidSocketImpl::OnSocketCanConnectWithoutBlocking(int aFd)
mConnectionStatus = SOCKET_IS_CONNECTED;
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -528,7 +535,7 @@ DroidSocketImpl::QueryReceiveBuffer(
/**
* |ReceiveRunnable| transfers data received on the I/O thread
* to an instance of |BluetoothSocket| on the main thread.
* to an instance of |BluetoothSocket| on the consumer thread.
*/
class DroidSocketImpl::ReceiveRunnable final
: public SocketIORunnable<DroidSocketImpl>
@ -541,11 +548,11 @@ public:
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
DroidSocketImpl* io = SocketIORunnable<DroidSocketImpl>::GetIO();
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
MOZ_ASSERT(io->IsConsumerThread());
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return NS_OK;
@ -566,7 +573,8 @@ private:
void
DroidSocketImpl::ConsumeBuffer()
{
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
NS_DISPATCH_NORMAL);
}
void
@ -602,9 +610,9 @@ public:
void Connect(int aFd, const nsAString& aBdAddress,
int aConnectionStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
if (mImpl->IsShutdownOnMainThread()) {
if (mImpl->IsShutdownOnConsumerThread()) {
BT_LOGD("mConsumer is null, aborting send!");
return;
}
@ -615,16 +623,16 @@ public:
}
mImpl->mConsumer->SetAddress(aBdAddress);
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new SocketConnectTask(mImpl, aFd));
mImpl->GetIOLoop()->PostTask(FROM_HERE,
new SocketConnectTask(mImpl, aFd));
}
void OnError(BluetoothStatus aStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
BT_WARNING("Connect failed: %d", (int)aStatus);
if (!mImpl->IsShutdownOnMainThread()) {
if (!mImpl->IsShutdownOnConsumerThread()) {
// Instead of NotifyError(), call NotifyDisconnect() to trigger
// BluetoothOppManager::OnSocketDisconnect() as
// DroidSocketImpl::OnFileCanReadWithoutBlocking() in Firefox OS 2.0 in
@ -642,14 +650,15 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt)
bool aAuth, bool aEncrypt,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mImpl);
SetConnectionStatus(SOCKET_CONNECTING);
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
SetCurrentResultHandler(res);
@ -662,6 +671,23 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
return NS_OK;
}
nsresult
BluetoothSocket::Connect(const nsAString& aDeviceAddress,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt)
{
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
return Connect(aDeviceAddress, aServiceUuid, aType, aChannel, aAuth,
aEncrypt, consumerThread, XRE_GetIOMessageLoop());
}
class ListenResultHandler final : public BluetoothSocketResultHandler
{
public:
@ -673,15 +699,14 @@ public:
void Listen(int aFd) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
new SocketListenTask(mImpl, aFd));
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketListenTask(mImpl, aFd));
}
void OnError(BluetoothStatus aStatus) override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
BT_WARNING("Listen failed: %d", (int)aStatus);
}
@ -695,14 +720,15 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt)
bool aAuth, bool aEncrypt,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mImpl);
SetConnectionStatus(SOCKET_LISTENING);
mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this);
mImpl = new DroidSocketImpl(aConsumerThread, aIOLoop, this);
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
SetCurrentResultHandler(res);
@ -715,10 +741,26 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
return NS_OK;
}
nsresult
BluetoothSocket::Listen(const nsAString& aServiceName,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt)
{
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
return Listen(aServiceName, aServiceUuid, aType, aChannel, aAuth, aEncrypt,
consumerThread, XRE_GetIOMessageLoop());
}
void
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->ReceiveSocketData(this, aBuffer);
@ -729,11 +771,11 @@ BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
void
BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mImpl);
MOZ_ASSERT(!mImpl->IsShutdownOnMainThread());
MOZ_ASSERT(mImpl->IsConsumerThread());
MOZ_ASSERT(!mImpl->IsShutdownOnConsumerThread());
XRE_GetIOMessageLoop()->PostTask(
mImpl->GetIOLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<DroidSocketImpl, UnixSocketIOBuffer>(mImpl, aBuffer));
}
@ -743,12 +785,14 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
void
BluetoothSocket::Close()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(sBluetoothSocketInterface);
if (!mImpl) {
return;
}
MOZ_ASSERT(mImpl->IsConsumerThread());
// Stop any watching |SocketMessageWatcher|
if (mCurrentRes) {
sBluetoothSocketInterface->Close(mCurrentRes);
@ -757,10 +801,8 @@ BluetoothSocket::Close()
// From this point on, we consider mImpl as being deleted.
// We sever the relationship here so any future calls to listen or connect
// will create a new implementation.
mImpl->ShutdownOnMainThread();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
mImpl->ShutdownOnConsumerThread();
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
mImpl = nullptr;
NotifyDisconnect();
@ -769,7 +811,6 @@ BluetoothSocket::Close()
void
BluetoothSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
@ -779,7 +820,6 @@ BluetoothSocket::OnConnectSuccess()
void
BluetoothSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
SetCurrentResultHandler(nullptr);
@ -789,7 +829,6 @@ BluetoothSocket::OnConnectError()
void
BluetoothSocket::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnSocketDisconnect(this);
}

View File

@ -10,6 +10,9 @@
#include "BluetoothCommon.h"
#include "mozilla/ipc/DataSocket.h"
class MessageLoop;
class nsIThread;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocketObserver;
@ -21,12 +24,28 @@ class BluetoothSocket final : public mozilla::ipc::DataSocket
public:
BluetoothSocket(BluetoothSocketObserver* aObserver);
nsresult Connect(const nsAString& aDeviceAddress,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop);
nsresult Connect(const nsAString& aDeviceAddress,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt);
nsresult Listen(const nsAString& aServiceName,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
int aChannel,
bool aAuth, bool aEncrypt,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop);
nsresult Listen(const nsAString& aServiceName,
const BluetoothUuid& aServiceUuid,
BluetoothSocketType aType,
@ -35,7 +54,7 @@ public:
/**
* Method to be called whenever data is received. This is only called on the
* main thread.
* consumer thread.
*
* @param aBuffer Data received from the socket.
*/

View File

@ -28,7 +28,8 @@ class BluetoothSocket::BluetoothSocketIO final
, public DataSocketIO
{
public:
BluetoothSocketIO(MessageLoop* mIOLoop,
BluetoothSocketIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
BluetoothSocket* aConsumer,
UnixSocketConnector* aConnector);
~BluetoothSocketIO();
@ -82,10 +83,10 @@ public:
SocketBase* GetSocketBase() override;
bool IsShutdownOnMainThread() const override;
bool IsShutdownOnConsumerThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnMainThread() override;
void ShutdownOnConsumerThread() override;
void ShutdownOnIOThread() override;
private:
@ -95,8 +96,8 @@ private:
/**
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
* directly from main thread. All non-main-thread accesses should happen with
* mIO as container.
* directly from consumer thread. All non-consumer-thread accesses should
* happen with mIO as container.
*/
RefPtr<BluetoothSocket> mConsumer;
@ -121,7 +122,8 @@ private:
struct sockaddr_storage mAddress;
/**
* Task member for delayed connect task. Should only be access on main thread.
* Task member for delayed connect task. Should only be access on consumer
* thread.
*/
CancelableTask* mDelayedConnectTask;
@ -132,10 +134,12 @@ private:
};
BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
MessageLoop* mIOLoop,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
BluetoothSocket* aConsumer,
UnixSocketConnector* aConnector)
: UnixSocketWatcher(mIOLoop)
: UnixSocketWatcher(aIOLoop)
, DataSocketIO(aConsumerThread)
, mConsumer(aConsumer)
, mConnector(aConnector)
, mShuttingDownOnIOThread(false)
@ -148,8 +152,8 @@ BluetoothSocket::BluetoothSocketIO::BluetoothSocketIO(
BluetoothSocket::BluetoothSocketIO::~BluetoothSocketIO()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(IsShutdownOnConsumerThread());
}
void
@ -188,7 +192,7 @@ BluetoothSocket::BluetoothSocketIO::GetDataSocket()
void
BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = aTask;
}
@ -196,7 +200,7 @@ BluetoothSocket::BluetoothSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
void
BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = nullptr;
}
@ -204,7 +208,7 @@ BluetoothSocket::BluetoothSocketIO::ClearDelayedConnectTask()
void
BluetoothSocket::BluetoothSocketIO::CancelDelayedConnectTask()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
if (!mDelayedConnectTask) {
return;
@ -277,8 +281,9 @@ BluetoothSocket::BluetoothSocketIO::OnConnected()
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -326,8 +331,9 @@ BluetoothSocket::BluetoothSocketIO::OnSocketCanAcceptWithoutBlocking()
Close();
SetSocket(fd, SOCKET_IS_CONNECTED);
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -375,9 +381,10 @@ BluetoothSocket::BluetoothSocketIO::FireSocketError()
// Clean up watchers, statuses, fds
Close();
// Tell the main thread we've errored
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
// Tell the consumer thread we've errored
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
NS_DISPATCH_NORMAL);
}
@ -399,7 +406,7 @@ BluetoothSocket::BluetoothSocketIO::QueryReceiveBuffer(
/**
* |ReceiveRunnable| transfers data received on the I/O thread
* to an instance of |BluetoothSocket| on the main thread.
* to an instance of |BluetoothSocket| on the consumer thread.
*/
class BluetoothSocket::BluetoothSocketIO::ReceiveRunnable final
: public SocketIORunnable<BluetoothSocketIO>
@ -412,11 +419,11 @@ public:
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothSocketIO* io = SocketIORunnable<BluetoothSocketIO>::GetIO();
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
MOZ_ASSERT(io->IsConsumerThread());
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return NS_OK;
@ -437,7 +444,8 @@ private:
void
BluetoothSocket::BluetoothSocketIO::ConsumeBuffer()
{
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
NS_DISPATCH_NORMAL);
}
void
@ -455,18 +463,18 @@ BluetoothSocket::BluetoothSocketIO::GetSocketBase()
}
bool
BluetoothSocket::BluetoothSocketIO::IsShutdownOnMainThread() const
BluetoothSocket::BluetoothSocketIO::IsShutdownOnConsumerThread() const
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
return mConsumer == nullptr;
}
void
BluetoothSocket::BluetoothSocketIO::ShutdownOnMainThread()
BluetoothSocket::BluetoothSocketIO::ShutdownOnConsumerThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mConsumer = nullptr;
}
@ -480,7 +488,7 @@ BluetoothSocket::BluetoothSocketIO::IsShutdownOnIOThread() const
void
BluetoothSocket::BluetoothSocketIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
@ -502,7 +510,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
if (!IsCanceled()) {
GetIO()->Listen();
@ -520,7 +528,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
MOZ_ASSERT(!IsCanceled());
GetIO()->Connect();
@ -537,19 +545,19 @@ public:
void Run() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(GetIO()->IsConsumerThread());
if (IsCanceled()) {
return;
}
BluetoothSocketIO* io = GetIO();
if (io->IsShutdownOnMainThread()) {
if (io->IsShutdownOnConsumerThread()) {
return;
}
io->ClearDelayedConnectTask();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io));
io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
}
};
@ -576,7 +584,6 @@ BluetoothSocket::Connect(const nsAString& aDeviceAddress,
int aChannel,
bool aAuth, bool aEncrypt)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
nsAutoPtr<BluetoothUnixSocketConnector> connector(
@ -603,8 +610,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
int aChannel,
bool aAuth, bool aEncrypt)
{
MOZ_ASSERT(NS_IsMainThread());
nsAutoPtr<BluetoothUnixSocketConnector> connector(
new BluetoothUnixSocketConnector(NS_LITERAL_CSTRING(BLUETOOTH_ADDRESS_NONE),
aType, aChannel, aAuth, aEncrypt));
@ -625,7 +630,6 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
void
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->ReceiveSocketData(this, aBuffer);
@ -645,39 +649,68 @@ BluetoothSocket::SendSocketData(const nsACString& aStr)
nsresult
BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
int aDelayMs)
int aDelayMs,
nsIThread* aConsumerThread, MessageLoop* aIOLoop)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aConnector);
MOZ_ASSERT(aConsumerThread);
MOZ_ASSERT(aIOLoop);
MOZ_ASSERT(!mIO);
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
SetConnectionStatus(SOCKET_CONNECTING);
if (aDelayMs > 0) {
DelayedConnectTask* connectTask = new DelayedConnectTask(mIO);
mIO->SetDelayedConnectTask(connectTask);
MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
} else {
ioLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
aIOLoop->PostTask(FROM_HERE, new ConnectTask(mIO));
}
return NS_OK;
}
nsresult
BluetoothSocket::Connect(BluetoothUnixSocketConnector* aConnector,
int aDelayMs)
{
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
return Connect(aConnector, aDelayMs, consumerThread, XRE_GetIOMessageLoop());
}
nsresult
BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector,
nsIThread* aConsumerThread, MessageLoop* aIOLoop)
{
MOZ_ASSERT(aConnector);
MOZ_ASSERT(aConsumerThread);
MOZ_ASSERT(aIOLoop);
MOZ_ASSERT(!mIO);
mIO = new BluetoothSocketIO(aConsumerThread, aIOLoop, this, aConnector);
SetConnectionStatus(SOCKET_LISTENING);
aIOLoop->PostTask(FROM_HERE, new ListenTask(mIO));
return NS_OK;
}
nsresult
BluetoothSocket::Listen(BluetoothUnixSocketConnector* aConnector)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aConnector);
MOZ_ASSERT(!mIO);
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
mIO = new BluetoothSocketIO(ioLoop, this, aConnector);
SetConnectionStatus(SOCKET_LISTENING);
ioLoop->PostTask(FROM_HERE, new ListenTask(mIO));
return NS_OK;
return Listen(aConnector, consumerThread, XRE_GetIOMessageLoop());
}
void
@ -696,11 +729,11 @@ BluetoothSocket::GetAddress(nsAString& aAddrStr)
void
BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO);
MOZ_ASSERT(!mIO->IsShutdownOnMainThread());
MOZ_ASSERT(mIO->IsConsumerThread());
MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
XRE_GetIOMessageLoop()->PostTask(
mIO->GetIOLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<BluetoothSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
}
@ -710,20 +743,19 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
void
BluetoothSocket::Close()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mIO) {
return;
}
MOZ_ASSERT(mIO->IsConsumerThread());
mIO->CancelDelayedConnectTask();
// From this point on, we consider mIO as being deleted.
// We sever the relationship here so any future calls to listen or connect
// will create a new implementation.
mIO->ShutdownOnMainThread();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO->ShutdownOnConsumerThread();
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO = nullptr;
NotifyDisconnect();
@ -732,7 +764,6 @@ BluetoothSocket::Close()
void
BluetoothSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnSocketConnectSuccess(this);
}
@ -740,7 +771,6 @@ BluetoothSocket::OnConnectSuccess()
void
BluetoothSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnSocketConnectError(this);
}
@ -748,7 +778,6 @@ BluetoothSocket::OnConnectError()
void
BluetoothSocket::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mObserver);
mObserver->OnSocketDisconnect(this);
}

View File

@ -16,6 +16,8 @@
#include "nsString.h"
#include "nsThreadUtils.h"
class MessageLoop;
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothSocketObserver;
@ -41,7 +43,7 @@ public:
/**
* Method to be called whenever data is received. This is only called on the
* main thread.
* consumer thread.
*
* @param aBuffer Data received from the socket.
*/
@ -58,6 +60,19 @@ public:
*/
bool SendSocketData(const nsACString& aMessage);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
*
* @param aConnector Connector object for socket type specific functions
* @param aDelayMs Time delay in milli-seconds.
* @param aConsumerThread The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Connect(BluetoothUnixSocketConnector* aConnector, int aDelayMs,
nsIThread* aConsumerThread, MessageLoop* aIOLoop);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
@ -69,6 +84,18 @@ public:
nsresult Connect(BluetoothUnixSocketConnector* aConnector,
int aDelayMs = 0);
/**
* Starts a task on the socket that will try to accept a new connection in a
* non-blocking manner.
*
* @param aConnector Connector object for socket type specific functions
* @param aConsumerThread The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Listen(BluetoothUnixSocketConnector* aConnector,
nsIThread* aConsumerThread, MessageLoop* aIOLoop);
/**
* Starts a task on the socket that will try to accept a new connection in a
* non-blocking manner.

View File

@ -206,8 +206,9 @@ class BluetoothDaemonConnectionIO final
, public ConnectionOrientedSocketIO
{
public:
BluetoothDaemonConnectionIO(MessageLoop* aIOLoop, int aFd,
ConnectionStatus aConnectionStatus,
BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
int aFd, ConnectionStatus aConnectionStatus,
BluetoothDaemonConnection* aConnection,
BluetoothDaemonPDUConsumer* aConsumer);
@ -241,10 +242,10 @@ public:
SocketBase* GetSocketBase() override;
bool IsShutdownOnMainThread() const override;
bool IsShutdownOnConsumerThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnMainThread() override;
void ShutdownOnConsumerThread() override;
void ShutdownOnIOThread() override;
private:
@ -255,14 +256,17 @@ private:
};
BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
MessageLoop* aIOLoop, int aFd,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
int aFd,
ConnectionStatus aConnectionStatus,
BluetoothDaemonConnection* aConnection,
BluetoothDaemonPDUConsumer* aConsumer)
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
, mConnection(aConnection)
, mConsumer(aConsumer)
, mShuttingDownOnIOThread(false)
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
, ConnectionOrientedSocketIO(aConsumerThread)
, mConnection(aConnection)
, mConsumer(aConsumer)
, mShuttingDownOnIOThread(false)
{
MOZ_ASSERT(mConnection);
MOZ_ASSERT(mConsumer);
@ -308,8 +312,9 @@ BluetoothDaemonConnectionIO::OnConnected()
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -327,9 +332,10 @@ BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno)
// Clean up watchers, status, fd
Close();
// Tell the main thread we've errored
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
// Tell the consumer thread we've errored
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
NS_DISPATCH_NORMAL);
}
// |ConnectionOrientedSocketIO|
@ -397,9 +403,9 @@ BluetoothDaemonConnectionIO::GetSocketBase()
}
bool
BluetoothDaemonConnectionIO::IsShutdownOnMainThread() const
BluetoothDaemonConnectionIO::IsShutdownOnConsumerThread() const
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
return mConnection == nullptr;
}
@ -411,10 +417,10 @@ BluetoothDaemonConnectionIO::IsShutdownOnIOThread() const
}
void
BluetoothDaemonConnectionIO::ShutdownOnMainThread()
BluetoothDaemonConnectionIO::ShutdownOnConsumerThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mConnection = nullptr;
}
@ -422,7 +428,7 @@ BluetoothDaemonConnectionIO::ShutdownOnMainThread()
void
BluetoothDaemonConnectionIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
@ -437,10 +443,10 @@ BluetoothDaemonConnection::BluetoothDaemonConnection(
BluetoothDaemonPDUConsumer* aPDUConsumer,
BluetoothDaemonConnectionConsumer* aConsumer,
int aIndex)
: mPDUConsumer(aPDUConsumer)
: mIO(nullptr)
, mPDUConsumer(aPDUConsumer)
, mConsumer(aConsumer)
, mIndex(aIndex)
, mIO(nullptr)
{
MOZ_ASSERT(mConsumer);
}
@ -452,9 +458,10 @@ BluetoothDaemonConnection::~BluetoothDaemonConnection()
nsresult
BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
// |BluetoothDaemonConnection| now owns the connector, but doesn't
@ -465,7 +472,7 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
SetConnectionStatus(SOCKET_CONNECTING);
mIO = new BluetoothDaemonConnectionIO(
XRE_GetIOMessageLoop(), -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
this, mPDUConsumer);
aIO = mIO;
@ -477,10 +484,10 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
void
BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO);
MOZ_ASSERT(mIO->IsConsumerThread());
XRE_GetIOMessageLoop()->PostTask(
mIO->GetIOLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<BluetoothDaemonConnectionIO,
UnixSocketIOBuffer>(mIO, aBuffer));
@ -491,15 +498,15 @@ BluetoothDaemonConnection::SendSocketData(UnixSocketIOBuffer* aBuffer)
void
BluetoothDaemonConnection::Close()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mIO) {
CHROMIUM_LOG("Bluetooth daemon already disconnected!");
return;
}
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
MOZ_ASSERT(mIO->IsConsumerThread());
mIO->ShutdownOnConsumerThread();
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO = nullptr;
NotifyDisconnect();
@ -508,24 +515,18 @@ BluetoothDaemonConnection::Close()
void
BluetoothDaemonConnection::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectSuccess(mIndex);
}
void
BluetoothDaemonConnection::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectError(mIndex);
}
void
BluetoothDaemonConnection::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnDisconnect(mIndex);
}

View File

@ -12,6 +12,8 @@
#include "mozilla/ipc/ConnectionOrientedSocket.h"
#include "nsAutoPtr.h"
class MessageLoop;
namespace mozilla {
namespace ipc {
@ -92,7 +94,7 @@ private:
/*
* |BluetoothDaemonPDUConsumer| processes incoming PDUs from the Bluetooth
* daemon. Please note that its method |Handle| runs on a different than the
* main thread.
* consumer thread.
*/
class BluetoothDaemonPDUConsumer
{
@ -123,6 +125,8 @@ public:
//
nsresult PrepareAccept(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO) override;
// Methods for |DataSocket|
@ -139,10 +143,10 @@ public:
void OnDisconnect() override;
private:
BluetoothDaemonConnectionIO* mIO;
BluetoothDaemonPDUConsumer* mPDUConsumer;
BluetoothDaemonConnectionConsumer* mConsumer;
int mIndex;
BluetoothDaemonConnectionIO* mIO;
};
}

View File

@ -22,21 +22,21 @@ class BluetoothDaemonConnectionConsumer
{
public:
/**
* Callback for socket success. Main-thread only.
* Callback for socket success. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectSuccess(int aIndex) = 0;
/**
* Callback for socket errors. Main-thread only.
* Callback for socket errors. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectError(int aIndex) = 0;
/**
* Callback for socket disconnect. Main-thread only.
* Callback for socket disconnect. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/

View File

@ -9,9 +9,22 @@
namespace mozilla {
namespace ipc {
//
// ConnectionOrientedSocketIO
//
ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
nsIThread* aConsumerThread)
: DataSocketIO(aConsumerThread)
{ }
ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO()
{ }
//
// ConnectionOrientedSocket
//
ConnectionOrientedSocket::~ConnectionOrientedSocket()
{ }

View File

@ -10,6 +10,8 @@
#include <sys/socket.h>
#include "DataSocket.h"
class MessageLoop;
namespace mozilla {
namespace ipc {
@ -17,13 +19,14 @@ class UnixSocketConnector;
/*
* |ConnectionOrientedSocketIO| and |ConnectionOrientedSocket| define
* interfaces for implementing stream sockets on I/O and main thread.
* interfaces for implementing stream sockets on I/O and consumer thread.
* |ListenSocket| uses these classes to handle accepted sockets.
*/
class ConnectionOrientedSocketIO : public DataSocketIO
{
public:
ConnectionOrientedSocketIO(nsIThread* aConsumerThread);
virtual ~ConnectionOrientedSocketIO();
virtual nsresult Accept(int aFd,
@ -36,14 +39,18 @@ class ConnectionOrientedSocket : public DataSocket
public:
/**
* Prepares an instance of |ConnectionOrientedSocket| in DISCONNECTED
* state for accepting a connection. Main-thread only.
* state for accepting a connection. Consumer-thread only.
*
* @param aConnector The new connector object, owned by the
* connection-oriented socket.
* @param aConsumerThread The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @param[out] aIO, Returns an instance of |ConnectionOrientedSocketIO|.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
virtual nsresult PrepareAccept(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO) = 0;
protected:

View File

@ -50,7 +50,8 @@ DataSocketIO::ReceiveData(int aFd)
nsresult rv = QueryReceiveBuffer(&incoming);
if (NS_FAILED(rv)) {
/* an error occured */
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
NS_DISPATCH_NORMAL);
return -1;
}
@ -58,12 +59,14 @@ DataSocketIO::ReceiveData(int aFd)
if (res < 0) {
/* an I/O error occured */
DiscardBuffer();
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
NS_DISPATCH_NORMAL);
return -1;
} else if (!res) {
/* EOF or peer shut down sending */
DiscardBuffer();
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
NS_DISPATCH_NORMAL);
return 0;
}
@ -90,7 +93,8 @@ DataSocketIO::SendPendingData(int aFd)
ssize_t res = outgoing->Send(aFd);
if (res < 0) {
/* an I/O error occured */
NS_DispatchToMainThread(new SocketIORequestClosingRunnable(this));
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
NS_DISPATCH_NORMAL);
return NS_ERROR_FAILURE;
} else if (!res && outgoing->GetSize()) {
/* I/O is currently blocked; try again later */
@ -105,7 +109,8 @@ DataSocketIO::SendPendingData(int aFd)
return NS_OK;
}
DataSocketIO::DataSocketIO()
DataSocketIO::DataSocketIO(nsIThread* aConsumerThread)
: SocketIOBase(aConsumerThread)
{ }
//

View File

@ -90,7 +90,7 @@ public:
nsresult SendPendingData(int aFd);
protected:
DataSocketIO();
DataSocketIO(nsIThread* aConsumerThread);
private:
/**
@ -120,10 +120,10 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!SocketIOTask<Tio>::IsCanceled());
Tio* io = SocketIOTask<Tio>::GetIO();
MOZ_ASSERT(!io->IsConsumerThread());
MOZ_ASSERT(!io->IsShutdownOnIOThread());
io->Send(mData);

View File

@ -27,7 +27,8 @@ class ListenSocketIO final
public:
class ListenTask;
ListenSocketIO(MessageLoop* mIOLoop,
ListenSocketIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ListenSocket* aListenSocket,
UnixSocketConnector* aConnector);
~ListenSocketIO();
@ -55,10 +56,10 @@ public:
SocketBase* GetSocketBase() override;
bool IsShutdownOnMainThread() const override;
bool IsShutdownOnConsumerThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnMainThread() override;
void ShutdownOnConsumerThread() override;
void ShutdownOnIOThread() override;
private:
@ -66,8 +67,8 @@ private:
/**
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
* directly from main thread. All non-main-thread accesses should happen with
* mIO as container.
* directly from consumer thread. All non-consumer-thread accesses should
* happen with mIO as container.
*/
RefPtr<ListenSocket> mListenSocket;
@ -94,11 +95,12 @@ private:
ConnectionOrientedSocketIO* mCOSocketIO;
};
ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop,
ListenSocketIO::ListenSocketIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ListenSocket* aListenSocket,
UnixSocketConnector* aConnector)
: UnixSocketWatcher(mIOLoop)
, SocketIOBase()
: UnixSocketWatcher(aIOLoop)
, SocketIOBase(aConsumerThread)
, mListenSocket(aListenSocket)
, mConnector(aConnector)
, mShuttingDownOnIOThread(false)
@ -111,8 +113,8 @@ ListenSocketIO::ListenSocketIO(MessageLoop* mIOLoop,
ListenSocketIO::~ListenSocketIO()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(IsShutdownOnConsumerThread());
}
UnixSocketConnector*
@ -166,8 +168,9 @@ ListenSocketIO::OnListening()
AddWatchers(READ_WATCHER, true);
/* We signal a successful 'connection' to a local address for listening. */
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
}
void
@ -187,9 +190,10 @@ ListenSocketIO::FireSocketError()
// Clean up watchers, statuses, fds
Close();
// Tell the main thread we've errored
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
// Tell the consumer thread we've errored
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
NS_DISPATCH_NORMAL);
}
void
@ -228,9 +232,9 @@ ListenSocketIO::GetSocketBase()
}
bool
ListenSocketIO::IsShutdownOnMainThread() const
ListenSocketIO::IsShutdownOnConsumerThread() const
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
return mListenSocket == nullptr;
}
@ -242,10 +246,10 @@ ListenSocketIO::IsShutdownOnIOThread() const
}
void
ListenSocketIO::ShutdownOnMainThread()
ListenSocketIO::ShutdownOnConsumerThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mListenSocket = nullptr;
}
@ -253,7 +257,7 @@ ListenSocketIO::ShutdownOnMainThread()
void
ListenSocketIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
@ -277,7 +281,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
if (!IsCanceled()) {
GetIO()->Listen(mCOSocketIO);
@ -293,9 +297,9 @@ private:
//
ListenSocket::ListenSocket(ListenSocketConsumer* aConsumer, int aIndex)
: mConsumer(aConsumer)
: mIO(nullptr)
, mConsumer(aConsumer)
, mIndex(aIndex)
, mIO(nullptr)
{
MOZ_ASSERT(mConsumer);
}
@ -307,12 +311,13 @@ ListenSocket::~ListenSocket()
nsresult
ListenSocket::Listen(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocket* aCOSocket)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
mIO = new ListenSocketIO(XRE_GetIOMessageLoop(), this, aConnector);
mIO = new ListenSocketIO(aConsumerThread, aIOLoop, this, aConnector);
// Prepared I/O object, now start listening.
nsresult rv = Listen(aCOSocket);
@ -325,10 +330,22 @@ ListenSocket::Listen(UnixSocketConnector* aConnector,
return NS_OK;
}
nsresult
ListenSocket::Listen(UnixSocketConnector* aConnector,
ConnectionOrientedSocket* aCOSocket)
{
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
return Listen(aConnector, consumerThread, XRE_GetIOMessageLoop(), aCOSocket);
}
nsresult
ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aCOSocket);
MOZ_ASSERT(mIO);
@ -342,7 +359,9 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket)
}
nsAutoPtr<ConnectionOrientedSocketIO> io;
rv = aCOSocket->PrepareAccept(connector, *io.StartAssignment());
rv = aCOSocket->PrepareAccept(connector,
mIO->GetConsumerThread(), mIO->GetIOLoop(),
*io.StartAssignment());
if (NS_FAILED(rv)) {
return rv;
}
@ -352,7 +371,7 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket)
SetConnectionStatus(SOCKET_LISTENING);
XRE_GetIOMessageLoop()->PostTask(
mIO->GetIOLoop()->PostTask(
FROM_HERE, new ListenSocketIO::ListenTask(mIO, io.forget()));
return NS_OK;
@ -363,19 +382,17 @@ ListenSocket::Listen(ConnectionOrientedSocket* aCOSocket)
void
ListenSocket::Close()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mIO) {
return;
}
MOZ_ASSERT(mIO->IsConsumerThread());
// From this point on, we consider mIO as being deleted. We sever
// the relationship here so any future calls to listen or connect
// will create a new implementation.
mIO->ShutdownOnMainThread();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO->ShutdownOnConsumerThread();
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO = nullptr;
NotifyDisconnect();
@ -384,24 +401,18 @@ ListenSocket::Close()
void
ListenSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectSuccess(mIndex);
}
void
ListenSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectError(mIndex);
}
void
ListenSocket::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnDisconnect(mIndex);
}

View File

@ -10,6 +10,9 @@
#include "nsString.h"
#include "mozilla/ipc/SocketBase.h"
class MessageLoop;
class nsIThread;
namespace mozilla {
namespace ipc {
@ -20,12 +23,31 @@ class UnixSocketConnector;
class ListenSocket final : public SocketBase
{
protected:
virtual ~ListenSocket();
public:
/**
* Constructs an instance of |ListenSocket|.
*
* @param aConsumer The consumer for the socket.
* @param aIndex An arbitrary index.
*/
ListenSocket(ListenSocketConsumer* aConsumer, int aIndex);
/**
* Starts a task on the socket that will try to accept a new connection
* in a non-blocking manner.
*
* @param aConnector Connector object for socket-type-specific functions
* @param aConsumerThread The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @param aCOSocket The connection-oriented socket for handling the
* accepted connection.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Listen(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocket* aCOSocket);
/**
* Starts a task on the socket that will try to accept a new connection
* in a non-blocking manner.
@ -57,10 +79,13 @@ public:
void OnConnectError() override;
void OnDisconnect() override;
protected:
virtual ~ListenSocket();
private:
ListenSocketIO* mIO;
ListenSocketConsumer* mConsumer;
int mIndex;
ListenSocketIO* mIO;
};
} // namespace ipc

View File

@ -19,21 +19,21 @@ public:
virtual ~ListenSocketConsumer();
/**
* Callback for socket success. Main-thread only.
* Callback for socket success. Consumer-thread only.
*
* @param aIndex The index that has been given to the listening socket.
*/
virtual void OnConnectSuccess(int aIndex) = 0;
/**
* Callback for socket errors. Main-thread only.
* Callback for socket errors. Consumer-thread only.
*
* @param aIndex The index that has been given to the listening socket.
*/
virtual void OnConnectError(int aIndex) = 0;
/**
* Callback for socket disconnect. Main-thread only.
* Callback for socket disconnect. Consumer-thread only.
*
* @param aIndex The index that has been given to the listeing socket.
*/

View File

@ -186,24 +186,18 @@ UnixSocketRawData::Send(int aFd)
SocketConnectionStatus
SocketBase::GetConnectionStatus() const
{
MOZ_ASSERT(NS_IsMainThread());
return mConnectionStatus;
}
int
SocketBase::GetSuggestedConnectDelayMs() const
{
MOZ_ASSERT(NS_IsMainThread());
return mConnectDelayMs;
}
void
SocketBase::NotifySuccess()
{
MOZ_ASSERT(NS_IsMainThread());
mConnectionStatus = SOCKET_CONNECTED;
mConnectTimestamp = PR_IntervalNow();
OnConnectSuccess();
@ -212,8 +206,6 @@ SocketBase::NotifySuccess()
void
SocketBase::NotifyError()
{
MOZ_ASSERT(NS_IsMainThread());
mConnectionStatus = SOCKET_DISCONNECTED;
mConnectDelayMs = CalculateConnectDelayMs();
mConnectTimestamp = 0;
@ -223,8 +215,6 @@ SocketBase::NotifyError()
void
SocketBase::NotifyDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mConnectionStatus = SOCKET_DISCONNECTED;
mConnectDelayMs = CalculateConnectDelayMs();
mConnectTimestamp = 0;
@ -234,8 +224,6 @@ SocketBase::NotifyDisconnect()
uint32_t
SocketBase::CalculateConnectDelayMs() const
{
MOZ_ASSERT(NS_IsMainThread());
uint32_t connectDelayMs = mConnectDelayMs;
if (mConnectTimestamp && (PR_IntervalNow()-mConnectTimestamp) > connectDelayMs) {
@ -272,12 +260,31 @@ SocketBase::SetConnectionStatus(SocketConnectionStatus aConnectionStatus)
// SocketIOBase
//
SocketIOBase::SocketIOBase()
{ }
SocketIOBase::SocketIOBase(nsIThread* aConsumerThread)
: mConsumerThread(aConsumerThread)
{
MOZ_ASSERT(mConsumerThread);
}
SocketIOBase::~SocketIOBase()
{ }
nsIThread*
SocketIOBase::GetConsumerThread() const
{
return mConsumerThread;
}
bool
SocketIOBase::IsConsumerThread() const
{
nsIThread* thread = nullptr;
if (NS_FAILED(NS_GetCurrentThread(&thread))) {
return false;
}
return thread == GetConsumerThread();
}
//
// SocketIOEventRunnable
//
@ -291,11 +298,11 @@ SocketIOEventRunnable::SocketIOEventRunnable(SocketIOBase* aIO,
NS_METHOD
SocketIOEventRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
SocketIOBase* io = SocketIORunnable<SocketIOBase>::GetIO();
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
MOZ_ASSERT(io->IsConsumerThread());
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return NS_OK;
@ -327,11 +334,11 @@ SocketIORequestClosingRunnable::SocketIORequestClosingRunnable(
NS_METHOD
SocketIORequestClosingRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
SocketIOBase* io = SocketIORunnable<SocketIOBase>::GetIO();
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
MOZ_ASSERT(io->IsConsumerThread());
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return NS_OK;
@ -373,19 +380,19 @@ SocketIOShutdownTask::SocketIOShutdownTask(SocketIOBase* aIO)
void
SocketIOShutdownTask::Run()
{
MOZ_ASSERT(!NS_IsMainThread());
SocketIOBase* io = SocketIOTask<SocketIOBase>::GetIO();
MOZ_ASSERT(!io->IsConsumerThread());
MOZ_ASSERT(!io->IsShutdownOnIOThread());
// At this point, there should be no new events on the I/O thread
// after this one with the possible exception of an accept task,
// which ShutdownOnIOThread will cancel for us. We are now fully
// shut down, so we can send a message to the main thread to delete
// |io| safely knowing that it's not reference any longer.
MOZ_ASSERT(!io->IsShutdownOnIOThread());
// shut down, so we can send a message to the consumer thread to
// delete |io| safely knowing that it's not reference any longer.
io->ShutdownOnIOThread();
NS_DispatchToMainThread(new SocketIODeleteInstanceRunnable(io));
io->GetConsumerThread()->Dispatch(new SocketIODeleteInstanceRunnable(io),
NS_DISPATCH_NORMAL);
}
}

View File

@ -256,23 +256,23 @@ public:
/**
* Queues the internal representation of socket for deletion. Can be called
* from main thread.
* from consumer thread.
*/
virtual void Close() = 0;
/**
* Callback for socket connect/accept success. Called after connect/accept has
* finished. Will be run on main thread, before any reads take place.
* finished. Will be run on consumer thread before any reads take place.
*/
virtual void OnConnectSuccess() = 0;
/**
* Callback for socket connect/accept error. Will be run on main thread.
* Callback for socket connect/accept error. Will be run on consumer thread.
*/
virtual void OnConnectError() = 0;
/**
* Callback for socket disconnect. Will be run on main thread.
* Callback for socket disconnect. Will be run on consumer thread.
*/
virtual void OnDisconnect() = 0;
@ -340,7 +340,7 @@ public:
*
* @return True if the socket class has been shut down, false otherwise.
*/
virtual bool IsShutdownOnMainThread() const = 0;
virtual bool IsShutdownOnConsumerThread() const = 0;
/**
* Signals to the socket I/O classes that it has been shut down.
@ -351,10 +351,26 @@ public:
* Signals to the socket I/O classes that the socket class has been
* shut down.
*/
virtual void ShutdownOnMainThread() = 0;
virtual void ShutdownOnConsumerThread() = 0;
/**
* Returns the consumer thread.
*
* @return A pointer to the consumer thread.
*/
nsIThread* GetConsumerThread() const;
/**
* @return True if the current thread is thre consumer thread, or false
* otherwise.
*/
bool IsConsumerThread() const;
protected:
SocketIOBase();
SocketIOBase(nsIThread* nsConsumerThread);
private:
nsCOMPtr<nsIThread> mConsumerThread;
};
//
@ -362,7 +378,7 @@ protected:
//
/* |SocketIORunnable| is a runnable for sending a message from
* the I/O thread to the main thread.
* the I/O thread to the consumer thread.
*/
template <typename T>
class SocketIORunnable : public nsRunnable
@ -389,7 +405,7 @@ private:
/**
* |SocketIOEventRunnable| reports the connection state on the
* I/O thread back to the main thread.
* I/O thread back to the consumer thread.
*/
class SocketIOEventRunnable final : public SocketIORunnable<SocketIOBase>
{
@ -410,7 +426,7 @@ private:
/**
* |SocketIORequestClosingRunnable| closes an instance of |SocketBase|
* to the main thread.
* to the consumer thread.
*/
class SocketIORequestClosingRunnable final
: public SocketIORunnable<SocketIOBase>
@ -422,7 +438,7 @@ public:
};
/**
* |SocketIODeleteInstanceRunnable| deletes an object on the main thread.
* |SocketIODeleteInstanceRunnable| deletes an object on the consumer thread.
*/
class SocketIODeleteInstanceRunnable final : public nsRunnable
{
@ -477,7 +493,7 @@ private:
/**
* |SocketIOShutdownTask| signals shutdown to the socket I/O class on
* the I/O thread and sends it to the main thread for destruction.
* the I/O thread and sends it to the consumer thread for destruction.
*/
class SocketIOShutdownTask final : public SocketIOTask<SocketIOBase>
{

View File

@ -29,10 +29,12 @@ public:
class DelayedConnectTask;
class ReceiveRunnable;
StreamSocketIO(MessageLoop* mIOLoop,
StreamSocketIO(nsIThread* aConsumerThread,
MessageLoop* mIOLoop,
StreamSocket* aStreamSocket,
UnixSocketConnector* aConnector);
StreamSocketIO(MessageLoop* mIOLoop, int aFd,
StreamSocketIO(nsIThread* aConsumerThread,
MessageLoop* mIOLoop, int aFd,
ConnectionStatus aConnectionStatus,
StreamSocket* aStreamSocket,
UnixSocketConnector* aConnector);
@ -86,10 +88,10 @@ public:
SocketBase* GetSocketBase() override;
bool IsShutdownOnMainThread() const override;
bool IsShutdownOnConsumerThread() const override;
bool IsShutdownOnIOThread() const override;
void ShutdownOnMainThread() override;
void ShutdownOnConsumerThread() override;
void ShutdownOnIOThread() override;
private:
@ -97,8 +99,8 @@ private:
/**
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
* directly from main thread. All non-main-thread accesses should happen with
* mIO as container.
* directly from consumer thread. All non-consumer-thread accesses should
* happen with mIO as container.
*/
RefPtr<StreamSocket> mStreamSocket;
@ -123,7 +125,8 @@ private:
struct sockaddr_storage mAddress;
/**
* Task member for delayed connect task. Should only be access on main thread.
* Task member for delayed connect task. Should only be access on consumer
* thread.
*/
CancelableTask* mDelayedConnectTask;
@ -133,10 +136,12 @@ private:
nsAutoPtr<UnixSocketRawData> mBuffer;
};
StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop,
StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
StreamSocket* aStreamSocket,
UnixSocketConnector* aConnector)
: UnixSocketWatcher(mIOLoop)
: UnixSocketWatcher(aIOLoop)
, ConnectionOrientedSocketIO(aConsumerThread)
, mStreamSocket(aStreamSocket)
, mConnector(aConnector)
, mShuttingDownOnIOThread(false)
@ -147,11 +152,13 @@ StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop,
MOZ_ASSERT(mConnector);
}
StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd,
ConnectionStatus aConnectionStatus,
StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
int aFd, ConnectionStatus aConnectionStatus,
StreamSocket* aStreamSocket,
UnixSocketConnector* aConnector)
: UnixSocketWatcher(mIOLoop, aFd, aConnectionStatus)
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
, ConnectionOrientedSocketIO(aConsumerThread)
, mStreamSocket(aStreamSocket)
, mConnector(aConnector)
, mShuttingDownOnIOThread(false)
@ -164,8 +171,8 @@ StreamSocketIO::StreamSocketIO(MessageLoop* mIOLoop, int aFd,
StreamSocketIO::~StreamSocketIO()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(IsShutdownOnConsumerThread());
}
StreamSocket*
@ -183,7 +190,7 @@ StreamSocketIO::GetDataSocket()
void
StreamSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = aTask;
}
@ -191,7 +198,7 @@ StreamSocketIO::SetDelayedConnectTask(CancelableTask* aTask)
void
StreamSocketIO::ClearDelayedConnectTask()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
mDelayedConnectTask = nullptr;
}
@ -199,7 +206,7 @@ StreamSocketIO::ClearDelayedConnectTask()
void
StreamSocketIO::CancelDelayedConnectTask()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
if (!mDelayedConnectTask) {
return;
@ -246,8 +253,9 @@ StreamSocketIO::OnConnected()
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -312,9 +320,10 @@ StreamSocketIO::FireSocketError()
// Clean up watchers, statuses, fds
Close();
// Tell the main thread we've errored
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR));
// Tell the consumer thread we've errored
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
NS_DISPATCH_NORMAL);
}
// |ConnectionOrientedSocketIO|
@ -334,8 +343,9 @@ StreamSocketIO::Accept(int aFd,
memcpy(&mAddress, aAddress, mAddressLength);
// Signal success
NS_DispatchToMainThread(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS));
GetConsumerThread()->Dispatch(
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
NS_DISPATCH_NORMAL);
AddWatchers(READ_WATCHER, true);
if (HasPendingData()) {
@ -362,7 +372,7 @@ StreamSocketIO::QueryReceiveBuffer(UnixSocketIOBuffer** aBuffer)
/**
* |ReceiveRunnable| transfers data received on the I/O thread
* to an instance of |StreamSocket| on the main thread.
* to an instance of |StreamSocket| on the consumer thread.
*/
class StreamSocketIO::ReceiveRunnable final
: public SocketIORunnable<StreamSocketIO>
@ -375,11 +385,11 @@ public:
NS_IMETHOD Run() override
{
MOZ_ASSERT(NS_IsMainThread());
StreamSocketIO* io = SocketIORunnable<StreamSocketIO>::GetIO();
if (NS_WARN_IF(io->IsShutdownOnMainThread())) {
MOZ_ASSERT(io->IsConsumerThread());
if (NS_WARN_IF(io->IsShutdownOnConsumerThread())) {
// Since we've already explicitly closed and the close
// happened before this, this isn't really an error.
return NS_OK;
@ -400,7 +410,8 @@ private:
void
StreamSocketIO::ConsumeBuffer()
{
NS_DispatchToMainThread(new ReceiveRunnable(this, mBuffer.forget()));
GetConsumerThread()->Dispatch(new ReceiveRunnable(this, mBuffer.forget()),
NS_DISPATCH_NORMAL);
}
void
@ -418,9 +429,9 @@ StreamSocketIO::GetSocketBase()
}
bool
StreamSocketIO::IsShutdownOnMainThread() const
StreamSocketIO::IsShutdownOnConsumerThread() const
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(IsConsumerThread());
return mStreamSocket == nullptr;
}
@ -432,10 +443,10 @@ StreamSocketIO::IsShutdownOnIOThread() const
}
void
StreamSocketIO::ShutdownOnMainThread()
StreamSocketIO::ShutdownOnConsumerThread()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!IsShutdownOnMainThread());
MOZ_ASSERT(IsConsumerThread());
MOZ_ASSERT(!IsShutdownOnConsumerThread());
mStreamSocket = nullptr;
}
@ -443,7 +454,7 @@ StreamSocketIO::ShutdownOnMainThread()
void
StreamSocketIO::ShutdownOnIOThread()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!IsConsumerThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
Close(); // will also remove fd from I/O loop
@ -464,7 +475,7 @@ public:
void Run() override
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!GetIO()->IsConsumerThread());
MOZ_ASSERT(!IsCanceled());
GetIO()->Connect();
@ -476,24 +487,24 @@ class StreamSocketIO::DelayedConnectTask final
{
public:
DelayedConnectTask(StreamSocketIO* aIO)
: SocketIOTask<StreamSocketIO>(aIO)
: SocketIOTask<StreamSocketIO>(aIO)
{ }
void Run() override
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(GetIO()->IsConsumerThread());
if (IsCanceled()) {
return;
}
StreamSocketIO* io = GetIO();
if (io->IsShutdownOnMainThread()) {
if (io->IsShutdownOnConsumerThread()) {
return;
}
io->ClearDelayedConnectTask();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new ConnectTask(io));
io->GetIOLoop()->PostTask(FROM_HERE, new ConnectTask(io));
}
};
@ -502,9 +513,9 @@ public:
//
StreamSocket::StreamSocket(StreamSocketConsumer* aConsumer, int aIndex)
: mConsumer(aConsumer)
: mIO(nullptr)
, mConsumer(aConsumer)
, mIndex(aIndex)
, mIO(nullptr)
{
MOZ_ASSERT(mConsumer);
}
@ -517,20 +528,16 @@ StreamSocket::~StreamSocket()
void
StreamSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->ReceiveSocketData(mIndex, aBuffer);
}
nsresult
StreamSocket::Connect(UnixSocketConnector* aConnector,
int aDelayMs)
StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs,
nsIThread* aConsumerThread, MessageLoop* aIOLoop)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
mIO = new StreamSocketIO(ioLoop, this, aConnector);
mIO = new StreamSocketIO(aConsumerThread, aIOLoop, this, aConnector);
SetConnectionStatus(SOCKET_CONNECTING);
if (aDelayMs > 0) {
@ -539,24 +546,38 @@ StreamSocket::Connect(UnixSocketConnector* aConnector,
mIO->SetDelayedConnectTask(connectTask);
MessageLoop::current()->PostDelayedTask(FROM_HERE, connectTask, aDelayMs);
} else {
ioLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO));
aIOLoop->PostTask(FROM_HERE, new StreamSocketIO::ConnectTask(mIO));
}
return NS_OK;
}
nsresult
StreamSocket::Connect(UnixSocketConnector* aConnector, int aDelayMs)
{
nsIThread* consumerThread = nullptr;
nsresult rv = NS_GetCurrentThread(&consumerThread);
if (NS_FAILED(rv)) {
return rv;
}
return Connect(aConnector, aDelayMs, consumerThread, XRE_GetIOMessageLoop());
}
// |ConnectionOrientedSocket|
nsresult
StreamSocket::PrepareAccept(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mIO);
MOZ_ASSERT(aConnector);
SetConnectionStatus(SOCKET_CONNECTING);
mIO = new StreamSocketIO(XRE_GetIOMessageLoop(),
mIO = new StreamSocketIO(aConsumerThread, aIOLoop,
-1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
this, aConnector);
aIO = mIO;
@ -569,11 +590,11 @@ StreamSocket::PrepareAccept(UnixSocketConnector* aConnector,
void
StreamSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO);
MOZ_ASSERT(mIO->IsConsumerThread());
MOZ_ASSERT(!mIO->IsShutdownOnConsumerThread());
MOZ_ASSERT(!mIO->IsShutdownOnMainThread());
XRE_GetIOMessageLoop()->PostTask(
mIO->GetIOLoop()->PostTask(
FROM_HERE,
new SocketIOSendTask<StreamSocketIO, UnixSocketIOBuffer>(mIO, aBuffer));
}
@ -583,18 +604,16 @@ StreamSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
void
StreamSocket::Close()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mIO);
MOZ_ASSERT(mIO->IsConsumerThread());
mIO->CancelDelayedConnectTask();
// From this point on, we consider |mIO| as being deleted. We sever
// the relationship here so any future calls to |Connect| will create
// a new I/O object.
mIO->ShutdownOnMainThread();
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO->ShutdownOnConsumerThread();
mIO->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mIO));
mIO = nullptr;
NotifyDisconnect();
@ -603,24 +622,18 @@ StreamSocket::Close()
void
StreamSocket::OnConnectSuccess()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectSuccess(mIndex);
}
void
StreamSocket::OnConnectError()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnConnectError(mIndex);
}
void
StreamSocket::OnDisconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mConsumer->OnDisconnect(mIndex);
}

View File

@ -9,6 +9,8 @@
#include "ConnectionOrientedSocket.h"
class MessageLoop;
namespace mozilla {
namespace ipc {
@ -19,15 +21,34 @@ class UnixSocketConnector;
class StreamSocket final : public ConnectionOrientedSocket
{
public:
/**
* Constructs an instance of |StreamSocket|.
*
* @param aConsumer The consumer for the socket.
* @param aIndex An arbitrary index.
*/
StreamSocket(StreamSocketConsumer* aConsumer, int aIndex);
/**
* Method to be called whenever data is received. Main-thread only.
* Method to be called whenever data is received. Consumer-thread only.
*
* @param aBuffer Data received from the socket.
*/
void ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
*
* @param aConnector Connector object for socket type specific functions
* @param aDelayMs Time delay in milliseconds.
* @param aConsumerThread The socket's consumer thread.
* @param aIOLoop The socket's I/O thread.
* @return NS_OK on success, or an XPCOM error code otherwise.
*/
nsresult Connect(UnixSocketConnector* aConnector, int aDelayMs,
nsIThread* aConsumerThread, MessageLoop* aIOLoop);
/**
* Starts a task on the socket that will try to connect to a socket in a
* non-blocking manner.
@ -42,6 +63,8 @@ public:
//
nsresult PrepareAccept(UnixSocketConnector* aConnector,
nsIThread* aConsumerThread,
MessageLoop* aIOLoop,
ConnectionOrientedSocketIO*& aIO) override;
// Methods for |DataSocket|
@ -61,9 +84,9 @@ protected:
virtual ~StreamSocket();
private:
StreamSocketIO* mIO;
StreamSocketConsumer* mConsumer;
int mIndex;
StreamSocketIO* mIO;
};
} // namespace ipc

View File

@ -21,7 +21,7 @@ class StreamSocketConsumer
{
public:
/**
* Method to be called whenever data is received. Main-thread only.
* Method to be called whenever data is received. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
* @param aBuffer Data received from the socket.
@ -30,21 +30,21 @@ public:
nsAutoPtr<UnixSocketBuffer>& aBuffer) = 0;
/**
* Callback for socket success. Main-thread only.
* Callback for socket success. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectSuccess(int aIndex) = 0;
/**
* Callback for socket errors. Main-thread only.
* Callback for socket errors. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/
virtual void OnConnectError(int aIndex) = 0;
/**
* Callback for socket disconnect. Main-thread only.
* Callback for socket disconnect. Consumer-thread only.
*
* @param aIndex The index that has been given to the stream socket.
*/