2016-03-28 8 views
0

私がやっていることは、HTTP(S)接続を処理するフォークプロキシです:GET(SSLなし)リクエストが正常に実行され、コンテンツがクライアントリモートサーバへのconnect()の送信はすぐには成功しないかもしれないので、実際には成功しません。HTTPSプロキシが正常に接続を管理しない

リモートサーバーに接続された非ブロッキングソケットを試しましたので、connect()がすぐに実行されるか、または時間がかかります:select()リモートサーバーがいつ送信する準備ができているかを確認します私にデータ:まだ、connect()は決して接続しません。

ここに私のプロキシmain()コードです:

ClientManager::ClientManager() { 
    sockfd_client = -1; // socket connected to client 
    new_sockfd_client = -1; // socket accepting connection from client 
    sockfd_server = -1; // socket connected to remote server 
} 

// error controls omitted 
bool ClientManager::startListeningForClient(int port) { 
    struct sockaddr_in serv_addr; 
    bzero((char*)&serv_addr,sizeof(serv_addr)); 

    serv_addr.sin_family=AF_INET; 
    serv_addr.sin_port=htons(port); 
    serv_addr.sin_addr.s_addr=INADDR_ANY; 

    sockfd_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    bind(sockfd_client,(struct sockaddr*)&serv_addr, sizeof(serv_addr)); 
    listen(sockfd_client, 50); 
    return true; 
} 

// error controls omitted 
int ClientManager::acceptConnectionFromClient(void) { 
    struct sockaddr_in cli_addr; 
    unsigned int clilen; 
    bzero((char*)&cli_addr, sizeof(cli_addr)); 
    clilen = sizeof(cli_addr); 
    new_sockfd_client = accept(sockfd_client, (struct sockaddr*)&cli_addr, &clilen); 
    return new_sockfd_client; 
} 

int ClientManager::forkAndManageClient() { 
    // getRequestFromClient: the method below receives requests from 
    // clients and parses the infos I need (i.e. what method, 
    // hostname of remote server to be resolved, its port, ...) 
    getRequestFromClient(); 
    // managing the HTTP(S) request by the child process 
    int pid = fork(); 
    if (pid < 0) { 
     perror("ERROR on fork"); 
    } 
    else if (pid > 0) { 
     // parent process 
     // do nothing 
    } 
    else { 
     // close immediately the client socket used for accepting new connections from the parent process 
     close (sockfd_client); 
     if (!manageRequest()) { 
      perror("Error managing request from client"); 
     } 
     // close the connection from the client 
     close (new_sockfd_client); 
     new_sockfd_client = -1; 
     // the child process will terminate now 
     _exit(EXIT_SUCCESS); 
    } 
    return pid; 
} 

// now the problematic method... 
bool ClientManager::manageRequest(void) { 
    // if this is a CONNECT request 
    if (rm.isCONNECT()) { 
     struct sockaddr_in remote_server; 
     int conn_res; 
     remote_server.sin_family = AF_INET; 
     remote_server.sin_addr.s_addr = rm.getServerAddr(); 
     remote_server.sin_port = rm.getServerPort(); 
     fd_set fdset; 
     struct timeval tv; 

     sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
     // make socket not blocking 
     int flags = fcntl(sockfd_server, F_GETFL, 0); 
     flags = flags | O_NONBLOCK; 
     if (fcntl(sockfd_server, F_SETFL, flags) == -1) { 
      perror("FCNTL:"); 
     } 
     printf("CONNECT set socket to non-blocking mode\n"); 

     conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in)); 

     printf("AFTER CONNECT()\n"); 
     if (conn_res < 0) { 
      if (errno != EINPROGRESS) { 
       printf("CONNECT: connect() failed, quitting\n"); 
       return false; 
      } 
     } 
     printf("CONNECT connection is taking place...\n"); 

     // connected immediately 
     if (conn_res == 0) { 
      printf("CONNECT connected OK!\n"); 
      goto CONNECTED; 
     } 

     FD_ZERO(&fdset); 
     FD_SET(sockfd_server, &fdset); 
     tv.tv_sec = 5; // tried 5, 20, 60 seconds, but it always times out 
     tv.tv_usec = 0; 

     printf("CONNECT attempting select()\n"); 
     if (select(sockfd_server+1, NULL, &fdset, NULL, &tv) == 0) { 
      errno = ETIMEDOUT; 
      close(sockfd_server); 
      sockfd_server = -1; 
      return false; 
     } 

     if (FD_ISSET(sockfd_server, &fdset)) { 
      int so_error; 
      socklen_t len = sizeof so_error; 
      if (getsockopt(sockfd_server, SOL_SOCKET, SO_ERROR, &so_error, &len) < 0) { 
       return false; 
      } 
     } else { 
      printf("sockfd_server not set\n"); 
     } 

     CONNECTED: 
     fcntl(sockfd_server, F_SETFL, flags &~ O_NONBLOCK); 
     // yeah, now I will start to deal the HTTPS flow in both directions 
     return true; 
    } 
} 

それは設定を管理します:

