digitalmars.D.learn - Abstract sockets (linux)
- freeman (22/22) Jun 25 2015 I am having trouble using abstract sockets on Linux.
- Steven Schveighoffer (5/27) Jun 25 2015 I believe there was a recently fixed bug regarding unix sockets. The
- freeman (20/24) Jun 25 2015 Unfortunately the problem persists (I was using ldc2 before):
- Daniel Kozak via Digitalmars-d-learn (7/34) Jun 25 2015 instead of:
- freeman (11/17) Jun 25 2015 It is the null character that makes it an abstract socket (see
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (14/36) Jun 25 2015 I've found an old example of mine, which uses abstract sockets.
- freeman (14/27) Jun 26 2015 Thank you for the example code! I verified that client and
- Kagamin (4/11) Jun 26 2015 Looks like contrary to other sockets, name of an abstract socket
- freeman (59/82) Jun 26 2015 OK, I believe I've figured it out. The strace output I posted
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/4) Jun 26 2015 If it's a bug, yes. :)
I am having trouble using abstract sockets on Linux.
Here is sample python code that works, which works:
     ptm_sockname = "\0/var/run/ptmd.socket"
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
     sock.connect(ptm_sockname)
     sock.setblocking(1)
     sock.sendall('get-status detail')
Similar code in D, which does not work:
     string socket_name = "\0/var/run/ptmd.socket";
     auto address = new UnixAddress(socket_name);
     auto sock = new Socket(AddressFamily.UNIX, SocketType.STREAM);
     scope(exit) sock.close();
     sock.blocking = true;
     sock.connect(address);
     sock.send("get-status detail");
This is the equivalent with socat, which works:
     $ echo "get-status detail" | socat - 
ABSTRACT-CLIENT:/var/run/ptmd.socket
My test D program exits on connect:
std.socket.SocketOSException runtime/phobos/std/socket.d(2674): 
Unable to connect socket: Connection refused
Any pointers?
 Jun 25 2015
On 6/25/15 11:56 AM, freeman wrote:
 I am having trouble using abstract sockets on Linux.
 Here is sample python code that works, which works:
      ptm_sockname = "\0/var/run/ptmd.socket"
      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
      sock.connect(ptm_sockname)
      sock.setblocking(1)
      sock.sendall('get-status detail')
 Similar code in D, which does not work:
      string socket_name = "\0/var/run/ptmd.socket";
      auto address = new UnixAddress(socket_name);
      auto sock = new Socket(AddressFamily.UNIX, SocketType.STREAM);
      scope(exit) sock.close();
      sock.blocking = true;
      sock.connect(address);
      sock.send("get-status detail");
 This is the equivalent with socat, which works:
      $ echo "get-status detail" | socat -
 ABSTRACT-CLIENT:/var/run/ptmd.socket
 My test D program exits on connect:
 std.socket.SocketOSException runtime/phobos/std/socket.d(2674): Unable
 to connect socket: Connection refused
 Any pointers?
I believe there was a recently fixed bug regarding unix sockets. The 
upcoming 2.068 may help, have you tried the beta?
http://downloads.dlang.org/pre-releases/2.x/2.068.0/
-Steve
 Jun 25 2015
On Thursday, 25 June 2015 at 16:07:51 UTC, Steven Schveighoffer wrote:I believe there was a recently fixed bug regarding unix sockets. The upcoming 2.068 may help, have you tried the beta? http://downloads.dlang.org/pre-releases/2.x/2.068.0/ -SteveUnfortunately the problem persists (I was using ldc2 before): $ ./test std.socket.SocketOSException std/socket.d(2808): Unable to connect socket: Connection refused ---------------- ./test(_Dmain+0xce) [0x443b42] ./test(_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv+0x1f) [0x44ad7b] ./test(void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate())+0x2a) [0x44acd6] ./test(void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll()+0x2b) [0x44ad37] ./test(void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate())+0x2a) [0x44acd6] ./test(_d_run_main+0x1d2) [0x44ac56] ./test(main+0x12) [0x447e96] /lib64/libc.so.6(__libc_start_main+0xfd) [0x7f1bff50cd5d]
 Jun 25 2015
