1 /* 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef MainThreadWebSocketChannel_h 32 #define MainThreadWebSocketChannel_h 33 34 #include "core/fileapi/FileError.h" 35 #include "core/fileapi/FileReaderLoaderClient.h" 36 #include "core/page/ConsoleTypes.h" 37 #include "core/platform/Timer.h" 38 #include "core/platform/network/SocketStreamHandleClient.h" 39 #include "modules/websockets/WebSocketChannel.h" 40 #include "modules/websockets/WebSocketDeflateFramer.h" 41 #include "modules/websockets/WebSocketFrame.h" 42 #include "modules/websockets/WebSocketHandshake.h" 43 #include "modules/websockets/WebSocketPerMessageDeflate.h" 44 #include "wtf/Deque.h" 45 #include "wtf/Forward.h" 46 #include "wtf/PassOwnPtr.h" 47 #include "wtf/RefCounted.h" 48 #include "wtf/Vector.h" 49 #include "wtf/text/CString.h" 50 51 namespace WebCore { 52 53 class Blob; 54 class Document; 55 class FileReaderLoader; 56 class SocketStreamHandle; 57 class SocketStreamError; 58 class WebSocketChannelClient; 59 60 class MainThreadWebSocketChannel : public RefCounted<MainThreadWebSocketChannel>, public SocketStreamHandleClient, public WebSocketChannel, public FileReaderLoaderClient { 61 WTF_MAKE_FAST_ALLOCATED; 62 public: 63 // You can specify the source file and the line number information 64 // explicitly by passing the last parameter. 65 // In the usual case, they are set automatically and you don't have to 66 // pass it. 67 static PassRefPtr<MainThreadWebSocketChannel> create(Document* document, WebSocketChannelClient* client, const String& sourceURL = String(), unsigned lineNumber = 0) { return adoptRef(new MainThreadWebSocketChannel(document, client, sourceURL, lineNumber)); } 68 virtual ~MainThreadWebSocketChannel(); 69 70 bool send(const char* data, int length); 71 72 // WebSocketChannel functions. 73 virtual void connect(const KURL&, const String& protocol) OVERRIDE; 74 virtual String subprotocol() OVERRIDE; 75 virtual String extensions() OVERRIDE; 76 virtual WebSocketChannel::SendResult send(const String& message) OVERRIDE; 77 virtual WebSocketChannel::SendResult send(const ArrayBuffer&, unsigned byteOffset, unsigned byteLength) OVERRIDE; 78 virtual WebSocketChannel::SendResult send(const Blob&) OVERRIDE; 79 virtual unsigned long bufferedAmount() const OVERRIDE; 80 // Start closing handshake. Use the CloseEventCodeNotSpecified for the code 81 // argument to omit payload. 82 virtual void close(int code, const String& reason) OVERRIDE; 83 virtual void fail(const String& reason, MessageLevel, const String&, unsigned lineNumber) OVERRIDE; 84 using WebSocketChannel::fail; 85 virtual void disconnect() OVERRIDE; 86 87 virtual void suspend() OVERRIDE; 88 virtual void resume() OVERRIDE; 89 90 // SocketStreamHandleClient functions. 91 virtual void willOpenSocketStream(SocketStreamHandle*) OVERRIDE; 92 virtual void didOpenSocketStream(SocketStreamHandle*) OVERRIDE; 93 virtual void didCloseSocketStream(SocketStreamHandle*) OVERRIDE; 94 virtual void didReceiveSocketStreamData(SocketStreamHandle*, const char*, int) OVERRIDE; 95 virtual void didUpdateBufferedAmount(SocketStreamHandle*, size_t bufferedAmount) OVERRIDE; 96 virtual void didFailSocketStream(SocketStreamHandle*, const SocketStreamError&) OVERRIDE; 97 98 // FileReaderLoaderClient functions. 99 virtual void didStartLoading(); 100 virtual void didReceiveData(); 101 virtual void didFinishLoading(); 102 virtual void didFail(FileError::ErrorCode); 103 104 using RefCounted<MainThreadWebSocketChannel>::ref; 105 using RefCounted<MainThreadWebSocketChannel>::deref; 106 107 protected: 108 // WebSocketChannel functions. 109 virtual void refWebSocketChannel() OVERRIDE { ref(); } 110 virtual void derefWebSocketChannel() OVERRIDE { deref(); } 111 112 private: 113 MainThreadWebSocketChannel(Document*, WebSocketChannelClient*, const String&, unsigned); 114 115 bool appendToBuffer(const char* data, size_t len); 116 void skipBuffer(size_t len); 117 bool processBuffer(); 118 void resumeTimerFired(Timer<MainThreadWebSocketChannel>*); 119 void startClosingHandshake(int code, const String& reason); 120 void closingTimerFired(Timer<MainThreadWebSocketChannel>*); 121 122 bool processFrame(); 123 124 // It is allowed to send a Blob as a binary frame if hybi-10 protocol is in use. Sending a Blob 125 // can be delayed because it must be read asynchronously. Other types of data (String or 126 // ArrayBuffer) may also be blocked by preceding sending request of a Blob. 127 // 128 // To address this situation, messages to be sent need to be stored in a queue. Whenever a new 129 // data frame is going to be sent, it first must go to the queue. Items in the queue are processed 130 // in the order they were put into the queue. Sending request of a Blob blocks further processing 131 // until the Blob is completely read and sent to the socket stream. 132 enum QueuedFrameType { 133 QueuedFrameTypeString, 134 QueuedFrameTypeVector, 135 QueuedFrameTypeBlob 136 }; 137 struct QueuedFrame { 138 WebSocketFrame::OpCode opCode; 139 QueuedFrameType frameType; 140 // Only one of the following items is used, according to the value of frameType. 141 CString stringData; 142 Vector<char> vectorData; 143 RefPtr<Blob> blobData; 144 }; 145 void enqueueTextFrame(const CString&); 146 void enqueueRawFrame(WebSocketFrame::OpCode, const char* data, size_t dataLength); 147 void enqueueBlobFrame(WebSocketFrame::OpCode, const Blob&); 148 149 void failAsError(const String& reason) { fail(reason, ErrorMessageLevel, m_sourceURLAtConnection, m_lineNumberAtConnection); } 150 void processOutgoingFrameQueue(); 151 void abortOutgoingFrameQueue(); 152 153 enum OutgoingFrameQueueStatus { 154 // It is allowed to put a new item into the queue. 155 OutgoingFrameQueueOpen, 156 // Close frame has already been put into the queue but may not have been sent yet; 157 // m_handle->close() will be called as soon as the queue is cleared. It is not 158 // allowed to put a new item into the queue. 159 OutgoingFrameQueueClosing, 160 // Close frame has been sent or the queue was aborted. It is not allowed to put 161 // a new item to the queue. 162 OutgoingFrameQueueClosed 163 }; 164 165 // In principle, this method is called only by processOutgoingFrameQueue(). 166 // It does work necessary to build frames including Blob loading for queued 167 // data in order. Calling this method directly jumps in the process. 168 bool sendFrame(WebSocketFrame::OpCode, const char* data, size_t dataLength); 169 170 enum BlobLoaderStatus { 171 BlobLoaderNotStarted, 172 BlobLoaderStarted, 173 BlobLoaderFinished, 174 BlobLoaderFailed 175 }; 176 177 enum ChannelState { 178 ChannelIdle, 179 ChannelClosing, 180 ChannelClosed 181 }; 182 183 Document* m_document; 184 WebSocketChannelClient* m_client; 185 OwnPtr<WebSocketHandshake> m_handshake; 186 RefPtr<SocketStreamHandle> m_handle; 187 Vector<char> m_buffer; 188 189 Timer<MainThreadWebSocketChannel> m_resumeTimer; 190 bool m_suspended; 191 bool m_didFailOfClientAlreadyRun; 192 bool m_receivedClosingHandshake; 193 Timer<MainThreadWebSocketChannel> m_closingTimer; 194 ChannelState m_state; 195 bool m_shouldDiscardReceivedData; 196 unsigned long m_unhandledBufferedAmount; 197 198 unsigned long m_identifier; // m_identifier == 0 means that we could not obtain a valid identifier. 199 200 // Private members only for hybi-10 protocol. 201 bool m_hasContinuousFrame; 202 WebSocketFrame::OpCode m_continuousFrameOpCode; 203 Vector<char> m_continuousFrameData; 204 unsigned short m_closeEventCode; 205 String m_closeEventReason; 206 207 Deque<OwnPtr<QueuedFrame> > m_outgoingFrameQueue; 208 OutgoingFrameQueueStatus m_outgoingFrameQueueStatus; 209 210 // FIXME: Load two or more Blobs simultaneously for better performance. 211 OwnPtr<FileReaderLoader> m_blobLoader; 212 BlobLoaderStatus m_blobLoaderStatus; 213 214 String m_sourceURLAtConnection; 215 unsigned m_lineNumberAtConnection; 216 WebSocketPerMessageDeflate m_perMessageDeflate; 217 WebSocketDeflateFramer m_deflateFramer; 218 }; 219 220 } // namespace WebCore 221 222 #endif // MainThreadWebSocketChannel_h 223