int main(int argc, char *argv[]) { 
    // ClientManager.cpp is described below 
    ClientManager cm; 
    //listening on port given by argv 
    if (cm.startListeningForClient(listening_port)) { 
     while(true) { 
      int new_client_socket = cm.acceptConnectionFromClient(); 
      if (new_client_socket >= 0) { 
       cm.forkAndManageClient(); 
      } 
      else { 
       perror("accept error"); 
      } 
     } 
    } else { 
     perror("Error on start listening"); 
    } 
    return EXIT_SUCCESS; 
} 

今、その機能がmain()に呼ばれている以上、私の問題は、ClientManager.cpp、に関与していないいくつかのomissisと、次のは、ソケットを非ブロックモードに設定し、CONNECT connection is taking place...を出力しますが、常にError managing request from client: Connection timed outを返します。

私はLOCのマイルをポストすることをお詫びしますが、これは何日も狂ってしまいます。投稿、チュートリアル、ガイドを読んだ後、私は本当に何をすべきか分かりません。

答えて

0

これは、HTTPS接続が必要なすべてのサイトに接続します。 ソケットディスクリプタの適切なエラーチェックとクローズがありませんでした。ここに私のコードは次のとおりです。ブロックまたは非ブロッキングソケットを設定

bool ClientManager::manageRequest(void) { 

if (rm.isCONNECT()) { 
    struct sockaddr_in remote_server, local_bind; 
    int conn_res, select_res; 

    memset(&remote_server, 0, sizeof(remote_server)); 
    remote_server.sin_family = AF_INET; 
    remote_server.sin_addr.s_addr = rm.getServerAddr(); 
    remote_server.sin_port = rm.getServerPort(); 

    memset(&local_bind, 0, sizeof(local_bind)); 
    local_bind.sin_family = AF_INET; 
    local_bind.sin_addr.s_addr = htonl(INADDR_ANY); 
    local_bind.sin_port = htons(0); 

    fd_set rdset, wrset; 
    struct timeval tv; 

    sockfd_server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (sockfd_server < 0) { 
     perror("socket: "); 
    } 

    if(!setNonBlocking(sockfd_server)) 
     perror("fcntl"); 
    debug_green("CONNECT set socket to non-blocking mode\n"); 

    bind(sockfd_server, (struct sockaddr*) &local_bind, sizeof(local_bind)); 

    conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in)); 
    // The socket is nonblocking and the connection cannot be completed immediately 
    // check for EINPROGRESS 
    if ((conn_res == -1) && (errno != EINPROGRESS)) { 

     FD_ZERO(&rdset); 
     FD_SET(sockfd_server, &rdset); 
     wrset = rdset; 
     tv.tv_sec = 0; 
     tv.tv_usec = 0; 

     debug_yellow("CONNECT attempting select()\n"); 
     do { 
      select_res = select(sockfd_server+1, &rdset, &wrset, NULL, &tv); 
     } while ((select_res == -1) && (errno == EINTR)); 

     if ((!FD_ISSET(sockfd_server, &rdset)) && ((!FD_ISSET(sockfd_server, &wrset)))) { 
      debug_red("SELECT sockfds not responding\n"); 
      close(sockfd_server); 
      sockfd_server = -1; 
      return false; 
     } 

     conn_res = connect(sockfd_server, (struct sockaddr *)&remote_server, sizeof(struct sockaddr_in)); 
     if (conn_res == -1) { 
      if(errno == EISCONN) 
       printf ("connect(): connections already existing, OK\n"); 
      else { 
       printf("connect() for safety check: connection NOT successfull\n"); 
       close(sockfd_server); 
       sockfd_server = -1; 
       return false; 
      } 
     } 
     printf("connection OK\n"); 
     fflush(stdout); 
    } else { 
     debug_green("Connection immediately OK\n"); 
     fflush(stdout); 
    } 
    if (!setBlocking(sockfd_server)) { 
     perror("FCNTL:"); 
    } 
    debug_green("CONNECT set socket back to blocking mode\n");fflush(stdout); 
} 

return true; 
} 

機能:

bool ClientManager::setNonBlocking(int sockfd) { 
    printf("setting non block socket\n"); fflush(stdout); 
    int flags; 
    if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0) 
     return false; 
    flags |= O_NONBLOCK; 
    if (fcntl(sockfd, F_SETFL, flags) < 0) 
     return false; 
    return true; 
} 

bool ClientManager::setBlocking(int sockfd) { 
    printf("setting block socket\n"); fflush(stdout); 
    int flags; 
    if ((flags = fcntl(sockfd, F_GETFL, 0)) < 0) 
     return false; 
    flags &= (~O_NONBLOCK); 
    if (fcntl(sockfd, F_SETFL, flags) < 0) 
     return false; 
    return true; 
} 

デバッグ機能:

#define DEFAULTCOLOR "\033[0m" 
#define RED    "\033[22;31m" 
#define YELLOW   "\033[1;33m" 
#define GREEN   "\033[0;0;32m" 

#define debug_red(...) std::cout << RED << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout); 
#define debug_yellow(...) std::cout << YELLOW << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout); 
#define debug_green(...) std::cout << GREEN << __VA_ARGS__ << DEFAULTCOLOR; fflush(stdout); 
関連する問題