Example #1
0
int
main (int argc, const char *argv[]) {
    WebSocketRef webSocket = WebSocketCreateWithHostAndPort(NULL, kWebSocketHostAny, 60001, NULL);
    if (webSocket) {
        webSocket->callbacks.didClientReadCallback = Callback;
        CFRunLoopRun();
        WebSocketRelease(webSocket);
    }
    return 0;
}
Example #2
0
WebSocketRef
WebSocketCreateWithHostAndPort (CFAllocatorRef allocator, CFStringRef host, UInt16 port, void *userInfo) {
    WebSocketRef self = CFAllocatorAllocate(allocator, sizeof(WebSocket), 0);
    if (self) {
        self->allocator = allocator ? CFRetain(allocator) : NULL;
        self->retainCount = 1;
        self->userInfo = userInfo;

        self->clientsLength = 1024;
        self->clientsUsedLength = 0;
        if (NULL == (self->clients = CFAllocatorAllocate(allocator, self->clientsLength, 0))) {
            WebSocketRelease(self), self = NULL;
            goto fin;
        }

        // Callbacks
        self->callbacks.didAddClientCallback     = NULL;
        self->callbacks.willRemoveClientCallback = NULL;
        self->callbacks.didClientReadCallback    = NULL;

        // Setup the context;
        CFSocketContext context = {
            .copyDescription = NULL,
            .retain = NULL,
            .release = NULL,
            .version = 0,
            .info = self
        };

        if (NULL == (self->socket = CFSocketCreate(self->allocator, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, __WebSocketAcceptCallBack, &context))) {
            WebSocketRelease(self), self = NULL;
            goto fin;
        }

        // Re-use local addresses, if they're still in TIME_WAIT
        int yes = 1;
        setsockopt(CFSocketGetNative(self->socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));

        // Set the port and address we want to listen on
        memset(&self->addr, 0, sizeof(self->addr));
        self->addr.sin_len = sizeof(self->addr);
        self->addr.sin_family = AF_INET;

        if (CFEqual(kWebSocketHostAny, host)) {

            // Host is set to "0.0.0.0", set it to INADDR_ANY
            self->addr.sin_addr.s_addr = htonl(INADDR_ANY);
        } else {

            // Set the host based on provided string. TODO: hostname resolution?
            CFIndex hostCStringLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(host), kCFStringEncodingASCII) + 1;
            char *hostCString = CFAllocatorAllocate(self->allocator, hostCStringLength, 0);
            if (hostCString) {
                if (CFStringGetCString(host, hostCString, hostCStringLength, kCFStringEncodingASCII)) {
                    inet_aton(hostCString, &self->addr.sin_addr);
                } else {

                    // TODO: Couldn't get CString
                }
                CFAllocatorDeallocate(self->allocator, hostCString);
            } else {

                // TODO: Couldn't allocate buffer
            }
        }

        self->addr.sin_port = htons(port);

        CFDataRef address = CFDataCreate(self->allocator, (const void *) &self->addr, sizeof(self->addr));
        if (address) {
            if (CFSocketSetAddress(self->socket, (CFDataRef) address) != kCFSocketSuccess) {
                WebSocketRelease(self), self = NULL;
                CFRelease(address);
                goto fin;
            }
            CFRelease(address);
        }

        // Create run loop source and add it to the current run loop
        CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(self->allocator, self->socket, 0);
        CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
        CFRelease(source);
    }

fin:

    return self;
}

WebSocketRef
WebSocketCreate (CFAllocatorRef allocator, void *userInfo) {
    return WebSocketCreateWithHostAndPort(allocator, kWebSocketHostLoopBack, kWebSocketPortAny, userInfo);
}

void
WebSocketRetain (WebSocketRef self) {
    if_self {
        ++self->retainCount;
    }
}