Ошибка сегментации потока CFHTTPS во время NSRunLoop - PullRequest
0 голосов
/ 06 сентября 2010

Я пытаюсь собрать игрушечное приложение для взаимодействия с http-серверами через CoreFoundation. Я не использую NSURLConnection, потому что я хочу иметь возможность указать прокси, отличный от того, который установлен в Системных настройках OSX.

Моя проблема в том, что я не смог найти ни одного рабочего примера, а документация Apple не содержит рабочего фрагмента кода.

Во всяком случае, это код, который я собрал:

#import <CoreFoundation/CoreFoundation.h>
#import <CoreServices/CoreServices.h>
#import <Foundation/Foundation.h>

void myCallBack (CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo){
  NSLog(@"Something happened");
  BOOL *done = ((BOOL *)clientCallBackInfo);
  *done = TRUE;
}

int main(int argc, char *argv[]){
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  CFStringRef bodyString = CFSTR(""); // Usually used for POST data

  CFStringRef url = CFSTR("http://www.apple.com");
  CFURLRef myURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);

  CFStringRef requestMethod = CFSTR("GET");
  CFHTTPMessageRef myRequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, 
                              requestMethod, 
                              myURL,
                              kCFHTTPVersion1_1);


  if (myRequest){
    NSLog(@"Request created: %@ %@", CFHTTPMessageCopyRequestMethod(myRequest), 
      CFURLGetString(CFHTTPMessageCopyRequestURL(myRequest)));
  }

  CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, bodyString, kCFStringEncodingASCII, 0);
  CFHTTPMessageSetBody(myRequest, bodyData);
  NSLog(@"HTTPMessage body set");

  CFDataRef mySerializedRequest = CFHTTPMessageCopySerializedMessage(myRequest);
  NSLog(@"Serialized string generated");
  CFStringRef mySerializedString = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault,
                                        mySerializedRequest,
                                        kCFStringEncodingASCII);
  NSLog(@"Serialized request: %@", mySerializedString);

  CFReadStreamRef myReadStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, myRequest);
  BOOL done = FALSE;
  CFReadStreamOpen(myReadStream);

  CFOptionFlags registeredEvents = kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  NSLog(@"Setting read stream client");
  if (CFReadStreamSetClient(myReadStream, registeredEvents, myCallBack, (void *)&done)){
      CFReadStreamScheduleWithRunLoop(myReadStream, CFRunLoopGetCurrent(),
                      kCFRunLoopCommonModes);

      while (!done){
    NSLog(@"Wait");
    [[NSRunLoop currentRunLoop] run];
      }


    }else{
      NSLog(@"Error setting readstream client");
    }  

  CFRelease(myRequest);
  CFRelease(myURL);
  CFRelease(url);
  CFRelease(mySerializedRequest);
  myRequest = NULL;
  mySerializedRequest = NULL;

  [pool drain];
}

Код компилируется, но при этом возникает ошибка:

Reading symbols for shared libraries .+++++...................... done
2010-09-06 21:36:34.470 a.out[27973:a0f] Request created: GET http://www.apple.com
2010-09-06 21:36:34.473 a.out[27973:a0f] HTTPMessage body set
2010-09-06 21:36:34.474 a.out[27973:a0f] Serialized string generated
2010-09-06 21:36:34.474 a.out[27973:a0f] Serialized request: GET / HTTP/1.1

2010-09-06 21:36:34.478 a.out[27973:a0f] Setting read stream client
2010-09-06 21:36:34.479 a.out[27973:a0f] Wait

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: 13 at address: 0x0000000000000000
0x00007fff83b7b83d in _signalEventSync ()
(gdb) bt
#0  0x00007fff83b7b83d in _signalEventSync ()
#1  0x00007fff83b7b7f4 in _cfstream_solo_signalEventSync ()
#2  0x00007fff83b7b734 in _CFStreamSignalEvent ()
#3  0x00007fff8391c3a1 in HTTPReadStream::streamEvent ()
#4  0x00007fff83b7b883 in _signalEventSync ()
#5  0x00007fff83b7c5d9 in _cfstream_shared_signalEventSync ()
#6  0x00007fff83b1be91 in __CFRunLoopDoSources0 ()
#7  0x00007fff83b1a089 in __CFRunLoopRun ()
#8  0x00007fff83b1984f in CFRunLoopRunSpecific ()
#9  0x00007fff8300fa18 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#10 0x00007fff8300f8f7 in -[NSRunLoop(NSRunLoop) run] ()
#11 0x0000000100000c94 in main (argc=1, argv=0x7fff5fbff5b8) at test.m:56

Я не понимаю, где ошибка. Кто-нибудь может показать мне свет или указать на четкий пример того, как управлять потоками CFHTTPS?

Спасибо, Andrea

1 Ответ

1 голос
/ 08 сентября 2010

Проблема заключалась в том, что я не внимательно прочитал документацию CFReadStreamSetClient. Третий параметр должен быть ссылкой на CFStreamClientContext, тогда как я передавал ссылку на произвольный указатель, который вместо этого должен быть включен в контекст.

Исправление этой ошибки позволило устранить ошибку сегментации, и теперь тест ca работает, как и ожидалось.

...