Skip to content

Commit

Permalink
Merge pull request #86 from sundermann/local-socket
Browse files Browse the repository at this point in the history
Add local unix socket support
  • Loading branch information
TBSniller authored Oct 2, 2022
2 parents 1c470b3 + a94be23 commit 19eb7ce
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 43 deletions.
130 changes: 92 additions & 38 deletions src/hyperion_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>

#include "hyperion_reply_reader.h"
#include "hyperion_request_builder.h"

static int _connect_unix_socket(const char* hostname);
static int _connect_inet_socket(const char* hostname, int port);
static int _send_message(const void* buffer, size_t size);
static bool _parse_reply(hyperionnet_Reply_table_t reply);

Expand All @@ -25,53 +28,20 @@ static const char* _origin = NULL;
static bool _connected = false;
unsigned char recvBuff[1024];

int hyperion_client(const char* origin, const char* hostname, int port, int priority)
int hyperion_client(const char* origin, const char* hostname, int port, bool unix_socket, int priority)
{
_origin = origin;
_priority = priority;
_connected = false;
_registered = false;
sockfd = 0;
struct sockaddr_in serv_addr;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
WARN("Could not create socket: %s", strerror(errno));
return 1;
}
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
sizeof(timeout))
< 0) {
WARN("setsockopt(SO_SNDTIMEO) failed: %s", strerror(errno));
return 1;
}

if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout))
< 0) {
WARN("setsockopt(SO_RCVTIMEO) failed: %s", strerror(errno));
return 1;
}

memset(&serv_addr, '0', sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);

if (inet_pton(AF_INET, hostname, &serv_addr.sin_addr) <= 0) {
WARN("inet_pton error occured (hostname: %s): %s", hostname, strerror(errno));
return 1;
}

if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
WARN("connect() to %s:%d failed: %s", hostname, port, strerror(errno));
return 1;
if (unix_socket) {
return _connect_unix_socket(hostname);
} else {
return _connect_inet_socket(hostname, port);
}
_connected = true;

return 0;
}

int hyperion_read()
Expand Down Expand Up @@ -197,3 +167,87 @@ bool _parse_reply(hyperionnet_Reply_table_t reply)

return false;
}

int _connect_inet_socket(const char* hostname, int port)
{
struct sockaddr_in serv_addr_in;

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
WARN("Could not create socket: %s", strerror(errno));
return 1;
}
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
sizeof(timeout))
< 0) {
WARN("setsockopt(SO_SNDTIMEO) failed: %s", strerror(errno));
return 1;
}

if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout))
< 0) {
WARN("setsockopt(SO_RCVTIMEO) failed: %s", strerror(errno));
return 1;
}

memset(&serv_addr_in, 0, sizeof(serv_addr_in));

serv_addr_in.sin_family = AF_INET;
serv_addr_in.sin_port = htons(port);

if (inet_pton(AF_INET, hostname, &serv_addr_in.sin_addr) <= 0) {
WARN("inet_pton error occured (hostname: %s): %s", hostname, strerror(errno));
return 1;
}

if (connect(sockfd, (struct sockaddr*)&serv_addr_in, sizeof(serv_addr_in)) < 0) {
WARN("connect() to %s:%d failed: %s", hostname, port, strerror(errno));
return 1;
}
_connected = true;

return 0;
}

int _connect_unix_socket(const char* hostname)
{
struct sockaddr_un serv_addr_un;

if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
WARN("Could not create socket: %s", strerror(errno));
return 1;
}
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;

if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout,
sizeof(timeout))
< 0) {
WARN("setsockopt(SO_SNDTIMEO) failed: %s", strerror(errno));
return 1;
}

if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout,
sizeof(timeout)) < 0) {
WARN("setsockopt(SO_RCVTIMEO) failed: %s", strerror(errno));
return 1;
}

memset(&serv_addr_un, 0, sizeof(serv_addr_un));

serv_addr_un.sun_family = AF_LOCAL;
strcpy(serv_addr_un.sun_path, hostname);

if (connect(sockfd, (struct sockaddr*)&serv_addr_un, sizeof(serv_addr_un)) < 0) {
WARN("connect() to unix socket %s failed: %s", hostname, strerror(errno));
return 1;
}
_connected = true;

return 0;
}
3 changes: 2 additions & 1 deletion src/hyperion_client.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <stdbool.h>

