iosobjective-ciphonecfsocket

CFSocket crashes on successful connection


This is my Client and Server code for CFSocket communication but on successful connection this code crashes.

Client.m

    -(void)createConnection
    {
        CFSocketContext socketContext = {0,(__bridge void *)(self),NULL,NULL,NULL};

    _socket =  CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketConnectCallBack,(CFSocketCallBack)kCFSocketConnectCallBack, &socketContext);

    if (_socket != nil) {
        struct sockaddr_in addr4;
        memset (& addr4, 0, sizeof (addr4));
        addr4.sin_len = sizeof (addr4);
        addr4.sin_family = AF_INET;
        addr4.sin_port = htons (8888);
        NSString *strAddress = @"xxx.xxx.x.xxx";
        addr4.sin_addr.s_addr = inet_addr ([strAddress UTF8String]);


        CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));
        CFSocketConnectToAddress (_socket,address,-1);

        CFSocketEnableCallBacks(_socket, kCFSocketConnectCallBack);

        CFRunLoopRef cRunRef = CFRunLoopGetCurrent ();
        CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
        CFRunLoopAddSource (cRunRef,sourceRef,kCFRunLoopCommonModes);

        char ethadd []= "helloworld";
        CFDataRef Data = CFDataCreate(NULL, (const UInt8*)ethadd, sizeof(ethadd));
        int socket_error = CFSocketSendData (_socket, (CFDataRef) address, (CFDataRef) Data, 10);
        if (socket_error < 0){
            NSLog(@"Data could not be sent!");
            //            return EXIT_FAILURE;
        }
        else NSLog(@"Data Sent");

        CFRelease (sourceRef);
    }
}

void TCPServerConnectCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
    if (data != NULL) {
        // When the socket is kCFSocketConnectCallBack failure callback failed to return an error code pointer, other returns NULL
        NSLog (@"connection failed");
        return;
    }
    Client * client = (__bridge Client *) info;
   [client readStream];
}


- (void)readStream {
    char buffer [1024];
    while (recv (CFSocketGetNative (_socket), // ??Socket associated with the authority has failed to return -1: INVALID_SOCKET is
                 buffer, sizeof (buffer), 0)) {
        NSLog (@"%@", [NSString stringWithUTF8String: buffer]);
    } 
}

- (void) SendMessage :(NSString *)text {
//    [self createConnection];
    NSString * stringTosend = text;
    char * data = (char *)[stringTosend UTF8String];
    send (CFSocketGetNative (_socket), data, strlen (data) + 1, 0);
}

Server.m

-(void)setupSocket
{
    setupSocket();
}

int setupSocket () {

    _socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
    if (NULL == _socket) {
        NSLog (@ "Cannot create socket!");
        return 0; 
    }
    int optval = 1;
    setsockopt (CFSocketGetNative (_socket), SOL_SOCKET, SO_REUSEADDR, // ??allow reuse of local address and port
                    (void *) & optval, sizeof (optval));

    struct sockaddr_in addr4;
    memset (& addr4, 0, sizeof (addr4));
    addr4.sin_len = sizeof (addr4);
    addr4.sin_family = AF_INET;
    addr4.sin_port = htons (8888);
    addr4.sin_addr.s_addr = inet_addr ([@"xxx.xxx.x.xxx" UTF8String]);//htlon(INADDR_ANY)
    CFDataRef address = CFDataCreate (kCFAllocatorDefault, (UInt8 *) & addr4, sizeof (addr4));

        if (kCFSocketSuccess != CFSocketSetAddress (_socket, address)) {
            NSLog (@ "Bind to address failed!");
            if (_socket)
                CFRelease (_socket); 
            _socket = NULL;
            return 0;
        }

    CFSocketEnableCallBacks(_socket, kCFSocketAcceptCallBack);

    CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent ();
    CFRunLoopSourceRef source = CFSocketCreateRunLoopSource (kCFAllocatorDefault, _socket, 0);
    CFRunLoopAddSource (cfRunLoop, source, kCFRunLoopCommonModes);

    return 1;
}

void TCPServerAcceptCallBack (CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void * data, void * info) {
     if (kCFSocketAcceptCallBack == type) {
        // Local socket handle
        CFSocketNativeHandle nativeSocketHandle = * (CFSocketNativeHandle *) data;
        uint8_t name [SOCK_MAXADDRLEN];
        socklen_t nameLen = sizeof (name);
        if (0 != getpeername (nativeSocketHandle, (struct sockaddr *) name, & nameLen)) {
            NSLog (@"error");
//            Exit (1);
        }
         NSLog (@ "%s connected.", inet_ntoa (((struct sockaddr_in *) name) -> sin_addr));

         CFReadStreamRef iStream;
         CFWriteStreamRef oStream;

         CFReadStreamClientCallBack readStream;
         CFReadStreamClientCallBack writeStream;
         CFWriteStreamRef wStream;
         // Create a socket connection can read and write
         CFStreamCreatePairWithSocket (kCFAllocatorDefault, nativeSocketHandle, &iStream, & oStream);
         if (iStream && oStream) {
             CFStreamClientContext streamContext = {0, NULL, NULL, NULL};
             if (! CFReadStreamSetClient (iStream, kCFStreamEventHasBytesAvailable,
                                          readStream, // callback function is called when the data readable
                                          &streamContext)) {
//                 Exit (1);
             }

             if (! CFReadStreamSetClient (iStream, kCFStreamEventCanAcceptBytes, writeStream, &streamContext)) {
//                 Exit (1);
             }

             CFReadStreamScheduleWithRunLoop (iStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
             CFWriteStreamScheduleWithRunLoop (wStream, CFRunLoopGetCurrent (), kCFRunLoopCommonModes);
             CFReadStreamOpen (iStream);
             CFWriteStreamOpen (wStream); 
         }
         else
         {
             close (nativeSocketHandle); 
         } 
     } 
}

// Read data
void readStream (CFReadStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
    UInt8 buff [255];
    CFReadStreamRead (stream, buff, 255);
    printf ("received:%s", buff);
}

void writeStream (CFWriteStreamRef stream, CFStreamEventType eventType, void * clientCallBackInfo) {
    outputStream = stream;
}

//int main()
//{
//    char * str = "nihao";
//    UInt8 buff [255];
//    if (outputStream != NULL) {
//        CFWriteStreamWrite (outputStream, buff, strlen (str) + 1);
//    }
//    else
//    {
//        NSLog (@ "Cannot send data!");
//    }
//}

// Open up a thread in the thread function
void runLoopInThread () {
    int res = setupSocket ();
    if (res) {
        EXIT_FAILURE;
    }
    CFRunLoopRun (); // run the current thread CFRunLoop of objects
}

In the above code crashes for Server when CFSocketConnectToAddress executes in Client and after that client app also crashes.


Solution

  • _socket = CFSocketCreate (kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)kCFSocketAcceptCallBack, NULL);
    

    In above method i had to pass my callback method instead of "(CFSocketCallBack)kCFSocketAcceptCallBack".Which fixed my issue.