void FetchClientPrivate::write_ready() { if (m_postSize == 0) return; char buff[4096]; unsigned tail = m_postSize; if (tail > sizeof(buff)) tail = sizeof(buff); const char *data = m_client->read_data(buff, tail); if (data == NULL){ m_socket->error_state("Read error"); return; } m_postSize -= tail; m_socket->writeBuffer.pack(data, tail); m_socket->write(); if (m_speed){ m_sendSize += tail; time_t now; time(&now); if ((unsigned)now != m_sendTime){ m_sendTime = now; m_sendSize = 0; } if (m_sendSize > (m_speed << 18)){ m_socket->pause(1); return; } } }
void FetchClientPrivate::packet_ready() { if (m_socket->readBuffer.readPos() == m_socket->readBuffer.writePos()) return; for (;;){ if (m_state == Data){ unsigned size = m_socket->readBuffer.writePos() - m_socket->readBuffer.readPos(); if (size){ if (!m_client->write_data(m_socket->readBuffer.data(m_socket->readBuffer.readPos()), size)){ m_socket->error_state("Write error"); return; } } m_received += size; if (m_received >= m_size){ m_state = Done; m_socket->error_state(""); return; } m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); return; } log_packet(m_socket->readBuffer, false, HTTPPacket); string line; string opt; if (!read_line(line)){ m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); return; } switch (m_state){ case None: #ifdef USE_OPENSSL case SSLConnect: #endif if (getToken(line, ' ').substr(0, 5) != "HTTP/"){ m_socket->error_state("Bad HTTP answer"); return; } m_code = atol(getToken(line, ' ').c_str()); m_state = Header; break; case Header: if (line.empty()){ m_state = Data; break; } m_hIn += line; m_hIn += '\x00'; opt = getToken(line, ':'); if (opt == "Content-Length"){ const char *p; for (p = line.c_str(); *p; p++) if (*p != ' ') break; m_size = atol(p); } if ((opt == "Location") && m_bRedirect){ const char *p; for (p = line.c_str(); *p; p++) if (*p != ' ') break; string proto; string host; string user; string pass; string uri; string extra; unsigned short port; if (!FetchClient::crackUrl(p, proto, host, port, user, pass, uri, extra)){ FetchClient::crackUrl(m_uri.c_str(), proto, host, port, user, pass, uri, extra); extra = ""; if (*p == '/'){ uri = p; }else{ int n = uri.find_last_of('/'); uri = uri.substr(0, n + 1); uri += p; } } m_uri = proto; m_uri += "://"; m_uri += host; m_uri += ":"; m_uri += number(port); m_uri += uri; if (!extra.empty()){ m_uri += "?"; m_uri += extra; } m_state = Redirect; m_socket->close(); m_socket->error_state(""); return; } break; default: break; } } }
void FetchClientPrivate::connect_ready() { #ifdef USE_OPENSSL if ((m_state == None) & m_bHTTPS){ m_socket->setRaw(true); m_socket->readBuffer.init(0); HTTPSClient *https = new HTTPSClient(m_socket->socket()); if (!https->init()){ m_socket->error_state("Can't initialize HTTPS"); return; } m_state = SSLConnect; m_socket->setSocket(https); https->connect(); https->process(); return; } #endif log(L_DEBUG, "HTTP connect ready"); m_socket->setRaw(true); m_socket->writeBuffer.packetStart(); string proto; string host; string user; string pass; string uri; string extra; unsigned short port; FetchClient::crackUrl(m_uri.c_str(), proto, host, port, user, pass, uri, extra); if (!extra.empty()){ uri += "?"; uri += extra; } unsigned postSize = m_client->post_size(); m_socket->writeBuffer << ((postSize != NO_POSTSIZE) ? "POST " : "GET ") << uri.c_str() << " HTTP/1.0\r\n"; if (!findHeader("Host")) m_socket->writeBuffer << "Host: " << host.c_str() << "\r\n"; if (!findHeader("User-Agent")) m_socket->writeBuffer << "User-Agent: " << FetchManager::manager->user_agent.c_str() << "\r\n"; if (!findHeader("Authorization") && !user.empty()) m_socket->writeBuffer << "Authorization: basic " << basic_auth(user.c_str(), pass.c_str()).c_str() << "\r\n"; if (postSize != NO_POSTSIZE){ if (!findHeader("Content-Length")) m_socket->writeBuffer << "Content-Length: " << number(postSize).c_str() << "\r\n"; m_postSize = postSize; } for (HEADERS_MAP::iterator it = m_hOut.begin(); it != m_hOut.end(); ++it){ m_socket->writeBuffer << (*it).first.c_str() << ": " << (*it).second.c_str() << "\r\n"; } m_socket->writeBuffer << "\r\n"; log_packet(m_socket->writeBuffer, true, HTTPPacket); m_socket->write(); m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); }
void FetchClientPrivate::_fetch(const char *headers, Buffer *postData, bool bRedirect) { stop(); m_bDone = false; m_data.init(0); m_data.packetStart(); m_postData = postData; m_bRedirect = bRedirect; m_postSize = 0; m_sendTime = 0; m_sendSize = 0; #ifdef WIN32 m_thread = NULL; #endif if (headers){ string head = headers; while (!head.empty()){ string header = getToken(head, '\n'); string key = getToken(header, ':'); unsigned n; for (n = 0; n < header.length(); n++) if (header[n] != ' ') break; header = header.substr(n); addHeader(key.c_str(), header.c_str()); } } #ifdef WIN32 m_errCode = 0; if (hInet){ m_state = Data; m_thread = new FetchThread(this); m_thread->start(); return; } #endif m_received = 0; m_socket = new ClientSocket(this); #ifdef USE_OPENSSL m_bHTTPS = false; #endif string proto; string host; string user; string pass; string uri; string extra; unsigned short port; if (!FetchClient::crackUrl(m_uri.c_str(), proto, host, port, user, pass, uri, extra)){ m_socket->error_state("Bad URL"); return; } if (proto != "http"){ #ifdef USE_OPENSSL if (proto == "https"){ m_bHTTPS = true; }else{ #endif log(L_WARN, "Unsupported protocol %s", m_uri.c_str()); return; #ifdef USE_OPENSSL } #endif } log(L_DEBUG, "Start connect %s:%u", host.c_str(), port); m_socket->connect(host.c_str(), port, (TCPClient*)(-1)); }