On Thu, 25 Jun 2015 15:56:04 +0000
freeman via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> wrote:
 I am having trouble using abstract sockets on Linux.
 
 Here is sample python code that works, which works:
      ptm_sockname = "\0/var/run/ptmd.socket"
      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
      sock.connect(ptm_sockname)
      sock.setblocking(1)
      sock.sendall('get-status detail')
 
 Similar code in D, which does not work:
      string socket_name = "\0/var/run/ptmd.socket";
      auto address = new UnixAddress(socket_name);
      auto sock = new Socket(AddressFamily.UNIX, SocketType.STREAM);
      scope(exit) sock.close();
      sock.blocking = true;
      sock.connect(address);
      sock.send("get-status detail");
 
 This is the equivalent with socat, which works:
      $ echo "get-status detail" | socat - 
 ABSTRACT-CLIENT:/var/run/ptmd.socket
 
 My test D program exits on connect:
 std.socket.SocketOSException runtime/phobos/std/socket.d(2674): 
 Unable to connect socket: Connection refused
 
 Any pointers?
instead of:
string socket_name = "\0/var/run/ptmd.socket";
try:
string socket_name = "/var/run/ptmd.socket";
works for me
 Jun 25 2015
On Thursday, 25 June 2015 at 18:50:29 UTC, Daniel Kozak wrote:It is the null character that makes it an abstract socket (see man unix). There is no file /var/run/ptmd.socket, as what follows the null character is just a name: $ ls -al /var/run/ptmd.socket ls: cannot access /var/run/ptmd.socket: No such file or directory Here is what happens when I remove the null: std.socket.SocketOSException runtime/phobos/std/socket.d(2674): Unable to connect socket: No such file or directoryAny pointers?instead of: string socket_name = "\0/var/run/ptmd.socket"; try: string socket_name = "/var/run/ptmd.socket"; works for me
 Jun 25 2015
On 06/25/2015 08:56 AM, freeman wrote:
 I am having trouble using abstract sockets on Linux.
 Here is sample python code that works, which works:
      ptm_sockname = "\0/var/run/ptmd.socket"
      sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
      sock.connect(ptm_sockname)
      sock.setblocking(1)
      sock.sendall('get-status detail')
 Similar code in D, which does not work:
      string socket_name = "\0/var/run/ptmd.socket";
      auto address = new UnixAddress(socket_name);
      auto sock = new Socket(AddressFamily.UNIX, SocketType.STREAM);
      scope(exit) sock.close();
      sock.blocking = true;
      sock.connect(address);
      sock.send("get-status detail");
 This is the equivalent with socat, which works:
      $ echo "get-status detail" | socat -
 ABSTRACT-CLIENT:/var/run/ptmd.socket
 My test D program exits on connect:
 std.socket.SocketOSException runtime/phobos/std/socket.d(2674): Unable
 to connect socket: Connection refused
 Any pointers?
I've found an old example of mine, which uses abstract sockets. 
Apparently, it was a concurrency experiment as well. Just translated 
from Turkish to English:
   http://ddili.org/ornek_kod/client_server.d
One difference I see is that mine doesn't set blocking. You can use it 
like this:
1) Start it as a server:
   ./deneme --role=server
2) Start as many clients as needed:
   ./deneme --role=client
Ali
P.S. And here is the original Turkish version:
   http://ddili.org/ornek_kod/istemci_sunucu.d
 Jun 25 2015
On Thursday, 25 June 2015 at 19:47:37 UTC, Ali Çehreli wrote:I've found an old example of mine, which uses abstract sockets. Apparently, it was a concurrency experiment as well. Just translated from Turkish to English: http://ddili.org/ornek_kod/client_server.d One difference I see is that mine doesn't set blocking. You can use it like this: 1) Start it as a server: ./deneme --role=server 2) Start as many clients as needed: ./deneme --role=client Ali P.S. And here is the original Turkish version: http://ddili.org/ornek_kod/istemci_sunucu.dThank you for the example code! I verified that client and server communicated, and that a standard file-based unix socket was not created. Then I simply changed the socketName to the socket I was interested in, and tried the client against it. Still no luck unfortunately, same error as earlier. I have noticed that successful connect calls appear to show the size as 23, whereas unsuccessful connect calls show 24. This works (socat): connect(3, {sa_family=AF_FILE, path= "/var/run/ptmd.socket"}, 23) = 0 This does not (from deneme, modified): connect(3, {sa_family=AF_FILE, path= "/var/run/ptmd.socket"}, 24) = -1 ECONNREFUSED (Connection refused)
 Jun 26 2015
