Vis innlegg

Denne delen lar deg se alle innlegg laget av dette medlemmet. Merk at du bare kan se innlegg gjort i områder du har tilgang til.

Meldinger - Floyd-ATC

Sider: [1] 2 3 ... 52
Generelt teknisk / Rust: How to test a module that uses TcpStream?
« på: 27. April 2023, 14:06 pm »
How do you make a module testable that requires a std::net::TcpStream?

I had this problem with a (toy) project of mine that used a struct to encapsulate a BufReader and a BufWriter, presenting only the following in order to make it impossible to accidentally leak data into or out of the raw stream:

Kode: [Velg]
    pub fn new(TcpStream) -> Self
    pub fn reader(&mut self) -> &mut BufReader<TcpStream>
    pub fn writer(&mut self) -> &mut BufWriter<TcpStream>
    pub fn close(&mut self)

My initial though was to use generics to allow any type of stream but this turned out to be both really hard (because std::net::TcpStream uses .try_clone() rather than implementing the Clone trait, and it uses .shutdown(Shutdown) instead of .close()) and it would have required all the modules that depended on this one to deal with the generics that weren't needed to begin with. What started as a simple problem was now becoming really complicated in my mind.

I could turn it around by saying that my component now just implements a new trait, but this would not only require a whole lot of extra code just to implement, it would still require all the other modules to deal with the extra generics and most importantly: it would actually bring me no closer to the original goal: Testing this really quite simple module right here.

During my evening walk, it finally dawned on me that the people who designed the IP stack already thought of this exact problem (as well as many other problems) decades ago and they implemented a solution so simple it's easy to forget about it and make things harder than they need be:

The loopback address.

Specifying a port number of 0 means the operating system gets to pick an unused port for you. So I simply added one more function, a double constructor that creates a pair of object instances connected to each other:

