Пример #1
0
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;
}
Пример #2
0
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);
  }
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
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;
}
Пример #8
0
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;
}
Пример #9
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;
}
Пример #10
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);
  }
}
Пример #11
0
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; 
}
Пример #12
0
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;

}
Пример #13
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;
}
Пример #15
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;
}
Пример #16
0
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);
}
Пример #17
0
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");
    }
}
Пример #18
0
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);
    }
}
Пример #19
0
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;
}