int hyperion_client(const char* origin, const char* hostname, int port, int priority);
int hyperion_client(const char* origin, const char* hostname, int port, bool unix_socket, int priority);
int hyperion_read();
int hyperion_destroy();
int hyperion_set_image(const unsigned char* image, int width, int height);
Expand Down
7 changes: 6 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static struct option long_options[] = {
{ "height", required_argument, 0, 'y' },
{ "address", required_argument, 0, 'a' },
{ "port", required_argument, 0, 'p' },
{ "unix-socket", no_argument, 0, 'l' },
{ "fps", required_argument, 0, 'f' },
{ "no-video", no_argument, 0, 'V' },
{ "no-gui", no_argument, 0, 'G' },
Expand All @@ -50,6 +51,7 @@ static void print_usage()
printf(" -y, --height=HEIGHT Height of video frame (default 108)\n");
printf(" -a, --address=ADDR IP address of Hyperion server\n");
printf(" -p, --port=PORT Port of Hyperion flatbuffers server (default 19400)\n");
printf(" -l, --unix-socket Connect through unix socket\n");
printf(" -f, --fps=FPS Framerate for sending video frames (default 0 = unlimited)\n");
printf(" -b, --backend=BE Use specific video capture backend (default auto)\n");
printf(" -u, --ui-backend=BE Use specific ui capture backend (default auto)\n");
Expand All @@ -70,7 +72,7 @@ static int parse_options(int argc, char* argv[])
int opt, longindex;
int ret;

while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:vnhdVG", long_options, &longindex)) != -1) {
while ((opt = getopt_long(argc, argv, "x:y:a:p:f:b:u:q:c:lvnhdVG", long_options, &longindex)) != -1) {
switch (opt) {
case 'x':
settings.width = atoi(optarg);
Expand All @@ -85,6 +87,9 @@ static int parse_options(int argc, char* argv[])
case 'p':
settings.port = atol(optarg);
break;
case 'l':
settings.unix_socket = true;
break;
case 'f':
settings.fps = atoi(optarg);
break;
Expand Down
7 changes: 4 additions & 3 deletions src/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ void* connection_loop(void* data)
DBG("Starting connection loop");
while (service->connection_loop_running) {
INFO("Connecting hyperion-client..");
if ((hyperion_client("webos", service->settings->address, service->settings->port, service->settings->priority)) != 0) {
if ((hyperion_client("webos", service->settings->address, service->settings->port,
service->settings->unix_socket, service->settings->priority)) != 0) {
ERR("Error! hyperion_client.");
} else {
INFO("hyperion-client connected!");
Expand Down Expand Up @@ -407,7 +408,7 @@ static bool videooutput_callback(LSHandle* sh __attribute__((unused)), LSMessage
hdr_enabled = true;
}

int ret = set_hdr_state(service->settings->address, RPC_PORT, hdr_enabled);
int ret = set_hdr_state(service->settings->unix_socket ? "127.0.0.1" : service->settings->address, RPC_PORT, hdr_enabled);
if (ret != 0) {
ERR("videooutput_callback: set_hdr_state failed, ret: %d", ret);
}
Expand Down Expand Up @@ -459,7 +460,7 @@ static bool picture_callback(LSHandle* sh __attribute__((unused)), LSMessage* ms
hdr_enabled = true;
}

int ret = set_hdr_state(service->settings->address, RPC_PORT, hdr_enabled);
int ret = set_hdr_state(service->settings->unix_socket ? "127.0.0.1" : service->settings->address, RPC_PORT, hdr_enabled);
if (ret != 0) {
ERR("videooutput_callback: set_hdr_state failed, ret: %d", ret);
}
Expand Down
4 changes: 4 additions & 0 deletions src/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ void settings_init(settings_t* settings)
settings->address = strdup("");
settings->port = 19400;
settings->priority = 150;
settings->unix_socket = false;

settings->fps = 30;
settings->width = 320;
Expand Down Expand Up @@ -51,6 +52,8 @@ int settings_load_json(settings_t* settings, jvalue_ref source)
jnumber_get_i32(value, &settings->port);
if ((value = jobject_get(source, j_cstr_to_buffer("priority"))) && jis_number(value))
jnumber_get_i32(value, &settings->priority);
if ((value = jobject_get(source, j_cstr_to_buffer("unix-socket"))) && jis_boolean(value))
jboolean_get(value, &settings->unix_socket);

if ((value = jobject_get(source, j_cstr_to_buffer("fps"))) && jis_number(value))
jnumber_get_i32(value, &settings->fps);
Expand Down Expand Up @@ -81,6 +84,7 @@ int settings_save_json(settings_t* settings, jvalue_ref target)
jobject_set(target, j_cstr_to_buffer("address"), jstring_create(settings->address));
jobject_set(target, j_cstr_to_buffer("port"), jnumber_create_i32(settings->port));
jobject_set(target, j_cstr_to_buffer("priority"), jnumber_create_i32(settings->priority));
jobject_set(target, j_cstr_to_buffer("unix-socket"), jboolean_create(settings->unix_socket));

jobject_set(target, j_cstr_to_buffer("fps"), jnumber_create_i32(settings->fps));
jobject_set(target, j_cstr_to_buffer("width"), jnumber_create_i32(settings->width));
Expand Down
1 change: 1 addition & 0 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ typedef struct _settings_t {
char* address;
int port;
int priority;
bool unix_socket;

int fps;
int width;
Expand Down

0 comments on commit 19eb7ce

Please sign in to comment.