Неполное чтение из сокета сервера при использовании readDataToLength: метод - PullRequest
0 голосов
/ 04 февраля 2019

Я занимаюсь разработкой веб-прокси для использования с iOS и OSX с использованием библиотеки cocoaAsyncSocket и столкнулся с проблемой.Я могу принять несколько подключений от клиента, проанализировать заголовки, подключиться к месту назначения через порт 80/443 и начать получать данные, одновременно передавая данные обратно в сокет клиента.Однако у меня проблема в том, что серверный сокет закрывается перед завершением чтения содержимого при использовании метода readDataToLength: x, однако, если я просто использую readDataWithTimeout, все в порядке, и страница будет загружаться.

Использование curlчерез мой прокси я вижу, что данные частично получены, но соединение закрывается с

transfer closed with 12 bytes remaining to read
* stopped the pause stream!
* Closing connection 0
curl: (18) transfer closed with 12 bytes remaining to read

Однако метод делегата

socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag

сообщает мне, что он завершил частичное чтение 12 байтовтак что может показаться, что чтение завершено.

-(void)socket:(GCDAsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {
    NSLog(@"READ PARTIAL DATA %lu with tag: %lu",partialLength, tag);
    [sock readDataToLength:partialLength withTimeout:3 tag:tag];
}
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    ConnectionData *socketData;
    @synchronized (self) {
        socketData = [self getConnectionDataForSocket:sock];
    }
    if (tag == CLIENT_SOCK_READ) {
        //NSLog(@"READ FROM CLIENT");
        if (!socketData.serverSocket){
            //We dont have a server socket yet, assume that we are reading the header data.

            NSString *headers = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

            //Decide if we have a http or ssl connection
            if ([headers containsString:@"CONNECT"]) {
                //TLS SESSION
                NSString* hostToConnect = [self extractStringFromString:headers from:@"CONNECT " to:@":"];
                NSError *connectError;
                GCDAsyncSocket *serverSock = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:[self socketsDispatchQueue]];
                @synchronized (self) {
                    socketData.serverSocket = serverSock;
                }
                if (![serverSock connectToHost:hostToConnect onPort:443 withTimeout:10 error:&connectError]){
                    NSLog(@"Failed to connect to host: %@", [connectError debugDescription]);
                }
                NSString *tlsClientResponse = @"HTTP/1.0 200 Connection established\r\n\r\n";
                [[socketData clientSocket]writeData:[tlsClientResponse dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:CLIENT_SOCK_WRITE];
            } else {
                NSString *hostToConnect = [self extractStringFromString:headers from:@"http://" to:@"/"];
                NSString *newheaderLine = [self prepareHttpHeader:headers];

                //Rewite headers
                NSError *connectError;
                GCDAsyncSocket *serverSock = [[GCDAsyncSocket alloc]initWithDelegate:self delegateQueue:[self socketsDispatchQueue]];

                @synchronized (self) {
                    socketData.serverSocket = serverSock;
                }
                if (![serverSock connectToHost:hostToConnect onPort:80 withTimeout:10 error:&connectError]){
                    NSLog(@"Failed to connect to host: %@", [connectError debugDescription]);
                }
                [socketData.serverSocket writeData:[newheaderLine dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:false] withTimeout:10 tag:SERVER_SOCK_WRITE];
            }
        } else {
            [socketData.serverSocket writeData:data withTimeout:3 tag:SERVER_SOCK_WRITE];
        }

    } else if (tag == SERVER_SOCK_READ){
        [socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];
        [socketData.clientSocket writeData:data withTimeout:3 tag:CLIENT_SOCK_WRITE];
    }

}

-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    ConnectionData *socketData;
    @synchronized (self) {
        socketData = [self getConnectionDataForSocket:sock];
    }
    if (tag == SERVER_SOCK_WRITE){
        [socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];
    } else if (tag == CLIENT_SOCK_WRITE){
        [socketData.clientSocket readDataToLength:25 withTimeout:3 tag:CLIENT_SOCK_READ];
        [socketData.serverSocket readDataToLength:25 withTimeout:3 tag:SERVER_SOCK_READ];


    }
}

Я ожидал, что чтение завершится в сокете перед закрытием, как это происходит, когда я вызываю readDataWithTimeout, если кто-нибудь может указать мне правильное направление, еслиочень благодарен!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...