Esempio n. 1
0
static void psync_p2p_check(const packet_check *packet){
  unsigned char hashhex[PSYNC_HASH_DIGEST_HEXLEN], hashsource[PSYNC_HASH_BLOCK_SIZE], hashbin[PSYNC_HASH_DIGEST_LEN];
  packet_check_resp resp;
  if (!memcmp(packet->computername, computername, PSYNC_HASH_DIGEST_HEXLEN))
    return;
  if (psync_p2p_has_file(packet->hashstart, packet->genhash, packet->rand, packet->filesize, hashhex))
    resp.type=P2P_RESP_HAVEIT;
  else if (psync_p2p_is_downloading(packet->hashstart, packet->genhash, packet->rand, packet->filesize, hashhex))
    resp.type=P2P_RESP_WAIT;
  else
    return;
  resp.port=tcpport;
  psync_ssl_rand_weak(resp.rand, sizeof(resp.rand));
  memcpy(hashsource, hashhex, PSYNC_HASH_DIGEST_HEXLEN);
  memcpy(hashsource+PSYNC_HASH_DIGEST_HEXLEN, resp.rand, sizeof(resp.rand));
  psync_hash(hashsource, PSYNC_HASH_BLOCK_SIZE, hashbin);
  psync_binhex(resp.genhash, hashbin, PSYNC_HASH_DIGEST_LEN);
  debug(D_NOTICE, "replying with %u to a check from %s, looking for %."NTO_STR(PSYNC_HASH_DIGEST_HEXLEN)"s", (unsigned int)resp.type, p2p_get_peer_address(), hashhex);
  if (files_serving)
    psync_milisleep(files_serving*10);
  if (resp.type==P2P_RESP_WAIT)
    psync_milisleep(PSYNC_P2P_INITIAL_TIMEOUT/4);
  if (!sendto(udpsock, (const char *)&resp, sizeof(resp), 0, (const struct sockaddr *)&paddr, paddrlen))
    debug(D_WARNING, "sendto to %s failed", p2p_get_peer_address());
}
Esempio n. 2
0
static void status_change_thread(void *ptr){
  pstatus_change_callback_t callback=(pstatus_change_callback_t)ptr;
  while (1){
    psync_milisleep(5);
    pthread_mutex_lock(&statusmutex);
    while (!statuschanges)
      pthread_cond_wait(&statuscond, &statusmutex);
    statuschanges=0;
    pthread_mutex_unlock(&statusmutex);
    if (!psync_do_run)
      break;
    callback(&psync_status);
  }
}
Esempio n. 3
0
static void status_change_thread(void *ptr){
  char downloadstr[MAX_STATUS_STR_LEN], uploadstr[MAX_STATUS_STR_LEN];
  pstatus_change_callback_t callback=(pstatus_change_callback_t)ptr;
  while (1){
    // Maximum 2 updates/sec
    psync_milisleep(500);
    pthread_mutex_lock(&statusmutex);
    while (statuschanges<=0){
      statuschanges=-1;
      pthread_cond_wait(&statuscond, &statusmutex);
    }
    statuschanges=0;
    if (((status_old.filestodownload > 0 ) && (psync_status.filestodownload == 0)) ||
        ((psync_status.filestodownload > 0 ) && (status_old.filestodownload == 0)) ||
        ((status_old.filestoupload > 0 ) && (psync_status.filestoupload == 0)) ||
        ((psync_status.filestoupload > 0 ) && (status_old.filestoupload == 0)) ||
        ((psync_status.localisfull != status_old.localisfull)) ||
        ((psync_status.remoteisfull != status_old.remoteisfull)) ||
        ((psync_status.status != status_old.status) && (
          (psync_status.status == PSTATUS_STOPPED) ||
          (psync_status.status == PSTATUS_PAUSED) ||
          (psync_status.status == PSTATUS_OFFLINE) ||
          (status_old.status == PSTATUS_STOPPED) ||
          (status_old.status == PSTATUS_PAUSED) ||
          (status_old.status == PSTATUS_OFFLINE) ) )
    )
      psync_run_ratelimited("Rebuild icons.", psync_rebuild_icons, 1, 1);
    status_old = psync_status;
    pthread_mutex_unlock(&statusmutex);
    if (!psync_do_run)
      break;
    status_fill_formatted_str(&psync_status, downloadstr, uploadstr);
    debug(D_NOTICE, "sending status update, dwlstr: %s, uplstr: %s", psync_status.downloadstr, psync_status.uploadstr);
    callback(&psync_status);
  }
}
Esempio n. 4
0
int psync_p2p_check_download(psync_fileid_t fileid, const unsigned char *filehashhex, uint64_t fsize, const char *filename){
  struct sockaddr_in6 addr;
  fd_set rfds;
  packet_check pct1;
  packet_get pct2;
  packet_check_resp resp;
  struct timeval tv;
  psync_interface_list_t *il;
  psync_socket_t *sockets;
  size_t i, tlen;
  psync_socket_t sock, msock;
  packet_resp_t bresp;
  unsigned char hashsource[PSYNC_HASH_BLOCK_SIZE], hashbin[PSYNC_HASH_DIGEST_LEN], hashhex[PSYNC_HASH_DIGEST_HEXLEN];
  unsigned char *token;
  socklen_t slen;
  int sret;
  if (!psync_setting_get_bool(_PS(p2psync)))
    return PSYNC_NET_PERMFAIL;
  debug(D_NOTICE, "sending P2P_CHECK for file with hash %."NTO_STR(PSYNC_HASH_DIGEST_HEXLEN)"s", filehashhex);
  pct1.type=P2P_CHECK;
  memcpy(pct1.hashstart, filehashhex, PSYNC_P2P_HEXHASH_BYTES);
  pct1.filesize=fsize;
  psync_ssl_rand_weak(pct1.rand, sizeof(pct1.rand));
  memcpy(hashsource, filehashhex, PSYNC_HASH_DIGEST_HEXLEN);
  memcpy(hashsource+PSYNC_HASH_DIGEST_HEXLEN, pct1.rand, sizeof(pct1.rand));
  psync_hash(hashsource, PSYNC_HASH_BLOCK_SIZE, hashbin);
  psync_binhex(pct1.genhash, hashbin, PSYNC_HASH_DIGEST_LEN);
  memcpy(pct1.computername, computername, PSYNC_HASH_DIGEST_HEXLEN);
  il=psync_list_ip_adapters();
  sockets=psync_new_cnt(psync_socket_t, il->interfacecnt);
  FD_ZERO(&rfds);
  msock=0;
  for (i=0; i<il->interfacecnt; i++){
    sockets[i]=INVALID_SOCKET;
    sock=psync_create_socket(il->interfaces[i].address.ss_family, SOCK_DGRAM, IPPROTO_UDP);
    if (unlikely(sock==INVALID_SOCKET)){
      debug(D_NOTICE, "could not create a socket for address family %u", (unsigned)il->interfaces[i].address.ss_family);
      continue;
    }
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char *)&on, sizeof(on));
    if (unlikely_log(bind(sock, (struct sockaddr *)&il->interfaces[i].address, il->interfaces[i].addrsize)==SOCKET_ERROR)){
      psync_close_socket(sock);
      continue;
    }
    if (il->interfaces[i].broadcast.ss_family==AF_INET)
      ((struct sockaddr_in *)(&il->interfaces[i].broadcast))->sin_port=htons(PSYNC_P2P_PORT);
    else if (il->interfaces[i].broadcast.ss_family==AF_INET6)
      ((struct sockaddr_in6 *)(&il->interfaces[i].broadcast))->sin6_port=htons(PSYNC_P2P_PORT);
    if (sendto(sock, (const char *)&pct1, sizeof(pct1), 0, (struct sockaddr *)&il->interfaces[i].broadcast, il->interfaces[i].addrsize)!=SOCKET_ERROR){
      sockets[i]=sock;
      FD_SET(sock, &rfds);
      if (sock>=msock)
        msock=sock+1;
    }
    else
      psync_close_socket(sock);
  }
  if (unlikely_log(!msock))
    goto err_perm;
  tv.tv_sec=PSYNC_P2P_INITIAL_TIMEOUT/1000;
  tv.tv_usec=(PSYNC_P2P_INITIAL_TIMEOUT%1000)*1000;
  sret=select(msock, &rfds, NULL, NULL, &tv);
  if (sret==0 || unlikely_log(sret==SOCKET_ERROR))
    goto err_perm;
  bresp=P2P_RESP_NOPE;
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET && FD_ISSET(sockets[i], &rfds)){
      slen=sizeof(addr);
      sret=recvfrom(sockets[i], (char *)&resp, sizeof(resp), 0, (struct sockaddr *)&addr, &slen);
      if (unlikely_log(sret==SOCKET_ERROR) || unlikely_log(sret<sizeof(resp)))
        continue;
      if (!memcmp(pct1.rand, resp.rand, sizeof(resp.rand))){
        debug(D_WARNING, "clients are supposed to generate random data, not to reuse mine");
        continue;
      }
      memcpy(hashsource, filehashhex, PSYNC_HASH_DIGEST_HEXLEN);
      memcpy(hashsource+PSYNC_HASH_DIGEST_HEXLEN, resp.rand, sizeof(resp.rand));
      psync_hash(hashsource, PSYNC_HASH_BLOCK_SIZE, hashbin);
      psync_binhex(hashhex, hashbin, PSYNC_HASH_DIGEST_LEN);
      if (unlikely_log(memcmp(hashhex, resp.genhash, PSYNC_HASH_DIGEST_HEXLEN)))
        continue;
      if (resp.type==P2P_RESP_HAVEIT){
        debug(D_NOTICE, "got P2P_RESP_HAVEIT");
        bresp=P2P_RESP_HAVEIT;
        break;
      }
      else if (resp.type==P2P_RESP_WAIT && bresp==P2P_RESP_NOPE)
        bresp=P2P_RESP_WAIT;
    }
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET)
      psync_close_socket(sockets[i]);
  psync_free(il);
  psync_free(sockets);
  if (bresp==P2P_RESP_NOPE)
    goto err_perm2;
  else if (bresp==P2P_RESP_WAIT){
    psync_milisleep(PSYNC_P2P_SLEEP_WAIT_DOWNLOAD);
    goto err_temp2;
  }
  if (psync_p2p_check_rsa())
    goto err_perm2;
  sret=psync_p2p_get_download_token(fileid, filehashhex, fsize, &token, &tlen);
  debug(D_NOTICE, "got token");
  if (unlikely_log(sret!=PSYNC_NET_OK)){
    if (sret==PSYNC_NET_TEMPFAIL)
      goto err_temp2;
    else
      goto err_perm2;
  }
  if (addr.sin6_family==AF_INET6){
    sock=psync_create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
    addr.sin6_port=htons(resp.port);
  }
  else if (addr.sin6_family==AF_INET){
    sock=psync_create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    ((struct sockaddr_in *)&addr)->sin_port=htons(resp.port);
  }
  else{
    debug(D_ERROR, "unknown address family %u", (unsigned)addr.sin6_family);
    goto err_perm2;
  }
  if (unlikely_log(sock==INVALID_SOCKET))
    goto err_perm3;
  if (unlikely(connect(sock, (struct sockaddr *)&addr, slen)==SOCKET_ERROR)){
    debug(D_WARNING, "could not connect to %s port %u", p2p_get_address(&addr), (unsigned)resp.port);
    goto err_perm3;
  }
  debug(D_NOTICE, "connected to peer");
  pct2.type=P2P_GET;
  memcpy(pct2.hashstart, filehashhex, PSYNC_P2P_HEXHASH_BYTES);
  pct2.filesize=fsize;
  pct2.keylen=psync_rsa_public_bin->datalen;
  pct2.tokenlen=tlen;
  memcpy(pct2.rand, pct1.rand, sizeof(pct1.rand));
  memcpy(pct2.genhash, pct1.genhash, sizeof(pct1.genhash));
  memcpy(pct2.computername, computername, PSYNC_HASH_DIGEST_HEXLEN);
  if (socket_write_all(sock, &pct2, sizeof(pct2)) ||
      socket_write_all(sock, psync_rsa_public_bin->data, psync_rsa_public_bin->datalen) ||
      socket_write_all(sock, token, tlen)){
    debug(D_WARNING, "writing to socket failed");
    goto err_temp3;
  }
  psync_free(token);
  sret=psync_p2p_download(sock, fileid, filehashhex, fsize, filename);
  psync_close_socket(sock);
  return sret;
