int HttpClient::sendRequest(int times, HttpStat& stat, StringBuffer& req) { StringBuffer request; if(req.length() <= 2) { throw MakeStringException(-1, "request too short"); } bool endofheaders = false; char c0 = req.charAt(0); char c1 = req.charAt(1); if(c0 == '\n') request.append("\r\n"); else request.append(c0); if(c1 == '\n') { if(c0 == '\r') request.append(c1); else { request.append("\r\n"); if(c0 == '\n') endofheaders = true; } } else request.append(c1); unsigned seq = 2; while(seq < req.length() && !endofheaders) { char c = req.charAt(seq); if(c == '\n') { char c1 = req.charAt(seq - 1); char c2 = req.charAt(seq - 2); if(c1 == '\n' || (c1 == '\r' && c2 == '\n')) endofheaders = true; if(c1 != '\r') request.append("\r\n"); else request.append(c); } else request.append(c); seq++; } if(seq < req.length()) request.append(req.length() - seq, req.str() + seq); if(httptest_tracelevel > 5) fprintf(m_ofile, ">>sending out request to %s:%d for %d times\n", m_host.str(), m_port, times); unsigned start = msTick(); int slowest = 0; int fastest = 2147483647; for(int i = 0; i < times; i++) { SocketEndpoint ep; ep.set(m_host.str(), m_port); Owned<ISocket> socket; try { socket.setown(ISocket::connect(ep)); if(m_use_ssl && m_ssctx.get() != NULL) { Owned<ISecureSocket> securesocket = m_ssctx->createSecureSocket(socket.getLink()); int res = securesocket->secure_connect(); if(res >= 0) { socket.set(securesocket.get()); } } } catch(IException *excpt) { StringBuffer errMsg; DBGLOG("Error connecting to %s:%d - %d:%s", m_host.str(), m_port, excpt->errorCode(), excpt->errorMessage(errMsg).str()); continue; } catch(...) { DBGLOG("can't connect to %s:%d", m_host.str(), m_port); continue; } if(socket.get() == NULL) { StringBuffer urlstr; DBGLOG(">>Can't connect to %s", ep.getUrlStr(urlstr).str()); continue; } if(m_delay > 0) sleep(m_delay); if(httptest_tracelevel > 5) fprintf(m_ofile, ">>sending out request:\n"); if(httptest_tracelevel > 10) fprintf(m_ofile, "%s%s%s\n", sepstr, request.str(), sepstr); unsigned start1 = msTick(); socket->write(request.str(), request.length()); if(httptest_tracelevel > 5) fprintf(m_ofile, ">>receiving response:\n"); StringBuffer buf; Owned<IByteOutputStream> ostream = createOutputStream(buf); stat.totalresplen += receiveData(socket.get(), ostream.get(), true); if(httptest_tracelevel > 10) fprintf(m_ofile, "%s%s%s\n", sepstr, buf.str(), sepstr); char tmpbuf[256]; unsigned int sizeread; do { socket->read(tmpbuf, 0, 256, sizeread); } while(sizeread > 0); socket->shutdown(); socket->close(); fflush(m_ofile); unsigned end1 = msTick(); int duration = end1 - start1; if(duration <= fastest) fastest = duration; if(duration > slowest) slowest = duration; if(i % 100 == 0) fprintf(stderr, "sent out %d\n", i); } unsigned end = msTick(); stat.msecs = end - start; stat.numrequests = times; stat.totalreqlen = times * request.length(); stat.slowest = slowest; stat.fastest = fastest; return 0; }
virtual int run() { Thread::Link(); int ret = 0; try { char peername[256]; int clientport = m_client->peer_name(peername, 256); char inbuf[1024]; char outbuf[1024]; memset(inbuf, 0, 1024); memset(outbuf, 0, 1024); unsigned int len = 0; unsigned int lenread = 0; m_client->read(inbuf, 8, 8, lenread); if(lenread != 8) { DBGLOG("didn't get the first 8 bytes, invalid socks request."); return -1; } len += lenread; m_client->read(inbuf + len, 0, 1, lenread); StringBuffer username; while(lenread > 0) { len += lenread; if(len >= 1023) { len = 0; } if(inbuf[len - 1] == '\0') { break; } char c = inbuf[len - 1]; username.append(c); m_client->read(inbuf + len, 0, 1, lenread); } if(http_tracelevel >= 5) fprintf(m_ofile, "\n>>receivd SOCKS request from %s:%d, user %s\n", peername, clientport, username.str()); outbuf[0] = '\0'; outbuf[1] = (char)0x5a; m_client->write(outbuf, 8); char ubyte = inbuf[2]; char lbyte = inbuf[3]; unsigned short port = (unsigned short)ubyte; port = port << 8; port += lbyte; // TBD IPV6 (should use serialize/deserialize) IpAddress ip; ip.setNetAddress(4,inbuf+4); StringBuffer ipstr; ip.getIpText(ipstr); if(http_tracelevel >= 5) fprintf(m_ofile, "\n>>The request is for %s:%d\n", ipstr.str(), port); SocketEndpoint ep; ep.set(port, ip); m_remotesocket.setown(ISocket::connect(ep)); m_client->set_nonblock(false); m_remotesocket->set_nonblock(false); CReadWriteThread t1(m_client.get(), m_remotesocket.get(), m_ofile); CReadWriteThread t2(m_remotesocket.get(), m_client.get(), m_ofile); t1.start(); t2.start(); t1.join(); t2.join(); m_remotesocket->shutdown(); m_remotesocket->close(); m_client->shutdown(); m_client->close(); } catch(IException *excpt) { StringBuffer errMsg; DBGLOG("%s", excpt->errorMessage(errMsg).str()); ret = -1; } catch(...) { DBGLOG("unknown exception"); ret = -1; } Thread::Release(); return 0; }
bool CHttpProtocol::notifySelected(ISocket *sock,unsigned selected, IPersistentHandler* persistentHandler, bool shouldClose) { try { char name[256]; int port = sock->name(name, 255); CEspApplicationPort *apport = queryApplicationPort(port); if(apport == NULL) throw MakeStringException(-1, "binding not found!"); if(apport != NULL) { Owned<ISocket> accepted; if (persistentHandler == nullptr) accepted.setown(sock->accept()); else accepted.set(sock); if (accepted.get() != NULL) { char peername[256]; int port = accepted->peer_name(peername, 256); #if defined(_DEBUG) DBGLOG("HTTP connection from %s:%d on %s socket", peername, port, persistentHandler?"persistent":"new"); #endif if(m_maxConcurrentThreads > 0) { // Using Threading pool instead of generating one thread per request. void ** holder = new void*[7]; holder[0] = (void*)(accepted.getLink()); holder[1] = (void*)apport; int maxEntityLength = getMaxRequestEntityLength(); holder[2] = (void*)&maxEntityLength; bool useSSL = false; holder[3] = (void*)&useSSL; ISecureSocketContext* ctx = NULL; holder[4] = (void*)ctx; holder[5] = (void*)persistentHandler; holder[6] = (void*)&shouldClose; try { http_thread_pool->start((void*)holder, "", m_threadCreateTimeout > 0?m_threadCreateTimeout*1000:0); } catch(...) { IERRLOG("Error starting thread from http thread pool."); if(accepted.get()) { accepted->close(); //Assumption here is that if start() throws exception, that means the new //thread hasn't been started, so there's no other thread holding a link. CInterface* ci = dynamic_cast<CInterface*>(accepted.get()); if(ci && ci->IsShared()) accepted->Release(); } delete [] holder; throw; } delete [] holder; } else { /* create one thread per request */ CHttpThread *workthread = new CHttpThread(accepted.getLink(), apport, CEspProtocol::getViewConfig(), false, nullptr, persistentHandler); workthread->setMaxRequestEntityLength(getMaxRequestEntityLength()); workthread->setShouldClose(shouldClose); workthread->start(); workthread->Release(); } } } else { throw MakeStringException(-1, "can't acquire bindings IEspHttpBinding interface (via dynamic_cast)!"); } } catch (IException *e) { StringBuffer estr; IERRLOG("Exception(%d, %s) in CHttpProtocol::notifySelected()", e->errorCode(), e->errorMessage(estr).str()); e->Release(); } catch(...) { IERRLOG("Unknown Exception in CHttpProtocol::notifySelected()"); } return false; }