//  public
void MhProtoClient::DownloadMetadataFromServer(int smd,
        const char *remote_file,
        int64_t chunk_size) {
    int16_t response;
    char abs_file[2048];

    DEBUG("MhProtoClient::DownloadMetadataFromServer()\n");
    SndCmd(smd, DOWNLOAD_METADATA);
    write(smd, &chunk_size, sizeof(int64_t));

    int16_t path_size = strlen(remote_file);
    write(smd, &path_size, sizeof(int16_t));
    write(smd, remote_file, path_size);

    so_read(smd, &response, sizeof(int16_t));
    DEBUG("DownloadMetadataFromServer->response : %d\n", response);
    if (response == MH_FILE_NOT_FOUND) {
        printf("Remote file not found.\n");
        ClearResources();
        exit(1);
    }

    CopyString(abs_file, AbsoluteFile(remote_file));
    StrCat(abs_file, ".mdata");

    // Metadata::SaveMetadata only updates, so create "touch" metadata
    // file first.
    int fd = open(abs_file , O_WRONLY | O_CREAT, 0000644);
    close(fd);

    Metadata metadata;
    metadata.ReadMetadataHeader(smd);
    metadata.initControlData();
    metadata.SaveMetadata(abs_file);
}
Exemple #2
0
static void test_tcp_server(void)
{
	int re;
	int sd;
	int reader = 0;
	char buf[5];
	struct sockaddr_in sa;
	struct sockaddr_in sa2;
	socklen_t sa_len;

	printf("[tcp(server)] start\n");

	sd = so_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if ( sd < 0 ) {
		goto error;
	}
	DEBUG_PRINT(("server_task: so_socket = %d(%d, %d)\n", sd, MERCD(sd), SERCD(sd)));

	bzero(&sa, sizeof sa);
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_ANY);
	sa.sin_port = htons(12345);
	re = so_bind(sd, (struct sockaddr*)&sa, sizeof sa);
	DEBUG_PRINT(("server_task: so_bind = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}

	re = so_listen(sd, 5);
	DEBUG_PRINT(("server_task: so_listen = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}

	tk_sig_sem(semid, 1);
	DEBUG_PRINT(("server_task: server semaphore signaled 1\n"));

	reader = so_accept(sd, (struct sockaddr*)&sa2, &sa_len);
	DEBUG_PRINT(("server_task: so_accept = %d(%d, %d)\n", reader, MERCD(reader), SERCD(reader)));
	if ( reader < 0 ) {
		goto error;
	}

	wait_data(reader);

	bzero(buf, sizeof buf);
	re = so_sockatmark(reader);
	DEBUG_PRINT(("server_task: so_sockatmark = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}
	re = so_read(reader, buf, 4);
	DEBUG_PRINT(("server_task: so_read = %d(%d, %d), buf = %s\n", re, MERCD(re), SERCD(re), buf));
	if ( re < 0 || memcmp(buf, "1234", 4) != 0 ) {
		goto error;
	}

	wait_data(reader);

	bzero(buf, sizeof buf);
	re = so_sockatmark(reader);
	DEBUG_PRINT(("server_task: so_sockatmark = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re < 0 ) {
		goto error;
	}
	re = so_recv(reader, buf, 4, MSG_OOB);
	DEBUG_PRINT(("server_task: so_recv = %d(%d, %d), buf = %s\n", re, MERCD(re), SERCD(re), buf));
	if ( re < 0 || buf[0] != 'a' ) {
		goto error;
	}

	tk_sig_sem(semid2, 1);
	DEBUG_PRINT(("server_task: server semaphore for break signaled 2\n"));

	DEBUG_PRINT(("server_task: pre-accept for break\n"));
	re = so_accept(sd, (struct sockaddr*)&sa2, &sa_len);
	DEBUG_PRINT(("server_task: so_accept = %d(%d, %d)\n", re, MERCD(re), SERCD(re)));
	if ( re != EX_INTR ) {
		goto error;
	}

	so_close(reader);
	so_close(sd);

	printf("[tcp(server)] OK\n");
	return;

error:
	printf("[tcp(server)] FAILED\n");
	if ( sd > 0 ) {
		so_close(sd);
	}
	if ( reader > 0 ) {
		so_close(reader);
	}
	tk_del_sem(semid2);
	return;
}
// Private Methods
void MhProtoClient::DownloadFileFromServer(
        int cd_sd,
        const char *metaFile,
        const char *localFile) {
    unsigned char *rcv_buffer = NULL;
    unsigned char rcv_md5sum[16];
    int64_t rcv_dataSize;
    MD5Utils md5Utils;
    rcv_buffer = static_cast<unsigned char*>(malloc(MAX_CHUNK_SIZE));

    SndCmd(cd_sd, DOWNLOAD_CHUNK);

    metadata_.LoadMetadata(metaFile);
    metadata_.WriteMetadataHeader(cd_sd);

    int fd_download = open(localFile , O_WRONLY | O_CREAT , 0000644);
    if (fd_download == -1) {
        perror("open download file ");
        exit(1);
    }

    int64_t chunkNumber = -1;
    int br = 0;
    bool sock_error = false;
    off_t filePos;
    do {
        DEBUG("Before lock : %ld - \033[1m\033[32m%d\033[0m\n",
                i64toLong(chunkNumber),
                getpid());
        sem_->semaphore_get_lock();
        metadata_.LoadMetadata(metaFile);
        chunkNumber = metadata_.getNextPendingChunk();
        if (chunkNumber == -1) {
            sem_->semaphore_release_lock();
            break;
        }
        metadata_.setChunkStatus(chunkNumber, CH_DOWNLOAD, NULL);
        metadata_.UpdateControlData(metaFile);
        DEBUG("Next Pending Chunk : %ld\n", i64toLong(chunkNumber));
        sem_->semaphore_release_lock();

        // Receive chunk
        RequestChunk(cd_sd, chunkNumber);

        DEBUG("Next Pending Chunk-v : %ld\n", i64toLong(chunkNumber));

        br = so_read(cd_sd, rcv_md5sum, DIGEST_SIZE);
        DEBUG("MD5       : <%s>\n", md5Utils.digestToStr(rcv_md5sum));
        if (br != DIGEST_SIZE) {
            sock_error = true;
            goto update;
        }

        br = so_read(cd_sd, (unsigned char*)&rcv_dataSize, sizeof(int64_t));
        DEBUG("Data Size : %ld\n", i64toLong(rcv_dataSize));
        if (br != sizeof(int64_t)) {
            sock_error = true;
            goto update;
        }

        br = so_read(cd_sd, rcv_buffer, rcv_dataSize);
        if (br != rcv_dataSize) {
            sock_error = true;
            goto update;
        }

        // hex_dump((char*)rcv_buffer,200);
        filePos = (chunkNumber*metadata_.getChunkSize());
        lseek(fd_download, filePos, SEEK_SET);
        write(fd_download, rcv_buffer, rcv_dataSize);
update:
        sem_->semaphore_get_lock();
        metadata_.LoadMetadata(metaFile);
        if (sock_error) {
            metadata_.setChunkStatus(chunkNumber, CH_ERROR, rcv_md5sum);
            chunkNumber = -1;
        } else {
            metadata_.setChunkStatus(chunkNumber, CH_OK, rcv_md5sum);
        }
        metadata_.UpdateControlData(metaFile);
        sem_->semaphore_release_lock();
    } while (chunkNumber != -1 && *kill_proc_ == 0);
    close(fd_download);
    if (rcv_buffer != NULL) free(rcv_buffer);
    DEBUG("Process: no more chunks to download.\n");
}