err_perm3:
  psync_free(token);
  goto err_perm2;
err_perm:
  for (i=0; i<il->interfacecnt; i++)
    if (sockets[i]!=INVALID_SOCKET)
      psync_close_socket(sockets[i]);
  psync_free(il);
  psync_free(sockets);
err_perm2:
  return PSYNC_NET_PERMFAIL;
err_temp3:
  psync_close_socket(sock);
  psync_free(token);
err_temp2:
  return PSYNC_NET_TEMPFAIL;
}
Esempio n. 5
0
static void psync_p2p_thread(){
  ssize_t ret;
  char buff[2048];
/*  struct sockaddr_in6 addr; */
  struct sockaddr_in addr4;
  psync_socket_t tcpsock, socks[2], *inconn;
  socklen_t sl;
  int sret;
  psync_wait_statuses_array(requiredstatuses, ARRAY_SIZE(requiredstatuses));
  tcpsock=INVALID_SOCKET;
/*  udpsock=psync_create_socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
  if (unlikely_log(udpsock==INVALID_SOCKET)){*/
    udpsock=psync_create_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (unlikely_log(udpsock==INVALID_SOCKET))
      goto ex;
    setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr4, 0, sizeof(addr4));
    addr4.sin_family=AF_INET;
    addr4.sin_port  =htons(PSYNC_P2P_PORT);
    addr4.sin_addr.s_addr=INADDR_ANY;
    if (unlikely_log(bind(udpsock, (struct sockaddr *)&addr4, sizeof(addr4))==SOCKET_ERROR))
      goto ex;
