1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-26 23:36:08 +03:00
vimr/Commons/Sources/CommonsObjC/NetUtils.m
2020-10-03 09:29:17 +02:00

71 lines
1.6 KiB
Objective-C

/**
* Greg Omelaenko - http://omelaen.co
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import "NetUtils.h"
#import <os/log.h>
#import <sys/socket.h>
#import <netinet/in.h>
static os_log_t logger;
@implementation NetUtils
// from https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/UsingSocketsandSocketStreams.html#//apple_ref/doc/uid/CH73-SW9
// and http://stackoverflow.com/a/20850182/6939513
// slightly modified
+ (in_port_t)openPort {
static dispatch_once_t token;
dispatch_once(&token, ^{
// See Defs.swift
logger = os_log_create("com.qvacua.VimR", "general");
});
const int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
os_log_error(logger, "Could not open socket");
return 0;
}
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(0);
if (bind(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
if (errno == EADDRINUSE) {
os_log_error(logger, "the port is not available.");
return 0;
} else {
os_log_error(
logger,
"could not bind to process (%{public}d) %{public}s",
errno,
strerror(errno)
);
return 0;
}
}
socklen_t len = sizeof(sin);
if (getsockname(sock, (struct sockaddr *) &sin, &len) == -1) {
os_log_error(logger, "getsockname failed.");
return 0;
}
const in_port_t result = ntohs(sin.sin_port);
if (close(sock) < 0) {
os_log_error(logger, "socket did not close: %{public}s", strerror(errno));
return 0;
}
return result;
}
@end