Forum > Unix

Textfiles and unix-domain sockets

<< < (2/3) > >>

MarkMLl:
Couple of questions arising from this.

The first is that Connect() is marked deprecated but fpConnect() isn't overlaid with Text or File parameters... what should I be using here?

The second is that Connect() doesn't have an overlaid variant with the TUnixSockAddr parameter which is needed for a unix-domain socket (which is /specifically/ what I was asking about when I stared the thread)... any comments?

I could probably hack this from the sockets POV, but I'm concerned that this would be merely a slippery slope and that changes would be needed in WriteLn() etc. if the existing socket support is entirely for the inet domain.

MarkMLl

marcov:

--- Quote from: MarkMLl on January 02, 2022, 09:09:15 pm ---Couple of questions arising from this.

The first is that Connect() is marked deprecated but fpConnect() isn't overlaid with Text or File parameters... what should I be using here?

--- End quote ---

Non FP version might have 1.0.x errorhandling that is not entirely ok. fp* versions have error handling the same as the APIs it connects too.

MarkMLl:
Connect() fails with a unix-domain socket since the length of the address structure is truncated when it's passed to fpConnect() internally.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  var    reopenedInput: Text;                (* Placeholder, probably not needed     *)    procedure reopenUDSocket(var t: Text; const n: string);   type    TSockAddr= record                 case boolean of                   false: (inet: TInetSockAddr);                   true:  (udom: TUnixSockAddr)                 end;   var    skt: TSocket;    ipcAddr: TSockAddr;     i: integer;   begin    CloseFile(t);    skt:= fpSocket(PF_UNIX, SOCK_STREAM, 0);    if skt < 0 then begin      if not quiet then        WriteLn(stderr, 'Cannot create unix-domain socket handle');      Halt(9)    end;    FillChar(ipcAddr, SizeOf(ipcAddr), 0);    ipcAddr.udom.family:= AF_UNIX;    StrPCopy(ipcAddr.udom.path, n);  i := fpConnect(skt, @ipcAddr.inet, SizeOf(ipcAddr.inet));   // <---- this fails i := fpConnect(skt, @ipcAddr.inet, SizeOf(ipcAddr.udom));   // <---- this works     if not Connect(skt, ipcAddr.inet, reopenedInput, t) then begin // <---- this fails      if not quiet then        WriteLn(stderr, 'Cannot open unix-domain socket "' + n + '"');      Halt(9)    end;    Rewrite(t)  end { reopenUDSocket } ; 
MarkMLl

MarkMLl:
I've added this:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  (* 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.  *)  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 } ; 
If it fails, check whether the file exists; if it exists then it probably means that the listener has terminated.

Test with e.g.

$ nc -lkU ~/dsocket

If the -k option is omitted then Netcat will terminate without deleting the placeholder in the filesystem when the writer closes the connection.

MarkMLl