/*  }
  else{
    setsockopt(udpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr, 0, sizeof(addr));
    addr.sin6_family=AF_INET6;
    addr.sin6_port  =htons(PSYNC_P2P_PORT);
    addr.sin6_addr  =in6addr_any;
    if (unlikely_log(bind(udpsock, (struct sockaddr *)&addr, sizeof(addr))==SOCKET_ERROR))
      goto ex;
  }
  tcpsock=psync_create_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
  if (unlikely_log(tcpsock==INVALID_SOCKET)){*/
    tcpsock=psync_create_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (unlikely_log(tcpsock==INVALID_SOCKET))
      goto ex;
    setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr4, 0, sizeof(addr4));
    addr4.sin_family=AF_INET;
    addr4.sin_port  =htons(0);
    addr4.sin_addr.s_addr=INADDR_ANY;
    if (unlikely_log(bind(tcpsock, (struct sockaddr *)&addr4, sizeof(addr4))==SOCKET_ERROR))
      goto ex;
    sl=sizeof(addr4);
    if (unlikely_log(getsockname(tcpsock, (struct sockaddr *)&addr4, &sl)==SOCKET_ERROR))
      goto ex;
    tcpport=ntohs(addr4.sin_port);
/*  }
  else{
    setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
    memset(&addr, 0, sizeof(addr));
    addr.sin6_family=AF_INET6;
    addr.sin6_port  =htons(0);
    addr.sin6_addr  =in6addr_any;
    if (unlikely_log(bind(tcpsock, (struct sockaddr *)&addr, sizeof(addr))==SOCKET_ERROR))
      goto ex;
    sl=sizeof(addr);
    if (unlikely_log(getsockname(tcpsock, (struct sockaddr *)&addr, &sl)==SOCKET_ERROR))
      goto ex;
    tcpport=ntohs(addr.sin6_port);
  }*/
  if (unlikely_log(listen(tcpsock, 2)))
    goto ex;
  socks[0]=udpsock;
  socks[1]=tcpsock;
  while (psync_do_run){
    if (unlikely(!psync_setting_get_bool(_PS(p2psync)))){
      pthread_mutex_lock(&p2pmutex);
      if (!psync_setting_get_bool(_PS(p2psync))){
        running=0;
        psync_close_socket(tcpsock);
        psync_close_socket(udpsock);
        pthread_mutex_unlock(&p2pmutex);
        return;
      }
      pthread_mutex_unlock(&p2pmutex);
    }
    psync_wait_statuses_array(requiredstatuses, ARRAY_SIZE(requiredstatuses));
    sret=psync_select_in(socks, 2, -1);
    if (unlikely_log(sret==-1)){
      psync_milisleep(1);
      continue;
    }
    if (sret==0){
      paddrlen=sizeof(paddr);
      ret=recvfrom(udpsock, buff, sizeof(buff), 0, (struct sockaddr *)&paddr, &paddrlen);
      if (likely_log(ret!=SOCKET_ERROR))
        psync_p2p_process_packet(buff, ret);
      else
        psync_milisleep(1);
    }
    else if (sret==1){
      inconn=psync_new(psync_socket_t);
      *inconn=accept(tcpsock, NULL, NULL);
      if (unlikely_log(*inconn==INVALID_SOCKET))
        psync_free(inconn);
      else
        psync_run_thread1("p2p tcp", psync_p2p_tcphandler, inconn);
    }
  }
ex:
  pthread_mutex_lock(&p2pmutex);
  running=0;
  psync_close_socket(tcpsock);
  psync_close_socket(udpsock);
  pthread_mutex_unlock(&p2pmutex);
}