blob: 9f1994277dbbd583c548c16eaa305a045c72347c [file] [log] [blame]
/*
* 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 <wtf/PassOwnPtr.h>
using namespace WebKit;
namespace WebCore {
class SocketStreamHandleInternal : public WebSocketStreamHandleClient {
public:
static PassOwnPtr<SocketStreamHandleInternal> 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<WebSocketStreamHandle> 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)