I am trying to make a bridge via unix domain socket between Ruby script as server and C app as client but currently I am stuck in the read loop until I kill Ruby script maybe someone could look at the code?
struct sockaddr_un addr;
int fd,rc;
char *socket_path = "/tmp/auth.sock";
char *output_packet = cern_format_packet(pw, key);
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
error("socket error");
return 0;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
error("connect error");
return 0;
}
logit("cern_output: %s", output_packet);
write(fd, output_packet, strlen(output_packet));
#define BUFFERSIZE 1024
#define MAXDATASIZE 256
int c, q = 0, success;
char* input_buffer;
char data_buffer[MAXDATASIZE];
size_t input_buffer_size = BUFFERSIZE;
input_buffer = malloc(input_buffer_size);
if (input_buffer)
{
while((c = read(fd, data_buffer, MAXDATASIZE)) > 0)
{
if (c + q > input_buffer_size)
{
input_buffer_size *= 2; /* Arbitrary doubling of size. */
char* tmp = realloc(input_buffer, input_buffer_size);
if (tmp)
{
input_buffer = tmp;
}
else
{
/* memory allocation failure. */
free(input_buffer);
input_buffer = 0;
break;
}
}
memcpy(input_buffer + q, data_buffer, c);
q += c;
}
}
json_error_t error;
json_t *root = json_loads( input_buffer, 0, &error );
if (root) {
json_t *json_status = json_object_get( root, "status" );
json_t *json_command = json_object_get( root, "command" );
const char *return_comamnd = json_string_value( json_command );
success = (int)json_integer_value(json_status);
logit("json_response: status: %i command: %s",success, return_comamnd);
}
close(fd);
return success;
And the ruby script
require "socket"
require 'msgpack'
require "json"
file = "/tmp/auth.sock"
File.unlink if File.exists?(file) && File.socket?(file)
serv = UNIXServer.new(file)
loop do
s = serv.accept
msg = s.gets
msg = msg.gsub("\n", "") if msg
p JSON.parse(msg)
a = {}
a["status"] = 1
a["command"] = "hello world"
s.write(JSON.generate(a))
s.close
end
The client's call to read()
most likely blocks because the server did send less then the client was told to read, that is MAXDATASIZE
bytes.
Do get around this let the server orderly shutdown the socket before closing it.
I'm no Ruby expert but may be something like:
s.shutdown
s.close
would do the job.
Also in the server this line:
msg = s.gets
might block until a \n
had been received. (See here for details on gets
: http://www.ruby-doc.org/core-2.0.0/IO.html#method-i-gets)