Fixed some more threading issues in HTTP proxy - clarified code.
This commit is contained in:
		
							parent
							
								
									3ab6d3f47f
								
							
						
					
					
						commit
						40a99ece9a
					
				
					 1 changed files with 30 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -329,46 +329,48 @@ namespace Connector_HTTP {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    //lock the mutex for this connection, and handle the request
 | 
			
		||||
    tthread::lock_guard<tthread::mutex> guard(connectorConnections[uid]->inUse);
 | 
			
		||||
    ConnConn * myCConn = connectorConnections[uid];
 | 
			
		||||
    myCConn->inUse.lock();
 | 
			
		||||
    connMutex.unlock();
 | 
			
		||||
    //if the server connection is dead, handle as timeout.
 | 
			
		||||
    if ( !connectorConnections[uid]->conn->connected()){
 | 
			
		||||
      connectorConnections[uid]->conn->close();
 | 
			
		||||
    if ( !myCConn->conn->connected()){
 | 
			
		||||
      myCConn->conn->close();
 | 
			
		||||
      return proxyHandleTimeout(H, conn);
 | 
			
		||||
    }
 | 
			
		||||
    //forward the original request
 | 
			
		||||
    connectorConnections[uid]->conn->SendNow(request);
 | 
			
		||||
    connectorConnections[uid]->lastUse = 0;
 | 
			
		||||
    myCConn->conn->SendNow(request);
 | 
			
		||||
    myCConn->lastUse = 0;
 | 
			
		||||
    unsigned int timeout = 0;
 | 
			
		||||
    unsigned int retries = 0;
 | 
			
		||||
    //wait for a response
 | 
			
		||||
    while (connectorConnections.count(uid) && connectorConnections[uid]->conn->connected() && conn->connected()){
 | 
			
		||||
    while (myCConn->conn->connected() && conn->connected()){
 | 
			
		||||
      conn->spool();
 | 
			
		||||
      if (connectorConnections[uid]->conn->Received().size() || connectorConnections[uid]->conn->spool()){
 | 
			
		||||
      if (myCConn->conn->Received().size() || myCConn->conn->spool()){
 | 
			
		||||
        //make sure we end in a \n
 | 
			
		||||
        if ( *(connectorConnections[uid]->conn->Received().get().rbegin()) != '\n'){
 | 
			
		||||
          std::string tmp = connectorConnections[uid]->conn->Received().get();
 | 
			
		||||
          connectorConnections[uid]->conn->Received().get().clear();
 | 
			
		||||
          if (connectorConnections[uid]->conn->Received().size()){
 | 
			
		||||
            connectorConnections[uid]->conn->Received().get().insert(0, tmp);
 | 
			
		||||
        if ( *(myCConn->conn->Received().get().rbegin()) != '\n'){
 | 
			
		||||
          std::string tmp = myCConn->conn->Received().get();
 | 
			
		||||
          myCConn->conn->Received().get().clear();
 | 
			
		||||
          if (myCConn->conn->Received().size()){
 | 
			
		||||
            myCConn->conn->Received().get().insert(0, tmp);
 | 
			
		||||
          }else{
 | 
			
		||||
            connectorConnections[uid]->conn->Received().append(tmp);
 | 
			
		||||
            myCConn->conn->Received().append(tmp);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        //check if the whole response was received
 | 
			
		||||
        if (H.Read(connectorConnections[uid]->conn->Received().get())){
 | 
			
		||||
        if (H.Read(myCConn->conn->Received().get())){
 | 
			
		||||
          //208 means the fragment is too new, retry in 3s
 | 
			
		||||
          if (H.url == "208"){
 | 
			
		||||
            retries++;
 | 
			
		||||
            if (retries >= 5){
 | 
			
		||||
              std::cout << "[5 retry-laters, cancelled]" << std::endl;
 | 
			
		||||
              connectorConnections[uid]->conn->close();
 | 
			
		||||
              myCConn->conn->close();
 | 
			
		||||
              myCConn->inUse.unlock();
 | 
			
		||||
              return proxyHandleTimeout(H, conn);
 | 
			
		||||
            }
 | 
			
		||||
            connectorConnections[uid]->lastUse = 0;
 | 
			
		||||
            myCConn->lastUse = 0;
 | 
			
		||||
            timeout = 0;
 | 
			
		||||
            Util::sleep(3000);
 | 
			
		||||
            connectorConnections[uid]->conn->SendNow(request);
 | 
			
		||||
            myCConn->conn->SendNow(request);
 | 
			
		||||
            H.Clean();
 | 
			
		||||
            continue;
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -378,16 +380,18 @@ namespace Connector_HTTP {
 | 
			
		|||
        //keep trying unless the timeout triggers
 | 
			
		||||
        if (timeout++ > 4000){
 | 
			
		||||
          std::cout << "[20s timeout triggered]" << std::endl;
 | 
			
		||||
          connectorConnections[uid]->conn->close();
 | 
			
		||||
          myCConn->conn->close();
 | 
			
		||||
          myCConn->inUse.unlock();
 | 
			
		||||
          return proxyHandleTimeout(H, conn);
 | 
			
		||||
        }else{
 | 
			
		||||
          Util::sleep(5);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if ( !connectorConnections.count(uid) || !connectorConnections[uid]->conn->connected() || !conn->connected()){
 | 
			
		||||
    if ( !myCConn->conn->connected() || !conn->connected()){
 | 
			
		||||
      //failure, disconnect and sent error to user
 | 
			
		||||
      connectorConnections[uid]->conn->close();
 | 
			
		||||
      myCConn->conn->close();
 | 
			
		||||
      myCConn->inUse.unlock();
 | 
			
		||||
      return proxyHandleTimeout(H, conn);
 | 
			
		||||
    }else{
 | 
			
		||||
      long long int ret = Util::getMS();
 | 
			
		||||
| 
						 | 
				
			
			@ -397,15 +401,16 @@ namespace Connector_HTTP {
 | 
			
		|||
        H.SetHeader("X-UID", uid);
 | 
			
		||||
        H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
 | 
			
		||||
        conn->SendNow(H.BuildResponse("200", "OK"));
 | 
			
		||||
        myCConn->inUse.unlock();
 | 
			
		||||
      }else{
 | 
			
		||||
        //unknown length
 | 
			
		||||
        H.SetHeader("X-UID", uid);
 | 
			
		||||
        H.SetHeader("Server", "mistserver/" PACKAGE_VERSION "/" + Util::Config::libver);
 | 
			
		||||
        conn->SendNow(H.BuildResponse("200", "OK"));
 | 
			
		||||
        //switch out the connection for an empty one - it makes no sense to keep these globally
 | 
			
		||||
        Socket::Connection * myConn = connectorConnections[uid]->conn;
 | 
			
		||||
        connectorConnections[uid]->conn = new Socket::Connection();
 | 
			
		||||
        connectorConnections[uid]->inUse.unlock();
 | 
			
		||||
        Socket::Connection * myConn = myCConn->conn;
 | 
			
		||||
        myCConn->conn = new Socket::Connection();
 | 
			
		||||
        myCConn->inUse.unlock();
 | 
			
		||||
        //continue sending data from this socket and keep it permanently in use
 | 
			
		||||
        while (myConn->connected() && conn->connected()){
 | 
			
		||||
          if (myConn->Received().size() || myConn->spool()){
 | 
			
		||||
| 
						 | 
				
			
			@ -555,10 +560,9 @@ int main(int argc, char ** argv){
 | 
			
		|||
    Socket::Connection S = server_socket.accept();
 | 
			
		||||
    if (S.connected()){ //check if the new connection is valid
 | 
			
		||||
      //spawn a new thread for this connection
 | 
			
		||||
      tthread::thread * T = new tthread::thread(Connector_HTTP::proxyHandleHTTPConnection, (void *)(new Socket::Connection(S)));
 | 
			
		||||
      tthread::thread T(Connector_HTTP::proxyHandleHTTPConnection, (void *)(new Socket::Connection(S)));
 | 
			
		||||
      //detach it, no need to keep track of it anymore
 | 
			
		||||
      T->detach();
 | 
			
		||||
      delete T;
 | 
			
		||||
      T.detach();
 | 
			
		||||
    }else{
 | 
			
		||||
      Util::sleep(10); //sleep 10ms
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue