Browse Source

add support to libssh2 for hole punching...

remotes/client/ssh-main
John-Mark Gurney 3 years ago
parent
commit
79171e6e22
3 changed files with 112 additions and 0 deletions
  1. +2
    -0
      libssh2/include/libssh2_sftp.h
  2. +105
    -0
      libssh2/src/sftp.c
  3. +5
    -0
      libssh2/src/sftp.h

+ 2
- 0
libssh2/include/libssh2_sftp.h View File

@@ -251,6 +251,8 @@ LIBSSH2_API int libssh2_sftp_readdir_ex(LIBSSH2_SFTP_HANDLE *handle, \

LIBSSH2_API ssize_t libssh2_sftp_write(LIBSSH2_SFTP_HANDLE *handle,
const char *buffer, size_t count);
LIBSSH2_API int libssh2_sftp_punchhole(LIBSSH2_SFTP_HANDLE *handle,
off_t off, off_t len);
LIBSSH2_API int libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *handle);

LIBSSH2_API int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);


+ 105
- 0
libssh2/src/sftp.c View File

@@ -2336,6 +2336,111 @@ libssh2_sftp_fsync(LIBSSH2_SFTP_HANDLE *hnd)
}


static int sftp_punchhole(LIBSSH2_SFTP_HANDLE *handle, off_t off, off_t len)
{
LIBSSH2_SFTP *sftp = handle->sftp;
LIBSSH2_CHANNEL *channel = sftp->channel;
LIBSSH2_SESSION *session = channel->session;
/* 55 = packet_len(4) + packet_type(1) + request_id(4) +
string_len(4) + strlen("punchhole@funkthat.com")(22) + handle_len(4) +
off_len(8) + len_len(8) */
uint32_t packet_len = handle->handle_len + 55;
size_t data_len;
unsigned char *packet, *s, *data;
ssize_t rc;
uint32_t retcode;

if(sftp->punchhole_state == libssh2_NB_state_idle) {
_libssh2_debug(session, LIBSSH2_TRACE_SFTP,
"Issuing punchhole command");
s = packet = LIBSSH2_ALLOC(session, packet_len);
if(!packet) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate memory for FXP_EXTENDED "
"packet");
}

_libssh2_store_u32(&s, packet_len - 4);
*(s++) = SSH_FXP_EXTENDED;
sftp->punchhole_request_id = sftp->request_id++;
_libssh2_store_u32(&s, sftp->punchhole_request_id);
_libssh2_store_str(&s, "punchhole@funkthat.com", 22);
_libssh2_store_str(&s, handle->handle, handle->handle_len);
_libssh2_store_u64(&s, off);
_libssh2_store_u64(&s, len);

sftp->punchhole_state = libssh2_NB_state_created;
}
else {
packet = sftp->punchhole_packet;
}

if(sftp->punchhole_state == libssh2_NB_state_created) {
rc = _libssh2_channel_write(channel, 0, packet, packet_len);
if(rc == LIBSSH2_ERROR_EAGAIN ||
(0 <= rc && rc < (ssize_t)packet_len)) {
sftp->punchhole_packet = packet;
return LIBSSH2_ERROR_EAGAIN;
}

LIBSSH2_FREE(session, packet);
sftp->punchhole_packet = NULL;

if(rc < 0) {
sftp->punchhole_state = libssh2_NB_state_idle;
return _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND,
"_libssh2_channel_write() failed");
}
sftp->punchhole_state = libssh2_NB_state_sent;
}

rc = sftp_packet_require(sftp, SSH_FXP_STATUS,
sftp->punchhole_request_id, &data, &data_len, 9);
if(rc == LIBSSH2_ERROR_EAGAIN) {
return rc;
}
else if(rc == LIBSSH2_ERROR_BUFFER_TOO_SMALL) {
if(data_len > 0) {
LIBSSH2_FREE(session, data);
}
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"SFTP punchhole packet too short");
}
else if(rc) {
sftp->punchhole_state = libssh2_NB_state_idle;
return _libssh2_error(session, rc,
"Error waiting for FXP EXTENDED REPLY");
}

sftp->punchhole_state = libssh2_NB_state_idle;

retcode = _libssh2_ntohu32(data + 5);
LIBSSH2_FREE(session, data);

if(retcode != LIBSSH2_FX_OK) {
sftp->last_errno = retcode;
return _libssh2_error(session, LIBSSH2_ERROR_SFTP_PROTOCOL,
"punchhole failed");
}

return 0;
}

/* libssh2_sftp_punchhole
* Punch hole in remote file.
*/
LIBSSH2_API int
libssh2_sftp_punchhole(LIBSSH2_SFTP_HANDLE *hnd, off_t off, off_t len)
{
int rc;
if(!hnd)
return LIBSSH2_ERROR_BAD_USE;
BLOCK_ADJUST(rc, hnd->sftp->channel->session,
sftp_punchhole(hnd, off, len));
return rc;
}


/*
* sftp_fstat
*


+ 5
- 0
libssh2/src/sftp.h View File

@@ -183,6 +183,11 @@ struct _LIBSSH2_SFTP
unsigned char *fsync_packet;
uint32_t fsync_request_id;

/* State variables used in sftp_punchhole() */
libssh2_nonblocking_states punchhole_state;
unsigned char *punchhole_packet;
uint32_t punchhole_request_id;

/* State variables used in libssh2_sftp_readdir() */
libssh2_nonblocking_states readdir_state;
unsigned char *readdir_packet;


Loading…
Cancel
Save