Edit

thodg/cgminer/util.c

Branch :

  • Show log

    Commit

  • Author : Jeff Garzik
    Date : 2010-11-25 04:03:59
    Hash : 945be82e
    Message : Move utility routines to util.c.

  • util.c
  • /*
     * Copyright 2010 Jeff Garzik
     *
     * This program is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the Free
     * Software Foundation; either version 2 of the License, or (at your option) 
     * any later version.  See COPYING for more details.
     */
    
    #define _GNU_SOURCE
    #include "cpuminer-config.h"
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <jansson.h>
    #include <curl/curl.h>
    #include "miner.h"
    
    struct data_buffer {
    	void		*buf;
    	size_t		len;
    };
    
    struct upload_buffer {
    	const void	*buf;
    	size_t		len;
    };
    
    static void databuf_free(struct data_buffer *db)
    {
    	if (!db)
    		return;
    	
    	free(db->buf);
    
    	memset(db, 0, sizeof(*db));
    }
    
    static size_t all_data_cb(const void *ptr, size_t size, size_t nmemb,
    			  void *user_data)
    {
    	struct data_buffer *db = user_data;
    	size_t len = size * nmemb;
    	size_t oldlen, newlen;
    	void *newmem;
    	static const unsigned char zero;
    
    	oldlen = db->len;
    	newlen = oldlen + len;
    
    	newmem = realloc(db->buf, newlen + 1);
    	if (!newmem)
    		return 0;
    
    	db->buf = newmem;
    	db->len = newlen;
    	memcpy(db->buf + oldlen, ptr, len);
    	memcpy(db->buf + newlen, &zero, 1);	/* null terminate */
    
    	return len;
    }
    
    static size_t upload_data_cb(void *ptr, size_t size, size_t nmemb,
    			     void *user_data)
    {
    	struct upload_buffer *ub = user_data;
    	int len = size * nmemb;
    
    	if (len > ub->len)
    		len = ub->len;
    
    	if (len) {
    		memcpy(ptr, ub->buf, len);
    		ub->buf += len;
    		ub->len -= len;
    	}
    
    	return len;
    }
    
    json_t *json_rpc_call(const char *url, const char *userpass, const char *rpc_req)
    {
    	CURL *curl;
    	json_t *val;
    	int rc;
    	struct data_buffer all_data = { };
    	struct upload_buffer upload_data;
    	json_error_t err = { };
    	struct curl_slist *headers = NULL;
    	char len_hdr[64];
    
    	curl = curl_easy_init();
    	if (!curl)
    		return NULL;
    
    	if (opt_protocol)
    		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
    	curl_easy_setopt(curl, CURLOPT_URL, url);
    	curl_easy_setopt(curl, CURLOPT_ENCODING, "");
    	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
    	curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
    	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, all_data_cb);
    	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &all_data);
    	curl_easy_setopt(curl, CURLOPT_READFUNCTION, upload_data_cb);
    	curl_easy_setopt(curl, CURLOPT_READDATA, &upload_data);
    	if (userpass) {
    		curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
    		curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    	}
    	curl_easy_setopt(curl, CURLOPT_POST, 1);
    
    	if (opt_protocol)
    		printf("JSON protocol request:\n%s\n", rpc_req);
    
    	upload_data.buf = rpc_req;
    	upload_data.len = strlen(rpc_req);
    	sprintf(len_hdr, "Content-Length: %lu",
    		(unsigned long) upload_data.len);
    
    	headers = curl_slist_append(headers,
    		"Content-type: application/json");
    	headers = curl_slist_append(headers, len_hdr);
    	headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
    
    	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    
    	rc = curl_easy_perform(curl);
    	if (rc)
    		goto err_out;
    
    	val = json_loads(all_data.buf, &err);
    	if (!val) {
    		fprintf(stderr, "JSON failed(%d): %s\n", err.line, err.text);
    		goto err_out;
    	}
    
    	if (opt_protocol) {
    		char *s = json_dumps(val, JSON_INDENT(3));
    		printf("JSON protocol response:\n%s\n", s);
    		free(s);
    	}
    
    	databuf_free(&all_data);
    	curl_slist_free_all(headers);
    	curl_easy_cleanup(curl);
    	return val;
    
    err_out:
    	databuf_free(&all_data);
    	curl_slist_free_all(headers);
    	curl_easy_cleanup(curl);
    	return NULL;
    }
    
    char *bin2hex(unsigned char *p, size_t len)
    {
    	int i;
    	char *s = malloc((len * 2) + 1);
    	if (!s)
    		return NULL;
    	
    	for (i = 0; i < len; i++)
    		sprintf(s + (i * 2), "%02x", (unsigned int) p[i]);
    
    	return s;
    }
    
    bool hex2bin(unsigned char *p, const char *hexstr, size_t len)
    {
    	while (*hexstr && len) {
    		char hex_byte[3];
    		unsigned int v;
    
    		if (!hexstr[1]) {
    			fprintf(stderr, "hex2bin str truncated\n");
    			return false;
    		}
    
    		hex_byte[0] = hexstr[0];
    		hex_byte[1] = hexstr[1];
    		hex_byte[2] = 0;
    
    		if (sscanf(hex_byte, "%x", &v) != 1) {
    			fprintf(stderr, "hex2bin sscanf '%s' failed\n",
    				hex_byte);
    			return false;
    		}
    
    		*p = (unsigned char) v;
    
    		p++;
    		hexstr += 2;
    		len--;
    	}
    
    	return (len == 0 && *hexstr == 0) ? true : false;
    }