pico_errno pico_finish(PICO * pico) { if (pico == NULL) return OK; if (pico->valid && pico->file != NULL) { if (! pico->hash_valid) { pico_get_hash(pico); write_header(pico); } if (fflush(pico->file)) { DEBUG("Unable to flush stream."); return CANNOT_WRITE; } } pico->valid = false; // Header is now invalid. pico->file = NULL; pico->key_length = 0; pico_free(pico->key); pico->key = NULL; if (pico_is_error(pico)) { DEBUG("%s", pico->error_text); } pico_errno errno = pico->errno; pico_free(pico); return errno; }
static struct pico_dns_query *pico_dns_client_add_query(struct pico_dns_prefix *hdr, uint16_t len, struct pico_dns_query_suffix *suffix, void (*callback)(char *, void *), void *arg) { struct pico_dns_query *q = NULL, *found = NULL; q = pico_zalloc(sizeof(struct pico_dns_query)); if (!q) return NULL; q->query = (char *)hdr; q->len = len; q->id = short_be(hdr->id); q->qtype = short_be(suffix->qtype); q->qclass = short_be(suffix->qclass); q->retrans = 1; q->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); q->callback = callback; q->arg = arg; q->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dns_client_callback); if (!q->s) { pico_free(q); return NULL; } found = pico_tree_insert(&DNSTable, q); if (found) { pico_err = PICO_ERR_EAGAIN; pico_socket_close(q->s); pico_free(q); return NULL; } return q; }
static void pico_dns_client_retransmission(unsigned long now, void *arg) { struct pico_dns_key *key = (struct pico_dns_key *)arg; struct pico_dns_ns *q_ns = NULL; if (!key->retrans) { dns_dbg("DNS: no retransmission!\n"); pico_free(key->q_hdr); if(pico_tree_delete(&DNSTable,key)) pico_free(key); } else if (key->retrans <= PICO_DNS_CLIENT_MAX_RETRANS) { key->retrans++; dns_dbg("DNS: retransmission! (%u attempts)\n", key->retrans); // ugly hack q_ns = pico_tree_next(pico_tree_findNode(&NSTable,&key->q_ns))->keyValue; if (q_ns) key->q_ns = *q_ns; else key->q_ns = *((struct pico_dns_ns *)pico_tree_first(&NSTable)); pico_dns_client_send(key); pico_timer_add(PICO_DNS_CLIENT_RETRANS, pico_dns_client_retransmission, key); } else { dns_dbg("DNS ERROR: no reply from nameservers! (%u attempts)\n", key->retrans); pico_socket_close(key->s); pico_err = PICO_ERR_EIO; key->callback(NULL, key->arg); pico_free(key->q_hdr); /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ if(pico_tree_delete(&DNSTable,key)) pico_free(key); } }
static struct pico_dhcp_server_setting *pico_dhcp_server_add_setting(struct pico_dhcp_server_setting *setting) { uint16_t port = PICO_DHCPD_PORT; struct pico_dhcp_server_setting *dhcps = NULL, *found = NULL, test = {0}; struct pico_ipv4_link *link = NULL; link = pico_ipv4_link_get(&setting->server_ip); if (!link) { pico_err = PICO_ERR_EINVAL; return NULL; } test.dev = setting->dev; found = pico_tree_findKey(&DHCPSettings, &test); if (found) { pico_err = PICO_ERR_EINVAL; return NULL; } dhcps = pico_zalloc(sizeof(struct pico_dhcp_server_setting)); if (!dhcps) { pico_err = PICO_ERR_ENOMEM; return NULL; } dhcps->lease_time = setting->lease_time; dhcps->pool_start = setting->pool_start; dhcps->pool_next = setting->pool_next; dhcps->pool_end = setting->pool_end; dhcps->dev = link->dev; dhcps->server_ip = link->address; dhcps->netmask = link->netmask; /* default values if not provided */ if (!dhcps->pool_start) dhcps->pool_start = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_START; if (!dhcps->pool_end) dhcps->pool_end = (dhcps->server_ip.addr & dhcps->netmask.addr) | DHCP_SERVER_POOL_END; if (!dhcps->lease_time) dhcps->lease_time = DHCP_SERVER_LEASE_TIME; dhcps->pool_next = dhcps->pool_start; dhcps->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &pico_dhcpd_wakeup); if (!dhcps->s) { dhcps_dbg("DHCP server ERROR: failure opening socket (%s)\n", strerror(pico_err)); pico_free(dhcps); return NULL; } if (pico_socket_bind(dhcps->s, &dhcps->server_ip, &port) < 0) { dhcps_dbg("DHCP server ERROR: failure binding socket (%s)\n", strerror(pico_err)); pico_free(dhcps); return NULL; } pico_tree_insert(&DHCPSettings, dhcps); return dhcps; }
static struct pico_dns_ns *pico_dns_client_add_ns(struct pico_ip4 *ns_addr) { struct pico_dns_ns *dns = NULL, *found = NULL, test = {{0}}; dns = pico_zalloc(sizeof(struct pico_dns_ns)); if (!dns) { pico_err = PICO_ERR_ENOMEM; return NULL; } dns->ns = *ns_addr; found = pico_tree_insert(&NSTable, dns); if (found) { /* nameserver already present */ pico_free(dns); return found; } /* default NS found, remove it */ pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr); found = pico_tree_findKey(&NSTable, &test); if (found && (found->ns.addr != ns_addr->addr)) pico_dns_client_del_ns(&found->ns); return dns; }
static int pico_dns_client_del_query(uint16_t id) { struct pico_dns_query test = { 0 }, *found = NULL; test.id = id; found = pico_tree_findKey(&DNSTable, &test); if (!found) return -1; pico_free(found->query); pico_socket_close(found->s); pico_tree_delete(&DNSTable, found); pico_free(found); return 0; }
PICO * pico_new(FILE * file, uint16_t keylength, uint8_t * key, uint32_t md_length, pico_errno * perrno) { if (file == NULL) { if (perrno != NULL) *perrno = USAGE; DEBUG("File is NULL."); return NULL; } if (keylength < 1 || key == NULL) { if (perrno != NULL) *perrno = KEY_ERROR; DEBUG("Key is NULL or zero length."); return NULL; } // Save the key. uint8_t * keycopy = MALLOC(uint8_t, keylength); if (keycopy == NULL) { if (perrno != NULL) *perrno = NO_MEMORY; DEBUG("Cannot get memory for key."); return NULL; } memcpy(keycopy, key, keylength); // Allocate the structure. PICO * pico = MALLOC(PICO, 1); if (pico == NULL) { if (perrno != NULL) *perrno = NO_MEMORY; DEBUG("Cannot get memory for PICO structure."); pico_free(keycopy); return NULL; } // Initialize the header. pico->file = file; pico->major = VERSION_MAJOR; pico->minor = VERSION_MINOR; pico->offset = KEY_POS + keylength + md_length; pico->hash_valid = false; pico->errno = OK; pico->md_length = 0; pico->data_length = 0; pico->key_length = keylength; pico->key = keycopy; pico->valid = false; // Not yet valid! // Write the header now. if (write_header(pico)) { return pico; } // Done. if (perrno != NULL) *perrno = OK; pico->valid = true; // Now the header is valid. return pico; }
static int pico_dhcp_client_del_cookie(uint32_t xid) { struct pico_dhcp_client_cookie test = { 0 }, *found = NULL; test.xid = xid; found = pico_tree_findKey(&DHCPCookies, &test); if (!found) return -1; pico_socket_close(found->s); pico_ipv4_link_del(found->dev, found->address); pico_tree_delete(&DHCPCookies, found); pico_free(found); return 0; }
static int pico_dns_client_del_ns(struct pico_ip4 *ns_addr) { struct pico_dns_ns test = {{0}}, *found = NULL; test.ns = *ns_addr; found = pico_tree_findKey(&NSTable, &test); if (!found) return -1; pico_tree_delete(&NSTable, found); pico_free(found); /* no NS left, add default NS */ if (pico_tree_empty(&NSTable)) pico_dns_client_init(); return 0; }
static void ping_timeout(uint32_t now, void *arg) { struct pico_icmp4_ping_cookie *cookie = (struct pico_icmp4_ping_cookie *)arg; IGNORE_PARAMETER(now); if(pico_tree_findKey(&Pings,cookie)){ if (cookie->err == PICO_PING_ERR_PENDING) { struct pico_icmp4_stats stats; stats.dst = cookie->dst; stats.seq = cookie->seq; stats.time = 0; stats.size = cookie->size; stats.err = PICO_PING_ERR_TIMEOUT; dbg(" ---- Ping timeout!!!\n"); cookie->cb(&stats); } pico_tree_delete(&Pings,cookie); pico_free(cookie); } }
static struct pico_dhcp_server_negotiation *pico_dhcp_server_add_negotiation(struct pico_device *dev, struct pico_dhcp_hdr *hdr) { struct pico_dhcp_server_negotiation *dhcpn = NULL; struct pico_dhcp_server_setting test = {0}; struct pico_ip4 *ciaddr = NULL; if (pico_dhcp_server_find_negotiation(hdr->xid)) return NULL; dhcpn = pico_zalloc(sizeof(struct pico_dhcp_server_negotiation)); if (!dhcpn) { pico_err = PICO_ERR_ENOMEM; return NULL; } dhcpn->xid = hdr->xid; dhcpn->state = PICO_DHCP_STATE_DISCOVER; memcpy(dhcpn->hwaddr.addr, hdr->hwaddr, PICO_SIZE_ETH); test.dev = dev; dhcpn->dhcps = pico_tree_findKey(&DHCPSettings, &test); if (!dhcpn->dhcps) { dhcps_dbg("DHCP server WARNING: received DHCP message on unconfigured link %s\n", dev->name); pico_free(dhcpn); return NULL; } ciaddr = pico_arp_reverse_lookup(&dhcpn->hwaddr); if (!ciaddr) { dhcpn->ciaddr.addr = dhcpn->dhcps->pool_next; dhcpn->dhcps->pool_next = long_be(long_be(dhcpn->dhcps->pool_next) + 1); pico_arp_create_entry(dhcpn->hwaddr.addr, dhcpn->ciaddr, dhcpn->dhcps->dev); } else { dhcpn->ciaddr = *ciaddr; } pico_tree_insert(&DHCPNegotiations, dhcpn); return dhcpn; }
int pico_icmp4_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp4_stats *)) { static uint16_t next_id = 0x91c0; struct pico_icmp4_ping_cookie *cookie; if((dst == NULL) || (interval == 0) || (timeout == 0) || (count == 0)){ pico_err = PICO_ERR_EINVAL; return -1; } cookie = pico_zalloc(sizeof(struct pico_icmp4_ping_cookie)); if (!cookie) { pico_err = PICO_ERR_ENOMEM; return -1; } if (pico_string_to_ipv4(dst, &cookie->dst.addr) < 0) { pico_err = PICO_ERR_EINVAL; pico_free(cookie); return -1; } cookie->seq = 1; cookie->id = next_id++; cookie->err = PICO_PING_ERR_PENDING; cookie->size = (uint16_t)size; cookie->interval = interval; cookie->timeout = timeout; cookie->cb = cb; cookie->count = count; pico_tree_insert(&Pings,cookie); send_ping(cookie); return 0; }
pico_errno pico_encode_file(char *infile, char *outfile, keylen_t key_length, uint8_t *key, offset_t md_length, FILE *err) { if (infile == NULL) { DEBUG("ERROR: Input file name is NULL.\n"); return USAGE; } if (outfile == NULL) { DEBUG("ERROR: Output file name is NULL.\n"); return USAGE; } // Allocate the buffer. uint8_t * buffer = MALLOC(uint8_t, CHUNK_SIZE); if (buffer == NULL) { DEBUG("ERROR: Unable to allocate buffer.\n"); return NO_MEMORY; } // Open the file to encode. FILE * fin = fopen(infile, "r"); if (fin == NULL) { pico_free(buffer); DEBUG("ERROR: Unable to open input file.\n"); return CANNOT_READ; } // Open the file to get output. FILE * fout = fopen(outfile, "w+"); if (fout == NULL) { fclose(fin); pico_free(buffer); DEBUG("ERROR: Unable to open output file.\n"); return CANNOT_WRITE; } PICO * pico = pico_new(fout, key_length, key, md_length, NULL); if (pico == NULL) { fclose(fout); fclose(fin); pico_free(buffer); DEBUG("ERROR: Unable to create Pico file."); return CANNOT_WRITE; } // Read and copy chunks until we fail to read. size_t count= 0; size_t position = 0; do { // Read a chunk. count = fread(buffer, 1, CHUNK_SIZE, fin); if (count == 0) break; // Write a chunk. pico_set(pico, position, count, buffer); position += count; if (pico_is_error(pico)) { pico_errno errno = pico->errno; DEBUG("ERROR: %s\n", pico->error_text); pico_finish(pico); fclose(fout); fclose(fin); pico_free(buffer); return errno; } } while (count == CHUNK_SIZE); // Done. pico_finish(pico); fclose(fout); fclose(fin); pico_free(buffer); return OK; }
int pico_dns_client_nameserver(struct pico_ip4 *ns, uint8_t flag) { struct pico_dns_ns test, *key = NULL; if (!ns) { pico_err = PICO_ERR_EINVAL; return -1; } switch (flag) { case PICO_DNS_NS_ADD: key = pico_zalloc(sizeof(struct pico_dns_ns)); if (!key) { pico_err = PICO_ERR_ENOMEM; return -1; } key->ns = *ns; if(pico_tree_insert(&NSTable,key)){ dns_dbg("DNS WARNING: nameserver %08X already added\n",ns->addr); pico_err = PICO_ERR_EINVAL; pico_free(key); return -1; /* Element key already exists */ } dns_dbg("DNS: nameserver %08X added\n", ns->addr); /* If default NS found, remove it */ pico_string_to_ipv4(PICO_DNS_NS_GOOGLE, &test.ns.addr); if (ns->addr != test.ns.addr) { key = pico_tree_findKey(&NSTable,&test); if (key) { if(pico_tree_delete(&NSTable,key)) { dns_dbg("DNS: default nameserver %08X removed\n", test.ns.addr); pico_free(key); } else { pico_err = PICO_ERR_EAGAIN; return -1; } } } break; case PICO_DNS_NS_DEL: test.ns = *ns; key = pico_tree_findKey(&NSTable,&test); if (!key) { dns_dbg("DNS WARNING: nameserver %08X not found\n", ns->addr); pico_err = PICO_ERR_EINVAL; return -1; } /* RB_REMOVE returns pointer to removed element, NULL to indicate error */ if(pico_tree_delete(&NSTable,key)) { dns_dbg("DNS: nameserver %08X removed\n",key->ns.addr); pico_free(key); } else { pico_err = PICO_ERR_EAGAIN; return -1; } /* If no NS left, add default NS */ if(pico_tree_first(&NSTable) == NULL){ dns_dbg("DNS: add default nameserver\n"); return pico_dns_client_init(); } break; default: pico_err = PICO_ERR_EINVAL; return -1; } return 0; }
int8_t pico_processURI(const char * uri, struct pico_http_uri * urikey) { uint16_t lastIndex = 0, index; if(!uri || !urikey || uri[0] == '/') { pico_err = PICO_ERR_EINVAL; goto error; } // detect protocol => search for "://" if(memcmp(uri,HTTP_PROTO_TOK,HTTP_PROTO_LEN) == 0) // could be optimized { // protocol identified, it is http urikey->protoHttp = TRUE; lastIndex = HTTP_PROTO_LEN; } else { if(strstr(uri,"://")) // different protocol specified { urikey->protoHttp = FALSE; goto error; } // no protocol specified, assuming by default it's http urikey->protoHttp = TRUE; } // detect hostname index = lastIndex; while(uri[index] && uri[index]!='/' && uri[index]!=':') index++; if(index == lastIndex) { // wrong format urikey->host = urikey->resource = NULL; urikey->port = urikey->protoHttp = 0u; goto error; } else { // extract host urikey->host = (char *)pico_zalloc((uint32_t)(index-lastIndex+1)); if(!urikey->host) { // no memory goto error; } memcpy(urikey->host,uri+lastIndex,(size_t)(index-lastIndex)); } if(!uri[index]) { // nothing specified urikey->port = 80u; urikey->resource = pico_zalloc(2u); urikey->resource[0] = '/'; return HTTP_RETURN_OK; } else if(uri[index] == '/') { urikey->port = 80u; } else if(uri[index] == ':') { urikey->port = 0u; index++; while(uri[index] && uri[index]!='/') { // should check if every component is a digit urikey->port = (uint16_t)(urikey->port*10 + (uri[index] - '0')); index++; } } // extract resource if(!uri[index]) { urikey->resource = pico_zalloc(2u); urikey->resource[0] = '/'; } else { lastIndex = index; while(uri[index] && uri[index]!='?' && uri[index]!='&' && uri[index]!='#') index++; urikey->resource = (char *)pico_zalloc((size_t)(index-lastIndex+1)); if(!urikey->resource) { // no memory pico_err = PICO_ERR_ENOMEM; goto error; } memcpy(urikey->resource,uri+lastIndex,(size_t)(index-lastIndex)); } return HTTP_RETURN_OK; error : if(urikey->resource) { pico_free(urikey->resource); urikey->resource = NULL; } if(urikey->host) { pico_free(urikey->host); urikey->host = NULL; } return HTTP_RETURN_ERROR; }
void pico_vde_destroy(struct pico_device *dev) { struct pico_device_vde *vde = (struct pico_device_vde *) dev; vde_close(vde->conn); pico_free(vde); }
void wget_callback(uint16_t ev, uint16_t conn) { static char data[1024 * 128]; /* Buffer: 128kb */ static uint32_t _length = 0u; static uint32_t _length_tot = 0u; static uint32_t start_time = 0u; static int fd = -1; if(ev & EV_HTTP_CON) { printf("Connected to the download server\n"); start_time = PICO_TIME_MS(); pico_http_client_sendHeader(conn, NULL, HTTP_HEADER_DEFAULT); _length = 0u; } if(ev & EV_HTTP_REQ) { struct pico_http_header *header = pico_http_client_readHeader(conn); printf("Received header from server...\n"); printf("Server response : %d\n", header->responseCode); printf("Location : %s\n", header->location); printf("Transfer-Encoding : %d\n", header->transferCoding); printf("Size/Chunk : %d\n", header->contentLengthOrChunk); fd = http_open_file(); } if(ev & EV_HTTP_BODY) { int len; struct pico_http_header *header = pico_http_client_readHeader(conn); printf("Reading data... len=%d\n", _length_tot + _length); if (_length + 1024 >= sizeof(data)) { http_save_file(fd, data, _length); _length_tot += _length; _length = 0u; } /* Read from buffer */ while((len = pico_http_client_readData(conn, data + _length, 1024)) && len > 0) { _length += (uint32_t)len; } if(header->contentLengthOrChunk == _length) ev = EV_HTTP_CLOSE; } if(ev & EV_HTTP_CLOSE) { struct pico_http_header *header = pico_http_client_readHeader(conn); int len; uint32_t speed; printf("Connection was closed...\n"); printf("Reading remaining data, if any ...\n"); if(!header) { printf("No header received\n"); pico_http_client_close(conn); } /* first save any open read bytes */ http_save_file(fd, data, _length); _length_tot += _length; _length = 0u; while((len = pico_http_client_readData(conn, data + _length, 1000u)) && len > 0) { _length += (uint32_t)len; } printf("Read a total data of : %d bytes \n", _length_tot); if(header->transferCoding == HTTP_TRANSFER_CHUNKED) { if(header->contentLengthOrChunk) { printf("Last chunk data not fully read !\n"); exit(1); } else { printf("Transfer ended with a zero chunk! OK !\n"); } } else { if(header->contentLengthOrChunk == (_length + _length_tot)) { printf("Received the full : %d \n", _length + _length_tot); } else { printf("Received %d , waiting for %d\n", _length + _length_tot, header->contentLengthOrChunk); } } if (!url_filename) { printf("Failed to get local filename\n"); } len = http_save_file(fd, data, _length); http_close_file(fd); if ((len < 0) || ((uint32_t)len < _length)) { printf("Failed to save file: %s\n", strerror(errno)); } speed = _length_tot / (PICO_TIME_MS() - start_time) * 8; printf("Download speed: %d kbps\n", speed); pico_http_client_close(conn); pico_free(url_filename); } if(ev & EV_HTTP_ERROR) { printf("Connection error (probably dns failed : check the routing table), trying to close the client...\n"); pico_http_client_close(conn); } if(ev & EV_HTTP_DNS) { printf("The DNS query was successful ... \n"); } }
void serverWakeup(uint16_t ev, uint16_t conn) { static FILE *f; char buffer[SIZE]; if(ev & EV_HTTP_CON) { printf("New connection received....\n"); pico_http_server_accept(); } if(ev & EV_HTTP_REQ) /* new header received */ { uint16_t read; char *resource; int method; printf("Header request was received...\n"); printf("> Resource : %s\n", pico_http_getResource(conn)); resource = pico_http_getResource(conn); method = pico_http_getMethod(conn); if(strcmp(resource, "/") == 0 || strcmp(resource, "index.html") == 0 || strcmp(resource, "/index.html") == 0) { if(method == HTTP_METHOD_GET) { /* Accepting request */ printf("Received GET request\n"); pico_http_respond(conn, HTTP_RESOURCE_FOUND); f = fopen("test/examples/form.html", "r"); if(!f) { fprintf(stderr, "Unable to open the file /test/examples/form.html\n"); } read = (uint16_t)fread(buffer, 1u, SIZE, f); pico_http_submitData(conn, buffer, read); } else if(method == HTTP_METHOD_POST) { printf("Received POST request\n"); printf("Form fields: %s\n", pico_http_getBody(conn)); pico_http_respond(conn, HTTP_RESOURCE_FOUND); strcpy(buffer, "Thanks for posting your data"); if(pico_http_submitData(conn, buffer, (uint16_t)strlen(buffer)) == HTTP_RETURN_ERROR) { printf("error submitting data\n"); } else { printf("data submitted correctly\n"); } } } else if(strcmp(resource, "/download") == 0) { const char download_url_field [] = "download_url="; char *download_url = NULL; char *download_basename = NULL; char *decoded_download_url = NULL; char *http_body = NULL; http_body = pico_http_getBody(conn); if(http_body != NULL) { download_url = strstr(http_body, download_url_field); if(download_url != NULL) { download_url = download_url + strlen(download_url_field); decoded_download_url = pico_zalloc(strlen(download_url) + 1); url_decode(decoded_download_url, download_url); printf("Download url: %s\n", decoded_download_url); if(pico_http_client_open(decoded_download_url, wget_callback) < 0) { fprintf(stderr, " error opening the url : %s, please check the format\n", decoded_download_url); pico_http_respond(conn, HTTP_RESOURCE_NOT_FOUND); } download_basename = basename(decoded_download_url); url_filename = pico_zalloc(strlen(download_basename) + 1); strcpy(url_filename, download_basename); pico_free(decoded_download_url); pico_http_respond(conn, HTTP_RESOURCE_FOUND); strcpy(buffer, "Download started"); if(pico_http_submitData(conn, buffer, (uint16_t)strlen(buffer)) == HTTP_RETURN_ERROR) { printf("error submitting data\n"); } } else { printf("no download url\n"); pico_http_respond(conn, HTTP_RESOURCE_NOT_FOUND); } } else { printf("no http body\n"); pico_http_respond(conn, HTTP_RESOURCE_NOT_FOUND); } } else { /* reject */ printf("Rejected connection...\n"); pico_http_respond(conn, HTTP_RESOURCE_NOT_FOUND); } } if(ev & EV_HTTP_PROGRESS) /* submitted data was sent */ { uint16_t sent, total; pico_http_getProgress(conn, &sent, &total); printf("Chunk statistics : %d/%d sent\n", sent, total); } if(ev & EV_HTTP_SENT) /* submitted data was fully sent */ { int method; method = pico_http_getMethod(conn); if(method == HTTP_METHOD_GET) { uint16_t read; read = (uint16_t)fread(buffer, 1, SIZE, f); printf("Chunk was sent...\n"); if(read > 0) { printf("Sending another chunk...\n"); pico_http_submitData(conn, buffer, read); } else { printf("Last chunk get !\n"); pico_http_submitData(conn, NULL, 0); /* send the final chunk */ fclose(f); } } else if(method == HTTP_METHOD_POST) { printf("Last chunk post !\n"); pico_http_submitData(conn, NULL, 0); /* send the final chunk */ } } if(ev & EV_HTTP_CLOSE) { printf("Close request...\n"); pico_http_close(conn); } if(ev & EV_HTTP_ERROR) { printf("Error on server...\n"); pico_http_close(conn); } }
pico_errno pico_decode_file(char *infile, char *outfile, bool testhash, FILE *err) { if (infile == NULL) { DEBUG("ERROR: Input file name is NULL.\n"); return USAGE; } if (outfile == NULL) { DEBUG("ERROR: Output file name is NULL.\n"); return USAGE; } // Allocate the buffer. uint8_t * buffer = MALLOC(uint8_t, CHUNK_SIZE); if (buffer == NULL) { DEBUG("ERROR: Unable to allocate buffer.\n"); return NO_MEMORY; } // Open the file to decode. FILE * fin = fopen(infile, "r"); if (fin == NULL) { pico_free(buffer); DEBUG("ERROR: Unable to open input file.\n"); return CANNOT_READ; } // Open the file to get output. FILE * fout = fopen(outfile, "w+"); if (fout == NULL) { fclose(fin); pico_free(buffer); DEBUG("ERROR: Unable to open output file.\n"); return CANNOT_WRITE; } // Read the header. PICO * pico = pico_open(fin, NULL); if (pico == NULL) { fclose(fout); fclose(fin); pico_free(buffer); DEBUG("ERROR: Unable to open Pico file."); return CANNOT_READ; } // Initialize the hash computation. uint8_t hash[HASH_LEN]; MD5_CTX md5data; if (testhash) MD5_Init(&md5data); // Read and copy chunks until we fail to read. size_t count = 0; size_t position = 0; do { // Read a chunk. count = pico_get(pico, position, CHUNK_SIZE, buffer); if (count == 0) break; if (pico_is_error(pico)) { pico_errno errno = pico->errno; if (testhash) MD5_Final(hash, &md5data); pico_finish(pico); fclose(fin); fflush(fout); fclose(fout); pico_free(buffer); DEBUG("ERROR: %s\n", pico->error_text); return errno; } if (testhash) MD5_Update(&md5data, buffer, count); // Write a chunk. fwrite(buffer, 1, count, fout); position += count; } while (count == CHUNK_SIZE); // Check the hash. bool hash_match = true; if (testhash) { MD5_Final(hash, &md5data); for (size_t index = 0; index < HASH_LEN; ++index) { if (hash[index] != pico->hash[index]) { // Hash mismatch. hash_match = false; } } // Loop over hash bytes. } // Done. pico_finish(pico); fclose(fin); fflush(fout); fclose(fout); pico_free(buffer); return hash_match ? OK : HASH_ERROR; }