fdpass 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,35 @@
1
+ = Libarchive/Ruby
2
+
3
+ == Description
4
+
5
+ This is a library to transmit the file descriptor between the processes.
6
+
7
+ == Example
8
+ === Server (Reciever)
9
+ require 'fdpass'
10
+
11
+ begin
12
+ fdpass = FDPass.server('/tmp/fdpass.sock')
13
+
14
+ t = Thread.fork {
15
+ loop do
16
+ fd = fdpass.recv
17
+ io = IO.open(fd)
18
+ io.puts('%s: %s' % [fd, __FILE__])
19
+ end
20
+ }
21
+
22
+ t.join
23
+ ensure
24
+ fdpass.close
25
+ end
26
+
27
+ == Client (Sender)
28
+ require 'fdpass'
29
+
30
+ begin
31
+ fdpass = FDPass.client('/tmp/fdpass.sock')
32
+ fdpass.send($stderr.fileno)
33
+ ensure
34
+ fdpass.close if fdpass.closed?
35
+ end
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ $CFLAGS += ' -Wall '
3
+ create_makefile('fdpass')
@@ -0,0 +1,25 @@
1
+ #include "fdpass.h"
2
+
3
+ VALUE rb_mFDPass;
4
+ VALUE rb_eFDPassError;
5
+ extern VALUE rb_cFDPassServer;
6
+ extern VALUE rb_cFDPassClient;
7
+
8
+ static VALUE rb_fdpass_server(VALUE self, VALUE path) {
9
+ return rb_funcall(rb_cFDPassServer, rb_intern("new"), 1, path);
10
+ }
11
+
12
+ static VALUE rb_fdpass_client(VALUE self, VALUE path) {
13
+ return rb_funcall(rb_cFDPassClient, rb_intern("new"), 1, path);
14
+ }
15
+
16
+ void Init_fdpass() {
17
+ rb_mFDPass = rb_define_module("FDPass");
18
+ rb_define_module_function(rb_mFDPass, "server", rb_fdpass_server, 1);
19
+ rb_define_module_function(rb_mFDPass, "client", rb_fdpass_client, 1);
20
+
21
+ rb_eFDPassError = rb_define_class_under(rb_mFDPass, "Error", rb_eStandardError);
22
+
23
+ Init_fdpass_server();
24
+ Init_fdpass_client();
25
+ }
@@ -0,0 +1,26 @@
1
+ #ifndef __FDPASS_H__
2
+ #define __FDPASS_C__
3
+
4
+ #include <string.h>
5
+
6
+ #include <sys/socket.h>
7
+ #include <sys/un.h>
8
+ #include <sys/types.h>
9
+ #include <sys/stat.h>
10
+ #include <unistd.h>
11
+
12
+ #include <errno.h>
13
+
14
+ #include <ruby.h>
15
+
16
+ #ifndef RSTRING_PTR
17
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
18
+ #endif
19
+ #ifndef RSTRING_LEN
20
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
21
+ #endif
22
+
23
+ void Init_fdpass_server();
24
+ void Init_fdpass_client();
25
+
26
+ #endif // __FDPASS_H__
@@ -0,0 +1,88 @@
1
+ #include "fdpass.h"
2
+ #include "fdpass_socket.h"
3
+
4
+ extern VALUE rb_mFDPass;
5
+ extern VALUE rb_eFDPassError;
6
+ VALUE rb_cFDPassClient;
7
+
8
+ static VALUE rd_fdpass_client_initialize(VALUE self, VALUE path) {
9
+ struct fdpass_socket *p;
10
+ char *cpath;
11
+ int sock;
12
+ struct sockaddr_un addr;
13
+
14
+ Data_Get_Struct(self, struct fdpass_socket, p);
15
+
16
+ Check_Type(path, T_STRING);
17
+ cpath = RSTRING_PTR(path);
18
+
19
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
20
+
21
+ if (sock < 0) {
22
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
23
+ }
24
+
25
+ memset(&addr, 0, sizeof(addr));
26
+ addr.sun_family = AF_UNIX;
27
+ strncpy(addr.sun_path, cpath, sizeof(addr.sun_path) - 1);
28
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
29
+
30
+ if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
31
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
32
+ }
33
+
34
+ p->sock = sock;
35
+ p->closed = 0;
36
+ p->path = path;
37
+ p->is_server = 0;
38
+
39
+ return Qnil;
40
+ }
41
+
42
+ static VALUE rb_fdpass_client_send(VALUE self, VALUE fd) {
43
+ struct fdpass_socket *p;
44
+ struct msghdr msg = { 0 };
45
+ struct cmsghdr *cmsg;
46
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
47
+ int ifd, *cmsg_data;
48
+ struct iovec iov;
49
+
50
+ ifd = NUM2INT(fd);
51
+
52
+ Data_Get_Struct(self, struct fdpass_socket, p);
53
+ Check_Socket(p);
54
+
55
+ iov.iov_base = "\0";
56
+ iov.iov_len = 1;
57
+
58
+ msg.msg_name = NULL;
59
+ msg.msg_namelen = 0;
60
+ msg.msg_iov = &iov;
61
+ msg.msg_iovlen = 1;
62
+ msg.msg_control = cmsgbuf;
63
+ msg.msg_controllen = sizeof(cmsgbuf);
64
+
65
+ cmsg = CMSG_FIRSTHDR(&msg);
66
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
67
+ cmsg->cmsg_level = SOL_SOCKET;
68
+ cmsg->cmsg_type = SCM_RIGHTS;
69
+
70
+ cmsg_data = (int *) CMSG_DATA(cmsg);
71
+ *cmsg_data = ifd;
72
+ msg.msg_controllen = cmsg->cmsg_len;
73
+
74
+ if (sendmsg(p->sock, &msg, 0) < 0) {
75
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
76
+ }
77
+
78
+ return Qnil;
79
+ }
80
+
81
+ void Init_fdpass_client() {
82
+ rb_cFDPassClient = rb_define_class_under(rb_mFDPass, "Client", rb_cObject);
83
+ rb_define_alloc_func(rb_cFDPassClient, fdpass_socket_alloc);
84
+ rb_define_private_method(rb_cFDPassClient, "initialize", rd_fdpass_client_initialize, 1);
85
+ rb_define_method(rb_cFDPassClient, "close", rd_fdpass_socket_close, 0);
86
+ rb_define_method(rb_cFDPassClient, "closed?", rd_fdpass_socket_is_closed, 0);
87
+ rb_define_method(rb_cFDPassClient, "send", rb_fdpass_client_send, 1);
88
+ }
@@ -0,0 +1,81 @@
1
+ #include "fdpass.h"
2
+ #include "fdpass_socket.h"
3
+
4
+ extern VALUE rb_mFDPass;
5
+ extern VALUE rb_eFDPassError;
6
+ VALUE rb_cFDPassServer;
7
+
8
+ static VALUE rd_fdpass_server_initialize(VALUE self, VALUE path) {
9
+ struct fdpass_socket *p;
10
+ char *cpath;
11
+ int sock;
12
+ struct sockaddr_un addr;
13
+
14
+ Data_Get_Struct(self, struct fdpass_socket, p);
15
+
16
+ Check_Type(path, T_STRING);
17
+ cpath = RSTRING_PTR(path);
18
+
19
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
20
+
21
+ if (sock < 0) {
22
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
23
+ }
24
+
25
+ memset(&addr, 0, sizeof(addr));
26
+ addr.sun_family = AF_UNIX;
27
+ strncpy(addr.sun_path, cpath, sizeof(addr.sun_path) - 1);
28
+ addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
29
+
30
+ if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
31
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
32
+ }
33
+
34
+ p->sock = sock;
35
+ p->closed = 0;
36
+ p->path = path;
37
+ p->is_server = 1;
38
+
39
+ return Qnil;
40
+ }
41
+
42
+ static VALUE rb_fdpass_server_recv(VALUE self) {
43
+ struct fdpass_socket *p;
44
+ struct msghdr msg = { 0 };
45
+ struct cmsghdr *cmsg;
46
+ char cmsgbuf[CMSG_SPACE(sizeof(int))];
47
+ int *cmsg_data;
48
+ struct iovec iov;
49
+ char iov_data[1];
50
+
51
+ Data_Get_Struct(self, struct fdpass_socket, p);
52
+ Check_Socket(p);
53
+
54
+ iov.iov_base = iov_data;
55
+ iov.iov_len = sizeof(iov_data);
56
+
57
+ msg.msg_name = NULL;
58
+ msg.msg_namelen = 0;
59
+ msg.msg_iov = &iov;
60
+ msg.msg_iovlen = 1;
61
+ msg.msg_control = cmsgbuf;
62
+ msg.msg_controllen = sizeof(cmsgbuf);
63
+
64
+ if (recvmsg(p->sock, &msg, MSG_WAITALL) < 0) {
65
+ rb_raise(rb_eFDPassError, "%s", strerror(errno));
66
+ }
67
+
68
+ cmsg = CMSG_FIRSTHDR(&msg);
69
+ cmsg_data = (int *) CMSG_DATA(cmsg);
70
+
71
+ return INT2NUM(*cmsg_data);
72
+ }
73
+
74
+ void Init_fdpass_server() {
75
+ rb_cFDPassServer = rb_define_class_under(rb_mFDPass, "Server", rb_cObject);
76
+ rb_define_alloc_func(rb_cFDPassServer, fdpass_socket_alloc);
77
+ rb_define_private_method(rb_cFDPassServer, "initialize", rd_fdpass_server_initialize, 1);
78
+ rb_define_method(rb_cFDPassServer, "close", rd_fdpass_socket_close, 0);
79
+ rb_define_method(rb_cFDPassServer, "closed?", rd_fdpass_socket_is_closed, 0);
80
+ rb_define_method(rb_cFDPassServer, "recv", rb_fdpass_server_recv, 0);
81
+ }
@@ -0,0 +1,64 @@
1
+ #include "fdpass_socket.h"
2
+
3
+ extern VALUE rb_eFDPassError;
4
+
5
+ static void unlink_socket(struct fdpass_socket *p) {
6
+ #ifdef S_ISSOCK
7
+ char *cpath;
8
+ struct stat st;
9
+
10
+ if (!p->is_server || NIL_P(p->path)) {
11
+ return;
12
+ }
13
+
14
+ Check_Type(p->path, T_STRING);
15
+ cpath = RSTRING_PTR(p->path);
16
+
17
+ if (stat(cpath, &st) == 0 && S_ISSOCK(st.st_mode)) {
18
+ unlink(cpath);
19
+ }
20
+ #endif
21
+ }
22
+
23
+ static void fdpass_socket_mark(struct fdpass_socket *p) {
24
+ rb_gc_mark(p->path);
25
+ }
26
+
27
+ static void fdpass_socket_free(struct fdpass_socket *p) {
28
+ if (!p->closed) {
29
+ close(p->sock);
30
+ unlink_socket(p);
31
+ }
32
+
33
+ xfree(p);
34
+ }
35
+
36
+ VALUE fdpass_socket_alloc(VALUE klass) {
37
+ struct fdpass_socket *p = ALLOC(struct fdpass_socket);
38
+ p->sock = -1;
39
+ p->closed = 1;
40
+ p->path = Qnil;
41
+ return Data_Wrap_Struct(klass, fdpass_socket_mark, fdpass_socket_free, p);
42
+ }
43
+
44
+ VALUE rd_fdpass_socket_close(VALUE self) {
45
+ struct fdpass_socket *p;
46
+
47
+ Data_Get_Struct(self, struct fdpass_socket, p);
48
+
49
+ if (!p->closed) {
50
+ close(p->sock);
51
+ unlink_socket(p);
52
+ p->sock = -1;
53
+ p->closed = 1;
54
+ p->path = Qnil;
55
+ }
56
+
57
+ return Qnil;
58
+ }
59
+
60
+ VALUE rd_fdpass_socket_is_closed(VALUE self) {
61
+ struct fdpass_socket *p;
62
+ Data_Get_Struct(self, struct fdpass_socket, p);
63
+ return p->closed ? Qtrue : Qfalse;
64
+ }
@@ -0,0 +1,24 @@
1
+ #ifndef __FDPASS_SOCKET_H__
2
+ #define __FDPASS_SOCKET_C__
3
+
4
+ #include "fdpass.h"
5
+
6
+ struct fdpass_socket {
7
+ int sock;
8
+ int closed;
9
+ VALUE path;
10
+ int is_server;
11
+ };
12
+
13
+ #define Check_Socket(p) do { \
14
+ if ((p)->sock < 0 || (p)->closed || NIL_P((p)->path)) { \
15
+ rb_raise(rb_eFDPassError, "Invalid socket"); \
16
+ } \
17
+ Check_Type((p)->path, T_STRING); \
18
+ } while(0)
19
+
20
+ VALUE fdpass_socket_alloc(VALUE klass);
21
+ VALUE rd_fdpass_socket_close(VALUE self);
22
+ VALUE rd_fdpass_socket_is_closed(VALUE self);
23
+
24
+ #endif // __FDPASS_SOCKET_H__
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fdpass
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - winebarrel
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-01 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: sgwr_dts@yahoo.co.jp
24
+ executables: []
25
+
26
+ extensions:
27
+ - ext/extconf.rb
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - ext/fdpass.c
32
+ - ext/fdpass_client.c
33
+ - ext/fdpass_server.c
34
+ - ext/fdpass_socket.c
35
+ - ext/fdpass.h
36
+ - ext/fdpass_socket.h
37
+ - ext/extconf.rb
38
+ - README
39
+ has_rdoc: true
40
+ homepage: https://github.com/winebarrel/fdpass
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.7
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: This is a library to transmit the file descriptor between the processes.
73
+ test_files: []
74
+