Can't find unit unixsockets lazarus / 66-Unix ---------------------------------------------------------------------- TCH · 2025-02-15 22:53 I am porting some C code to FreePascal which relies on macros like CMSG_LEN, CMSG_DATA, etc. and types like struct msghdr, struct cmsghdr, etc. I found these listed in here; for instance: https://www.freepascal.org/daily/packages/libc/libc/cmsghdr.html. It says, it is in unit libc. However, after putting uses libc into the code, i get this message:Code: [Select]Fatal: Can't find unit libc used by unit_nameAfter some searching for this error message, i found this topic and this manual page. Okay, so unit libc is not allowed. But what to use instead? The manuals do not say at all... After some more searching, i found this mail thread, which states, these are in unit unixsockets. Well, unixsockets is under packages/rtl-extra/src/unix/ all right, but when i put uses unixsockets into the code, i get this message:Code: [Select]Fatal: Can't find unit unixsockets used by unit nameSearching for this error message only yielded a supplementary unixsockets unit, but i'd rather use the one provided by the RTL. How can i use CMSG_LEN, struct msghdr, etc. with FreePascal? ---------------------------------------------------------------------- Thaddy · 2025-02-16 11:42 Why would you want a unit named linux sockets? The sockets unit is pure berkely sockets, so unix sockets... Their structures should also have equivalents in fcl-net. Maybe you want the translated syntax to mimic the C code simply too close and so you would want to work with code that is deprecated. Any code that requires the libc unit is deprecated, afaik, not the libc library. This may help: https://wiki.freepascal.org/libc_unit That also describes you should use sockets not unixsockets. In general it will help you port code in a more sane way, ---------------------------------------------------------------------- Alexx2000 · 2025-02-16 13:27 QuoteHow can i use CMSG_LEN, struct msghdr, etc. with FreePascal?Something like this. ---------------------------------------------------------------------- Thaddy · 2025-02-16 13:30 That would do the trick.. ---------------------------------------------------------------------- TCH · 2025-02-16 15:35 Quote from: Thaddy on February 16, 2025, 12:42:06 pmWhy would you want a unit named linux sockets? The sockets unit is pure berkely sockets, so unix sockets... What...? Seriously...what? Who wanted a unit named linux sockets? I explicitly wrote unixsockets several times. My post did not even contain the word "Linux". I have no idea what are you talking about.Quote from: Thaddy on February 16, 2025, 12:42:06 pmTheir structures should also have equivalents in fcl-net.Which are...?Quote from: Thaddy on February 16, 2025, 12:42:06 pmMaybe you want the translated syntax to mimic the C code simply too close and so you would want to work with code that is deprecated. Any code that requires the libc unit is deprecated, afaik, not the libc library. This may help: https://wiki.freepascal.org/libc_unitI know. I've even linked in the very same manual page what you did...Quote from: Thaddy on February 16, 2025, 12:42:06 pmThat also describes you should use sockets not unixsockets. In general it will help you port code in a more sane way,sockets has already been pulled in (i just forgot to mention it), but it did not provide CMSG_LEN and the rest.Quote from: Alexx2000 on February 16, 2025, 02:27:54 pmQuoteHow can i use CMSG_LEN, struct msghdr, etc. with FreePascal?Something like this.Thank you, but this is also just a supplementary unixsockets unit, just like the one made by md and what i use now. I'd like to stick to the RTL. Or do you mean, it is not possible to do it with unixsockets and that one has to provide those functions and structures by hand? ---------------------------------------------------------------------- Alexx2000 · 2025-02-16 15:54 I guess unixsockets unit simply is not installed (binary unixsockets.ppu). What Linux distro do you use? ---------------------------------------------------------------------- TCH · 2025-02-16 15:58 Debian 11, but i use the packages provided by the Lazarus Team, not by Debian Team. unixsockets.pp does exist in packages/rtl- extra/src/unix/. You say, it should be compiled to a PPU? I thought FreePascal automatically does that: if the .ppu does not exist, but the .pp or .pas does, then it compiles the source to a binary unit. Or that only applies to the local units, not the global ones? ---------------------------------------------------------------------- Alexx2000 · 2025-02-16 16:03 QuoteYou say, it should be compiled to a PPU?Yes. It is a standard practice of binary distro. QuoteI thought FreePascal automatically does thatIt can do it. But only if unit in the unit search paths. ---------------------------------------------------------------------- TCH · 2025-02-16 16:17 I see, thank you. I've tried to do fpc unixsockets.pp, but:Code: [Select]Free Pascal Compiler version 3.2.2 [2021/07/09] for x86_64 Copyright (c) 1993-2021 by Florian Klaempfl and others Target OS: Linux for x86-64 Compiling unixsockets.pp unixsockets.pp(12,2) Warning: Illegal compiler directive "$UNIXSOCKETSH" unixsockets.pp(16,2) Warning: Illegal compiler directive "$UNIXSOCKETS" 19 lines compiled, 0.0 sec 2 warning(s) issuedThe PPU was created, but i guess it is erroneous. Or not? What flags i should provide? ---------------------------------------------------------------------- Alexx2000 · 2025-02-16 16:35 Looks like this unit are buggy. It should be: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit unixsockets; {$mode objfpc}{$H+} {$packrecords C} interface uses  cTypes, BaseUnix;  {$I unixsocketsh.inc} implementation {$I unixsockets.inc} end. also you need to have files: Quotertl-extra\src\linux\unixsockets.inc rtl-extra\src\linux\unixsocketsh.incin the include files search paths. It looks like no one has even tried to compile it. ---------------------------------------------------------------------- TCH · 2025-02-16 16:57 Thanks, i fixed the file, but i cannot compile it. I tried to include the path with both -I and -Fi, but no avail. I tried /usr/share/fpcsrc/3.2.2/packages/rtl-extra/src/linux/, 3.2.2/packages/rtl-extra/src/linux/, packages/rtl-extra/src/linux/ and rtl-extra/src/linux/, but:Code: [Select]unixsockets.pp(12,2) Fatal: Cannot open include file "$unixsocketsh.inc"The file does exist, i've checked it. ---------------------------------------------------------------------- Alexx2000 · 2025-02-16 17:07 Are you fixed a unit as I show above? Quote-Fi/usr/share/fpcsrc/3.2.2/packages/rtl-extra/src/linux should work. But, looks like this unit a totally broken. I don't know why it is included in the FPC distro at all. ---------------------------------------------------------------------- TCH · 2025-02-16 17:28 I did, but i screwed up, i left the dollar sign at the beginning of the files... :/ Thanks, now it tries to compile, but fails:Code: [Select]unixsockets.inc(12,12) Error: Identifier not found "__cmsg_nxthdr" unixsockets.pp(20) Fatal: There were 1 errors compiling module, stoppingThis is caused by rtl-extra/src/linux/unixsockets.inc:12:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function CMSG_NXTHDR(mhdr: Pmsghdr; cmsg: Pcmsghdr): Pcmsghdr;begin   Result:=__cmsg_nxthdr(mhdr, cmsg);end;rtl- extra/src/linux/unixsockets.inc seems to be also buggy: it lacks this line:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function __cmsg_nxthdr(__mhdr:Pmsghdr; __cmsg:Pcmsghdr):Pcmsghdr;cdecl;external 'c' name '__cmsg_nxthdr';If i include it, then it dies with this message:Code: [Select]unixsocketsh.inc(32,12) Error: Forward declaration not solved "CMSG_DATA(Pcmsghdr):^Byte;"Which is caused, that rtl-extra/src/linux/unixsocketsh.inc:32 says:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   function CMSG_DATA(cmsg : pcmsghdr) : Pbyte;while rtl- extra/src/linux/unixsockets.inc:32 says:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function CMSG_DATA(cmsg: Pointer): PByte;I am not sure, but i guess, the header is correct and the body is erroneous. After changing cmsg: Pointer to cmsg: Pcmsghdr, the unit finally compiles. Whew... You were right. It was totally broken. Even the includes were. But now my unit finally compiles with using the bundled unixsockets unit. Thank you very much for your help. I think these fixes on the unit and the includes should be sent to FPC team. ---------------------------------------------------------------------- Thaddy · 2025-02-17 07:18 Quote from: Alexx2000 on February 16, 2025, 06:07:17 pmBut, looks like this unit a totally broken. I don't know why it is included in the FPC distro at all. It should be broken, must be broken otherwise and marked as deprecated, because it is deprecated and not maintained. It's presence is unwarranted and it should be removed to prevent people using it. I told you so, use sockets. Now somebody is writing code that is close to its grave at its conception. You should discourage such code, not try to fix it. ---------------------------------------------------------------------- Thaddy · 2025-02-17 07:30 Reported as request to mark deprecated on the bug tracker: #41152 but I temporary closed it because I can provide a patch. [edit] Re-opened without patch. That would be counter to the report. ---------------------------------------------------------------------- TCH · 2025-02-17 15:51 Quote from: Thaddy on February 17, 2025, 08:18:06 amI told you so, use sockets.If by sockets, you mean unit sockets, it was pulled in for other types, but did not provide CMSG_LEN and the rest. ---------------------------------------------------------------------- MarkMLl · 2025-02-17 16:06 I don't like getting involved /but/... Quote from: TCH on February 17, 2025, 04:51:36 pmQuote from: Thaddy on February 17, 2025, 08:18:06 amI told you so, use sockets.If by sockets, you mean unit sockets, it was pulled in for other types, but did not provide CMSG_LEN and the rest. ...and certain people who have been somewhat forward in telling you that you were doing everything wrong could instead have usefully turned their formidable intellects to answering your original question. Macros, particularly function-like macros that take one or more parameters, are very poorly served by FPC. However I have to ask here: what are you actually trying to do? I regularly mess around with sockets at a fairly low level (since the sort of thing I do isn't merely passing parameters to a website), but I don't immediately recognise the macros and structures you mention. Obligatory xkcd https://xkcd.com/1481/ MarkMLl ---------------------------------------------------------------------- Thaddy · 2025-02-17 16:24 Mark, the structures are elsewhere in the basic unix units, but may have slightly different names. After all these structures are needed for sockets. I maintain what I stated and I still haven't seen anything that warrants NOT to mark that unit as deprecated. ---------------------------------------------------------------------- MarkMLl · 2025-02-17 16:40 Quote from: Thaddy on February 17, 2025, 05:24:51 pmMark, the structures are elsewhere in the basic unix units, but may have slightly different names. After all these structures are needed for sockets. I maintain what I stated and I still haven't seen anything that warrants NOT to mark that unit as deprecated. Come on, you don't weasel out of it that easily. WHERE ARE THEY? MarkMLl ---------------------------------------------------------------------- Alexx2000 · 2025-02-17 18:22 Quote from: Thaddy on February 17, 2025, 08:18:06 amIt should be broken, must be broken otherwise and marked as deprecated The libc unit are deprecated, unixsockets are not deprecated. But it has bugs which we discussed above. ---------------------------------------------------------------------- MarkMLl · 2025-02-17 18:42 Quote from: Alexx2000 on February 17, 2025, 07:22:08 pmQuote from: Thaddy on February 17, 2025, 08:18:06 amIt should be broken, must be broken otherwise and marked as deprecated The libc unit are deprecated, unixsockets are not deprecated. But it has bugs which we discussed above. As would be apparent to anybody who took the trouble to read the thread. In practice, I'm fairly sure that fpSend() (for connected sockets, i.e. TCP) or fpSendTo() (for unconnected sockets, i.e. UDP) would do the trick. Having said that, and emphasising that OP hasn't told us what he's actually trying to do, I do have to say that there's areas in which the network stack (as implemented in FPC's RTL) hasn't had as much love as it deserves: things like SCTP support and a few of the more obscure ways of interacting with Pascal's Input/Output devices come to mind. MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-17 21:29 Quote from: MarkMLl on February 17, 2025, 05:06:04 pmMacros, particularly function-like macros that take one or more parameters, are very poorly served by FPC.They were there, although as functions. But that too works for me.Quote from: MarkMLl on February 17, 2025, 05:06:04 pmHowever I have to ask here: what are you actually trying to do?I was porting a C unit which transmits/receives live socket descriptors through datagram sockets. (To be able to pass an opened socket to another process.)Quote from: Alexx2000 on February 17, 2025, 07:22:08 pmQuote from: Thaddy on February 17, 2025, 08:18:06 amIt should be broken, must be broken otherwise and marked as deprecated The libc unit are deprecated, unixsockets are not deprecated. But it has bugs which we discussed above.We've already fixed the bugs, or have we? You've fixed the unit, i've fixed the includes and now both unixsockets and my unit compile. Sure, there is no patch (yet), but all of the fixes are documented here and there are only three small changes. Should i make a patch? ---------------------------------------------------------------------- MarkMLl · 2025-02-17 22:09 Quote from: TCH on February 17, 2025, 10:29:18 pmThey were there, although as functions. But that too works for me. Yes, but functions aren't macros. QuoteI was porting a C unit which transmits/receives live socket descriptors through datagram sockets. (To be able to pass an opened socket to another process.) OK, fpSendTo() works fine with datagrams. For strictly local use consider unix-domain sockets rather than UDP. QuoteShould i make a patch? Not necessarily, but you should certainly raise a bug report for those malformed include directives (possibly referencing anything incoherent that Thaddy attempted). MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-17 22:27 Quote from: MarkMLl on February 17, 2025, 11:09:15 pmYes, but functions aren't macros.I know, but in this case they were usable as a drop-in replacement.Quote from: MarkMLl on February 17, 2025, 11:09:15 pmOK, fpSendTo() works fine with datagrams. For strictly local use consider unix-domain sockets rather than UDP.But i did use unix domain sockets; they can be datagram ones and AFAIK to pass an FD to another process, one has to use datagram sockets. (Fixme?)Quote from: MarkMLl on February 17, 2025, 11:09:15 pmNot necessarily, but you should certainly raise a bug report for those malformed include directives (possibly referencing anything incoherent that Thaddy attempted).Okay. Where should i do that? On SourceForge, or GitLab, or GitHub, or here in a specific zone/group? Edit: Okay, i found, that it is GitLab. Edit: But i cannot log in to my GitLab account, because that stupid CloudFlare botchecker does not let me in. From Chromium, it simply gives back the checkbox each time i check in and from Pale Moon it simply never gives the checkbox. Great... ---------------------------------------------------------------------- MarkMLl · 2025-02-18 08:19 Quote from: TCH on February 17, 2025, 11:27:25 pmI know, but in this case they were usable as a drop-in replacement. Yes, it's the only way to do it but there's things that quite simply can't be expressed like that. QuoteBut i did use unix domain sockets; they can be datagram ones and AFAIK to pass an FD to another process, one has to use datagram sockets. (Fixme?) I don't entirely understand what you're doing with FDs, and it sounds- at the minimum- to be highly OS-specific (i.e. even if it works on Linux it might not work on Berkeley derivatives). But if you can do something with unix domain sockets, then I see no reason why UDP wouldn't work... until somebody tried to use it to send info between different hosts, or potentially different namespaces (i.e. containers etc.). QuoteOkay. Where should i do that? On SourceForge, or GitLab, or GitHub, or here in a specific zone/group? Edit: Okay, i found, that it is GitLab. Edit: But i cannot log in to my GitLab account, because that stupid CloudFlare botchecker does not let me in. From Chromium, it simply gives back the checkbox each time i check in and from Pale Moon it simply never gives the checkbox. Great... That one I can't help with, hopefully one of the core team will spot it. MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-18 13:26 There is a process, which opens a listener socket and waits for incoming connections, then accepts them. Then it passes the socket descriptor of the just connected client to a worker process. That's all. This works on BSD-s too, actually the code i used to build the original C unit is a BSD4.3/BSD4.4 code (with separate branches for them), so it should work on all POSIX systems.Quote from: MarkMLl on February 18, 2025, 09:19:00 amI don't entirely understand what you're doing with FDs, and it sounds- at the minimum- to be highly OS- specific (i.e. even if it works on Linux it might not work on Berkeley derivatives).Quote from: MarkMLl on February 18, 2025, 09:19:00 amBut if you can do something with unix domain sockets, then I see no reason why UDP wouldn't work... until somebody tried to use it to send info between different hosts, or potentially different namespaces (i.e. containers etc.).UDP does work, these are UDP unix domain sockets. This is for incoming FD-s:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var        name: string        sock: cint;        sa: sockaddr_un; ...         name := '/tmp/my_socket';        fpunlink(name);        sock := fpsocket(PF_UNIX, SOCK_DGRAM, 0);      fillbyte(sa, sizeof(sockaddr_un), 0);        sa.sun_family := AF_UNIX;        sa.sun_path := name;        fpbind(sock, Psockaddr(@sa), sizeof(sa.sun_family) + length(name));and this is for sending FD-s:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var        name: string;        sock: cint;        sa: sockaddr_un; ...         name := '/tmp/my_socket';        sock := fpsocket(PF_UNIX, SOCK_DGRAM, 0);        fillbyte(sa, sizeof(sockaddr_un), 0);        sa.sun_family := AF_UNIX;        sa.sun_path := name;        fpconnect(sock, Psockaddr(@sa), sizeof(sa.sun_family) + length(name));These are unix domain sockets, but datagram ones. And through these, you can send or receive live descriptors. ---------------------------------------------------------------------- MarkMLl · 2025-02-18 14:01 I think I've heard of such things, but am still somewhat wary. However Quote from: TCH on February 18, 2025, 02:26:15 pmUDP does work, these are UDP unix domain sockets. This is for incoming FD-s:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ...        sock := fpsocket(PF_UNIX, SOCK_DGRAM, 0);... I think you mean that they're /datagram/ UD sockets, UDP looks like Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ...dnsClientSocketHandle := fpSocket(PF_INET, SOCK_DGRAM, 0);...  MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-18 14:44 I was not sure. I've misinterpreted some sources and thought UDP sockets are the datagram sockets (never worked with them before), but i realized now, that UDP sockets are network datagram sockets. I used unix domain datagram sockets, not network ones, of course. I was working with these sources (and some other snippets): passfd.c from Sampo Kellomaki (attached, inlined at the end of the post) and ht tp://web.archive.org/web/20161002061943/http://users.cs.cf.ac.uk/Dave. Marshall/C/node28.html However, with SOCK_STREAM, i could not pass FD-s. Then i found this source, with portlisten.c: https://www.mail-archive.com/kragen- hacks@canonical.org/msg00002.html and tried SOCK_DGRAM. And with that it worked. passfd.c:Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i /* passfd.c  -  BSD style file descriptor passing over unix domain sockets * * Copyright (c) 2000 Sampo Kellomaki , All Rights Reserved. * This module may be copied under the same terms as the perl itself. * * See also: * recvmsg(2) * sendmsg(2) * Richard Stevens: Unix Network Programming, Prentice Hall, 1990; chapter 6.10 * /usr/include/socketbits.h * /usr/include/sys/socket.h */ #include #include #include #include  /* I test here for __sun for lack of anything better, but I * mean Solaris 2.6. The idea of undefining SCM_RIGHTS is * to force the headers to behave BSD 4.3 way which I have * tested to work. * * In general, if you have compilation errors, you might consider * adding a test for your platform here. */#if defined(__sun)#undef SCM_RIGHTS#endif #ifdef SCM_RIGHTS /* It seems various versions of glibc headers (i.e. * /usr/include/socketbits.h) miss one or more of these */ #ifndef CMSG_DATA# define CMSG_DATA(cmsg) ((cmsg)->cmsg_data)#endif #ifndef CMSG_NXTHDR# define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg)#endif #ifndef CMSG_FIRSTHDR# define CMSG_FIRSTHDR(mhdr) \  ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr)          \   ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL)#endif #ifndef CMSG_ALIGN# define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \                         & ~(sizeof (size_t) - 1))#endif #ifndef CMSG_SPACE# define CMSG_SPACE(len) (CMSG_ALIGN (len) \                         + CMSG_ALIGN (sizeof (struct cmsghdr)))#endif #ifndef CMSG_LEN# define CMSG_LEN(len)   (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))#endif union fdmsg {        struct cmsghdr h;        char buf[CMSG_SPACE(sizeof(int))];};#endif /* Tested to work on perl 5.005_03 *   Linux-2.2.14 glibc-2.0.7 (libc.so.6) i586  BSD4.4 *   Linux-2.0.38 glibc-2.0.7 (libc.so.6) i586  BSD4.4 *   SunOS-5.6, gcc-2.7.2.3, Sparc BSD4.3 * see also: linux/net/unix/af_unix.c */ intsendfd(sock_fd, send_me_fd)        int sock_fd;        int send_me_fd;{        int ret = 0;        struct iovec  iov[1];        struct msghdr msg;                iov[0].iov_base = &ret;  /* Don't send any data. Note: der Mouse                                * says                                * that might work better if at least one                                * byte is sent. */        iov[0].iov_len  = 1;                msg.msg_iov     = iov;        msg.msg_iovlen  = 1;        msg.msg_name    = 0;        msg.msg_namelen = 0;         {#ifdef SCM_RIGHTS                /* New BSD 4.4 way (ouch, why does this have to be                 * so convoluted). */                 union  fdmsg  cmsg;                struct cmsghdr* h;                 msg.msg_control = cmsg.buf;                msg.msg_controllen = sizeof(union fdmsg);                msg.msg_flags = 0;                              h = CMSG_FIRSTHDR(&msg);                h->cmsg_len   = CMSG_LEN(sizeof(int));                h->cmsg_level = SOL_SOCKET;              h->cmsg_type  = SCM_RIGHTS;                *((int*)CMSG_DATA(h)) = send_me_fd;#else                /* Old BSD 4.3 way. Not tested. */                msg.msg_accrights = &send_me_fd;              msg.msg_accrightslen = sizeof(send_me_fd);#endif                 if (sendmsg(sock_fd, &msg, 0) < 0) {                        ret = 0;                } else {                        ret = 1;              }        }        /*fprintf(stderr,"send %d %d %d %d\n",sock_fd, send_me_fd, ret, errno);*/        return ret;} intrecvfd(sock_fd)        int sock_fd;{        int count;      int ret = 0;        struct iovec  iov[1];        struct msghdr msg;              iov[0].iov_base = &ret;  /* don't receive any data */      iov[0].iov_len  = 1;                msg.msg_iov = iov;        msg.msg_iovlen = 1;        msg.msg_name = NULL;        msg.msg_namelen = 0;         {#ifdef SCM_RIGHTS                union fdmsg  cmsg;              struct cmsghdr* h;                 msg.msg_control = cmsg.buf;                msg.msg_controllen = sizeof(union fdmsg);              msg.msg_flags = 0;                                h = CMSG_FIRSTHDR(&msg);                h->cmsg_len   = CMSG_LEN(sizeof(int));                h->cmsg_level = SOL_SOCKET;  /* Linux does not set these */                h->cmsg_type  = SCM_RIGHTS;  /* upon return */                *((int*)CMSG_DATA(h)) = -1;                              if ((count = recvmsg(sock_fd, &msg, 0)) < 0) {                      ret = 0;                } else {                      h = CMSG_FIRSTHDR(&msg);   /* can realloc? */                      if (   h == NULL                            || h->cmsg_len    != CMSG_LEN(sizeof(int))                            || h->cmsg_level  != SOL_SOCKET                            || h->cmsg_type   != SCM_RIGHTS ) {                                /* This should really never happen */                                if (h)                                fprintf(stderr,                                    "%s:%d: protocol failure: %d %d %d\n",                                    __FILE__, __LINE__,                                    h->cmsg_len,                                  h->cmsg_level, h->cmsg_type);                              else                                  fprintf(stderr,                                  "%s:%d: protocol failure: NULL cmsghdr*\n",                                    __FILE__, __LINE__);                              ret = 0;                        } else {                                ret = *((int*)CMSG_DATA(h));                              /*fprintf(stderr, "recv ok %d\n", ret);*/                      }                }#else                int receive_fd;              msg.msg_accrights = &receive_fd;                msg.msg_accrightslen = sizeof(receive_fd);                 if (recvmsg(sock_fd, &msg, 0) < 0) {                        ret = 0;              } else {                        ret = receive_fd;              }#endif        }                /*fprintf(stderr, "recv %d %d %d %d\n",sock_fd, ret, errno, count);*/        return ret;} /* EOF  -  passfd.c */ ---------------------------------------------------------------------- MarkMLl · 2025-02-18 15:12 Note that you've got PF_something (program family) and then an indication of whether something's a datagram or a stream. You've also separately got AF_something (address family). SOCK_DGRAM usually means UDP (on PF_INET) or unix-domain sockets (on PF_UNIX), I'm not sure that SOCK_STREAM on PF_UNIX is a valid comobination. If you're using PF_INET then you also need AF_INET to specify an IP address... minor variations in there for v6. However like a FIFO a unix-domain socket is named: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i (* Return true if the parameter is blank, representing an anonymous pipe  normally set up by the shell.*)function isPipe(const name: string): boolean; begin  result := name = ''end { isPipe } ;  (* Return true if the parameter represents a regular file.*)function isFile(const name: string): boolean; var  s: stat; begin  if name = '' then    exit(false);  if fpStat(name, s{%H-}) <> 0 then    exit(false); (* The low 9 bits of the mode are the usual permissions, the next 3 bits are  *)(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of   *)(* object i.e. ordinary file, directory and so on. There might be additional  *)(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension  *)(* to the inode structure.                                                  *) // Does this need special handling for symlinks, or are they followed?   result := ((s.st_mode and S_IFMT) = S_IFREG) or ((s.st_mode and S_IFMT) = S_IFCHR)end { isFile } ;  (* Return true if the parameter represents a FIFO (named pipe).*)function isFifo(const name: string): boolean; var  s: stat; begin  if name = '' then    exit(false);  if fpStat(name, s{%H-}) <> 0 then    exit(false); (* The low 9 bits of the mode are the usual permissions, the next 3 bits are  *)(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of   *)(* object i.e. ordinary file, directory and so on. There might be additional  *)(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension  *)(* to the inode structure.                                                  *) // Does this need special handling for symlinks, or are they followed?   result := (s.st_mode and S_IFMT) = S_IFIFOend { isFifo } ;  (* Return true if the parameter represents a unix domain socket.*)function isUDSocket(const name: string): boolean; var  s: stat; begin  if name = '' then    exit(false);  if fpStat(name, s{%H-}) <> 0 then    exit(false); (* The low 9 bits of the mode are the usual permissions, the next 3 bits are  *)(* the sticky, setgid and setuid bits, leaving 4 bits to define the type of *)(* object i.e. ordinary file, directory and so on. There might be additional  *)(* filesystem-specific attribute bits stored elsewhere, e.g. in an extension  *)(* to the inode structure.                                                  *) // Does this need special handling for symlinks, or are they followed?   result := (s.st_mode and S_IFMT) = S_IFSOCKend { isUDSocket } ;  (* Reopen something that isn't a unix- domain socket.*)procedure reopenFile(var t: Text; const n: string; alreadyClosed: boolean= false); begin  if not alreadyClosed then    CloseFile(t);  AssignFile(t, n);  Rewrite(t)end { reopenFile } ;  (* This is a reimplementation of the standard Connect() since it doesn't  support a unix-domain address and truncates it if told to cast it to an  inet domain address structure.   Test using e.g.  $ nc -lkU ~/dsocket  noting the -k to prevent the listener  terminating when the writer (this program) closes the connection.*)Function Connect(Sock:longint;const addr: TUnixSockAddr;var SockIn,SockOut:text):Boolean;    Function DoConnect(Sock:longint;const addr: TUnixSockAddr): Boolean;   var    res: longint;  begin    repeat      res:=fpconnect(Sock,@Addr,SizeOF(TUnixSockAddr)); (* NOTA BENE *)    until (res<>-1) or (SocketError <> EsockEINTR);    DoConnect:= res = 0;  end;  begin  Connect:=DoConnect(Sock,addr);  If Connect then     Sock2Text(Sock,SockIn,SockOut);end { Connect } ;  var  reopenedInput: Text;                  (* Dummy since only output is used      *)  (* Reopen a unix-domain socket. This needs special implementation of Connect()  as above.*)procedure reopenUDSocket(var t: Text; const n: string; alreadyClosed: boolean= false); var  skt: TSocket;  ipcAddr: TUnixSockAddr; begin  if not alreadyClosed then    CloseFile(t);  skt:= fpSocket(PF_UNIX, SOCK_STREAM, 0);  if skt < 0 then begin    if not quiet then      WriteLn(erroutput, 'Cannot create unix-domain socket handle');    Halt(9)  end;  FillChar(ipcAddr{%H-}, SizeOf(ipcAddr), 0);  ipcAddr.family:= AF_UNIX;  StrPCopy(ipcAddr.path, n);  if not Connect(skt, ipcAddr, reopenedInput, t) then begin    if not quiet then begin      Write(erroutput, 'Cannot open unix-domain socket "' + n + '" ');      if not FileExists(n) then        WriteLn(erroutput, '(does not exist)')      else        WriteLn(erroutput, '(check listener is running)');      Halt(9)    end  end;{$push }{$I- }  Reset(reopenedInput);{$pop        }  Rewrite(t)end { reopenUDSocket } ;  ...and that you might need to remove the names from the filesystem when your program finishes, or take special precautions when it starts and finds that the name already exists. Updated: C&P more example code so that it includes reworked Connect() etc. MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-18 18:57 Quote from: MarkMLl on February 18, 2025, 04:12:38 pmNote that you've got PF_something (program family) and then an indication of whether something's a datagram or a stream.I think you meant protocol family.Quote from: MarkMLl on February 18, 2025, 04:12:38 pmSOCK_DGRAM usually means UDP (on PF_INET) or unix-domain sockets (on PF_UNIX), I'm not sure that SOCK_STREAM on PF_UNIX is a valid comobination.It is not? This SO-topic says, it is:QuoteThe main difference is that one is connection based (STREAM) and the other is connection-less (DGRAM) - the difference between stream and packet oriented communication is usually much less important. With SOCK_STREAM you still get all the connection handling, i.e. listen/accept and you can tell if a connection is closed by the other side.Of course, he might be wrong, i am not an expert on sockets.Quote from: MarkMLl on February 18, 2025, 04:12:38 pmIf you're using PF_INET then you also need AF_INET to specify an IP address...Yep, i know, but this was IPC, not network.Quote from: MarkMLl on February 18, 2025, 04:12:38 pm...and that you might need to remove the names from the filesystem when your program finishes, or take special precautions when it starts and finds that the name already exists.Yes, i did: i do fpunlink(name) before the fpsocket call. Edit: Forgot to thank you for your pipe code; thanks. ---------------------------------------------------------------------- MarkMLl · 2025-02-19 08:07 Quote from: TCH on February 18, 2025, 07:57:09 pmI think you meant protocol family. You are of course quite right. Apropos _DGRAM vs _STREAM: more to the point, unix(7) says that both are acceptable, albeit with a couple of protocol caveats... and I'd need to think hard about some of the things I've used it for. However in the current case I thing it's best to focus on the "dgram vs stream" rather than "connected vs unconnected" aspect, since if you're passing block data around (i.e. FDs) you really do need datagrams. QuoteEdit: Forgot to thank you for your pipe code; thanks. You're welcome, I grabbed it in a hurry but forgot to check the dgram vs stream aspect... that might actually have all been streams since I was handling piped (etc.) data from a logic analyser to convert it into a standard format (and had checked the various channels fairly thoroughly). MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-19 14:51 Quote from: MarkMLl on February 19, 2025, 09:07:15 amApropos _DGRAM vs _STREAM: more to the point, unix(7) says that both are acceptable, albeit with a couple of protocol caveats... and I'd need to think hard about some of the things I've used it for. However in the current case I thing it's best to focus on the "dgram vs stream" rather than "connected vs unconnected" aspect, since if you're passing block data around (i.e. FDs) you really do need datagrams.So, that's why SOCK_STREAM did not worked: no blocks, just a stream of bytes without any particular meaning. Thanks, for pointing out. ---------------------------------------------------------------------- MarkMLl · 2025-02-19 15:23 Quote from: TCH on February 19, 2025, 03:51:51 pmSo, that's why SOCK_STREAM did not worked: no blocks, just a stream of bytes without any particular meaning. Thanks, for pointing out. Probably, or at the very least blocks getting merged arbitrarily. That's one reason why, when it was still unclear what you were doing, I threw SCTP into the mix: it's somewhat (!) more complex ("designed by committee" is the phrase that springs to mind), but offers reliable block delivery over a network (provided that the in-path routers etc. support it, which is rare). I've realised that I missed out some very juicy stuff from the example code I C&Ped yesterday, and am about to go back and extend it. MarkMLl ---------------------------------------------------------------------- TCH · 2025-02-20 00:36 Quote from: MarkMLl on February 19, 2025, 04:23:33 pmQuote from: TCH on February 19, 2025, 03:51:51 pmSo, that's why SOCK_STREAM did not worked: no blocks, just a stream of bytes without any particular meaning. Thanks, for pointing out. Probably, or at the very least blocks getting merged arbitrarily. That's one reason why, when it was still unclear what you were doing, I threw SCTP into the mix: it's somewhat (!) more complex ("designed by committee" is the phrase that springs to mind), but offers reliable block delivery over a network (provided that the in-path routers etc. support it, which is rare).No, i've never worked with SCTP. As a matter of fact, i did not even ever heard of it, but after a quick search, i think i am not alone with that: it is not very widespread.Quote from: MarkMLl on February 19, 2025, 04:23:33 pmI've realised that I missed out some very juicy stuff from the example code I C&Ped yesterday, and am about to go back and extend it.I think you should make a unit of it and commit it into the FPC RTL, or publish it in your repo. ---------------------------------------------------------------------- PascalDragon · 2025-02-20 20:48 Quote from: TCH on February 20, 2025, 01:36:37 amQuote from: MarkMLl on February 19, 2025, 04:23:33 pmQuote from: TCH on February 19, 2025, 03:51:51 pmSo, that's why SOCK_STREAM did not worked: no blocks, just a stream of bytes without any particular meaning. Thanks, for pointing out. Probably, or at the very least blocks getting merged arbitrarily. That's one reason why, when it was still unclear what you were doing, I threw SCTP into the mix: it's somewhat (!) more complex ("designed by committee" is the phrase that springs to mind), but offers reliable block delivery over a network (provided that the in-path routers etc. support it, which is rare).No, i've never worked with SCTP. As a matter of fact, i did not even ever heard of it, but after a quick search, i think i am not alone with that: it is not very widespread. It's more widespread than you might realize, cause it's one of the core protocols used by WebRTC which is supported by all modern browsers and other applications that use WebRTC to provide peer-to- peer communication. ---------------------------------------------------------------------- TCH · 2025-02-20 21:09 Perhaps the found topics and articles were too old. ---------------------------------------------------------------------- MarkMLl · 2025-02-20 21:09 Quote from: PascalDragon on February 20, 2025, 09:48:48 pmIt's more widespread than you might realize, cause it's one of the core protocols used by WebRTC which is supported by all modern browsers and other applications that use WebRTC to provide peer-to-peer communication. In fairness, /can/ be used by would be a better way of putting it. It works peer-to-peer on a local LAN, it works over a tunnel provided that the relevant ISPs are competent ** , but IME is not at all well- supported across commodity routers and firewalls. It's definitely got its good points, but an "SCTP lite" which offered reliable datagram transmission (i.e. like UD sockets but between systems) would go down well. ** Which is a strong argument for end-to-end encryption: if intermediate carriers can't see what's in there they aren't likely to try to filter it. MarkMLl ---------------------------------------------------------------------- duralast · 2025-02-20 21:56 Quote from: TCH on February 20, 2025, 01:36:37 amNo, i've never worked with SCTP. As a matter of fact, i did not even ever heard of it, but after a quick search, i think i am not alone with that: it is not very widespread. The Stream Control Transmission Protocol (SCTP) was originally designed by the Signaling Transport (SIGTRAN) group of IETF for Signalling System 7 (SS7) transport over IP-based networks. It is a reliable transport protocol operating on top of an unreliable connectionless service, such as IP. More info on SCTP is available in the Oracle Help Center at https://do cs.oracle.com/cd/E95618_01/html/sbc_scz810_acliconfiguration/GUID- 8D95AA21-4530-4E02-90FB-032E3856CC80.htm ---------------------------------------------------------------------- TCH · 2025-02-20 22:17 Thanks, i'll read it. ---------------------------------------------------------------------- PascalDragon · 2025-02-22 15:08 Quote from: MarkMLl on February 20, 2025, 10:09:42 pmQuote from: PascalDragon on February 20, 2025, 09:48:48 pmIt's more widespread than you might realize, cause it's one of the core protocols used by WebRTC which is supported by all modern browsers and other applications that use WebRTC to provide peer-to-peer communication. In fairness, /can/ be used by would be a better way of putting it. It works peer-to-peer on a local LAN, it works over a tunnel provided that the relevant ISPs are competent ** , but IME is not at all well- supported across commodity routers and firewalls. I can personally attest that it works rather well if it's set up correctly. We use it in one of our products at work to provide remote VNC in the browser. As long as one side is not connected to a symmetric NAT it will most likely be able to establish a connection using hole punching and otherwise a TURN relay will be used. This is completely transparent to the user of WebRTC (and it will use SCTP in any case, because the WebRTC suite is based on UDP sockets and thus needs something(TM) to make it reliable). Quote from: MarkMLl on February 20, 2025, 10:09:42 pmIt's definitely got its good points, but an "SCTP lite" which offered reliable datagram transmission (i.e. like UD sockets but between systems) would go down well. Then you might want to take a look at QUIC.