/* * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "SocketStreamHandle.h" #if ENABLE(WEB_SOCKETS) #include "Logging.h" #include "NotImplemented.h" #include "SocketStreamHandleClient.h" #include "WebData.h" #include "WebKit.h" #include "WebKitClient.h" #include "WebSocketStreamHandle.h" #include "WebSocketStreamHandleClient.h" #include "WebURL.h" #include using namespace WebKit; namespace WebCore { class SocketStreamHandleInternal : public WebSocketStreamHandleClient { public: static PassOwnPtr create(SocketStreamHandle* handle) { return new SocketStreamHandleInternal(handle); } virtual ~SocketStreamHandleInternal(); void connect(const KURL&); int send(const char*, int); void close(); virtual void didOpenStream(WebSocketStreamHandle*, int); virtual void didSendData(WebSocketStreamHandle*, int); virtual void didReceiveData(WebSocketStreamHandle*, const WebData&); virtual void didClose(WebSocketStreamHandle*); virtual void didFail(WebSocketStreamHandle*, const WebSocketStreamError&); private: explicit SocketStreamHandleInternal(SocketStreamHandle*); SocketStreamHandle* m_handle; OwnPtr m_socket; int m_maxPendingSendAllowed; int m_pendingAmountSent; }; SocketStreamHandleInternal::SocketStreamHandleInternal(SocketStreamHandle* handle) : m_handle(handle) , m_maxPendingSendAllowed(0) , m_pendingAmountSent(0) { } SocketStreamHandleInternal::~SocketStreamHandleInternal() { m_handle = 0; } void SocketStreamHandleInternal::connect(const KURL& url) { m_socket.set(webKitClient()->createSocketStreamHandle()); LOG(Network, "connect"); ASSERT(m_socket.get()); m_socket->connect(url, this); } int SocketStreamHandleInternal::send(const char* data, int len) { LOG(Network, "send len=%d", len); ASSERT(m_socket.get()); if (m_pendingAmountSent + len >= m_maxPendingSendAllowed) len = m_maxPendingSendAllowed - m_pendingAmountSent - 1; if (len <= 0) return len; WebData webdata(data, len); if (m_socket->send(webdata)) { m_pendingAmountSent += len; LOG(Network, "sent"); return len; } LOG(Network, "busy. buffering"); return 0; } void SocketStreamHandleInternal::close() { LOG(Network, "close"); m_socket->close(); } void SocketStreamHandleInternal::didOpenStream(WebSocketStreamHandle* socketHandle, int maxPendingSendAllowed) { LOG(Network, "SocketStreamHandleInternal::didOpen %d", maxPendingSendAllowed); ASSERT(maxPendingSendAllowed > 0); if (m_handle && m_socket.get()) { ASSERT(socketHandle == m_socket.get()); m_maxPendingSendAllowed = maxPendingSendAllowed; m_handle->m_state = SocketStreamHandleBase::Open; if (m_handle->m_client) { m_handle->m_client->didOpen(m_handle); return; } } LOG(Network, "no m_handle or m_socket?"); } void SocketStreamHandleInternal::didSendData(WebSocketStreamHandle* socketHandle, int amountSent) { LOG(Network, "SocketStreamHandleInternal::didSendData %d", amountSent); ASSERT(amountSent > 0); if (m_handle && m_socket.get()) { ASSERT(socketHandle == m_socket.get()); m_pendingAmountSent -= amountSent; ASSERT(m_pendingAmountSent >= 0); m_handle->sendPendingData(); } } void SocketStreamHandleInternal::didReceiveData(WebSocketStreamHandle* socketHandle, const WebData& data) { LOG(Network, "didReceiveData"); if (m_handle && m_socket.get()) { ASSERT(socketHandle == m_socket.get()); if (m_handle->m_client) m_handle->m_client->didReceiveData(m_handle, data.data(), data.size()); } } void SocketStreamHandleInternal::didClose(WebSocketStreamHandle* socketHandle) { LOG(Network, "didClose"); if (m_handle && m_socket.get()) { ASSERT(socketHandle == m_socket.get()); m_socket.clear(); SocketStreamHandle* h = m_handle; m_handle = 0; if (h->m_client) h->m_client->didClose(h); } } void SocketStreamHandleInternal::didFail(WebSocketStreamHandle* socketHandle, const WebSocketStreamError& err) { LOG(Network, "didFail"); if (m_handle && m_socket.get()) { ASSERT(socketHandle == m_socket.get()); m_socket.clear(); SocketStreamHandle* h = m_handle; m_handle = 0; if (h->m_client) h->m_client->didClose(h); // didFail(h, err); } } // FIXME: auth // SocketStreamHandle ---------------------------------------------------------- SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client) : SocketStreamHandleBase(url, client) { m_internal = SocketStreamHandleInternal::create(this); m_internal->connect(m_url); } SocketStreamHandle::~SocketStreamHandle() { setClient(0); m_internal.clear(); } int SocketStreamHandle::platformSend(const char* buf, int len) { if (!m_internal.get()) return 0; return m_internal->send(buf, len); } void SocketStreamHandle::platformClose() { if (m_internal.get()) m_internal->close(); } void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) { if (m_client) m_client->didReceiveAuthenticationChallenge(this, challenge); } void SocketStreamHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) { notImplemented(); } void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) { notImplemented(); } } // namespace WebCore #endif // ENABLE(WEB_SOCKETS)