0

tree_add is called by g_idle_add in another thread
odd behaviour is that the hash is garbage, how would the message digest end up garbled?

the rest of the odd behaviour has been fixed with the below suggestions

#include <pthread.h>
#include <openssl/evp.h>
#include <gcrypt.h>
#include <gtk/gtk.h>

unsigned char *mdSHA256(char *data, size_t *len) {
    unsigned char *md = calloc(33, sizeof(char));
    int mdlen;
    EVP_MD_CTX *mdctx;
    EVP_add_digest(EVP_sha256());
    mdctx = EVP_MD_CTX_create();
    EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL);
    EVP_DigestUpdate(mdctx, data, *len);
    EVP_DigestFinal_ex(mdctx, md, &mdlen);
    EVP_MD_CTX_destroy(mdctx);
    EVP_cleanup();
    *len = mdlen;
    return md;
}

struct peer {
    int approved;
    int port;
    unsigned char *address;
    gcry_sexp_t pubkey;
    struct sf_connection *connection;
    struct peer *next;
    struct peer *prev;
};

struct peer *peers = NULL;

struct peer *peer_new() {
    struct peer *_peer = malloc(sizeof(struct peer));
    if(peers == NULL) {
        _peer->next = _peer;
        _peer->prev = _peer;
        peers = _peer;
    }
    else {
        peers->prev->next = _peer;
        _peer->prev = peers->prev;
        peers->prev = _peer;
        _peer->next = peers;
    }
    return _peer;
}

void *mainthread(void *m) { //code removed so you can run this
    sleep(2);
    struct peer *new_peer = new_peer();
    new_peer->port = 66666;
    new_peer->address = "127.0.0.1";
    new_peer->pubkey = NULL;
    new_peer->approved = 0;
    g_idle_add(tree_add, new_peer);
}

gboolean tree_add(gpointer data) {
    struct peer *new_peer = data;
    GtkTreeIter iter;
    size_t size = gcry_sexp_sprint(new_peer->pubkey, GCRY   SEXP_FMT_ADVANCED, NULL, 0);
    char *buf = malloc(size);
    gcry_sexp_sprint(new_peer->pubkey, GCRYSEXP_FMT_ADVANCED, buf, size);
    unsigned char *md = mdSHA256(buf, &size);
    gtk_tree_store_append(serverstore, &iter, NULL);
    gtk_tree_store_set(serverstore, &iter,
                   COL_IP, new_peer->address,
                   COL_PORT, new_peer->port,
                   COL_PUBKEYMD, md,
                   COL_APPROVED, new_peer->approved,
                   -1);
    free(buf);
    free(md);
    return 0;
}

GtkWidget *setup_tree() {
    GtkWidget *tree;
    GtkTreeViewColumn *column;
    GtkCellRenderer *renderer;

    serverstore = gtk_tree_store_new(N_COLUMNS,
                                 G_TYPE_STRING,
                                 G_TYPE_INT,
                                 G_TYPE_STRING,
                                 G_TYPE_BOOLEAN);


    tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(serverstore));
    g_object_unref(G_OBJECT(serverstore));

    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes("IP", renderer, "text", COL_IP, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);

    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes("Port", renderer, "text", COL_PORT, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);

    renderer = gtk_cell_renderer_text_new();
    column = gtk_tree_view_column_new_with_attributes("PubKey", renderer, "text", COL_PUBKEYMD, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);

    renderer = gtk_cell_renderer_toggle_new();
    column = gtk_tree_view_column_new_with_attributes("Approved", renderer, "active", COL_APPROVED, NULL);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);

    return tree;
}

void on_window_main_destroy() {
    raise(SIGINT);
    gtk_main_quit();
}

int main(int argc, char **argv) {
    GtkWidget *window;
    GtkWidget *view;

    pthread_t main_thread;
    if(pthread_create(&main_thread, NULL, mainthread, NULL)) {
        fprintf(stderr, "Error creating thread\n");
        return 1;
    }

    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", on_window_main_destroy, NULL);
    gtk_window_set_title(GTK_WINDOW(window), "ProjXverse Master");
    gtk_window_set_default_size(GTK_WINDOW(window), 640, 480);
    view = setup_tree();
    gtk_container_add(GTK_CONTAINER(window), view);
    gtk_widget_show_all(window);
    gtk_main();

    pthread_join(main_thread, NULL);

    return 0;
}

to make

gcc -c main.c -o test `pkg-config --cflags --libs gtk+-3.0` -lcrypto -lgcrypt -lpthread
  • I don't know if this will fix it, but your GSourceFunc must return `gboolean`, not `void`, and the return value indicates whether to schedule the function again or not. Check the `g_idle_add()` documentation for details. Once you fix that you can remove the incorrect `(GSourceFunc)` cast. – andlabs Nov 28 '15 at 05:33
  • Also even with the code removed we still can't run this. What does your `mainthread()` do? I have a feeling the bug is in there. – andlabs Nov 28 '15 at 05:39
  • mainthread runs an ev_loop connecting peers, the purpose of the interface is to track the peers and approve them on the network – Gabriel Lambert Nov 28 '15 at 05:47
  • Ah I see. The `EVP_xxx()` functions do not give you the hash as a string. They give you the hash as a set of bytes; that is, it does `unsigned char md[] = { 0xAB, 0xCD, 0xEF, ... }`, not `unsigned char md[] = "ABCDEF..."`. You will need to convert the hash into a string in your `tree_add()` function before giving it to the GtkTreeStore. – andlabs Nov 28 '15 at 14:58
  • a string is an array of bytes, if its any different how would you convert it? I use it elsewhere and have no such problem. – Gabriel Lambert Nov 29 '15 at 22:47
  • A string is an array of bytes, yes, but the byte with hex value `AB` and the string `"AB"` are not the same bytes. The string `"AB"` is represented by the UTF-8 bytes `0x41 0x42` (GTK+ uses UTF-8). For what you want to do, you'd need to allocate a buffer that is `2*NumberOfBytesInHash + 1` bytes, fill each successive string byte with the hex representation of each nibble of each hash byte, fill the last string byte with `'\0'`, and *then* pass that to GtkTreeStore. You don't have to do it this exact way, but you still have to do it. – andlabs Nov 30 '15 at 00:44
  • [The OpenSSL documentation on the `EVP_xxx()` functions](https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html) has an example near the bottom of the page that merely prints each byte with `printf()`, if you want a concrete code example of what you have to do. It'll take some work to convert that to filling a string buffer, but it shouldn't be too hard. – andlabs Nov 30 '15 at 00:45
  • i get it now, i thought the hash was suppose to be alpha-numerical only – Gabriel Lambert Nov 30 '15 at 02:06
  • Yes; hashes are very long sequences of bytes. When printed, they're usually printed as one long hexadecimal number. Try this for yourself: run some files through `md5sum` and notice that the sums are all comprised of hexadecimal digits. If you take each pair of digits in isolation, you get the values for each individual byte of the hash. – andlabs Nov 30 '15 at 04:51
  • Did you figure it out by now? – andlabs Dec 02 '15 at 23:56
  • yes i did, thank you – Gabriel Lambert Dec 03 '15 at 21:33

0 Answers0