DaemonForums  

Go Back   DaemonForums > Miscellaneous > Programming

Programming C, bash, Python, Perl, PHP, Java, you name it.

Reply
 
Thread Tools Display Modes
  #1   (View Single Post)  
Old 24th February 2021
Omphalotus_japonicus Omphalotus_japonicus is offline
New User
 
Join Date: Jan 2021
Posts: 3
Default I am having trouble receiving uncorrupted file data with unix sockets.

I'm a relative newbie when it comes to the world of programming and have only recently taken up unix networking. I first created a program which downloaded files over the HTTP protocol to avail, and am now trying to make a file downloader that instead uses the Gemini protocol.

The issue, however, is that I can not apply my method of receiving uncorrupted data that I used with my HTTP file downloader as I used the content length header which Gemini lacks. I've experimented a little and came up with what I thought could be a solution, but does not work and I have yet to understand why.

Here's my code:

Code:
/*
 * Simple program which downloads a file originating from the Gemini protocol
 * using unix socket programming and the LibreSSL library.
 */

#include <netdb.h>
#include <libressl/openssl/ssl.h>

#include <cassert>
#include <iostream>
#include <fstream>

int
main()
{
        /*
         * Flag the to-be-created pointer to a linked-list pointer to allow
         * both IPV4 and IPV6 IP addresses and use TCP.
         */

        struct addrinfo flags = {0};
                        flags.ai_family = AF_UNSPEC;
                        flags.ai_socktype = SOCK_STREAM;

        /*
         * Return value for error handling.
         */

        int rv = 0;

        /*
         * Stores given address, port, and above-defined flags into a pointer
         * to a linked-list pointer which contains necessary connection
         * information.
         */

        struct addrinfo *conninfo;
        rv = getaddrinfo("skyjake.fi", "1965", &flags, &conninfo);
        assert(rv == 0);

        /*
         * Creates a communication endpoint and returns a file descriptor
         * relating to that endpoint and assigns it to the "sockfd" int.
         */

        int sockfd = socket(conninfo->ai_family, conninfo->ai_socktype,
                            conninfo->ai_protocol);
        assert(sockfd != -1);

        /*
         * Connects to given address on the socket referred
         * to by the "sockfd" int.
         */

        rv = connect(sockfd, conninfo->ai_addr, conninfo->ai_addrlen);
        assert(rv == 0);

        SSL_library_init();

        /*
         * Creates an SSL structure containing TLS/SSL connection information
         * including the SSL_CTX object which initializes the cipher list,
         * session cache setting, callbacks, and the keys of
         * certificates based off the connection method given, being the
         * TLSv1.2 protocol.
         */

        SSL *ssl = SSL_new(SSL_CTX_new(TLSv1_2_client_method()));
        assert(ssl != nullptr);

        /*
         * Sets the above-defined SSL object's socket file descriptor to the
         * one contained in the "sockfd" int.
         */

        rv = SSL_set_fd(ssl, sockfd);
        assert(rv == 1);


        /*
         * Initializes a TLS/SSL handshake with the connected server.
         */

        rv = SSL_connect(ssl);
        assert(rv == 1);

        std::string req = "gemini://skyjake.fi/lagrange/lagrange_about.png"
                          "\r\n";

        /*
         * Sends a GET request to the connected server for the requested file.
         */

        rv = SSL_write(ssl, req.data(), req.size());
        assert(rv > 0);

        std::string buffer = {0};
        int read_size = 8192;

        /*
         * Inputs received data into a buffer while its available and with each
         * iteration resize the buffer and read data by an addition of the read
         * size, storing the new data in a new portion of the buffer to prevent
         * any overwriting.... or so I thought
         */

        while (rv != 0)
        {
                int old_size = buffer.size();
                buffer.resize(old_size + read_size);
                rv = SSL_read(ssl, buffer.data() + old_size, old_size + read_size);
        }

        /*
         * Removes the Gemini header from the buffer.
         */

        buffer.erase(0, buffer.find("\r\n") + 2);

        std::ofstream file("image.png", std::ios::binary | std::ios::out
                                      | std::ios::trunc);


        SSL_shutdown(ssl);
        shutdown(sockfd, 2);

        return 0;
}

Last edited by J65nko; 4 Weeks Ago at 04:31 AM. Reason: Added [code] and [/code] tags
Reply With Quote
Reply

Tags
c++, networking, sockets, unix, unix networking

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Unix file permissions vs chroot + systrace e1-531g OpenBSD Security 4 10th August 2015 02:12 AM
Trouble pxe booting a .php file with dhcpd denriktiga OpenBSD General 3 6th October 2014 05:36 PM
any unix utility that determines the right extension of a file ? daemonfowl Other BSD and UNIX/UNIX-like 8 22nd March 2013 12:19 PM
Unix still data center darling, says survey J65nko News 3 15th July 2011 03:05 AM
.wav file playing very fast on unix, fine on win gosha General software and network 16 2nd June 2009 02:37 PM


All times are GMT. The time now is 05:23 PM.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
Content copyright © 2007-2010, the authors
Daemon image copyright ©1988, Marshall Kirk McKusick