void TCPConnectionPair::onPeerDataReceived(net::Socket&, const MutableBuffer& buffer, const net::Address& peerAddress) { TraceS(this) << "Peer => Client: " << buffer.size() << endl; // assert(pkt.buffer.position() == 0); // if (pkt.buffer.available() < 300) // TraceS(this) << "Peer => Client: " << pkt.buffer << endl; // auto socket = reinterpret_cast<net::Socket*>(sender); // char* buf = bufferCast<char*>(buf); // Buffer& buf = pkt.buffer; const char* buf = bufferCast<const char*>(buffer); std::size_t len = buffer.size(); if (client) { allocation.updateUsage(len); if (allocation.deleted()) return; // assert(buf.position() == 0); client->send(buf, len); } // Flash policy requests // TODO: Handle elsewhere? Bloody flash... else if (len == 23 && (strcmp(buf, "<policy-file-request/>") == 0)) { TraceS(this) << "Handle flash policy" << endl; std::string policy( "<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from " "domain=\"*\" to-ports=\"*\" /></cross-domain-policy>"); // assert(peer->get() == pkt.info->socket); peer->send(policy.c_str(), policy.length() + 1); peer->close(); } // Buffer early media // TODO: Make buffer size server option else { std::size_t maxSize = allocation.server().options().earlyMediaBufferSize; DebugS(this) << "Buffering early data: " << len << endl; //#ifdef _DEBUG // DebugS(this) << "Printing early data: " << std::string(buf, // len) << endl; //#endif if (len > maxSize) WarnL << "Dropping early media: Oversize packet: " << len << endl; if (earlyPeerData.size() > maxSize) WarnL << "Dropping early media: Buffer at capacity >= " << maxSize << endl; // earlyPeerData.append(static_cast<const char*>(pkt.data()), len); earlyPeerData.insert(earlyPeerData.end(), buf, buf + len); } }
void Server::onSocketRecv(void* sender, const MutableBuffer& buffer, const net::Address& peerAddress) { TraceL << "Data received: " << buffer.size() << endl; //auto info = reinterpret_cast<net::PacketInfo*>(packet.info); //assert(info); //if (!info) // return; const net::TCPSocket::Ptr& socket stun::Message message; auto socket = reinterpret_cast<net::Socket*>(sender); char* buf = bufferCast<char*>(buffer); std::size_t len = buffer.size(); std::size_t nread = 0; while (len > 0 && (nread = message.read(constBuffer(buf, len))) > 0) { if (message.classType() == stun::Message::Request || message.classType() == stun::Message::Indication) { Request request(message, socket->transport(), socket->address(), peerAddress); //getTCPSocket(socket->address()), //if (!request.socket) { // assert(0 && "invalid socket"); // continue; //} // TODO: Only authenticate stun::Message::Request types handleRequest(request, _observer.authenticateRequest(this, request)); } else { assert(0 && "unknown request type"); } buf += nread; len -= nread; } if (len == buffer.size()) WarnL << "Non STUN packet received" << std::endl; #if 0 stun::Message message; if (message.read(constBuffer(packet.data(), packet.size()))) { assert(message.state() == stun::Message::Request); Request request(*info->socket, message, info->socket->address(), info->peerAddress); AuthenticationState state = _observer.authenticateRequest(this, request); handleRequest(request, state); } else #endif } void Server::onTCPSocketClosed(void* sender) { TraceL << "TCP socket closed" << endl; releaseTCPSocket(reinterpret_cast<net::Socket*>(sender)); }
void TCPConnectionPair::onClientDataReceived(void*, const MutableBuffer& buffer, const net::Address& peerAddress) { TraceLS(this) << "Client => Peer: " << buffer.size() << endl; //assert(packet.buffer.position() == 0); //if (packet.size() < 300) // TraceLS(this) << "Client => Peer: " << packet.buffer << endl; if (peer) { allocation.updateUsage(buffer.size()); if (allocation.deleted()) return; peer->send(bufferCast<char*>(buffer), buffer.size()); } }
void WebSocketAdapter::handleServerRequest(const MutableBuffer& buffer) { //http::Request request; http::Parser parser(&_request); if (parser.parse(bufferCast<char *>(buffer), buffer.size())) { throw std::runtime_error("WebSocket error: Cannot parse request: Incomplete HTTP message"); } TraceLS(this) << "Verifying handshake: " << _request << endl; // Allow the application to verify the incoming request. // TODO: Handle authentication //VerifyServerRequest.emit(this, request); // Verify the WebSocket handshake request try { framer.acceptRequest(_request, _response); TraceLS(this) << "Handshake success" << endl; } catch (std::exception& exc) { WarnL << "Handshake failed: " << exc.what() << endl; } // Allow the application to override the response //PrepareServerResponse.emit(this, response); // Send response std::ostringstream oss; _response.write(oss); assert(socket); /*socket->*/SocketAdapter::send(oss.str().c_str(), oss.str().length()); }
void UDPAllocation::onPeerDataReceived(void*, const MutableBuffer& buffer, const net::Address& peerAddress) { //auto source = reinterpret_cast<net::PacketInfo*>(packet.info); TraceL << "Received UDP Datagram from " << peerAddress << endl; if (!hasPermission(peerAddress.host())) { TraceL << "No Permission: " << peerAddress.host() << endl; return; } updateUsage(buffer.size()); // Check that we have not exceeded out lifetime and bandwidth quota. if (IAllocation::deleted()) return; stun::Message message(stun::Message::Indication, stun::Message::DataIndication); // Try to use the externalIP value for the XorPeerAddress // attribute to overcome proxy and NAT issues. std::string peerHost(server().options().externalIP); if (peerHost.empty()) { peerHost.assign(peerAddress.host()); assert(0 && "external IP not set"); } auto peerAttr = new stun::XorPeerAddress; peerAttr->setAddress(net::Address(peerHost, peerAddress.port())); message.add(peerAttr); auto dataAttr = new stun::Data; dataAttr->copyBytes(bufferCast<const char*>(buffer), buffer.size()); message.add(dataAttr); //Mutex::ScopedLock lock(_mutex); TraceL << "Send data indication:" << "\n\tFrom: " << peerAddress << "\n\tTo: " << _tuple.remote() //<< "\n\tData: " << std::string(packet.data(), packet.size()) << endl; server().udpSocket().sendPacket(message, _tuple.remote()); //net::Address tempAddress("58.7.41.244", _tuple.remote().port()); //server().udpSocket().send(message, tempAddress); }
void Server::onSocketRecv(net::Socket& socket, const MutableBuffer& buffer, const net::Address& peerAddress) { TraceL << "Data received: " << buffer.size() << endl; stun::Message message; char* buf = bufferCast<char*>(buffer); std::size_t len = buffer.size(); std::size_t nread = 0; while (len > 0 && (nread = message.read(constBuffer(buf, len))) > 0) { if (message.classType() == stun::Message::Request || message.classType() == stun::Message::Indication) { Request request(message, socket.transport(), socket.address(), peerAddress); // TODO: Only authenticate stun::Message::Request types handleRequest(request, _observer.authenticateRequest(this, request)); } else { assert(0 && "unknown request type"); } buf += nread; len -= nread; } if (len == buffer.size()) WarnL << "Non STUN packet received" << std::endl; #if 0 stun::Message message; if (message.read(constBuffer(packet.data(), packet.size()))) { assert(message.state() == stun::Message::Request); Request request(*info->socket, message, info->socket->address(), info->peerAddress); AuthenticationState state = _observer.authenticateRequest(this, request); handleRequest(request, state); } else #endif } void Server::onTCPSocketClosed(net::Socket& socket) { TraceL << "TCP socket closed" << endl; releaseTCPSocket(&socket); }
void WebSocketAdapter::handleClientResponse(const MutableBuffer& buffer) { TraceLS(this) << "Client response: " << buffer.size() << endl; http::Parser parser(&_response); if (!parser.parse(bufferCast<char *>(buffer), buffer.size())) { throw std::runtime_error("WebSocket error: Cannot parse response: Incomplete HTTP message"); } // TODO: Handle resending request for authentication // Should we implement some king of callback for this? // Parse and check the response if (framer.checkHandshakeResponse(_response)) { TraceLS(this) << "Handshake success" << endl; SocketAdapter::onSocketConnect(); } }
void ConnectionAdapter::onSocketRecv(const MutableBuffer& buf, const net::Address& /* peerAddr */) { TraceS(this) << "On socket recv: " << buf.size() << endl; // TraceS(this) << "On socket recv: " << buf.str() << endl; if (_parser.complete()) { // Buggy HTTP servers might send late data or multiple responses, // in which case the parser state might already be HPE_OK. // In this case we discard the late message and log the error here, // rather than complicate the app with this error handling logic. // This issue was noted using Webrick with Ruby 1.9. WarnS(this) << "Dropping late HTTP response: " << buf.str() << endl; return; } // Parse incoming HTTP messages _parser.parse(bufferCast<const char*>(buf), buf.size()); }
void TCPClient::onRelayDataReceived(void* sender, const MutableBuffer& buffer, const net::Address& peerAddress) { auto ptr = reinterpret_cast<net::Socket*>(sender); auto req = reinterpret_cast<RelayConnectionBinding*>(ptr->opaque); assert(connections().has(req->peerAddress)); //TraceL << "Relay Data Received: " << peerAddress << ": " << req->peerAddress << endl; //assert(req->peerAddress == peerAddress); _observer.onRelayDataReceived(*this, bufferCast<const char*>(buffer), buffer.size(), req->peerAddress); }
void ClientConnection::onPayload(const MutableBuffer& buffer) { TraceS(this) << "On payload: " << buffer.size() << endl; // Update download progress IncomingProgress.update(buffer.size()); if (Incoming.numAdapters() > 0 || Incoming.emitter.ndelegates() > 0) { // if (!Incoming.active()); // throw std::runtime_error("startInputStream() must be called"); Incoming.write(bufferCast<const char*>(buffer), buffer.size()); } // if (_readStream) { // TraceS(this) << "Writing to stream: " << buffer.size() << endl; // _readStream->write(bufferCast<const char*>(buffer), buffer.size()); // _readStream->flush(); // } Payload.emit(this, buffer); }
void Connection::onSocketRecv(const MutableBuffer& buffer, const net::Address& peerAddress) { TraceS(this) << "On socket recv" << endl; //_timeout.stop(); if (Incoming.emitter.ndelegates()) { //RawPacket p(packet.data(), packet.size()); //Incoming.write(p); Incoming.write(bufferCast<const char*>(buffer), buffer.size()); } // Handle payload data onPayload(buffer); //mutableBuffer(bufferCast<const char*>(buf) }
void ClientConnection::onPayload(const MutableBuffer& buffer) { // LTrace("On payload: ", buffer.size()) //// Update download progress //IncomingProgress.update(buffer.size()); //// Write to the incoming packet stream if adapters are attached //if (Incoming.numAdapters() > 0 || Incoming.emitter.nslots() > 0) { // // if (!Incoming.active()); // // throw std::runtime_error("startInputStream() must be called"); // Incoming.write(bufferCast<const char*>(buffer), buffer.size()); //} // Write to the STL read stream if available if (_readStream) { // LTrace("Writing to stream: ", buffer.size()) _readStream->write(bufferCast<const char*>(buffer), buffer.size()); _readStream->flush(); } Payload.emit(buffer); }
void TCPSocket::onRecv(const MutableBuffer& buf) { TraceLS(this) << "Recv: " << buf.size() << endl; onSocketRecv(buf, peerAddress()); }
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; } }
void UDPSocket::onRecv(const MutableBuffer& buf, const net::Address& address) { TraceS(this) << "Recv: " << buf.size() << endl; //emitRecv(buf, address); onSocketRecv(buf, address); }