Using HTTPC - Not working?

Discussion in '3DS - Homebrew Development and Emulators' started by JackMacWindows, Dec 16, 2016.

  1. JackMacWindows
    OP

    JackMacWindows Member

    Newcomer
    41
    20
    Jan 16, 2016
    United States
    Hello,
    I am creating a program that connects to the internet to download files. I am trying to download a file from the program, but httpcInit() returns -522183694 and httpcOpenContext() returns -656406537. I am connected to the Internet when I run the program. Here is my code:
    Code:
    //
    //  main.cpp
    //  Homebrew Manager
    //
    //  Created by JackMacWindows on 1/15/16.
    //  Copyright © 2016 MCJack123. All rights reserved.
    //
    
    #include "utils.h"
    #include "parser.h"
    #include "execute.h"
    
    Result ret = 0;
    u8 *packagesF;
    httpcContext context;
    char *url = "http://raw.githubusercontent.com/MCJack123/HBM-repo/master/Packages";
    
    //from utils.h
    u8 * http_download(httpcContext *context) { //This error handling needs updated with proper text printing once ctrulib itself supports that.
        Result ret = 0;
        u32 statuscode = 0;
        u32 contentsize = 0;
        u8 *buf;
        ret = httpcBeginRequest(context);
        if (ret != 0) {debugPrint("\x1b[31mFailed to connect: request denied\x1b[37m"); return (u8*)"";}
        ret = httpcGetResponseStatusCode(context, &statuscode);
        if (ret != 0) {debugPrint("\x1b[31mFailed to connect: could not get status code\x1b[37m"); return (u8*)"";}
        if (statuscode != 200) {
    #ifdef __DEBUG
            printf("\x1b[31mError: Failed to connect: Bad status code (%lu %s)\x1b[37m\n", statuscode, httpResponses[statuscode]);
    #endif
            return (u8*)"";
        }
        ret=httpcGetDownloadSizeState(context, NULL, &contentsize);
        if (ret != 0) {debugPrint("\x1b[31mFailed to connect: could not get size\x1b[37m"); return (u8*)"";}
        gfxFlushBuffers();
        buf = (u8*)malloc(contentsize);
        if (buf == NULL) {debugPrint("\x1b[31mError: could not allocate memory\x1b[37m"); return (u8*)"";}
        memset(buf, 0, contentsize);
        ret = httpcDownloadData(context, buf, contentsize, NULL);
        if (ret != 0) {
            debugPrint("\x1b[31mFailed to connect: failed to download file\x1b[37m");
            free(buf);
            return (u8*)"";
        }
        return buf;
    }
    //done
    
    int main(int argc, char* argv[]) {
        gfxInitDefault();
        //Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one
        consoleInit(GFX_TOP, &screen);
        consoleInit(GFX_BOTTOM,&debug);
        consoleSelect(&screen);
        APT_CheckNew3DS(&consoletype);
        printf("Console type: %s\n",consoletype?"New 3DS. Good job!":"Old 3DS. This may be a bit slow.");
        debugPrint("Downloading packages file");
        consoleSelect(&debug);
        printf("%li ", httpcInit(256)); //httpcInit() returns -522183694
        ret = httpcOpenContext(&context, HTTPC_METHOD_GET, url, 1); //returns -656406537
        printf("%li", ret);
        consoleSelect(&screen);
        if (ret == 0) {
            debugPrint("Starting download");
            packagesF = http_download(&context);
            debugPrint((const char*)packagesF);
            parsePackagesFile(std::string((char*)packagesF));
            httpcCloseContext(&context);
            debugPrint("Done.");
        } else printf("\x1b[31mError: Failed to connect\x1b[37m\n");
        int selection = 0;
        consoleSelect(&screen);
        while (aptMainLoop()) {
            consoleClear();
            printf("Homebrew Manager for 3DS by JackMacWindows\nPlease select an option:\n\n %s Install official package\n %s Add/install unofficial repository\n %s Download other zip file", selection==0?"*":" ", selection==1?"*":" ", selection==2?"*":" ");
            hidScanInput();
            u32 kDown = hidKeysDown();
            if (kDown) {
                if (kDown & KEY_DOWN) selection = incIntWithMax(selection, 2);
                else if (kDown & KEY_UP) selection = decIntWithMax(selection, 2);
                else if (kDown & KEY_A) {
                    consoleClear();
                    printf("\n\nSelected option: ");
                    runManager(selection);
                }
                else if (kDown & KEY_START) goto End;
            }
            gfxFlushBuffers();
            gfxSwapBuffers();
            //Wait for VBlank
            gspWaitForVBlank();
            sleep(.075);
        }
    End:
        // Exit services
        httpcExit();
        gfxExit();
        return 0;
    }
    What is wrong with my program? If you need anything else, just ask me.
     
    Last edited by JackMacWindows, Dec 16, 2016
    Quantumcat likes this.
  2. JackMacWindows
    OP

    JackMacWindows Member

    Newcomer
    41
    20
    Jan 16, 2016
    United States
    Ok, I fixed it by using another download function. I now have a new problem: when downloading a ZIP file, it stops on the first "0x00" character or NULL character, and returns without continuing past that character. Here is the code for the download:
    Code:
    bool httpGet(const char* url, u8** buf, u32* size, const bool verbose) {
        httpcContext context;
        if (!CHECK(httpcOpenContext(&context, HTTPC_METHOD_GET, (char*)url, 0), "Could not open HTTP context")) return false;
        // Add User Agent field (required by Github API calls)
        if (!CHECK(httpcAddRequestHeaderField(&context, (char*)"User-Agent", (char*)"Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7498.US"), "Could not set User Agent")) return false;
    
        // Add root CA required for Github and AWS URLs
        CHECK(httpcAddTrustedRootCA(&context, cybertrust_cer, cybertrust_cer_len), "Could not add Cybertrust root CA");
        CHECK(httpcAddTrustedRootCA(&context, digicert_cer, digicert_cer_len), "Could not add Digicert root CA");
    
        if (!CHECK(httpcBeginRequest(&context), "Could not begin request")) return false;
    
        u32 statuscode = 0;
        if (!CHECK(httpcGetResponseStatusCode(&context, &statuscode), "Could not get status code")) return false;
        if (statuscode != 200) {
            // Handle 3xx codes
            if (statuscode >= 300 && statuscode < 400) {
                char newUrl[1024];
                if (!CHECK(httpcGetResponseHeader(&context, (char*)"Location", newUrl, 1024), "Could not get Location header for 3xx reply")) return false;
                if (!CHECK(httpcCloseContext(&context), "Could not close HTTP context")) return false;
                return httpGet(newUrl, buf, size, verbose);
            }
            debugPrint(formatErrMessage(std::string("Non-200 status code: " + std::string(httpResponses[statuscode])).c_str(), statuscode).c_str());
            return false;
        }
    
        u32 pos = 0;
        u32 dlstartpos = 0;
        u32 dlpos = 0;
        Result dlret = HTTPC_RESULTCODE_DOWNLOADPENDING;
    
        if (!CHECK(httpcGetDownloadSizeState(&context, &dlstartpos, size), "Could not get file size")) return false;
       
        *buf = (u8*)std::malloc(*size);
        if (*buf == NULL) {debugPrint(formatErrMessage("Could not allocate enough memory", *size).c_str()); return false;}
        std::memset(*buf, 0, *size);
        printf("%lu ", *size);
        while (pos < *size && dlret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING)
        {
            u32 sz = *size - pos;
            printf("%lu %lu ", sz, pos);
            dlret = httpcReceiveData(&context, *buf + pos, sz);
            if (!CHECK(httpcGetDownloadSizeState(&context, &dlpos, NULL), "Could not get file size")) return false;
            pos = dlpos - dlstartpos;
            printf("%lu %lu %lu ", dlpos, sz, pos);
            if (verbose) {
                consoleSelect(&debug);
                consoleClear();
                printf("Download progress: %lu / %lu", dlpos, *size);
                gfxFlushBuffers();
            }
        }
       
        if (verbose) {
            printf("\n");
        }
    
        if (!CHECK(httpcCloseContext(&context), "Could not close HTTP context")) return false;
        return true;
    }
    The ZIP file I am reading is http://raw.githubusercontent.com/MCJack123/HBM-repo/master/files/sample.hbp .