void SSLAdapter::flush() { //TraceL << "Flushing" << endl; if (!initialized()) { int r = SSL_connect(_ssl); if (r < 0) { TraceL << "Flush: Handle error" << endl; handleError(r); } return; } // Read any decrypted SSL data from the read BIO // NOTE: Overwriting the socket's raw SSL recv buffer int nread = 0; while ((nread = SSL_read(_ssl, _socket->_buffer.data(), _socket->_buffer.capacity())) > 0) { //_socket->_buffer.limit(nread); _socket->onRecv(mutableBuffer(_socket->_buffer.data(), nread)); } // Flush any pending outgoing data if (SSL_is_init_finished(_ssl)) { if (_bufferOut.size() > 0) { int r = SSL_write(_ssl, &_bufferOut[0], _bufferOut.size()); // causes the write_bio to fill up (which we need to flush) if (r < 0) { handleError(r); } _bufferOut.clear(); flushWriteBIO(); } } }
void ConnectionAdapter::onParserChunk(const char* buf, std::size_t len) { TraceS(this) << "On parser chunk: " << len << endl; // Dispatch the payload net::SocketAdapter::onSocketRecv(mutableBuffer(const_cast<char*>(buf), len), _connection.socket()->peerAddress()); }
void TCPSocket::onRead(const char* data, std::size_t len) { TraceLS(this) << "On read: " << len << endl; // Note: The const_cast here is relatively safe since the given // data pointer is the underlying _buffer.data() pointer, but // a better way should be devised. onRecv(mutableBuffer(const_cast<char*>(data), len)); }
void SSLAdapter::flushReadBIO() { int npending = BIO_ctrl_pending(_readBIO); if (npending > 0) { int nread; char buffer[MAX_TCP_PACKET_SIZE]; // TODO: allocate npending bytes while ((nread = SSL_read(_ssl, buffer, MAX_TCP_PACKET_SIZE)) > 0) { _socket->onRecv(mutableBuffer(buffer, nread)); } } }
void UDPSocket::onRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned /* flags */) { auto socket = static_cast<UDPSocket*>(handle->data); TraceL << "On recv: " << nread << endl; if (nread < 0) { //assert(0 && "unexpected error"); TraceL << "Recv error: " << uv_err_name(nread)<< endl; socket->setUVError("UDP error", nread); return; } if (nread == 0) { assert(addr == NULL); // Returning unused buffer, this is not an error // 11/12/13: This happens on linux but not windows //socket->setUVError("End of file", UV_EOF); return; } socket->onRecv(mutableBuffer(buf->base, nread), net::Address(addr, sizeof(*addr))); }
void WebSocketAdapter::onSocketRecv(const MutableBuffer& buffer, const net::Address& peerAddress) { TraceLS(this) << "On recv: " << buffer.size() << endl; // << ": " << buffer //assert(buffer.position() == 0); if (framer.handshakeComplete()) { // Note: The spec wants us to buffer partial frames, but our // software does not require this feature, and furthermore // it goes against our nocopy where possible policy. // This may need to change in the future, but for now // we just parse and emit packets as they arrive. // // Incoming frames may be joined, so we parse them // in a loop until the read buffer is empty. BitReader reader(buffer); int total = reader.available(); int offset = reader.position(); while (offset < total) { char* payload = nullptr; UInt64 payloadLength = 0; try { // Restore buffer state for next read //reader.position(offset); //reader.limit(total); #if 0 TraceLS(this) << "Read frame at: " << "\n\tinputPosition: " << offset << "\n\tinputLength: " << total << "\n\tbufferPosition: " << reader.position() << "\n\tbufferAvailable: " << reader.available() << "\n\tbufferLimit: " << reader.limit() << "\n\tbuffer: " << std::string(reader.current(), reader.limit()) << endl; #endif // Parse a frame to throw //int payloadLength = framer.readFrame(reader); payloadLength = framer.readFrame(reader, payload); assert(payload); // Update the next frame offset offset = reader.position(); // + payloadLength; if (offset < total) DebugLS(this) << "Splitting joined packet at " << offset << " of " << total << endl; // Drop empty packets if (!payloadLength) { DebugLS(this) << "Dropping empty frame" << endl; continue; } } catch (std::exception& exc) { WarnL << "Parser error: " << exc.what() << endl; socket->setError(exc.what()); return; } // Emit the result packet assert(payload); assert(payloadLength); SocketAdapter::onSocketRecv(mutableBuffer(payload, (std::size_t)payloadLength), peerAddress); } assert(offset == total); } else { try { if (framer.mode() == ws::ClientSide) handleClientResponse(buffer); else handleServerRequest(buffer); } catch (std::exception& exc) { WarnL << "Read error: " << exc.what() << endl; socket->setError(exc.what()); } return; } }