RickE:
I got a little "sequential packet Unix (local) socket" unit working, and was impressed with the sequential packet vs. stream socket type. Linux rightly brags about such a useful feature. In years past I would make a formatted web page to down load, but please forgive if I just try insert some code here;


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---UNIT LocalPacketSockets_Text_Unit;{******************************************************************************        FREEPASCAL LINUX C LIBRARY SOCKETS INTERFACE******************************************************************************} {*****************************************************************************}INTERFACE{$PACKRECORDS C}Uses Sockets_Text_Unit;{*****************************************************************************} {==============================================================================        LOCAL (UNIX) PACKET SOCKETS INTERFACE==============================================================================}Const{ Unix/Local Domain Socket Address Family }        AF_LOCAL = 1;        AF_UNIX = AF_LOCAL; { Unix/Local Domain Socket Types }        SOCK_STREAM = 1;                { Sequenced, reliable, connection-based byte streams. }        SOCK_SEQPACKET = 5;             { Sequenced, reliable, connection-based datagrams of fixed maximum length.} { Unix/Local Protocol Family }        PF_UNSPEC = 0;                  { Unspecified. Normally OK. }        PF_LOCAL = 1;                   { Local to host (pipes and file-domain). }        PF_UNIX = PF_LOCAL;             { POSIX name for PF_LOCAL. }         SOMAXCONN =     128;            { Maximum connect queue length specifiable by listen. }        Max_ConnectQueue = SOMAXCONN;         Max_SockAddrLength = 110;{ longest possible unix local domain socket address record } Type{ FreePascal String Type variable to hold a "FileName" }        t_UnixSocket_FilePathName = String[107]; { FreePascal Record Type variable to hold the C Structure parameter }        p_UnixSocket_AddressRecord = ^t_UnixSocket_AddressRecord ;        t_UnixSocket_AddressRecord = Record                                                                AddressFamily: word;                                                                FilePathName: array[0..107] of char;                                                                End; { t_UnixSocket_AddressRecord } { ============================================================================ }{ Create a New Local Packet Type Socket FileDescriptor. Returns False for errors. }Function CreateNew_LocalPacketSocket_OK( var param_var_NewSocketFD: Longint ): Boolean;  { Bind a Local Packet Type Socket FileDescriptor to a New Socket FilePathName. Returns False for errors. }Function Bind_LocalPacketSocket_PathName_OK( param_SocketFD: longint;                                                                                const param_NewSocketFilePathName: t_UnixSocket_FilePathName ):                                                                                Boolean; { Server Listens on a Local Packet Type Socket FileDescriptor for Client Connection Requests. Returns False for errors. }Function Listen_LocalPacketSocket_OK( param_ServerSocketFD,                                                                                param_MaxConnectRequests: Longint ):                                                                                Boolean; { Client Requests a Connection to a Listening  Local Packet Type Socket FileName. Create New Text Type I/O Channels on Client FileDescriptor. Returns False for errors. }Function ConnectRequest_NewTextPacketSocket_OK( param_ClientSocketFD: longint;                                                                                                const param_ServerSocket_FilePathName: t_UnixSocket_FilePathName;                                                                                                var param_var_NewClientTextInputChannel: Text;                                                                                                var param_var_NewClientTextOutputChannel: Text ):                                                                                                Boolean; { Server Accepts a Client Connection Request on a Listening Local Domain Server Socket FileDescriptor. Create a New AcceptConnection FileDescriptor on Server Socket. Create New Text Type I/O Channels on New Server Socket AcceptConnection FileDescriptor. Returns False for errors. }Function AcceptRequest_NewTextPacketSocket_OK( param_ServerSocketFD : longint;                                                                                                var param_var_NewAcceptConnectFD: longint;                                                                                                var param_var_ClientSocket_FilePathName: t_UnixSocket_FilePathName ;                                                                                                var param_var_NewServerTextInputChannel: Text;                                                                                                var param_var_NewServerTextOutputChannel: Text ):                                                                                                Boolean; {*****************************************************************************}IMPLEMENTATION{*****************************************************************************} { Construct t_UnixSocket_AddressRecord }Procedure PathName_to_SockAddrRec(const param_UnixSocket_FilePathName: t_UnixSocket_FilePathName;                                                                var param_var_SockAddrRecord: t_UnixSocket_AddressRecord;                                                                var param_var_SockAddrRecordLength: longint );        Begin        { Fill in AddressFamily field }                param_var_SockAddrRecord.AddressFamily := 1 ;   {AF_UNIX}         { Fill in FilePathName field with all 0s ==>> null terminated }            FillByte ( param_var_SockAddrRecord.FilePathName,                                SizeOf( param_var_SockAddrRecord.FilePathName ),                                0 );         { Assign FilePathName field }                Move( param_UnixSocket_FilePathName[1],                                param_var_SockAddrRecord.FilePathName,                                length( param_UnixSocket_FilePathName ) );         { Calculate sizeof(sockaddr_un) := sizeof(sa_family_t) + sizeof(sun_path) + sizeof(null character ) }                param_var_SockAddrRecordLength:= 2 + Length( param_UnixSocket_FilePathName ) + 1 ;         End; { Procedure PathName_to_SockAddrRec } { ============================================================================ }{ Create a NEW SOCKET of DOMAIN, TYPE, PROTOCOL. }{ Returns a new file descriptor for the new socket, or -1 for errors.   }{ Uses domain: AF_LOCAL = 1, type: SOCK_SEQPACKET = 5. }{ ============================================================================ }{libc}        Function LibcCall_Socket( __domain: longint;                                                                __type: longint;                                                                __protocol: longint ):                                                                longint; cdecl; external 'c' name 'socket'; { ---------------------------------------------------------------------------- }{ Libc Functions ==>> Pascal Functions }{ ---------------------------------------------------------------------------- }Function CreateNew_LocalPacketSocket_OK( var param_var_NewSocketFD: Longint ): Boolean;        Var                loc_var_LibcCall_Return : longint ;        Begin        { Initialize }                param_var_NewSocketFD := -1;                CreateNew_LocalPacketSocket_OK := False;         { Do Linux libc call }                loc_var_LibcCall_Return := LibcCall_Socket( 1, 5, 0 );         { If Success }                If loc_var_LibcCall_Return > 0                        Then                        Begin                                param_var_NewSocketFD := loc_var_LibcCall_Return;                                CreateNew_LocalPacketSocket_OK := True;                        End;         End; { Function CreateNew_LocalPacketSocket_OK } { ============================================================================ }{ Bind a Local Unix Socket FileName to a Local Unix Socket FileDescriptor }{ Give the Local Unix Socket FD the Local Unix Socket Address Record (which is LEN bytes long). }{ ============================================================================ }{libc}        Function LibcCall_Bind( __fd: longint ;                                                                __addr: p_UnixSocket_AddressRecord;                                                                __len: longint ):                                                                longint; cdecl; external 'c' name 'bind'; { ---------------------------------------------------------------------------- }{ Libc Functions ==>> Pascal Functions }{ ---------------------------------------------------------------------------- }Function Bind_LocalPacketSocket_PathName_OK( param_SocketFD: longint;                                                                                        const param_NewSocketFilePathName: t_UnixSocket_FilePathName ):                                                                                        Boolean;        Var                loc_var_SockAddrRecord:                 t_UnixSocket_AddressRecord;                loc_var_SockAddrRecordLength:   longint;                loc_var_LibcCall_Return:        longint;        Begin        { Initialize }                Bind_LocalPacketSocket_PathName_OK := False;         { Construct UnixDomainSocketAddress_Record }                PathName_to_SockAddrRec( param_NewSocketFilePathName,                                                                        loc_var_SockAddrRecord,                                                                        loc_var_SockAddrRecordLength );        { Do Linux libc call }                loc_var_LibcCall_Return := LibcCall_Bind( param_SocketFD,                                                                                                @loc_var_SockAddrRecord,                                                                                                loc_var_SockAddrRecordLength );        { If Success }                If loc_var_LibcCall_Return = 0                        Then Bind_LocalPacketSocket_PathName_OK := True;         End; { Function Bind_LocalPacketSocket_PathName_OK } { ============================================================================ }{ Listen and Wait until a Client Connection Request on Server Socket FD. }{ Server Listens prepared to accept connections on socket FD. }{ N connection requests will be queued before further requests are refused.}{ ============================================================================ }{libc}        Function LibcCall_Listen( __fd : longint ;                                                                __n : longint ):                                                                longint; cdecl; external 'c' name 'listen'; { ---------------------------------------------------------------------------- }{ Libc Functions ==>> Pascal Functions }{ ---------------------------------------------------------------------------- }Function Listen_LocalPacketSocket_OK( param_ServerSocketFD,                                                                                        param_MaxConnectRequests: Longint ):                                                                                        Boolean;        Var                loc_var_LibcCall_Return: longint;        Begin        { Initialize }                Listen_LocalPacketSocket_OK := False ;         { Do Linux libc call }                loc_var_LibcCall_Return := LibcCall_Listen( param_ServerSocketFD,                                                                                                        param_MaxConnectRequests );        { If Success }                If loc_var_LibcCall_Return = 0                        Then Listen_LocalPacketSocket_OK := True;         End; { Function Listen_LocalPacketSocket_OK } { ============================================================================ }{ Client Requests a connection to a Listening Server Socket FileName }{ Open a Connection on Client Socket FD to Server Socket at ADDR .}{ ============================================================================ }{libc}        Function LibcCall_Connect( __fd : longint ;                                                                __addr : p_UnixSocket_AddressRecord ;                                                                __len : longint ):                                                                longint; cdecl; external 'c' name 'connect'; { ---------------------------------------------------------------------------- }{ Libc Functions ==>> Pascal Functions }{ ---------------------------------------------------------------------------- }Function ConnectRequest_NewTextPacketSocket_OK( param_ClientSocketFD: longint;                                                                                        const param_ServerSocket_FilePathName: t_UnixSocket_FilePathName ;                                                                                        var param_var_NewClientTextInputChannel: Text ;                                                                                        var param_var_NewClientTextOutputChannel: Text ):                                                                                        Boolean;        Var                loc_var_ServerSockAddrRecord:           t_UnixSocket_AddressRecord;                loc_var_ServerSockAddrRecordLength:     longint;                loc_var_LibcCall_Return:                longint;         Begin        { Initialize }                ConnectRequest_NewTextPacketSocket_OK := False ;         { Construct UnixSockAddrRecord Path to Server }                PathName_to_SockAddrRec( param_ServerSocket_FilePathName,                                                                                loc_var_ServerSockAddrRecord,                                                                                loc_var_ServerSockAddrRecordLength ) ;        { Do Linux libc call }                loc_var_LibcCall_Return := LibcCall_Connect( param_ClientSocketFD,                                                                                                        @loc_var_ServerSockAddrRecord,                                                                                                        loc_var_ServerSockAddrRecordLength ) ;        { If Success }                If loc_var_LibcCall_Return = 0                        Then                        { Construct NEW Socket Communication channels }                        Begin                                Assign_SocketFD_to_SocketIO_TextChannels( param_ClientSocketFD,                                                                                                                        param_var_NewClientTextInputChannel,                                                                                                                        param_var_NewClientTextOutputChannel );                                 ConnectRequest_NewTextPacketSocket_OK := True ;                        End         End; { Function ConnectRequest_NewTextPacketSocket_OK } { ============================================================================ }{ When a Client Connection Request arrives, }{  create a NEW Server AcceptConnect Socket FD to communicate with it, }{  set  ADDR to the Address Record of the connecting Client Peer, }{  and return the new Server AcceptConnect Socket File Descriptor, or -1 for errors. }{ ============================================================================ }{libc}        Function LibcCall_Accept( __fd: longint;                                                                __addr: p_UnixSocket_AddressRecord;                                                                __addr_len: pLongint ):                                                                longint; cdecl; external 'c' name 'accept'; { ---------------------------------------------------------------------------- }{ Libc Functions ==>> Pascal Functions }{ ---------------------------------------------------------------------------- }Function AcceptRequest_NewTextPacketSocket_OK( param_ServerSocketFD : longint ;                                                                                                var param_var_NewAcceptConnectFD: longint;                                                                                                var param_var_ClientSocket_FilePathName: t_UnixSocket_FilePathName;                                                                                                var param_var_NewServerTextInputChannel: Text;                                                                                                var param_var_NewServerTextOutputChannel : Text ):                                                                                                Boolean;        var                loc_var_NewAcceptConnectFD: longint;                loc_var_ClientSockAddrRecord: t_UnixSocket_AddressRecord;                loc_var_ClientSockAddrRecordLength: longint;                loc_var_LibcCall_Return: longint;         Begin        { Initialize }                AcceptRequest_NewTextPacketSocket_OK := False;         { Initialize SockAddrRecord }                loc_var_ClientSockAddrRecord.FilePathName := '' ;         { Create enough space for return variable }                loc_var_ClientSockAddrRecordLength := Max_SockAddrLength;         { Do Linux libc call }                loc_var_LibcCall_Return := LibcCall_Accept( param_ServerSocketFD,                                                                                                @loc_var_ClientSockAddrRecord,                                                                                                @loc_var_ClientSockAddrRecordLength ) ;        { If Success }                If loc_var_LibcCall_Return > 0                        Then                        Begin                        { Set the NEW Server Connection ID }                                param_var_NewAcceptConnectFD := loc_var_LibcCall_Return ;                                loc_var_NewAcceptConnectFD := loc_var_LibcCall_Return ;                         { Construct returned Client Name String }                                Move( loc_var_ClientSockAddrRecord.FilePathName,                                                param_var_ClientSocket_FilePathName[1],                                                loc_var_ClientSockAddrRecordLength - 3 );                                 SetLength( param_var_ClientSocket_FilePathName,                                                        loc_var_ClientSockAddrRecordLength - 3 );                          { Construct NEW Socket Communication channels }                                Assign_SocketFD_to_SocketIO_TextChannels( loc_var_NewAcceptConnectFD,                                                                                                                        param_var_NewServerTextInputChannel,                                                                                                                        param_var_NewServerTextOutputChannel );                                 AcceptRequest_NewTextPacketSocket_OK := True;                        End         End ; { Function AcceptRequest_NewTextPacketSocket_OK } {******************************************************************************Initialize Unit******************************************************************************}Begin{ nothing }End.   

And always to thank the FreePascal team for their wonderful development system.

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version