Quiche (and BoringSSL) bindings lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 14:47 Hi everyone! I'm trying to create binding for Quiche, I managed to map several functions but as it's my very first time creating any bindings, I faced some issues. First I used H2Pas but the result was overwhelming, it seemed to need plenty of manual adjustment so for educational purposes I decided to do it manually from the ground up. I started with seemingly most important functions, testing them on-the-go. I managed to map several BoringSSL functions needed to create SSL context and a couple of Quiche functions needed to create a QUIC connection  Till this point, everything seemed to be working, so I took up quiche_conn_recv and that's where I faced first issues. I mapped it the same way I learn so far but calling it gives me Access violation. the header: 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 typedef struct {    struct sockaddr *from;    socklen_t from_len;    struct sockaddr *to;    socklen_t to_len;} quiche_recv_info; ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,                       const quiche_recv_info *info); mapped as: 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 typePQuiche_conn = ^Quiche_conn;  Quiche_conn = record  end; Pquiche_recv_info = ^quiche_recv_info;  quiche_recv_info = record      from : Psockaddr;      from_len : socklen_t;      to_ : Psockaddr;  //'to_' since 'to' is a reserved word      to_len : socklen_t;    end;  quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;                 info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; and the way I call the function: 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  bytes_received: CSsize_t;  buf: array of Byte;  //buffer: array[0..8191] of Char;  recv_info: Quiche_recv_info;  Precv_info: PQuiche_recv_info; SetLength(buf, 8192);FillChar(recv_info, SizeOf(recv_info), 0);Precv_info := @recv_info; bytes_received := quiche_conn_recv(conn, @buf[0], length(buf), Precv_info);  I was experimenting with the parameters but I wasn't able to make it work and I'm not sure if the problem is the mapping of the function or the parameters I pass to. Calling quiche_conn_recv is giving: QuoteAn unhandled exception occurred at $00007F22FA45392A:                                                                                          EAccessViolation: Access violation                                $00007F22FA45392A                                                 -------------------------------------------------- After being stuck at this for a couple of days, I peeked on the file generated by H2Pas and it looks different to my solution: 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 type  Pquiche_conn = ^quiche_conn;  Pquiche_recv_info = ^quiche_recv_info;    quiche_recv_info = record          from : Psockaddr;          from_len : socklen_t;          to : Psockaddr;          to_len : socklen_t;        end;    function quiche_conn_recv(var conn:quiche_conn; var buf:uint8_t; buf_len:size_t;                         var info:quiche_recv_info):ssize_t;cdecl;external External_library name 'quiche_conn_recv'; here, var conn:quiche_conn and var info:quiche_recv_info are not pointers. I'm puzzled. Any clue what I'm doing wrong? thanks in advance! ---------------------------------------------------------------------- Fred vS · 2024-10-06 15:30 Hello. Maybe try with this: 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 quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;             var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; (I know, using var when C uses const is strange but in many translation of header it is what was done.) ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 15:49 thanks for such a quick response. your solution has some effect, it's still an error but not Access violation: Quotethread '' panicked at src/ffi.rs:1891:14:                                                                                       not implemented: unsupported address type                                  stack backtrace:                                                     0:     0x7f88be87f055 -                                                                                       1:     0x7f88be8a16bb -                             2:     0x7f88be87cf5f -                                                                 3:     0x7f88be87ee2e -     4:     0x7f88be8800e9 -                                         5:     0x7f88be87fe8a -                                                                           6:     0x7f88be880583 -                 7:     0x7f88be88042b -                                                     8:     0x7f88be87f519 -                                                                                       9:     0x7f88be880197 -                            10:     0x7f88be708343 -                                                                11:     0x7f88be721a33 -    12:     0x7f88be7643ce - quiche_conn_recv                                               13:           0x402594 - $main                                                                                                          at ... ---------------------------------------------------------------------- Fred vS · 2024-10-06 16:10 OK, so could you try with this: 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  ...  buf: PByte;  ...   GetMem(buf, 8192);  ...  bytes_received := quiche_conn_recv(conn, @buf, 8192, Precv_info); ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 16:22 I tried your recommendation but I'm getting the same error :/ ---------------------------------------------------------------------- Fred vS · 2024-10-06 16:40 Quote from: r.lukasiak on October 06, 2024, 06:22:12 pmI tried your recommendation but I'm getting the same error :/  :'( Did you try to add in your pascal header ?: 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 {$PACKRECORDS C} If you get the same error when using array of Byte vs PByte, it could be that the error comes form Precv_info who is not filled correctly. What is the declaration of Psockaddr and socklen_t? Maybe use a declaration from ctype.pas instead. ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 17:01 Quote{$PACKRECORDS C} Thanks for reminding me this! I noticed this in some other bindings when I was gathering intel on the topic but I eventually forgot to try it. I did it now tho, but the error persist :/ QuoteWhat is the declaration of Psockaddr and socklen_t?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 typesocklen_t = cuint32; //from BaseUnixPsockaddr from Sockets ---------------------------------------------------------------------- Fred vS · 2024-10-06 17:09 Hum, Quiche resists... Dont worry we will win. Of course, you did check if conn was assigned with something like this: 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 if assigned(conn) thenbytes_received := quiche_conn_recv(conn, @buf, 8192, Precv_info)else writeln('Conn is not assigned ;-( ); I will do a walk with the dog, maybe a new idea will appear. ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 17:31 QuoteHum, Quiche resists... Dont worry we will win.this sounds promising! QuoteOf course, you did check if conn was assigned with something like this: yes, I tested conn itself in several ways. It was my first suspect but it turned out to be innocent. 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   if conn = nil then    begin      WriteLn('Failed to create QUIC connection.');    Exit;    end else    WriteLn('QUIC connection created successfully: ',PtrUInt(SSL) ); ..  if Assigned(conn) then writeln('conn assigned') else writeln('conn NOT assigned');..   if quiche_conn_is_established(conn)       then WriteLn('QUIC connection IS established already.')       else WriteLn('QUIC connection ISN''T established yet.');..  quiche_conn_stats(conn, Stats);  //it returns some values, I didn't dig into their making any sense but at first glance everything seems ok   and how about quiche_recv_info? 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 Pquiche_recv_info = ^quiche_recv_info;  quiche_recv_info = record    from : Psockaddr;      from_len : socklen_t;      to_ : Psockaddr;  //'to_' since 'to' is a reserved word      to_len : socklen_t;    end;   is it ok if the name of the 'to' field is changed? For obvious reasons it can't be 'to', but I'm not sure if it matters. I also tried 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 PQuiche_Recv_Info = ^Quiche_Recv_Info;Quiche_recv_info = recordend;  as far as I understand, this way I leave the record as it originally is or am I wrong? ---------------------------------------------------------------------- Fred vS · 2024-10-06 17:45 Quote from: r.lukasiak on October 06, 2024, 07:31:57 pmand how about quiche_recv_info? 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 Pquiche_recv_info = ^quiche_recv_info;  quiche_recv_info = record    from : Psockaddr;      from_len : socklen_t;      to_ : Psockaddr;  //'to_' since 'to' is a reserved word      to_len : socklen_t;    end;   is it ok if the name of the 'to' field is changed? For obvious reasons it can't be 'to', but I'm not sure if it matters. Hum, I dont know, I always use the same name as the one from the C headers but maybe it has no importance, only the index is used and the name does not matter. Sure somebody here can confirm/infirm this. Quote Code: [Select]PQuiche_Recv_Info = ^Quiche_Recv_Info; Quiche_recv_info = record end;  as far as I understand, this way I leave the record as it originally is or am I wrong? Sorry again, I dont know ;-( ---------------------------------------------------------------------- Fred vS · 2024-10-06 18:07 Quoteis it ok if the name of the 'to' field is changed? For obvious reasons it can't be 'to', but I'm not sure if it matters. A fast check gives this: https://stackoverflow.com/questions/17920716/is-it-possible-to-use- reserved-words-for-field-names And the great news is that fpc also allows the "&" operator. So you may try with this: 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 quiche_recv_info = record      from : Psockaddr;      from_len : socklen_t;      &to : Psockaddr;  //'to_' since 'to' is a reserved word      to_len : socklen_t;    end; And by the way, also try with quiche_recv_info = packed record ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 18:28 Quote&totrue...  QuoteAnd by the way, also try with quiche_recv_info = packed record ahh yes, I tried this when you reminded me about {$PACKRECORDS C}. I'm sorry I forgot to mention. The error persists :| ---------------------------------------------------------------------- Fred vS · 2024-10-06 18:48 Quote from: r.lukasiak on October 06, 2024, 08:28:54 pmThe error persists :| Maybe try with a bigger buffer: GetMem(buf, 8192 * 4); It would be great to know from where the error comes, from the filing of the buffer or the filling of quiche_recv_info. And the debugger seems not very cooperative. Maybe try with a buffer of char to see if the error is the same as with a buffer of byte. If the error is the same, there is a problem with the buffer. And try using a quiche_recv_info with record defined surely wrong to see if the error is the same. Once we know who is the guilty, he will pay. ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 19:02 Bigger buffer,not PChar did the trick.The error is still the same. QuoteAnd the debugger seems not very cooperative. I'm on Gentoo Linux, I tried to rebuild Quiche with the debug flag but it fails and it seems to be a known issue. I also dowloaded the source and compiled it manualjy but it's giving me some linking error when I try to build my program.It looks like Quiche objects to debugging ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 19:10 ...and messing with Quiche_Recv_Info doesn't change anything when it comes to the error but... I do 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 writeln('SizeOf(recv_info)=',SizeOf(recv_info));right before calling quiche_conn_recv and the result reflects changes in the definition of Quiche_Recv_Info; when it's (supposedly) correct, it returns 21, after I modified the record, it returned 24 but when I leave it "as it is",without deifning fields, it returns 0.I'm not sure if this information may help in anything. ---------------------------------------------------------------------- Fred vS · 2024-10-06 19:14 Quote from: r.lukasiak on October 06, 2024, 09:02:26 pmBigger buffer,not PChar did the trick.The error is still the same. QuoteAnd the debugger seems not very cooperative. I'm on Gentoo Linux, I tried to rebuild Quiche with the debug flag but it fails and it seems to be a known issue. I also dowloaded the source and compiled it manualjy but it's giving me some linking error when I try to build my program.It looks like Quiche objects to debugging Yes, I understand you totally, I just ended a hard battle to make libfdk-aac-2.so decode aac webstream and it takes me lot of white nights and hair. For dealing with C libraries, I prefer to use dynamic loading using loadlibrary() and then assign and test each methods. But it needs more work than using "external" but gives more control too. ---------------------------------------------------------------------- Fred vS · 2024-10-06 19:19 Quote from: r.lukasiak on October 06, 2024, 09:10:50 pm...and messing with Quiche_Recv_Info doesn't change anything when it comes to the error but... I do 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 writeln('SizeOf(recv_info)=',SizeOf(recv_info));right before calling quiche_conn_recv and the result reflects changes in the definition of Quiche_Recv_Info; when it's (supposedly) correct, it returns 21, after I modified the record, it returned 24 but when I leave it "as it is",without deifning fields, it returns 0.I'm not sure if this information may help in anything. Sorry, not sure to understand, can you access recv_info after calling quiche_conn_recv() ? I was thinking that after quiche_conn_recv there was a crash. ---------------------------------------------------------------------- TRon · 2024-10-06 19:30 don't mess with packed record, use packrecords c instead (though it is rust so do not know if that does the same layout as c. I assumed it does) 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 {$mode objfpc}{$h+}{$packrecords c} uses  unixtype, sockets; type  // A QUIC connection.  // typedef struct quiche_conn quiche_conn;  Tquiche_conn = record end;  Pquiche_conn = ^Tquiche_conn;   Pquiche_recv_info = ^Tquiche_recv_info;  Tquiche_recv_info = record    // The remote address the packet was received from.    from     : psockaddr;    from_len : socklen_t;     // The local address the packet was received on.    &to      : psockaddr;    to_len   : socklen_t;  end;    function quiche_conn_recv(conn: pquiche_conn; buf: pcuint8; buf_len: size_t; const info: pquiche_recv_info): ssize_t; cdecl; blah blah and blah blah Is what I am able to come up with. Do you perhaps need to change the struct to specifically use ip4 vs ip6 ? Quote from: r.lukasiak on October 06, 2024, 09:10:50 pmright before calling quiche_conn_recv and the result reflects changes in the definition of Quiche_Recv_Info; when it's (supposedly) correct, it returns 21, after I modified the record, it returned 24 but when I leave it "as it is",without deifning fields, it returns 0.I'm not sure if this information may help in anything. 32 bit or 64 bit os ? on 64-bit it should read 32 (on 32-bit 8 bytes less). ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 19:32 QuoteI was thinking that after quiche_conn_recv there was a crash.  yes, it crashed AFTER quiche_conn_recv but I do  SizeOf(recv_info) right BEFORE and it returns different values, depending on its definition. ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 19:57 thanks for joining, TRon! Quotedon't mess with packed record, use packrecords c insteadok, I'm back to just record with {$packrecords c} but Quotefunction quiche_conn_recv(conn: pquiche_conn; buf: pcuint8; buf_len: size_t; const info: pquiche_recv_info): ssize_t; cdecl;is giving Access violation as it was in the very beginning of this post :| Quotethough it is rust so do not know if that does the same layout as cthis was actually my concern right when I started facing errors but till now I was able to somehow solve them, conn_recv seems to be exceptionally stubborn tho. However... There is this: 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 type PQuiche_stats = ^Quiche_stats;  Quiche_stats = record    recv: QWord;    sent: QWord;    lost: QWord;    retrans: QWord;    delivered: QWord;    delivered_time: QWord;    smoothed_rtt: QWord;    rttvar: QWord;    min_rtt: QWord;    pkt_tx_count: QWord;    pkt_rx_count: QWord;  end;    var  Stats: Quiche_stats;..quiche_conn_stats(conn, Stats);    WriteLn('Connection Statistics:');    WriteLn('Packets received: ', stats.recv);    WriteLn('Packets sent: ', stats.sent);  WriteLn('Packets lost: ', stats.lost);    WriteLn('Retransmissions: ', stats.retrans);    WriteLn('Delivered: ', stats.delivered);    WriteLn('Delivery time: ', stats.delivered_time);    WriteLn('Smoothed RTT: ', stats.smoothed_rtt);    WriteLn('RTT variance: ', stats.rttvar);    WriteLn('Minimum RTT: ', stats.min_rtt);    WriteLn('Packet TX count: ', stats.pkt_tx_count);    WriteLn('Packet RX count: ', stats.pkt_rx_count);  and it works like a charm, regardless {$packrecords c}. I just converted it the way I just learnt and I didn't have a single error here. ---------------------------------------------------------------------- TRon · 2024-10-06 20:10 Quote from: r.lukasiak on October 06, 2024, 09:57:42 pmthanks for joining, TRon! You're most welcome. Quoteand it works like a charm, regardless {$packrecords c}. I just converted it the way I just learnt and I didn't have a single error here. Ok, hold on a moment. That is not what I see at https://github.com/clo udflare/quiche/blob/master/quiche/include/quiche.h What version of the header are you using/converting ? That last structure you showed should be 112 bytes not 88 :-/ Quoteis giving Access violation as it was in the very beginning of this post :| See previous question. I converted the function as expressed in the header in the provided link. If that still crashes for you then something else must be off. I am already a bit scared about the 21 and 24 bits you mentioned earlier. Could you share the order of which you include the units in your uses clause (both interface and implementation) ? 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 {$mode objfpc}{$h+}{$packrecords c} uses  unixtype, sockets;   type  Tquiche_stats = record    // The number of QUIC packets received on this connection.    recv : size_t;     // The number of QUIC packets sent on this connection.    sent : size_t;     // The number of QUIC packets that were lost.    lost : size_t;     // The number of sent QUIC packets with retransmitted data.    retrans : size_t;     // The number of sent bytes.    sent_bytes : uint64;     // The number of received bytes.    recv_bytes : uint64;     // The number of bytes acked.    acked_bytes : uint64;     // The number of bytes lost.    lost_bytes : uint64;     // The number of stream bytes retransmitted.    stream_retrans_bytes : uint64;     // The number of known paths for the connection.    paths_count : size_t;     // The number of streams reset by local.    reset_stream_count_local : uint64;     // The number of streams stopped by local.    stopped_stream_count_local: uint64;     // The number of streams reset by remote.    reset_stream_count_remote : uint64;     // The number of streams stopped by remote.    stopped_stream_count_remote : uint64;  end; ---------------------------------------------------------------------- TRon · 2024-10-06 20:22 My apologies I need to correct myself about some earlier statements about size: 32-bit: sizeof(Tquiche_recv_info) = 16 sizeof(Tquiche_stats)     = 92 64-bit: sizeof(Tquiche_recv_info) = 32 sizeof(Tquiche_stats)     = 112 ---------------------------------------------------------------------- tetrastes · 2024-10-06 20:54 It would be useful to write simple C program showing these sizeofs and compare them. ---------------------------------------------------------------------- Fred vS · 2024-10-06 23:08 Quote from: r.lukasiak on October 06, 2024, 09:57:42 pmHowever... There is this: 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 type PQuiche_stats = ^Quiche_stats;  Quiche_stats = record    recv: QWord;    sent: QWord;    lost: QWord;    retrans: QWord;    delivered: QWord;    delivered_time: QWord;    smoothed_rtt: QWord;    rttvar: QWord;    min_rtt: QWord;    pkt_tx_count: QWord;    pkt_rx_count: QWord;  end;    var  Stats: Quiche_stats;..quiche_conn_stats(conn, Stats);    WriteLn('Connection Statistics:');    WriteLn('Packets received: ', stats.recv);    WriteLn('Packets sent: ', stats.sent);  WriteLn('Packets lost: ', stats.lost);    WriteLn('Retransmissions: ', stats.retrans);    WriteLn('Delivered: ', stats.delivered);    WriteLn('Delivery time: ', stats.delivered_time);    WriteLn('Smoothed RTT: ', stats.smoothed_rtt);    WriteLn('RTT variance: ', stats.rttvar);    WriteLn('Minimum RTT: ', stats.min_rtt);    WriteLn('Packet TX count: ', stats.pkt_tx_count);    WriteLn('Packet RX count: ', stats.pkt_rx_count);  and it works like a charm, regardless {$packrecords c}. I just converted it the way I just learnt and I didn't have a single error here. Hum, in the C header, the method is defined like this: 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 void quiche_conn_stats(const quiche_conn *conn, quiche_stats *out); Where conn and out are pointers. But in your code: 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 quiche_conn_stats(conn, Stats); only conn is a pointer, Stats is a Quiche_stats = record. And it works like charm!  May I ask you how you defined quiche_conn_stats() in your Pascal header? So, maybe do the same for quiche_conn_recv()? 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     quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;                 var info: Quiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; var      ...      buf: PByte;      recv_info: Quiche_recv_info;      ...           GetMem(buf, 8192*8);  // big buffer      ...      bytes_received := quiche_conn_recv(conn, @buf, 8192, recv_info); Yes it should be strange if it works but all is strange those days. ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 23:10 QuoteOk, hold on a moment. That is not what I see at https://github.co m/cloudflare/quiche/blob/master/quiche/include/quiche.h indeed... now I'm wondering what I was looking at when I was converting this... and what makes me think even more, why this even worked? I was able to get the stats.... But I think it just proves that the name of the field doesn't matter, as long as the size is ok. I had fewer fields so it didn't exceed the real size. Anyway,now I corrected it and it's 112 bytes. Quote Could you share the order of which you include the units in your uses clause (both interface and implementation) ?I actually have uses only in the interface section: 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 interface usesCTypes, Sockets, BaseUnix;  QuoteI am already a bit scared about the 21 and 24 bits you mentioned earliernow I checked and sizeof(Tquiche_recv_info) = 32, it was 24 when I was trying packed records and 21 was when I was trying @Fred's suggestion to enter random data into the record to see if there is any reaction. now it'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 PQuiche_Recv_Info = ^TQuiche_Recv_Info;  TQuiche_Recv_Info = record    from : Psockaddr;      from_len : socklen_t;      &to : Psockaddr;    to_len : socklen_t;  end; and it weights 32 bytes ---------------------------------------------------------------------- r.lukasiak · 2024-10-06 23:29 @Fred vS QuoteMay I ask you how you defined quiche_conn_stats() in your Pascal header? now I see your point... 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  procedure quiche_conn_stats(var conn:PQuiche_conn; var _out:TQuiche_stats); cdecl; external QUICHE_LIB; but how the heck it didn't cause any error? o.O now I corrected it: 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 procedure quiche_conn_stats(var conn:PQuiche_conn; var &out:PQuiche_stats); cdecl; external QUICHE_LIB; //edit: "_out" -> "&out"  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  Stats: TQuiche_stats;  PStats: PQuiche_stats;    quiche_conn_stats(conn, PStats);    WriteLn('Connection Statistics:');    Writeln('SIZE='+SizeOf(Stats).ToString);    WriteLn('Packets received: ', stats.recv);    WriteLn('Packets sent: ', stats.sent);    WriteLn('Packets lost: ', stats.lost);    WriteLn('Retransmissions: ', stats.retrans);   and it still "works like a charm" and returns the same values  QuoteSo, maybe do the same for quiche_conn_recv()? Now I made changes and it's like you suggested but we're back to QuoteAn unhandled exception occurred at $00007F4392F4F9B1:                                                      EAccessViolation: Access violation                                                                                        $00007F4392F4F9B1           -------------------------------------------------- ---------------------------------------------------------------------- Fred vS · 2024-10-06 23:47 Ok, so the good news is that using recv_info: PQuiche_recv_info makes the app less sad. A other try with this? 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     quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                   var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; A other target to test is the result of the function and first test it alone ( without bytes_received := ) to see if the error is in CSsize_t result (should not but who knows) 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 quiche_conn_recv(conn, @buf, 8192, recv_info); ---------------------------------------------------------------------- r.lukasiak · 2024-10-07 00:04 QuoteA other target to test is the result of the function and first test it alone ( without bytes_received := ) to see if the error is in CSsize_t result (should not but who knows)calling the function without bytes_received :=  unfortunately doesn't change anything. Quotequiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                    var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;applied but it didn't change anything either :/ I need to go out in a moment and I'll be offline for almost 24h. When I'm back I'll clean the code because I have so many comments that I'm almost getting lost in the code. I'll clean it and post here entirely to have a better picture. ---------------------------------------------------------------------- TRon · 2024-10-07 00:09 Quote from: r.lukasiak on October 07, 2024, 01:10:19 amindeed... now I'm wondering what I was looking at when I was converting this... Keep in mind that whatever you were using for the conversion might (still) be valid. I linked to trunk (current development version) while you might be basing your conversion of another version of the library. Hnece why I asked about which version of the library you are using. Quoteand what makes me think even more, why this even worked? I was able to get the stats.... But I think it just proves that the name of the field doesn't matter, as long as the size is ok. I had fewer fields so it didn't exceed the real size. Anyway,now I corrected it and it's 112 bytes. It does not have to be the correct size. When bigger you are left with some data that is undetermined when smaller you (the call to the library function) might be overwriting memory that is in use with your program (which is able to lead to all kinds of strange issues, from access violation to other variables declared in your program being overwritten). The whole point of not using f.e. hard-coded Qword's is that most library headers (and the library itself) are made to work for different platforms. If you hard-code such definitions you make it fail when compiling for another target (not to mention that you never know if f.i. a record field is actually hard-coded by the library to be 32 bit or to change depending on the platform). Thank you for sharing the order of your uses clause. I had the idea that perhaps the last included unit was overriding some of the earlier unit types (that does not appear to be the case). BTW good that you are now able to show the same results that I have for the sizes of the records. another BTW and it is imho. Pascalifying c-headers is all nice and dandy but for initial conversion it is a no-no. There are many c function calls that allow for a pointer to a record to be nil so that the function can act differently. Using var declarations prevent that from ever being possible. If you can't make it work in the basics using the c declarations then it will become a guessing game as of why things fail when using pascalified parameter declarations. Either way, you would have to choose which path to follow because when I keep posting my suggestions (pure c translation) it will mess with your head when also trying Fred's suggestions (pascalified). in any way, a pointer to a record structure (in c) is not the same as a var parameter to a pointer to a record (in pascal). PS: is there any way I can install this library without the need to depend on rust (I really do not want that on my dev machine) ---------------------------------------------------------------------- Fred vS · 2024-10-07 00:20 Quote from: TRon on October 07, 2024, 02:09:45 amEither way, you would have to choose which path to follow because when I keep posting my suggestions (pure c translation) it will mess with your head when also trying Fred's suggestions (pascalified). I'm just trying to help, from the most logical translation from C to Pascal. It doesn't work so I suggested other ways but of course your path is better and I'll let you find the solution that you will surely find easily. Good night TRon and sorry for the shadow. ---------------------------------------------------------------------- TRon · 2024-10-07 00:48 Quote from: Fred vS on October 07, 2024, 02:20:32 amI'm just trying to help, from the most logical translation from C to Pascal. I did not state anywhere that you weren't trying to help. I chipped in because I did see a potential disaster coming up. Still is because there are too many unanswered and unseen variables in play. QuoteIt doesn't work so I suggested other ways And there is nothing wrong with that. I applaud you for it but guessing things without any further knowledge on what TS is working with is imho not the way to go. Quotebut of course your path is better and I'll let you find the solution that you will surely find easily. I did not say my path is better, it is imho more logical e.g. literally translating c to its pascal counterpart. Pascalifying you can do when things are known to work so that you have a (working) reference. Have you ever tried filing a bug-report using a fancy pascalified function declaration ? I for one am only able to do that with a literal translation which means the same bug appears when using c itself. QuoteGood night TRon and sorry for the shadow. A very good night to you as well (although I presume you meant it in a sarcastic way, sbi), and imho you are by any means not a shadow. all I did see is you trying to help TS but not knowing all the facts (we still don't know them). Translating headers is a precise and tiresome work and I have seen many things go wrong in so many ways that it isn't fun anymore. In this day and age I still regularly stumble upon translated headers that are 32-bit hard-coded and of course preferably windows only. I do not even use them as a starting point but start from scratch instead. And I did not even mention the lack of using proper pascal prefixes. But never mind all that. I was explicitly providing TS with a choice so that I am able to step back from this topic depending on what route TS wishes to take. I do not want to confuse him/her any further with my postings. Sorry to have upset you Fred. That was most certainly not my intention. ---------------------------------------------------------------------- Fred vS · 2024-10-07 01:11 Quote from: TRon on October 07, 2024, 02:48:55 amQuoteIt doesn't work so I suggested other ways And there is nothing wrong with that. I applaud you for it but guessing things without any further knowledge on what TS is working with is imho not the way to go. I like to guess things I already have a lot of trouble with like translating many C headers that work with buffers and internet connections and do not work out-of-the-box. Peace and have fun. Fre;D ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 09:27 I see you had some disagreement... I hope it won't discourage you from further helping me  I was cleaning the code and I merged all into 1 file to make it easier to paste here. I stripped it down to bare minimum and for now I have: 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 program project1; {$mode objfpc}{$H+}{$PACKRECORDS C} {$L ./libs/libssl.so}{$L ./libs/libcrypto.so}//{$L ./libs/libquiche_dbg.so} uses  {$IFDEF UNIX}  cthreads,  {$ENDIF}  Classes,  Crt, SysUtils, CTypes, BaseUnix, Sockets; type  CSsize_t = NativeInt;   PQuiche_config = ^TQuiche_config;  TQuiche_config = record  end;   PQuiche_conn = ^TQuiche_conn;  TQuiche_conn = record  end;   PSSL_METHOD = ^TSSL_METHOD;  TSSL_METHOD = record  end;   PSSL_CTX = ^TSSL_CTX;  TSSL_CTX = record  end;   PSSL = ^TSSL;  TSSL = record  end;   PQuiche_Recv_Info = ^TQuiche_Recv_Info;  TQuiche_Recv_Info = record    from : Psockaddr;      from_len : socklen_t;      &to : Psockaddr;    to_len : socklen_t;  end;   PQuiche_stats = ^TQuiche_stats;  Tquiche_stats = record    recv : size_t;    sent : size_t;    lost : size_t;    retrans : size_t;    sent_bytes : uint64;    recv_bytes : uint64;    acked_bytes : uint64;    lost_bytes : uint64;    stream_retrans_bytes : uint64;    paths_count : size_t;    reset_stream_count_local : uint64;    stopped_stream_count_local : uint64;    reset_stream_count_remote : uint64;    stopped_stream_count_remote : uint64;  end; var  i: integer;  ch: Char;  PConfig: Pquiche_config;  Pctx: PSSL_CTX;  SSL: PSSL;  method: PSSL_METHOD;  isServer: boolean = true;  scid, odcid: array[0..15] of Byte;  Pconn: PQuiche_conn;  Stats: TQuiche_stats;  PStats: PQuiche_stats;  localAddr, peerAddr: TSockAddr;  trace_id: PByte;  trace_id_len: Csize_t;  buf: PByte;  BUF_SIZE: size_t = 8192 * 4;  recv_info: TQuiche_recv_info;  Precv_info: PQuiche_recv_info;  bytes_received: CSsize_t; const  QUICHE_LIB = 'libquiche.so';  BORINGSSL_LIB = 'libssl.so';  CRYPTO_LIB = 'libcrypto.so';  QUICHE_PROTOCOL_VERSION = 1;  TLS1_3_VERSION = $0304; //0x0304  SSL_FILETYPE_PEM = 1;  SSL_OP_NO_RENEGOTIATION = 0; {---------- BORINGSSL ----------}function OpenSSL_version_num: cint; cdecl; external CRYPTO_LIB;function TLS_method: PSSL_METHOD; cdecl; external BORINGSSL_LIB;function SSL_CTX_new(const method: PSSL_METHOD): PSSL_CTX; cdecl; external BORINGSSL_LIB;procedure SSL_CTX_set_min_proto_version(ctx: PSSL_CTX; version: cint); cdecl; external BORINGSSL_LIB;procedure SSL_CTX_set_max_proto_version(ctx: PSSL_CTX; version: cint); cdecl; external BORINGSSL_LIB;function SSL_CTX_use_certificate_file(ctx: PSSL_CTX; const filename: PChar; type_: cint): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_use_PrivateKey_file(ctx: PSSL_CTX; const filename: PChar; type_: cint): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_check_private_key(ctx: PSSL_CTX): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_set_options(ctx: PSSL_CTX; options: UInt32 ): UInt32; cdecl; external BORINGSSL_LIB;function SSL_new(ctx: PSSL_CTX): PSSL; cdecl; external BORINGSSL_LIB; {---------- QUICHE ----------}function quiche_version: PChar; cdecl; external QUICHE_LIB;function quiche_config_new(version: UInt32): PQuiche_config; cdecl; external QUICHE_LIB;function quiche_config_load_cert_chain_from_pem_file(var config: TQuiche_config; path: Pansichar) : longint; cdecl; external QUICHE_LIB;function quiche_config_load_priv_key_from_pem_file(var config: TQuiche_config; path: Pansichar): longint;cdecl;external QUICHE_LIB;function quiche_conn_new_with_tls(const scid: PByte; scid_len: csize_t;                                  const odcid: PByte; odcid_len: csize_t;                                  const local: PSockAddr; local_len: csize_t;                                const peer: PSockAddr; peer_len: csize_t;                                const config: PQuiche_config; ssl: PSSL;                                is_server: Boolean): PQuiche_conn;                                cdecl; external QUICHE_LIB;function quiche_conn_is_established(var conn: PQuiche_conn): Boolean; cdecl; external QUICHE_LIB;function quiche_conn_is_closed(var conn:PQuiche_conn):Boolean; cdecl; external QUICHE_LIB;procedure quiche_conn_trace_id(const conn: PQuiche_Conn; var out: PByte; var out_len: Csize_t); cdecl; external QUICHE_LIB;procedure quiche_conn_source_id(const conn: PQuiche_Conn; var out: PByte; var out_len: Csize_t); cdecl; external QUICHE_LIB;procedure quiche_conn_stats(var conn:PQuiche_conn; var &out:PQuiche_stats); cdecl; external QUICHE_LIB; //function quiche_conn_recv(var conn:PQuiche_conn; buf:PByte; buf_len:csize_t; info:PQuiche_recv_info):cssize_t; cdecl; external QUICHE_LIB;{H2Pas}//function quiche_conn_recv(var conn:quiche_conn; var buf:Cuint8; buf_len:Csize_t; var info:quiche_recv_info):Cssize_t;cdecl;external QUICHE_LIB name 'quiche_conn_recv';//function quiche_conn_recv(var conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;  //                        var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;{TRon}  //function quiche_conn_recv(conn: pquiche_conn; buf: pcuint8; buf_len: size_t; const info: pquiche_recv_info): ssize_t; cdecl; external QUICHE_LIB;{Fred}// function quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;        //           var info: TQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;{Fred2} function quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                  var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; begin  writeln('Quiche version: ', quiche_version); //returns: 0.22.0  writeln('BoringSSL version: ', Format('%d.%d.%d.%d',                 [(OpenSSL_version_num shr 28) and $F,                  (OpenSSL_version_num shr 20) and $F,                (OpenSSL_version_num shr 12) and $F,                  (OpenSSL_version_num shr 4) and $F]));  //   Pconfig := quiche_config_new(QUICHE_PROTOCOL_VERSION);  if Pconfig = nil then writeln('Failed to create QUIC configuration')                   else writeln('QUIC configuration CREATED');   if quiche_config_load_cert_chain_from_pem_file(PConfig^, './keys/server.cert') = 0     then writeln('Cert OK') else writeln('Cert ERROR');  if quiche_config_load_priv_key_from_pem_file(PConfig^, './keys/server.key') = 0     then writeln('Priv_key OK') else writeln('Priv_key ERROR');   method := TLS_method;  Pctx := SSL_CTX_new(method);  if Pctx = nil then Writeln('Failed to create SSL_CTX') else Writeln('SSL_CTX CREATED!');  SSL_CTX_set_min_proto_version(Pctx, TLS1_3_VERSION);  SSL_CTX_set_max_proto_version(Pctx, TLS1_3_VERSION);  if SSL_CTX_use_certificate_file(Pctx, './keys/server.cert', SSL_FILETYPE_PEM) <= 0     then Writeln('SSL_CTX_use_certificate_file ERROR!')     else writeln('SSL_CTX_use_certificate_file OK!');  if SSL_CTX_use_PrivateKey_file(Pctx, './keys/server.key', SSL_FILETYPE_PEM) <= 0     then Writeln('SSL_CTX_use_PrivateKey_file ERROR!')     else Writeln('SSL_CTX_use_PrivateKey_file OK!');  if SSL_CTX_check_private_key(Pctx) <= 0 then Writeln('Private key DOES NOT match certificate')                                          else Writeln('Private key MATCHES certificate');  SSL_CTX_set_options(Pctx, SSL_OP_NO_RENEGOTIATION);  SSL := SSL_new(Pctx);  if SSL = nil then writeln('SSL_new ERROR')                 else writeln('SSL_new OK ');    Randomize;  for i := 0 to High(scid) do scid[i] := Random(256);  for i := 0 to High(odcid) do odcid[i] := Random(256);  FillChar(localAddr, SizeOf(localAddr), 0);  localAddr.sin_family := AF_INET;  localAddr.sin_port := htons(12345);  localAddr.sin_addr := StrToNetAddr('192.168.1.4');  FillChar(peerAddr, SizeOf(peerAddr), 0);  peerAddr.sin_family := AF_INET;  peerAddr.sin_port := htons(0);  peerAddr.sin_addr.s_addr := INADDR_ANY;   Pconn := quiche_conn_new_with_tls(@scid[0], Length(scid),                                  @odcid[0], Length(odcid),                                  @localAddr, SizeOf(localAddr),                                    @peerAddr, SizeOf(peerAddr),                                    Pconfig, SSL, isServer);  Writeln('--------------------------------------------------');  if Pconn = nil then WriteLn('Failed to create QUIC connection')               else WriteLn('QUIC connection created successfully!');  if quiche_conn_is_established(Pconn)     then WriteLn('QUIC connection IS established')     else WriteLn('QUIC connection ISN''T established');  if quiche_conn_is_closed(Pconn)       then Writeln('Conn CLOSED')     else Writeln('Conn NOT CLOSED');   quiche_conn_source_id(PConn, trace_id, trace_id_len);  if (trace_id <> nil) and (trace_id_len > 0) then    begin      Writeln('Trace ID Length: ', trace_id_len);      Write('Trace ID: ');      for i := 0 to trace_id_len - 1 do Write(trace_id[i], ' ');      Writeln;    end else writeln('  trace_id = nil');   writeln('SizeOf(recv_info)=',SizeOf(recv_info));  quiche_conn_stats(Pconn, PStats);   GetMem(buf, BUF_SIZE);   Writeln;  repeat    Writeln('bytes_received...');    {TRon} //bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info);    {Fred} //bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, recv_info);    {Fred2}bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info);    Sleep(10);    if KeyPressed then ch := ReadKey;  until Ch = #13;   //TODO: cleaning end.  and it results in: QuoteQuiche version: 0.22.0 BoringSSL version: 1.1.1.7 QUIC configuration CREATED Cert OK Priv_key OK SSL_CTX CREATED! SSL_CTX_use_certificate_file OK! SSL_CTX_use_PrivateKey_file OK! Private key MATCHES certificate SSL_new OK -------------------------------------------------- QUIC connection created successfully! QUIC connection ISN'T established Conn NOT CLOSED Trace ID Length: 16 Trace ID: 0 100 246 204 225 122 243 132 116 231 62 43 237 252 250 196 SizeOf(recv_info)=32 bytes_received... An unhandled exception occurred at $00007F178AFE392A:                                                      EAccessViolation: Access violation                                                                                        $00007F178AFE392A           -------------------------------------------------- Press enter What I noticed is that in the original version, there is some difference in the output: Quote.. QUIC connection IS established already. Conn CLOSED .. [/quote both are exactly the opposite, even though I just copy-pasted this part of the code. Anyway, the quiche_conn_recv error persists. ---------------------------------------------------------------------- tetrastes · 2024-10-08 11:05 May be I don't understand something, but from https://github.com/cloudflare/quiche/tree/master/quiche#calling- quiche-from-cc: QuoteCalling quiche from C/C++ quiche exposes a thin C API on top of the Rust API that can be used to more easily integrate quiche into C/C++ applications (as well as in other languages that allow calling C APIs via some form of FFI). The C API follows the same design of the Rust one, modulo the constraints imposed by the C language itself. When running cargo build, a static library called libquiche.a will be built automatically alongside the Rust one. This is fully stand-alone and can be linked directly into C/C++ applications. Note that in order to enable the FFI API, the ffi feature must be enabled (it is disabled by default), by passing --features ffi to cargo. and in Makefile from examples I see that C examples are linked with this libquiche.a. But you link with dynamic libquiche.so. I suppose that it is generated by rust. Why do you think that it's functions are C declared? ---------------------------------------------------------------------- tetrastes · 2024-10-08 11:53 You have to read about variable parameters in Pascal (https://www.freepascal.org/docs- html/current/ref/refsu65.html#x181-20500014.4.2). For example, this 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 quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                  var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;does not correspond to 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 ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,                       const quiche_recv_info *info); ---------------------------------------------------------------------- silvercoder70 · 2024-10-08 11:55 I was looking at the code from r.lukasiak and ... compared with code here https://android.googlesource.com/platform/external/rust/crates/quiche/ +/HEAD/examples/server.c and noticed the last parameter is filled out ... 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  quiche_recv_info recv_info = {            (struct sockaddr *)&peer_addr,            peer_addr_len,            conns->local_addr,            conns->local_addr_len,        };        ssize_t done = quiche_conn_recv(conn_io->conn, buf, read, &recv_info); whereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? ---------------------------------------------------------------------- Fred vS · 2024-10-08 12:29 Quote from: tetrastes on October 08, 2024, 01:53:51 pmYou have to read about variable parameters in Pascal (https://www.freepascal.org/docs- html/current/ref/refsu65.html#x181-20500014.4.2). For example, this 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 quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                  var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;does not correspond to 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 ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,                       const quiche_recv_info *info);  Yes, this code is not correct, we know it, it was for testing and of course did not help. It is a variation of code give by h2pas (see first post of OP). ---------------------------------------------------------------------- tetrastes · 2024-10-08 12:50 Yes, I understand. But reading this Quote from: r.lukasiak on October 06, 2024, 04:47:20 pmCode: 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 quiche_conn_recv(var conn:quiche_conn; var buf:uint8_t; buf_len:size_t;                           var info:quiche_recv_info):ssize_t;cdecl;external External_library name 'quiche_conn_recv'; here, var conn:quiche_conn and var info:quiche_recv_info are not pointers. I still think OP has to read about variable parameters in Pascal. ---------------------------------------------------------------------- tetrastes · 2024-10-08 12:57 Quote from: silvercoder70 on October 08, 2024, 01:55:48 pmwhereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? Yes, I think. You are the most attentive! ---------------------------------------------------------------------- Fred vS · 2024-10-08 13:21 Quote from: tetrastes on October 08, 2024, 02:57:16 pmQuote from: silvercoder70 on October 08, 2024, 01:55:48 pmwhereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? Yes, I think. You are the most attentive! Yep, well seen, but in a previous post, OP did it, maybe do it again with his last code?: 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 FillChar(recv_info, SizeOf(recv_info), 0); ---------------------------------------------------------------------- tetrastes · 2024-10-08 14:38 Quote from: Fred vS on October 08, 2024, 03:21:53 pmYep, well seen, but in a previous post, OP did it, maybe do it again with his last code?: 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 FillChar(recv_info, SizeOf(recv_info), 0); Well, I think it must be initialized not with zeros, but with some actual values, like in C code. ---------------------------------------------------------------------- Fred vS · 2024-10-08 15:37 Here binary of libquiche.so for Linux 64 bit: https://github.com/user-attachments/files/17295533/libquiche.so.zip Maybe the binary could help for exploration... 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 > file libquiche.so  libquiche.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,  BuildID[sha1]=ffc99bd0987e104ba3b7144a6862cae3be7ad5e9, stripped  quiche_conn_recv is indeed there. 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 > nm -D libquiche.so  ...  00000000000a7870 T quiche_conn_recv  ... ---------------------------------------------------------------------- Fred vS · 2024-10-08 17:24 Hello r.lukasiak I did try your demo program using libquiche.so from my previous post. But at linking, there is that error: Quoteundefined reference to `SSL_CTX_set_min_proto_version' undefined reference to `SSL_CTX_set_max_proto_version' So I commented their declaration + use because there are not defined in my libssl.so: 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 //SSL_CTX_set_min_proto_version(Pctx, TLS1_3_VERSION);//SSL_CTX_set_max_proto_version(Pctx, TLS1_3_VERSION); Also I dont have a SSL certificate file to test, so error while initialize it. So I get a crash far before your result, when trying quiche_conn_new_with_tls(). But, strangely, when using your declaration: 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 quiche_conn_new_with_tls(const scid: PByte; scid_len: csize_t;                                const odcid: PByte; odcid_len: csize_t;                                const local: PSockAddr; local_len: csize_t;                                  const peer: PSockAddr; peer_len: csize_t;                                  const config: PQuiche_config; ssl: PSSL;                                  is_server: Boolean): PQuiche_conn;                                  cdecl; external QUICHE_LIB; I get that error: 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 Quiche version: 0.22.0BoringSSL version: 3.0.0.2QUIC configuration CREATEDCert ERRORPriv_key ERRORSSL_CTX CREATED!SSL_CTX_use_certificate_file ERROR!SSL_CTX_use_PrivateKey_file ERROR!Private key DOES NOT match certificateSSL_new OK An unhandled exception occurred at $0000720615ABA658:EAccessViolation: Access violation  $0000720615ABA658  $0000720615A8E7AA But using this declaration: 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 quiche_conn_new_with_tls( scid: PByte; scid_len: csize_t;                                     odcid: PByte; odcid_len: csize_t;                                     local: PSockAddr; local_len: csize_t;                                     peer: PSockAddr; peer_len: csize_t;                                     var config: PQuiche_config; ssl: PSSL;                                      is_server: Boolean): PQuiche_conn;                                      cdecl; external QUICHE_LIB; There is still error but more detailed. 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 Quiche version: 0.22.0BoringSSL version: 3.0.0.2QUIC configuration CREATEDCert ERRORPriv_key ERRORSSL_CTX CREATED!SSL_CTX_use_certificate_file ERROR!SSL_CTX_use_PrivateKey_file ERROR!Private key DOES NOT match certificateSSL_new OK thread '' panicked at quiche/src/recovery/congestion/pacer.rs:83:24:attempt to divide by zeronote: run with `RUST_BACKTRACE=1` environment variable to display a backtracefatal runtime error: failed to initiate panic, error 5Aborted (core dumped) ---------------------------------------------------------------------- tetrastes · 2024-10-08 17:41 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 quiche_conn_new_with_tls( scid: PByte; scid_len: csize_t;                                     odcid: PByte; odcid_len: csize_t;                                     local: PSockAddr; local_len: csize_t;                                     peer: PSockAddr; peer_len: csize_t;                         { ! var ! } config: PQuiche_config; ssl: PSSL;                                     is_server: Boolean): PQuiche_conn;                                       cdecl; external QUICHE_LIB; ---------------------------------------------------------------------- Fred vS · 2024-10-08 17:52 Quote from: tetrastes on October 08, 2024, 07:41:20 pmCode: 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 quiche_conn_new_with_tls( scid: PByte; scid_len: csize_t;                                     odcid: PByte; odcid_len: csize_t;                                     local: PSockAddr; local_len: csize_t;                                     peer: PSockAddr; peer_len: csize_t;                         { ! var ! } config: PQuiche_config; ssl: PSSL;                                     is_server: Boolean): PQuiche_conn;                                       cdecl; external QUICHE_LIB; Without var or with const: 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 Quiche version: 0.22.0BoringSSL version: 3.0.0.2QUIC configuration CREATEDCert ERRORPriv_key ERRORSSL_CTX CREATED!SSL_CTX_use_certificate_file ERROR!SSL_CTX_use_PrivateKey_file ERROR!Private key DOES NOT match certificateSSL_new OK An unhandled exception occurred at $00007CBEE42BA658:EAccessViolation: Access violation  $00007CBEE42BA658  $00007CBEE428E7AA Note that a error is normal, the SSL key file is missing, but strange to have different error message. ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 17:57 @silvercoder70 and @tetrastes,thanks for joining! I'm still processing all your messages, will answer ASAP. @Fred vS Quoteundefined reference to `SSL_CTX_set_min_proto_version' undefined reference to `SSL_CTX_set_max_proto_version'it's becasue in your PATH you have only the "classic" OpenSSL, not BoringSSL. notice: 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 {$L ./libs/libssl.so}{$L ./libs/libcrypto.so} here you can get the file with the libs https://www.dropbox.com/scl/fi /8owmnokwe2wqwxssiq09w/Quiche_BoringSSL_test.tar.gz?rlkey=ln5cybe6xwh4 qf6a48fsgjzdg&st=byzouhgu&dl=0 just generate the keys and place them in ./keys ---------------------------------------------------------------------- Fred vS · 2024-10-08 18:02 Quote from: r.lukasiak on October 08, 2024, 07:57:32 pm@Fred vS Quoteundefined reference to `SSL_CTX_set_min_proto_version' undefined reference to `SSL_CTX_set_max_proto_version'it's becasue in your PATH you have only the "classic" OpenSSL, not BoringSSL. Ha, ok, (and indeed, BoringXXL  ). I will try asap with the boring libs. ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 19:07 Quote from: tetrastes on October 08, 2024, 01:05:23 pmMay be I don't understand something, but from https://github.com/cloudflare/quiche/tree/master/quiche#calling- quiche-from-cc: QuoteCalling quiche from C/C++ quiche exposes a thin C API on top of the Rust API that can be used to more easily integrate quiche into C/C++ applications (as well as in other languages that allow calling C APIs via some form of FFI). The C API follows the same design of the Rust one, modulo the constraints imposed by the C language itself. When running cargo build, a static library called libquiche.a will be built automatically alongside the Rust one. This is fully stand-alone and can be linked directly into C/C++ applications. Note that in order to enable the FFI API, the ffi feature must be enabled (it is disabled by default), by passing --features ffi to cargo. this would explain the error that's talking about FFI... The problem with .so s that I use Quiche fromPortage tree (Gentoo Linux), in order to make it.a I'd have to build it by myself which I alreay tried, with the debug flag but so far I wasn't able to have it work. I'll give it another try. Quote from: Fred vS on October 08, 2024, 02:29:40 pmQuote from: tetrastes on October 08, 2024, 01:53:51 pmYou have to read about variable parameters in Pascal (https://www.freepascal.org/docs- html/current/ref/refsu65.html#x181-20500014.4.2). For example, this 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 quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;                  var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;does not correspond to 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 ssize_t quiche_conn_recv(quiche_conn *conn, uint8_t *buf, size_t buf_len,                       const quiche_recv_info *info);  Yes, this code is not correct, we know it, it was for testing and of course did not help. It is a variation of code give by h2pas (see first post of OP). and in Makefile from examples I see that C examples are linked with this libquiche.a. But you link with dynamic libquiche.so. I suppose that it is generated by rust. Why do you think that it's functions are C declared? how about this: 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 quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;                const info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;now without vars, the const  like in the header, but his reminds me what Fred said about C's const being Pascal's var  Quote from: Fred vS on October 08, 2024, 03:21:53 pmQuote from: tetrastes on October 08, 2024, 02:57:16 pmQuote from: silvercoder70 on October 08, 2024, 01:55:48 pmwhereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? Yes, I think. You are the most attentive! Yep, well seen, but in a previous post, OP did it, maybe do it again with his last code?: 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 FillChar(recv_info, SizeOf(recv_info), 0);indeed, I missed this line in my new version. Added but without any positive outcome :/ the same error persist ---------------------------------------------------------------------- Fred vS · 2024-10-08 19:25 Quote from: r.lukasiak on October 08, 2024, 09:07:04 pmnow without vars, the const  like in the header, but his reminds me what Fred said about C's const being Pascal's var  Ooops, no, I said that strangely the h2pas program translate const into var. But of course C const are not Pas var. I still fight with your demo, the libs are loaded, the key recognized and... I get same crash as you. But also a error of bad connection. Anyway something to eat... Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Quiche version: 0.22.0BoringSSL version: 1.1.1.7QUIC configuration CREATEDCert OKPriv_key OKSSL_CTX CREATED!SSL_CTX_use_certificate_file OK!SSL_CTX_use_PrivateKey_file OK!Private key MATCHES certificateSSL_new OK --------------------------------------------------QUIC connection created successfully!QUIC connection ISN'T established   // HERE no connectConn NOT CLOSEDTrace ID Length: 16Trace ID: 2 186 213 85 62 176 136 248 221 208 96 9 218 116 60 185 SizeOf(recv_info)=32bytes_received...An unhandled exception occurred at $0000791CA064BDD4:EAccessViolation: Access violation  $0000791CA064BDD4 ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 19:48 QuoteOoops, no, I said that strangely the h2pas program translate const into var. But of course C const are not Pas var.ohh, now I get it. I'm sorry for twisting your words  QuoteQUIC connection created successfully! QUIC connection ISN'T established   // HERE no connect Conn NOT CLOSED beside the final error, this is another mystery.  Interestingly in the original version it's the opposite; "QUIC connection IS established" and "Conn CLOSED". I've been literally spelling both  filles and I can't find the difference in their implementation that causes the different output. :/ ---------------------------------------------------------------------- Fred vS · 2024-10-08 19:56 Quote from: r.lukasiak on October 08, 2024, 09:48:15 pmthis is another mystery.  Interestingly in the original version it's the opposite; "QUIC connection IS established" and "Conn CLOSED". I've been literally spelling both  filles and I can't find the difference in their implementation that causes the different output. :/ Hum, what is "the original version" ? ---------------------------------------------------------------------- tetrastes · 2024-10-08 20:06 Quote from: r.lukasiak on October 08, 2024, 09:07:04 pmQuote from: Fred vS on October 08, 2024, 03:21:53 pmQuote from: tetrastes on October 08, 2024, 02:57:16 pmQuote from: silvercoder70 on October 08, 2024, 01:55:48 pmwhereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? Yes, I think. You are the most attentive! Yep, well seen, but in a previous post, OP did it, maybe do it again with his last code?: 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 FillChar(recv_info, SizeOf(recv_info), 0);indeed, I missed this line in my new version. Added but without any positive outcome :/ the same error persist Note this: Quote from: tetrastes on October 08, 2024, 04:38:10 pmWell, I think it must be initialized not with zeros, but with some actual values, like in C code. Quote from: silvercoder70 on October 08, 2024, 01:55:48 pmI was looking at the code from r.lukasiak and ... compared with code here https://android.googlesource.com/platform/external/rust/crates/quiche/ +/HEAD/examples/server.c and noticed the last parameter is filled out ... 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  quiche_recv_info recv_info = {            (struct sockaddr *)&peer_addr,            peer_addr_len,            conns->local_addr,            conns->local_addr_len,        };        ssize_t done = quiche_conn_recv(conn_io->conn, buf, read, &recv_info); whereas in the Pascal code, this parameter (Precv_info) is passed in is not allocated any memory OR assigned Nil? Hope this helps? The fields of recv_info must be actual values of your connection. ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 20:08 @Fred vS QuoteHum, what is "the original version" ? the one I had when I started this post. BoringSSLand Quiche bindings in separate files + the test program apart, with plenty of comments and not tested functions/procedures. Last night I "refactored" it including only functions that I use in the test program. The old version was in 3 files and with few hundred lines of comments, mostly different versions of functions I was testing. ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 20:45 ohh.... you mean alike I did with quiche_conn_new_with_tls: 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 FillChar(localAddr, SizeOf(localAddr), 0);  localAddr.sin_family := AF_INET;  localAddr.sin_port := htons(12345);  localAddr.sin_addr := StrToNetAddr('192.168.1.4');  FillChar(peerAddr, SizeOf(peerAddr), 0);  peerAddr.sin_family := AF_INET;  peerAddr.sin_port := htons(0);  peerAddr.sin_addr.s_addr := INADDR_ANY;   recv_info.from := @localAddr;;  recv_info.from_len := SizeOf(localAddr);  recv_info.&to := @peerAddr;;  recv_info.to_len := SizeOf(peerAddr);   Precv_info := @recv_info;   ? and.... it WORKED!! well, before I start bragging that it "works like a charm"... I'd better say "the error is gone"  QuoteQuiche version: 0.22.0 BoringSSL version: 1.1.1.7 QUIC configuration CREATED Cert ERROR Priv_key OK SSL_CTX CREATED! SSL_CTX_use_certificate_file ERROR! SSL_CTX_use_PrivateKey_file OK! Private key DOES NOT match certificate SSL_new OK -------------------------------------------------- QUIC connection created successfully! QUIC connection ISN'T established Conn NOT CLOSED Trace ID Length: 16 Trace ID: 2 56 65 240 209 12 232 155 16 48 10 66 217 99 228 195 SizeOf(recv_info)=32 bytes_received... bytes_received... bytes_received... bytes_received... ... ... ... and now, the thing that doesn't let me sleep since I started playing with this... how can I actually find out if it really works and not only not throwing any error? debugging is highly limited. Yesterday I thought that Quiche_stats was working "like a charm" but it turned out that even the definition was messed up but it wasn't giving any errors so I marked it as "works" in the very beginning of this journey. ---------------------------------------------------------------------- Fred vS · 2024-10-08 21:00 Wait, wait, so really the game is already over? And the warrior who found the guilty is silvercoder70: https://forum.lazarus.freepascal.org/index.php/topic,68793.msg532737.h tml#msg532737  confirmed by tetrastes https://forum.lazarus.freepascal.org/index.php/topic,68793.msg532765.h tml#msg532765 Nice battle, and I am very happy that we win today, before deep night. Have fun. Fre;D ---------------------------------------------------------------------- TRon · 2024-10-08 21:04 Quote from: r.lukasiak on October 08, 2024, 10:45:47 pm how can I actually find out if it really works and not only not throwing any error? Checking if your header translations are correct is the most boring/tedious part. The easiest is by looking at the examples and re-create those in pascal and test/check. There are both a client and a server example written in c so you could compile f.i the server example in c and rewrite the client in pascal then run the server and see if the client works. Same can be done for the server (and in case you know the pascal client is already working then you can use that instead of the c version) Somewhere in the documentation is listed that they have a online test server you can use though I have not looked at it so don't know if if you are able to receive enough feedback from the server. ---------------------------------------------------------------------- Fred vS · 2024-10-08 21:18 It seems to really work. Adding this:   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 bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info);  Writeln('bytes_received = ' + inttostr(bytes_received)); // adding this Shows beautiful: 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 bytes_received = -3 // the firstbytes_received...bytes_received = 32768 // the othersbytes_received...bytes_received = 32768bytes_received...bytes_received = 32768bytes_received...bytes_received = 32768... Anyway, the victory is not far.  To resume, here it works with: 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 quiche_conn_recv(conn: PQuiche_Conn; const buf: PByte; buf_len: CSize_t;                  const info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; + initialize localAddr, peerAddr and recv_info with valid datas. and this: 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 bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info); ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 21:27 @Fred vS QuoteWait, wait, so really the game is already over?I'm not quite sure... the error is gone for now but now I'll review each single function having in mind all I learnt from this thread. QuoteAnd the warrior who found the guilty is silvercoder70: https://forum.lazarus.freepascal.org/index.php/topic,68793.msg532737.h tml#msg532737 confirmed by tetrastes https://forum.lazarus.freepascal.org/index.php/topic,68793.msg532765.h tml#msg532765 basically these 2  suggestions solved the original issue but we've gone through plenty of options and I learnt something from each one which is as important as the solution itself. @TRon QuoteChecking if your header translations are correct is the most boring/tedious part. I see... When I was searching for info on the topic, I came across a post on this forum where someone said that this requires A LOT of patience, even using H2Pas involves a lot of manual adjustment. QuoteThe easiest is by looking at the examples and re-create those in pascal and test/check. There are both a client and a server example written in c so you could compile f.i the server example in c and rewrite the client in pascal then run the server and see if the client works. Same can be done for the server (and in case you know the pascal client is already working then you can use that instead of the c version) thanks! I'll take this approach. So for now (as I guess I'll be back soon with more questions), everyone, thanks a lot! As always, you rule! cheers! //edit: typoes ---------------------------------------------------------------------- r.lukasiak · 2024-10-08 21:47 However... QuoteQuiche version: 0.22.0 BoringSSL version: 1.1.1.7 QUIC configuration CREATED Cert ERROR Priv_key OK SSL_CTX CREATED! SSL_CTX_use_certificate_file ERROR! SSL_CTX_use_PrivateKey_file OK! Private key DOES NOT match certificate SSL_new OK -------------------------------------------------- QUIC connection created successfully! QUIC connection ISN'T established Conn NOT CLOSED Trace ID Length: 16 Trace ID: 2 56 65 240 209 12 232 155 16 48 10 66 217 99 228 195 SizeOf(recv_info)=32 bytes_received... bytes_received... bytes_received... bytes_received... I moved my keys when I was gziping the file for you and I forgot to move them back before testing, and it still says "QUIC connection ISN'T established" (@Fred vS, how is it on your side?) but it supposedly "works"... hmm, I'm still not quite sure ---------------------------------------------------------------------- Fred vS · 2024-10-08 22:37 Hum, I already cleaned all... Ok, all reinstalled. Important: You need to be in the directory of the project to run it otherwise I get same error than you for the keys: 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 > cd /the_directory_of_your _project.Then run the app from there. Here the code I used: 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 program project1; {$mode objfpc}{$H+}{$PACKRECORDS C} {$L ./libs/libssl.so}{$L ./libs/libcrypto.so}//{$L ./libs/libquiche_dbg.so} uses  {$IFDEF UNIX}  cthreads,  {$ENDIF}  Classes,  Crt, SysUtils, CTypes, BaseUnix, Sockets; type  CSsize_t = NativeInt;   PQuiche_config = ^TQuiche_config;  TQuiche_config = record  end;   PQuiche_conn = ^TQuiche_conn;  TQuiche_conn = record  end;   PSSL_METHOD = ^TSSL_METHOD;  TSSL_METHOD = record  end;   PSSL_CTX = ^TSSL_CTX;  TSSL_CTX = record  end;   PSSL = ^TSSL;  TSSL = record  end;   PQuiche_Recv_Info = ^TQuiche_Recv_Info;  TQuiche_Recv_Info = record    from : Psockaddr;      from_len : socklen_t;      &to : Psockaddr;    to_len : socklen_t;  end;   PQuiche_stats = ^TQuiche_stats;  Tquiche_stats = record    recv : size_t;    sent : size_t;    lost : size_t;    retrans : size_t;    sent_bytes : uint64;    recv_bytes : uint64;    acked_bytes : uint64;    lost_bytes : uint64;    stream_retrans_bytes : uint64;    paths_count : size_t;    reset_stream_count_local : uint64;    stopped_stream_count_local : uint64;    reset_stream_count_remote : uint64;    stopped_stream_count_remote : uint64;  end; var  i: integer;  ch: Char;  PConfig: Pquiche_config;  Pctx: PSSL_CTX;  SSL: PSSL;  method: PSSL_METHOD;  isServer: boolean = true;  scid, odcid: array[0..15] of Byte;  Pconn: PQuiche_conn;  Stats: TQuiche_stats;  PStats: PQuiche_stats;  localAddr, peerAddr: TSockAddr;  trace_id: PByte;  trace_id_len: Csize_t;  buf: PByte;  BUF_SIZE: size_t = 8192 * 4;  recv_info: TQuiche_recv_info;  Precv_info: PQuiche_recv_info;  bytes_received: CSsize_t; const  QUICHE_LIB = 'libquiche.so';  BORINGSSL_LIB = 'libssl.so';  CRYPTO_LIB = 'libcrypto.so';  QUICHE_PROTOCOL_VERSION = 1;  TLS1_3_VERSION = $0304; //0x0304  SSL_FILETYPE_PEM = 1;  SSL_OP_NO_RENEGOTIATION = 0; {---------- BORINGSSL ----------}function OpenSSL_version_num: cint; cdecl; external CRYPTO_LIB;function TLS_method: PSSL_METHOD; cdecl; external BORINGSSL_LIB;function SSL_CTX_new(const method: PSSL_METHOD): PSSL_CTX; cdecl; external BORINGSSL_LIB;procedure SSL_CTX_set_min_proto_version(ctx: PSSL_CTX; version: cint); cdecl; external BORINGSSL_LIB;procedure SSL_CTX_set_max_proto_version(ctx: PSSL_CTX; version: cint); cdecl; external BORINGSSL_LIB;function SSL_CTX_use_certificate_file(ctx: PSSL_CTX; const filename: PChar; type_: cint): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_use_PrivateKey_file(ctx: PSSL_CTX; const filename: PChar; type_: cint): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_check_private_key(ctx: PSSL_CTX): cint; cdecl; external BORINGSSL_LIB;function SSL_CTX_set_options(ctx: PSSL_CTX; options: UInt32 ): UInt32; cdecl; external BORINGSSL_LIB;function SSL_new(ctx: PSSL_CTX): PSSL; cdecl; external BORINGSSL_LIB; {---------- QUICHE ----------}function quiche_version: PChar; cdecl; external QUICHE_LIB;function quiche_config_new(version: UInt32): PQuiche_config; cdecl; external QUICHE_LIB;function quiche_config_load_cert_chain_from_pem_file(var config: TQuiche_config; path: Pansichar) : longint; cdecl; external QUICHE_LIB;function quiche_config_load_priv_key_from_pem_file(var config: TQuiche_config; path: Pansichar): longint;cdecl;external QUICHE_LIB;function quiche_conn_new_with_tls(const scid: PByte; scid_len: csize_t;                                  const odcid: PByte; odcid_len: csize_t;                                  const local: PSockAddr; local_len: socklen_t;                                const peer: PSockAddr; peer_len: socklen_t;                                const config: PQuiche_config; ssl: PSSL;                                is_server: Boolean): PQuiche_conn;                                cdecl; external QUICHE_LIB;                                  function quiche_conn_set_session(conn: PQuiche_Conn; buf:PByte; buf_len:csize_t) : cint32; cdecl; external QUICHE_LIB;                                                                 function quiche_conn_is_established(var conn: PQuiche_conn): cBool; cdecl; external QUICHE_LIB;function quiche_conn_is_closed(var conn:PQuiche_conn): cbool; cdecl; external QUICHE_LIB;procedure quiche_conn_trace_id(const conn: PQuiche_Conn; var out: PByte; var out_len: Csize_t); cdecl; external QUICHE_LIB;procedure quiche_conn_source_id(const conn: PQuiche_Conn; var out: PByte; var out_len: Csize_t); cdecl; external QUICHE_LIB;procedure quiche_conn_stats(var conn:PQuiche_conn; var &out:PQuiche_stats); cdecl; external QUICHE_LIB; //function quiche_conn_recv(var conn:PQuiche_conn; buf:PByte; buf_len:csize_t; info:PQuiche_recv_info):cssize_t; cdecl; external QUICHE_LIB;{H2Pas}//function quiche_conn_recv(var conn:quiche_conn; var buf:Cuint8; buf_len:Csize_t; var info:quiche_recv_info):Cssize_t;cdecl;external QUICHE_LIB name 'quiche_conn_recv';//function quiche_conn_recv(var conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;  //                        var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;{TRon}  //function quiche_conn_recv(conn: pquiche_conn; buf: pcuint8; buf_len: size_t; const info: pquiche_recv_info): ssize_t; cdecl; external QUICHE_LIB;{Fred}// function quiche_conn_recv(conn: PQuiche_Conn; buf: PByte; buf_len: CSize_t;        //           var info: TQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;{Fred2} //function quiche_conn_recv(var conn: PQuiche_Conn; var buf: PByte; var buf_len: CSize_t;          //        var info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB;function quiche_conn_recv(conn: PQuiche_Conn; const buf: PByte; buf_len: CSize_t;                  const info: PQuiche_Recv_Info): CSsize_t; cdecl; external QUICHE_LIB; begin  writeln('Quiche version: ', quiche_version); //returns: 0.22.0  writeln('BoringSSL version: ', Format('%d.%d.%d.%d',                 [(OpenSSL_version_num shr 28) and $F,                  (OpenSSL_version_num shr 20) and $F,                (OpenSSL_version_num shr 12) and $F,                  (OpenSSL_version_num shr 4) and $F]));  //   Pconfig := quiche_config_new(QUICHE_PROTOCOL_VERSION);  if Pconfig = nil then writeln('Failed to create QUIC configuration')                   else writeln('QUIC configuration CREATED');   if quiche_config_load_cert_chain_from_pem_file(PConfig^, './keys/server.cert') = 0     then writeln('Cert OK') else writeln('Cert ERROR');  if quiche_config_load_priv_key_from_pem_file(PConfig^, './keys/server.key') = 0     then writeln('Priv_key OK') else writeln('Priv_key ERROR');   method := TLS_method;  Pctx := SSL_CTX_new(method);  if Pctx = nil then Writeln('Failed to create SSL_CTX') else Writeln('SSL_CTX CREATED!');  SSL_CTX_set_min_proto_version(Pctx, TLS1_3_VERSION);  SSL_CTX_set_max_proto_version(Pctx, TLS1_3_VERSION);  if SSL_CTX_use_certificate_file(Pctx, './keys/server.cert', SSL_FILETYPE_PEM) <= 0     then Writeln('SSL_CTX_use_certificate_file ERROR!')     else writeln('SSL_CTX_use_certificate_file OK!');  if SSL_CTX_use_PrivateKey_file(Pctx, './keys/server.key', SSL_FILETYPE_PEM) <= 0     then Writeln('SSL_CTX_use_PrivateKey_file ERROR!')     else Writeln('SSL_CTX_use_PrivateKey_file OK!');  if SSL_CTX_check_private_key(Pctx) <= 0 then Writeln('Private key DOES NOT match certificate')                                          else Writeln('Private key MATCHES certificate');  SSL_CTX_set_options(Pctx, SSL_OP_NO_RENEGOTIATION);  SSL := SSL_new(Pctx);  if SSL = nil then writeln('SSL_new ERROR')                 else writeln('SSL_new OK ');    Randomize;  for i := 0 to High(scid) do scid[i] := Random(256);  for i := 0 to High(odcid) do odcid[i] := Random(256);  FillChar(localAddr, SizeOf(localAddr), 0);  localAddr.sin_family := AF_INET;  localAddr.sin_port := htons(12345);  localAddr.sin_addr := StrToNetAddr('192.168.1.4');  FillChar(peerAddr, SizeOf(peerAddr), 0);  peerAddr.sin_family := AF_INET;  peerAddr.sin_port := htons(0);  peerAddr.sin_addr.s_addr := INADDR_ANY;   Pconn := quiche_conn_new_with_tls(@scid[0], Length(scid),                                  @odcid[0], Length(odcid),                                  @localAddr, SizeOf(localAddr),                                    @peerAddr, SizeOf(peerAddr),                                    Pconfig, SSL, isServer);  Writeln('--------------------------------------------------');  if Pconn = nil then WriteLn('Failed to create QUIC connection')               else WriteLn('QUIC connection created successfully!');  if quiche_conn_is_established(Pconn)     then WriteLn('QUIC connection IS established')     else WriteLn('QUIC connection ISN''T established');  if quiche_conn_is_closed(Pconn)       then Writeln('Conn CLOSED')     else Writeln('Conn NOT CLOSED');   quiche_conn_source_id(PConn, trace_id, trace_id_len);  if (trace_id <> nil) and (trace_id_len > 0) then    begin      Writeln('Trace ID Length: ', trace_id_len);      Write('Trace ID: ');      for i := 0 to trace_id_len - 1 do Write(trace_id[i], ' ');      Writeln;    end else writeln('  trace_id = nil');   writeln('SizeOf(recv_info)=',SizeOf(recv_info));  quiche_conn_stats(Pconn, PStats);   GetMem(buf, BUF_SIZE);//  FillChar(recv_info, SizeOf(recv_info), 0);     writeln(' avant quiche_conn_set_session'); //  Writeln(quiche_conn_set_session(PConn, @buf, BUF_SIZE));    FillChar(localAddr, SizeOf(localAddr), 0);  localAddr.sin_family := AF_INET;  localAddr.sin_port := htons(12345);  localAddr.sin_addr := StrToNetAddr('192.168.1.4');  FillChar(peerAddr, SizeOf(peerAddr), 0);  peerAddr.sin_family := AF_INET;  peerAddr.sin_port := htons(0);  peerAddr.sin_addr.s_addr := INADDR_ANY;   recv_info.from := @localAddr;;  recv_info.from_len := SizeOf(localAddr);  recv_info.&to := @peerAddr;;  recv_info.to_len := SizeOf(peerAddr);   Precv_info := @recv_info;     Writeln;  repeat    Writeln('bytes_received...');    {TRon} //bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info);   // {Fred} bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, recv_info);  {Fred2}bytes_received := quiche_conn_recv(PConn, buf, BUF_SIZE, Precv_info);    Writeln('bytes_received = ' + inttostr(bytes_received));    Sleep(10);    if KeyPressed then ch := ReadKey;  until Ch = #13;   //TODO: cleaning end.   and here the result: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Quiche version: 0.22.0BoringSSL version: 1.1.1.7QUIC configuration CREATEDCert OKPriv_key OKSSL_CTX CREATED!SSL_CTX_use_certificate_file OK!SSL_CTX_use_PrivateKey_file OK!Private key MATCHES certificateSSL_new OK --------------------------------------------------QUIC connection created successfully!QUIC connection ISN'T establishedConn NOT CLOSEDTrace ID Length: 16Trace ID: 205 247 189 17 202 103 191 159 132 79 54 168 8 133 19 96 SizeOf(recv_info)=32 avant quiche_conn_set_session bytes_received...bytes_received = -3bytes_received...bytes_received = 32768bytes_received...bytes_received = 32768bytes_received...... [EDIT] Ha, yes, I think I understood what you mean.            Indeed strange that QUIC connection ISN'T established            Also it seems to me that the buffer is filled very fast at each loop. ---------------------------------------------------------------------- r.lukasiak · 2024-10-09 15:13 QuoteImportant: You need to be in the directory of the project to run it otherwise I get same error than you for the keys: if you move the binary out of the directory, you need to carry the keys dir as well, or just set absolute path to the keys. QuoteIndeed strange that QUIC connection ISN'T establishedmaybe it's about the fact that no client connected? That's another thing, I need to learn QUIC itself. QuoteAlso it seems to me that the buffer is filled very fast at each loop. I'm just wondering why it's even receiving anything if nothing is actually sent. It seems like it still doesn't work as intended but as it finally doesn't throw errors, I can somehow debug it and learn how to use it. Once again, thanks for your commitment! ---------------------------------------------------------------------- Fred vS · 2024-10-09 18:01 Hello r.lukasiak In my previous post was added/used the method: 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 quiche_conn_set_session(conn: PQuiche_Conn; buf:PByte; buf_len:csize_t) : cint32; cdecl; external QUICHE_LIB; Here the result is always = -2. But I have no idea what this mean. (And I must also admit that I don't know what the purpose of your demo is, what data the buffer should get...  ) Imho, Quiche project is not the champion in documentation + help + demos. Yes, few demos in source (without any comment) but I did not find wiki, how to, forum, docs,... Have a perfect day and lot of fun! Fre;D ---------------------------------------------------------------------- r.lukasiak · 2024-10-09 18:23 QuoteAnd I must also admit that I don't know what the purpose of your demo is, what data the buffer should get... actually it's not even a demo and it's not supposed to even receive any data, hence my concern about it's working correctly. This "demo" is just a testing ground for each another procedure/function I "translate". But now as conn_recv is finally "working", I can start writing some kind of demo to see if it really "works like a charm" QuoteHave a perfect day and lot of fun! likewise! ---------------------------------------------------------------------- TRon · 2024-10-09 20:07 Quote from: Fred vS on October 09, 2024, 08:01:22 pmImho, Quiche project is not the champion in documentation + help + demos. Yes, few demos in source (without any comment) but I did not find wiki, how to, forum, docs,... I assume that the main problem is that it is originally written for/in rust. There are many examples and snippets that use the rust classes to setup connections. The issue is that these classes abstract away too much to be able to tell what is actually happening behind the scenes. The c examples are sparse and indeed hardly documented. See also https://docs.quic.tech/quiche/ ---------------------------------------------------------------------- TRon · 2024-10-09 22:45 Quote from: Fred vS on October 09, 2024, 08:01:22 pmCode: 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 quiche_conn_set_session(conn: PQuiche_Conn; buf:PByte; buf_len:csize_t) : cint32; cdecl; external QUICHE_LIB; Here the result is always = -2. But I have no idea what this mean. A complete translation of the headers can be helpful  Code: [Select]enum quiche_error {     // There is no more work to do.     QUICHE_ERR_DONE = -1,     // The provided buffer is too short.     QUICHE_ERR_BUFFER_TOO_SHORT = -2, ... ---------------------------------------------------------------------- Fred vS · 2024-10-10 00:02 Hello TRon. 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 QUICHE_ERR_BUFFER_TOO_SHORT = -2, Well seen!  But even with: 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 BUF_SIZE: size_t = 8192 *128; The result is still -2 ---------------------------------------------------------------------- TRon · 2024-10-10 00:24 Quote from: Fred vS on October 10, 2024, 02:02:45 amBut even with: That is strange  And you actually allocated that buffer as well and passed its memory pointer to the buf parameter ? The only other thing I was able to find: Code: [Select]pub fn set_session(&mut self, session: &[u8]) -> Result<()> Configures the given session for resumption. On the client, this can be used to offer the given serialized session, as returned by session(), for resumption. This must only be called immediately after creating a connection, that is, before any packet is sent or received. Which, if I am not mistaken, seem to suggest that the buffer passed to set_session is required to contain (actual) data of/from the session. ---------------------------------------------------------------------- Fred vS · 2024-10-10 00:40 @TRon: Of course I need to study how Quiche works. The only thing I have is the C header and I have extracted a few methods from it, but only like an explorer in a completely unknown world. Maybe (surely) set_session() is for something else than init the lib. Thanks for the link you give, I will study it (asap). ---------------------------------------------------------------------- TRon · 2024-10-10 00:45 For retrieving the session, I think, you can use session, e.g. 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 void quiche_conn_session(const quiche_conn *conn, const uint8_t **out, size_t *out_len); the returned out and out_len then passed to set_session But, I am only guestimating here ---------------------------------------------------------------------- Fred vS · 2024-10-10 01:37 I admit that I don't know what Quiche does. But since I now have something that moves, thanks to r.lukasiak, I keep it on standby. Maybe one day Quiche will make me some good little dishes. ---------------------------------------------------------------------- TRon · 2024-10-10 01:54 I am not that savvy on the subject either but there is some documentation. It seems to focus on UDP multiplex streaming with encryption, also supporting http3. With regards to the library itself (and as far as I am able to tell at this moment): - create config with quiche_config_new - customize configuration with the dozen or so functions - connect with quiche_connect for client and quiche_accept for server or quich_conn_new_with_tls - use the connection itself with the other functions such as the quiche_conn_sendXXXX or quich_conn_streamXXXX functions - I do not know where/when the quiche_negotiate_version function comes into play. There are also several peer and path functions and ofc the http3 (connection) functionality. Thus far I had the impression that r.lukasiak has the more experience/expertise with QUIC (perhaps quiche in particular ?) but perhaps he is able to tell why he wants to use it because I also like my appetizers ---------------------------------------------------------------------- r.lukasiak · 2024-10-10 23:32 @Fred vS QuoteI admit that I don't know what Quiche does. Quiche is an implementation of QUIC, which is a new encrypted transport layer network protocol built atop UDP but with TCP-like features and  more, using TLS 1.3  by default. @TRon Quotethat r.lukasiak has the more experience/expertise with QUICI have absolutely no experience, nor expertise on QUIC  Quotebut perhaps he is able to tell why he wants to use it because I also like my appetizerswell... that's a good question. I still don't know if I really need or want it. I was playing with Sockets and I was searching for TLS 1.3 option which is not available (as far as I know) for FreePascal. While googling I came across QUIC which seems pretty appealing to me, it comes with a couple of cool features like TLS 1.3 by default, multiple streams within one connection, 0-RTT etc. And since I had a lot of free time and there was no QUIC bindings for FreePascal.... here we are ---------------------------------------------------------------------- delphius · 2024-10-16 19:05 Quote from: r.lukasiak on October 11, 2024, 01:32:35 amwell... that's a good question. I still don't know if I really need or want it. I was playing with Sockets and I was searching for TLS 1.3 option which is not available (as far as I know) for FreePascal. While googling I came across QUIC which seems pretty appealing to me, it comes with a couple of cool features like TLS 1.3 by default, multiple streams within one connection, 0-RTT etc. And since I had a lot of free time and there was no QUIC bindings for FreePascal.... here we are  A year ago, I also started looking for a native library to implement TLS 1.3, and my search led to an existing good native implementation of TLS 1.2: https://my6.code.blog/2021/01/13/fundamentals-library/ - blog post https://github.com/fundamentalslib/fundamentals5 - the library itself https://github.com/fundamentalslib/fundamentals5/tree/master/Source/TL S - implementation https://fundamentals5.kouraklis.com/ - function reference guide There is also a wrapper for Windows, but it’s not a universal full native solution: https://github.com/Fr0sT-Brutal/Delphi_SChannelTLS The absence of a native TLS 1.3 forced me to write my own educational implementation: https://github.com/delphius/fpmtls - implementation https://github.com/delphius/fpmailsend/tree/main/native/tlsmail - an example of sending mail via smtp through a secure channel using a Google mail server. This is purely an educational example, using only one TLS_AES_128_GCM_SHA256 + curve25519 suite, but it works with most servers. After that, I didn’t have time to continue. This year, during vacation, I managed to complete the implementation of the second suite TLS_CHACHA20_POLY1305_SHA256 (attached), but I haven’t had the time or energy to integrate it into the implementation. The idea is to bring everything together and integrate it into fpc as a layer on top of https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/fcl- net/src/sslsockets.pp similar to OpenSSL - https://gitlab.com/freepascal.org/fpc/source/- /blob/main/packages/openssl/src/opensslsockets.pp GnuTLS - https://gitlab.com/freepascal.org/fpc/source/- /blob/main/packages/gnutls/src/gnutlssockets.pp purely as a placeholder, without claims to security and reliability, when TLS access to resources is needed, but there is no desire to use OpenSSL. Quote from: r.lukasiak on October 11, 2024, 01:32:35 amI have absolutely no experience, nor expertise on QUIC  I've been looking at QUIC for a year now, too, I even managed to read the RFC, now it's interesting to see how it works in life