Kode: [Velg]
    // Convenience function for testing
    pub fn loopback() -> Result<(Self, Self), std::io::Error> {
        let listener = TcpListener::bind("")?;

        // From viewpoint of the client
        let server_addr = listener.local_addr()?;
        let server = TcpStream::connect(server_addr)?;

        // From viewpoint of the server
        let (client, client_addr) = listener.accept()?;

        let conn1 = Self::new(server, server_addr);
        let conn2 = Self::new(client, client_addr);
        return Ok((conn1, conn2));

Not only did this make it trivial to test this module, it also made it dead simple to test all those other modules that depended on this one! The idea is easily transferred to other types of scenarios where you have to test code that uses TcpStream directly:

Kode: [Velg]
mod tests {
    use super::*;

    fn loopback() -> Result<(std::net::TcpStream, std::net::TcpStream), std::io::Error> {
        let listener = std::net::TcpListener::bind("")?;
        let server = std::net::TcpStream::connect(listener.local_addr().unwrap())?;
        let (client, _) = listener.accept()?;
        return Ok((server, client));

    // Actual tests here, just call loopback() whenever you need a pair of streams connected to each other
    // Put data into one, read it out of the other.
    // ...


Final note: On certain very locked-down platforms you may have to relax local firewall rules in order to allow loopback traffic, but no sane person would ever test their network code on a machine anywhere near production anyway so if this turns out to be a problem then maybe you should re-evaluate how and where you do things.

Minecraft / Sv: Ny minecraft-update (1.4.2,[...] og 1.10)
« på: 21. Februar 2022, 12:40 pm »
Ser at nettsiden er oppe også, men ikke det dynamiske kartet.
Hmm jeg lurer på om jeg vet hvorfor! Funker det nå?

Minecraft / Sv: Ny minecraft-update (1.4.2,[...] og 1.10)
« på: 18. Februar 2022, 10:09 am »
Serveren skal være oppe nå,

Oppdatering: Etter en del plundring har jeg fått på plass et systemd-oppsett som i teorien skal auto-starte serveren etter reboot pga. strømbrudd eller lignende. Tidligere har jeg måttet logge inn og starte den manuelt. Krysser fingrene for at det gir mer stabilitet.

Eco / Sv: Nede?
« på: 28. August 2021, 13:09 pm »
Jeg begriper ikke hvorfor det ikke funker. IP-adressen er ikke satt noe sted i ECO-serveren, den skal selv ta kontakt med en eller annen directory-tjeneste og registrere seg men et eller annet nekter tydeligvis å forstå at IP-adressen er endret :-|

At du har en "bookmark" fra tidligere er en ting, men selv når jeg søker opp serveren manuelt så forsøker klienten fortsatt å kontakte den gamle adressen.

Eco / Sv: Nede?
« på: 27. August 2021, 11:49 am »

Koplet over til gigabit fiber i går, mulig at serveren trenger en restart for å få med seg at den har fått ny IP-adresse. Forsøker nå.

Eco / Vote "No"
« på: 18. Juli 2021, 10:24 am »
To spillere fra Nederland, dikkenoob nl og TTV_Goodpuma, forsøker å ratifisere en ribbet grunnlov som vil gjøre dem til "president" og "vice precident" med all makt. Ingen spillere vil kunne fremme lovforslag eller påvirke noe som helst hvis denne loven går igjennom vil det være vanskelig å rekruttere flere spillere. Jeg vil derfor ikke ha annet valg enn å slette den som administrator, noe jeg helst vil slippe.

Logg inn. Stem "Nei".

Eco / Eksperimentell Eco-server "ATC Sanctuary"
« på: 16. Juli 2021, 08:37 am »
Jeg har satt opp en eksperimentell Eco-server, foreløpig med "no collaboration" men vi får se hva det er stemning for hvis det kommer spillere på den. Meteoren slår ned om først et år, så dette er en server ment for langsiktig og virkelighetstro bygging med hensyn til miljøet.

Jeg har NULL erfaring med det politiske aspektet ved Eco så hvis noen er interessert i å prøve seg er det bare å joine.

Rent teknisk, serveren står på 40 Mbps idag men gigabit fiber kommer i løpet av sommeren :-)

I wanted to use TLS on a regular socket file descriptor and could not find a single man-page or example explaining how to construct the BIO* that let me do cleartext BIO_read() and BIO_write() on a HTTPS socket.

After much experimenting, I finally figured it out. Making a note here for future reference.

Kode: [Velg]
// context is a smart pointer to a CTX* structure containing certs etc.
// server_fd is a plain TCP socket descriptor in "listen" mode
// returns client_fd that your application must close
// Use BIO_read() and BIO_write() to communicate with the client,
// you *MUST NOT* read/write on client_fd
int Socket::accept(const Context& context, int server_fd)
  this->verify_flag = -1;
  this->ssl = nullptr;
  this->bio = nullptr;

  // TCP accept
  int client_fd = Net::accept(server_fd);
  if (client_fd != -1) {
    // TCP accept successful

    // Create a BIO chain and get the SSL pointer
    BIO* raw = BIO_new_socket(client_fd, BIO_NOCLOSE);
    BIO* ssl = BIO_new_ssl(context.get(), 0); // 0=server, 1=client
    this->bio = BIO_push(ssl, raw);
    BIO_get_ssl(ssl, &this->ssl);
    // SSL protocol accept
    int rc = SSL_accept(this->ssl);
    if (rc <= 0) {
      // 0 = SSL failure, <0 = connection failure
      client_fd = -1;

    std::cout << "calling SSL_get_verify_result()" << std::endl;
    this->verify_flag = SSL_get_verify_result(this->ssl);
  return client_fd;

Generelt teknisk / C++ unique_ptr wrapper for strdup()
« på: 29. ſeptember 2020, 11:48 am »
How to wrap a char* from strdup() in a smart pointer to guarantee it gets freed?

Kode: [Velg]
#include <memory>
typedef std::unique_ptr<char, decltype(&std::free)> char_ptr;

char_ptr make_char_ptr(const std::string str)
  return char_ptr(strdup(, std::free);


char_ptr foo = make_char_ptr("bar");
foo.get(); // char* pointer to a copy of "bar"

// pointer automatically gets freed when 'foo' goes out of scope
// or can be freed manually with

This question seems to be a FAQ that nobody seems to understand or answer correctly, instead answering a lot of other questions dealing with clock irregularity and loss of precision when dealing with nanoseconds. Neither of which matter when you're using double precision and only want milliseconds for moving a game object on the screen or whatever and the occasional jitter or skew from a timesync event isn't going to bring about the end of civilization as we know it.

So here's how I finally managed to solve it with my fairly limited C++ skill:
Kode: [Velg]
double now() {
  auto time = std::chrono::system_clock::now().time_since_epoch();
  std::chrono::seconds seconds = std::chrono::duration_cast< std::chrono::seconds >(time);
  std::chrono::milliseconds ms = std::chrono::duration_cast< std::chrono::milliseconds >(time);
  return (double) seconds.count() + ((double) (ms.count() % 1000)/1000.0);

Sample output:
Kode: [Velg]
1577703729.406= Unix timestamp in seconds as a double with millisecond precision.

There you have it.

Useful in pretty much any formula that deals with time in seconds, yet somehow not documented anywhere and unbelievably verbose for a modern library supposedly written specifically to deal exclusively with time.

Generelt teknisk / intermittent dhclient bad udp checksum
« på: 12. November 2018, 08:01 am »
Running a CentOS 7.3 router with DHCP address from my ISP, I would sometimes get an IP address, sometimes not. Sometimes the IP address would get assigned but then fail to renew, causing seemingly random loss of connectivity. Rebooting would sometimes fix it, sometimes not. Very annoying.

Studying the problem over time, tcpdump revealed that the UDP checksum on outgoing packets from dhclient would periodically have bad checksums. Not empty, just incorrect. Why this happens only sometimes and not all the time is beyond me, it's probably just a stupid bug in dhclient but I found the following workaround:

Kode: [Velg]
firewall-cmd --permanent --direct --add-rule ipv4 mangle POSTROUTING 0 -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
This will recalculate the UDP checksum on all outgoing UDP/68 traffic and not touch anything else. Reload firewalld with "systemctl reload firewalld" or reboot for the change to take effect, then verify with tcpdump.

Kode: [Velg]
tcpdump -i ens160 -nn -vv port 68(Substitute ens160 with your external interface, obviously)

It's also possible to activate the change by repeating the firewall-cmd without the "--permanent" clause ofcourse, but I usually just reboot to make absolutely sure I didn't break anything while experimenting --  this may not be feasible in your environment BUT on the other hand, if you are reading this then chances are you are already experiencing random service interruptions so.... You decide.

Minecraft / Sv: Når serveren er nede så snakker vi her =)
« på: 08. November 2018, 09:55 am »
Har hatt en del problemer med internettleveransen de siste ukene, senest i går. Når jeg sniffer på routeren så ser jeg at det kommer DHCP-offers på en 192.168-adresse i stedet for den offisielle IP'en jeg skal ha, men når jeg forklarte dette til leverandør så pratet de om at de ikke fikk kontakt med kabelmodemet. Skrur av og på flere ganger, rebooter routeren flere ganger, ingen bedring... og så plutselig får jeg riktig IP og ting funker igjen. Lurer på om det kan være en eller annen apekatt som gjør noe rart i nettet her.

Minecraft / Sv: Når serveren er nede så snakker vi her =)
« på: 10. November 2017, 22:24 pm »
*urk* sikringen gikk for noen dager siden og jeg glemte å starte opp serveren etterpå :-|

Google Chrome will complain loudly if run as root, telling you to add --no-sandbox manually and then showing you a warning that this is a really bad idea. Imagine if you could have Gnome solve the problem for you?

Well, you can. First of all, understand that running a web browser as root IS a bad idea, because there will always be security vulnerabilities. However, since Linux is a modern operating system, it's quite possible to be logged in as root and still run the web browser as a less privileged process:

First, create a separate user account that will be used for web browsing. For example: "anonymous".
Make sure you give this user a really REALLY strong password. You will never need to actually use it.

Now copy the file "/usr/share/applications/google-chrome.desktop" to "/root/.local/share/applications/google-chrome.desktop"

Edit all the lines starting with "Exec=" by inserting "gksu -wu anonymous". For example:
Kode: [Velg]
Exec=gksu -wu anonymous /usr/bin/google-chrome-stable %U

Now log out and log back in to restart the Gnome shell, and you should be able to start Chrome without any hassle. Use the command "ps auxfw | grep chrome" to verify that the processes run as "anonymous" and not as "root". Remember that any manual changes to the browser settings etc. must be made under "/home/anonymous".

Spent several weeks banging my head against the wall with this problem. When trying to start "atom" it just never appeared. When trying with "atom -f" (to run in the foreground) I would get the following error messages:
Kode: [Velg]
[] Running without the SUID sandbox! See https:
[] Multiple instances of AudioManager detected
[] Multiple instances of AudioManager detected
[] X IO error received (X server probably went away)

I focused on the first error message for a long time and found all sorts of red herrings, closed bug reports and no actual solutions. Finally it dawned on me that the actual problem was the LAST error message. I access my desktop via X2GO and therefore have a pretty special DISPLAY environment variable. Maybe that had something to do with it?

Kode: [Velg]
# cp /usr/lib/x86_64-linux-gnu/ /opt/atom
# sed -i 's/BIG-REQUESTS/_IG-REQUESTS/' /opt/atom/

...and suddenly atom worked.

Sider: [1] 2 3 ... 52