/* vim:set ts=2 sw=2 et cindent: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include"nsSocketTransport2.h" #include"nsServerSocket.h" #include"nsProxyRelease.h" #include"nsError.h" #include"nsNetCID.h" #include"prnetdb.h" #include"prio.h" #include"nsThreadUtils.h" #include"mozilla/Attributes.h" #include"mozilla/EndianUtils.h" #include"mozilla/net/DNS.h" #include"mozilla/Unused.h" #include"nsServiceManagerUtils.h" #include"nsIFile.h" #ifdefined(XP_WIN) # include "private/pprio.h" # include <winsock2.h> # include <mstcpip.h>
nsServerSocket::nsServerSocket() { // we want to be able to access the STS directly, and it may not have been // constructed yet. the STS constructor sets gSocketTransportService. if (!gSocketTransportService) { // This call can fail if we're offline, for example.
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
} // make sure the STS sticks around as long as we do
NS_IF_ADDREF(gSocketTransportService);
}
nsServerSocket::~nsServerSocket() {
Close(); // just in case :)
// release our reference to the STS
nsSocketTransportService* serv = gSocketTransportService;
NS_IF_RELEASE(serv);
}
// tear down socket. this signals the STS to detach our socket handler.
mCondition = NS_BINDING_ABORTED;
// if we are attached, then we'll close the socket in our OnSocketDetached. // otherwise, call OnSocketDetached from here. if (!mAttached) OnSocketDetached(mFD);
}
// if we hit an error while trying to attach then bail... if (NS_FAILED(mCondition)) {
NS_ASSERTION(!mAttached, "should not be attached already");
OnSocketDetached(mFD);
}
}
if (!gSocketTransportService) return NS_ERROR_FAILURE;
// // find out if it is going to be ok to attach another socket to the STS. // if not then we have to wait for the STS to tell us that it is ok. // the notification is asynchronous, which means that when we could be // in a race to call AttachSocket once notified. for this reason, when // we get notified, we just re-enter this function. as a result, we are // sure to ask again before calling AttachSocket. in this way we deal // with the race condition. though it isn't the most elegant solution, // it is far simpler than trying to build a system that would guarantee // FIFO ordering (which wouldn't even be that valuable IMO). see bug // 194402 for more info. // if (!gSocketTransportService->CanAttachSocket()) {
nsCOMPtr<nsIRunnable> event = NewRunnableMethod( "net::nsServerSocket::OnMsgAttach", this, &nsServerSocket::OnMsgAttach); if (!event) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event); if (NS_FAILED(rv)) return rv;
}
// // ok, we can now attach our socket to the STS for polling //
rv = gSocketTransportService->AttachSocket(mFD, this); if (NS_FAILED(rv)) return rv;
if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL)) {
NS_WARNING("error polling on listening socket");
mCondition = NS_ERROR_UNEXPECTED; return;
}
PRFileDesc* clientFD;
PRNetAddr prClientAddr;
// NSPR doesn't tell us the peer address's length (as provided by the // 'accept' system call), so we can't distinguish between named, // unnamed, and abstract peer addresses. Clear prClientAddr first, so // that the path will at least be reliably empty for unnamed and // abstract addresses, and not garbage when the peer is unnamed.
memset(&prClientAddr, 0, sizeof(prClientAddr));
NetAddr clientAddr(&prClientAddr); // Accept succeeded, create socket transport and notify consumer
CreateClientTransport(clientFD, clientAddr);
}
void nsServerSocket::OnSocketDetached(PRFileDesc* fd) { // force a failure condition if none set; maybe the STS is shutting down :-/ if (NS_SUCCEEDED(mCondition)) mCondition = NS_ERROR_ABORT;
if (mListener) {
mListener->OnStopListening(this, mCondition);
// need to atomically clear mListener. see our Close() method.
RefPtr<nsIServerSocketListener> listener = nullptr;
{
MutexAutoLock lock(mLock);
listener = ToRefPtr(std::move(mListener));
}
// XXX we need to proxy the release to the listener's target thread to work // around bug 337492. if (listener) {
NS_ProxyRelease("nsServerSocket::mListener", mListenerTarget,
listener.forget());
}
}
}
if (PR_Bind(mFD, aAddr) != PR_SUCCESS) {
NS_WARNING("failed to bind socket"); goto fail;
}
if (aBackLog < 0) aBackLog = 5; // seems like a reasonable default
if (PR_Listen(mFD, aBackLog) != PR_SUCCESS) {
NS_WARNING("cannot listen on socket"); goto fail;
}
// get the resulting socket address, which may be different than what // we passed to bind. if (PR_GetSockName(mFD, &mAddr) != PR_SUCCESS) {
NS_WARNING("cannot get socket name"); goto fail;
}
// Set any additional socket defaults needed by child classes
rv = SetSocketDefaults(); if (NS_WARN_IF(NS_FAILED(rv))) { goto fail;
}
// wait until AsyncListen is called before polling the socket for // client connections. return NS_OK;
NS_IMETHODIMP
nsServerSocket::Close() {
{
MutexAutoLock lock(mLock); // we want to proxy the close operation to the socket thread if a listener // has been set. otherwise, we should just close the socket here... if (!mListener) { if (mFD) {
PR_Close(mFD);
mFD = nullptr;
} return NS_OK;
}
} return PostEvent(this, &nsServerSocket::OnMsgClose);
}
namespace {
class ServerSocketListenerProxy final : public nsIServerSocketListener {
~ServerSocketListenerProxy() = default;
// Child classes may need to do additional setup just before listening begins
nsresult rv = OnSocketListen(); if (NS_WARN_IF(NS_FAILED(rv))) { return rv;
}
NS_IMETHODIMP
nsServerSocket::GetPort(int32_t* aResult) { // no need to enter the lock here
uint16_t port; if (mAddr.raw.family == PR_AF_INET) {
port = mAddr.inet.port;
} elseif (mAddr.raw.family == PR_AF_INET6) {
port = mAddr.ipv6.port;
} else { return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsServerSocket::GetAddress(PRNetAddr* aResult) { // no need to enter the lock here
memcpy(aResult, &mAddr, sizeof(mAddr)); return NS_OK;
}
} // namespace net
} // namespace mozilla
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.