On Friday, 26 June 2015 at 13:36:49 UTC, freeman wrote:
 This works (socat):
     connect(3, {sa_family=AF_FILE, 
 path= "/var/run/ptmd.socket"}, 23) = 0
 This does not (from deneme, modified):
     connect(3, {sa_family=AF_FILE, 
 path= "/var/run/ptmd.socket"}, 24) = -1 ECONNREFUSED 
 (Connection refused)
Looks like contrary to other sockets, name of an abstract socket 
is treated as byte array instead of a string, hence every byte 
counts.
 Jun 26 2015
On Thursday, 25 June 2015 at 15:56:06 UTC, freeman wrote:
 I am having trouble using abstract sockets on Linux.
 Here is sample python code that works, which works:
     ptm_sockname = "\0/var/run/ptmd.socket"
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
     sock.connect(ptm_sockname)
     sock.setblocking(1)
     sock.sendall('get-status detail')
 Similar code in D, which does not work:
     string socket_name = "\0/var/run/ptmd.socket";
     auto address = new UnixAddress(socket_name);
     auto sock = new Socket(AddressFamily.UNIX, 
 SocketType.STREAM);
     scope(exit) sock.close();
     sock.blocking = true;
     sock.connect(address);
     sock.send("get-status detail");
 This is the equivalent with socat, which works:
     $ echo "get-status detail" | socat - 
 ABSTRACT-CLIENT:/var/run/ptmd.socket
 My test D program exits on connect:
 std.socket.SocketOSException runtime/phobos/std/socket.d(2674): 
 Unable to connect socket: Connection refused
 Any pointers?
OK, I believe I've figured it out.  The strace output I posted 
was the clue I needed to see what was going on.  The length of 
abstract sockets are seemingly improperly calculated.
In socket.d, I modified the constructor for UnixAddress as such:
         this(in char[] path)
         {
             //len = 
cast(socklen_t)(sockaddr_un.init.sun_path.offsetof + path.length 
+ 1);
             len = 
cast(socklen_t)(sockaddr_un.init.sun_path.offsetof + path.length);
             writefln("inside UnixSocket, len is %s", len);
             sun = cast(sockaddr_un*) (new ubyte[len]).ptr;
             sun.sun_family = AF_UNIX;
             sun.sun_path.ptr[0..path.length] = (cast(byte[]) 
path)[];
             sun.sun_path.ptr[path.length] = 0;
         }
This also explains why Ali's client/server code works with 
itself, but it doesn't work with my test case.
This seems to be a bug in socket.d.  If the first character of 
the path is a null character, do not add 1 to the length.  I 
don't have much socket programming experience, but my test code 
does work now.
My full test.d code follows, which now works as expected.  I 
compiled it with » ldc2 test.d std2/socket.d std2/socketstream.d. 
  The only modifications to socketstream.d was the module name and 
std.socket import.
     import std.stdio;
     import std2.socket;
     import std.stream;
     import std2.socketstream;
     void main() {
         enum string socket_name = "\0/var/run/ptmd.socket";
         auto address = new UnixAddress(socket_name);
         writefln("path is --%s--", address.path);
         writefln("length of string is --%s--", 
socket_name.length);
         writefln("length of address is --%s--", address.nameLen);
         auto sock = new Socket(AddressFamily.UNIX, 
SocketType.STREAM);
         scope(exit) sock.close();
         sock.blocking = true;
         sock.connect(address);
         writeln("connected!");
         Stream streamer = new SocketStream(sock);
         scope(exit) streamer.close();
         streamer.writeLine("get-status detail");
         while(true) {
             auto line = streamer.readLine();
             if (line.length == 0 || line == "EOF") {
                 break;
             }
             writeln(line);
         }
     }
Is this worthy of a bug report?  Not a lot of people use abstract 
sockets, but this was certainly frustrating for my use case :)
 Jun 26 2015
On 06/26/2015 07:39 AM, freeman wrote:Is this worthy of a bug report?If it's a bug, yes. :) Ali
 Jun 26 2015








 
  
  
 
 "freeman" <jamilio123+dlang gmail.com>
 "freeman" <jamilio123+dlang gmail.com> 