diff --git a/Applications/Downloader/main.cpp b/Applications/Downloader/main.cpp index dcca9f086b..ef9c62ee82 100644 --- a/Applications/Downloader/main.cpp +++ b/Applications/Downloader/main.cpp @@ -19,9 +19,9 @@ int main(int argc, char** argv) return; } auto& response = static_cast(*job->response()); - printf("on_receive: code=%d\n", response.code()); - printf("payload:\n"); - printf("%s", response.payload().pointer()); + printf("%s{%p}: on_receive: code=%d\n", job->class_name(), job, response.code()); + //printf("payload:\n"); + //printf("%s", response.payload().pointer()); printf("payload was %d bytes\n", response.payload().size()); }; diff --git a/Applications/IRCClient/IRCClient.cpp b/Applications/IRCClient/IRCClient.cpp index e8cf682339..a48f5ca5ac 100644 --- a/Applications/IRCClient/IRCClient.cpp +++ b/Applications/IRCClient/IRCClient.cpp @@ -45,15 +45,8 @@ void IRCClient::set_server(const String &hostname, int port) m_port = port; } -bool IRCClient::connect() +void IRCClient::on_socket_connected() { - if (m_socket->is_connected()) - ASSERT_NOT_REACHED(); - - bool success = m_socket->connect(m_hostname, m_port); - if (!success) - return false; - m_notifier = make(m_socket->fd(), GNotifier::Read); m_notifier->on_ready_to_read = [this] (GNotifier&) { receive_from_server(); }; @@ -62,13 +55,24 @@ bool IRCClient::connect() if (on_connect) on_connect(); +} + +bool IRCClient::connect() +{ + if (m_socket->is_connected()) + ASSERT_NOT_REACHED(); + + m_socket->on_connected = [this] { on_socket_connected(); }; + bool success = m_socket->connect(m_hostname, m_port); + if (!success) + return false; return true; } void IRCClient::receive_from_server() { while (m_socket->can_read_line()) { - auto line = m_socket->read_line(4096); + auto line = m_socket->read_line(PAGE_SIZE); if (line.is_null()) { if (!m_socket->is_connected()) { printf("IRCClient: Connection closed!\n"); diff --git a/Applications/IRCClient/IRCClient.h b/Applications/IRCClient/IRCClient.h index a3173afa26..0eacbcf301 100644 --- a/Applications/IRCClient/IRCClient.h +++ b/Applications/IRCClient/IRCClient.h @@ -109,6 +109,8 @@ private: void handle(const Message&, const String& verbatim); void handle_user_command(const String&); + void on_socket_connected(); + String m_hostname; int m_port { 6667 }; diff --git a/Applications/IRCClient/Makefile b/Applications/IRCClient/Makefile index b86c193838..67c23d6ecc 100644 --- a/Applications/IRCClient/Makefile +++ b/Applications/IRCClient/Makefile @@ -12,7 +12,7 @@ OBJS = \ APP = IRCClient -STANDARD_FLAGS = -std=c++17 +STANDARD_FLAGS = -std=c++17 -Wno-sized-deallocation WARNING_FLAGS = -Wextra -Wall -Wundef -Wcast-qual -Wwrite-strings -Wimplicit-fallthrough FLAVOR_FLAGS = -fno-exceptions -fno-rtti OPTIMIZATION_FLAGS = -Os diff --git a/LibGUI/GHttpJob.cpp b/LibGUI/GHttpJob.cpp index 3c278f0971..5ca7675460 100644 --- a/LibGUI/GHttpJob.cpp +++ b/LibGUI/GHttpJob.cpp @@ -13,19 +13,14 @@ GHttpJob::~GHttpJob() { } -void GHttpJob::start() +void GHttpJob::on_socket_connected() { - ASSERT(!m_socket); - m_socket = new GTCPSocket(this); - int success = m_socket->connect(m_request.hostname(), m_request.port()); - if (!success) - return did_fail(GNetworkJob::Error::ConnectionFailed); - auto raw_request = m_request.to_raw_request(); +#if 0 + printf("raw_request:\n%s\n", String::from_byte_buffer(raw_request).characters()); +#endif - printf("raw_request:\n%s\n", raw_request.pointer()); - - success = m_socket->send(raw_request); + bool success = m_socket->send(raw_request); if (!success) return deferred_invoke([this](auto&){ did_fail(GNetworkJob::Error::TransmissionFailed); }); @@ -99,3 +94,16 @@ void GHttpJob::start() did_finish(move(response)); }); } + +void GHttpJob::start() +{ + ASSERT(!m_socket); + m_socket = new GTCPSocket(this); + m_socket->on_connected = [this] { + printf("Socket on_connected callback\n"); + on_socket_connected(); + }; + bool success = m_socket->connect(m_request.hostname(), m_request.port()); + if (!success) + return did_fail(GNetworkJob::Error::ConnectionFailed); +} diff --git a/LibGUI/GHttpJob.h b/LibGUI/GHttpJob.h index 35ea33f243..adc0d72155 100644 --- a/LibGUI/GHttpJob.h +++ b/LibGUI/GHttpJob.h @@ -16,6 +16,8 @@ public: virtual const char* class_name() const override { return "GHttpJob"; } private: + void on_socket_connected(); + enum class State { InStatus, InHeaders, diff --git a/LibGUI/GIODevice.cpp b/LibGUI/GIODevice.cpp index 1a66fb0f2a..863c0e780d 100644 --- a/LibGUI/GIODevice.cpp +++ b/LibGUI/GIODevice.cpp @@ -145,7 +145,7 @@ bool GIODevice::populate_read_buffer() { if (m_fd < 0) return false; - auto buffer = ByteBuffer::create_uninitialized(1024); + auto buffer = ByteBuffer::create_uninitialized(PAGE_SIZE); int nread = ::read(m_fd, buffer.pointer(), buffer.size()); if (nread < 0) { set_error(errno); diff --git a/LibGUI/GNotifier.h b/LibGUI/GNotifier.h index 8ea7a1d81f..6876c481f4 100644 --- a/LibGUI/GNotifier.h +++ b/LibGUI/GNotifier.h @@ -18,6 +18,7 @@ public: int fd() const { return m_fd; } unsigned event_mask() const { return m_event_mask; } + void set_event_mask(unsigned event_mask) { m_event_mask = event_mask; } private: int m_fd { -1 }; diff --git a/LibGUI/GSocket.cpp b/LibGUI/GSocket.cpp index 69662439a5..1b8cee1fec 100644 --- a/LibGUI/GSocket.cpp +++ b/LibGUI/GSocket.cpp @@ -1,9 +1,12 @@ #include +#include #include #include #include +#include #include #include +#include GSocket::GSocket(Type type, GObject* parent) : GIODevice(parent) @@ -41,17 +44,29 @@ bool GSocket::connect(const GSocketAddress& address, int port) addr.sin_family = AF_INET; addr.sin_port = htons(port); + m_destination_address = address; + m_destination_port = port; + printf("Connecting to %s...", address.to_string().characters()); fflush(stdout); int rc = ::connect(fd(), (struct sockaddr*)&addr, sizeof(addr)); if (rc < 0) { + if (errno == EINPROGRESS) { + printf("in progress.\n"); + m_notifier = make(fd(), GNotifier::Event::Write); + m_notifier->on_ready_to_write = [this] (GNotifier&) { + printf("%s{%p} connected!\n", class_name(), this); + m_connected = true; + m_notifier->set_event_mask(GNotifier::Event::None); + if (on_connected) + on_connected(); + }; + return true; + } perror("connect"); exit(1); } printf("ok!\n"); - - m_destination_address = address; - m_destination_port = port; m_connected = true; return true; } diff --git a/LibGUI/GSocket.h b/LibGUI/GSocket.h index 6b3c9eb5b1..06cf7c1da2 100644 --- a/LibGUI/GSocket.h +++ b/LibGUI/GSocket.h @@ -32,6 +32,8 @@ private: IPv4Address m_ipv4_address; }; +class GNotifier; + class GSocket : public GIODevice { public: enum class Type { Invalid, TCP, UDP }; @@ -51,6 +53,8 @@ public: GSocketAddress destination_address() const { return m_source_address; } int destination_port() const { return m_destination_port; } + Function on_connected; + virtual const char* class_name() const override { return "GSocket"; } protected: @@ -65,5 +69,5 @@ protected: private: virtual bool open(GIODevice::OpenMode) override { ASSERT_NOT_REACHED(); } Type m_type { Type::Invalid }; - + OwnPtr m_notifier; }; diff --git a/LibGUI/GTCPSocket.cpp b/LibGUI/GTCPSocket.cpp index 1194e8adf0..ad53027674 100644 --- a/LibGUI/GTCPSocket.cpp +++ b/LibGUI/GTCPSocket.cpp @@ -4,7 +4,7 @@ GTCPSocket::GTCPSocket(GObject* parent) : GSocket(GSocket::Type::TCP, parent) { - int fd = socket(AF_INET, SOCK_STREAM, 0); + int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if (fd < 0) { set_error(fd); } else {