Skip to content

Commit ef6ee33

Browse files
authored
Merge pull request #1 from dacort/fix/big-files
[fix] Better uploading
2 parents c04172f + efb4cfb commit ef6ee33

9 files changed

Lines changed: 391 additions & 328 deletions

File tree

src/pyssm_client/cli/coordinator.py

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@
77
import sys
88
import termios
99
import tty
10-
from typing import Any, Callable, Optional
10+
from typing import Any
1111

1212
from ..communicator.data_channel import SessionDataChannel
1313
from ..communicator.utils import create_websocket_config
1414
from ..constants import CLIENT_VERSION
15-
from ..file_transfer.client import FileTransferClient
16-
from ..file_transfer.types import (
17-
ChecksumType,
18-
FileTransferOptions,
19-
)
2015
from ..session.plugins import StandardStreamPlugin
2116
from ..session.session_handler import SessionHandler
2217
from ..session.types import ClientConfig, SessionConfig, SessionType
@@ -479,132 +474,3 @@ async def _stop_resize_heartbeat(self) -> None:
479474
except asyncio.CancelledError:
480475
pass
481476
self._resize_task = None
482-
483-
async def upload_file(
484-
self,
485-
local_path: str,
486-
remote_path: str,
487-
target: str,
488-
progress_callback: Optional[Callable[[int, int], None]] = None,
489-
verify_checksum: bool = True,
490-
chunk_size: int = 65536,
491-
# AWS parameters
492-
profile: Optional[str] = None,
493-
region: Optional[str] = None,
494-
endpoint_url: Optional[str] = None,
495-
) -> bool:
496-
"""Upload a file to remote host via AWS SSM.
497-
498-
Args:
499-
local_path: Path to local file
500-
remote_path: Destination path on remote host
501-
target: EC2 instance or managed instance ID
502-
progress_callback: Optional callback for progress updates
503-
verify_checksum: Whether to verify file integrity
504-
chunk_size: Transfer chunk size in bytes
505-
profile: AWS profile name
506-
region: AWS region
507-
endpoint_url: Custom AWS endpoint URL
508-
509-
Returns:
510-
True if transfer successful, False otherwise
511-
"""
512-
options = FileTransferOptions(
513-
chunk_size=chunk_size,
514-
verify_checksum=verify_checksum,
515-
progress_callback=progress_callback,
516-
)
517-
518-
client = FileTransferClient()
519-
return await client.upload_file(
520-
local_path=local_path,
521-
remote_path=remote_path,
522-
target=target,
523-
options=options,
524-
profile=profile,
525-
region=region,
526-
endpoint_url=endpoint_url,
527-
)
528-
529-
async def download_file(
530-
self,
531-
remote_path: str,
532-
local_path: str,
533-
target: str,
534-
progress_callback: Optional[Callable[[int, int], None]] = None,
535-
verify_checksum: bool = True,
536-
chunk_size: int = 65536,
537-
# AWS parameters
538-
profile: Optional[str] = None,
539-
region: Optional[str] = None,
540-
endpoint_url: Optional[str] = None,
541-
) -> bool:
542-
"""Download a file from remote host via AWS SSM.
543-
544-
Args:
545-
remote_path: Path to remote file
546-
local_path: Local destination path
547-
target: EC2 instance or managed instance ID
548-
progress_callback: Optional callback for progress updates
549-
verify_checksum: Whether to verify file integrity
550-
chunk_size: Transfer chunk size in bytes
551-
profile: AWS profile name
552-
region: AWS region
553-
endpoint_url: Custom AWS endpoint URL
554-
555-
Returns:
556-
True if transfer successful, False otherwise
557-
"""
558-
options = FileTransferOptions(
559-
chunk_size=chunk_size,
560-
verify_checksum=verify_checksum,
561-
progress_callback=progress_callback,
562-
)
563-
564-
client = FileTransferClient()
565-
return await client.download_file(
566-
remote_path=remote_path,
567-
local_path=local_path,
568-
target=target,
569-
options=options,
570-
profile=profile,
571-
region=region,
572-
endpoint_url=endpoint_url,
573-
)
574-
575-
async def verify_remote_file(
576-
self,
577-
remote_path: str,
578-
target: str,
579-
checksum_type: str = "md5",
580-
# AWS parameters
581-
profile: Optional[str] = None,
582-
region: Optional[str] = None,
583-
endpoint_url: Optional[str] = None,
584-
) -> Optional[str]:
585-
"""Get checksum of remote file.
586-
587-
Args:
588-
remote_path: Path to remote file
589-
target: EC2 instance or managed instance ID
590-
checksum_type: Checksum algorithm (md5 or sha256)
591-
profile: AWS profile name
592-
region: AWS region
593-
endpoint_url: Custom AWS endpoint URL
594-
595-
Returns:
596-
Checksum string if successful, None otherwise
597-
"""
598-
checksum_enum = (
599-
ChecksumType.MD5 if checksum_type.lower() == "md5" else ChecksumType.SHA256
600-
)
601-
602-
client = FileTransferClient()
603-
return await client.verify_remote_file(
604-
remote_path=remote_path,
605-
target=target,
606-
checksum_type=checksum_enum,
607-
profile=profile,
608-
region=region,
609-
endpoint_url=endpoint_url,
610-
)

src/pyssm_client/cli/main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ def ssh(ctx: click.Context, **kwargs: Any) -> None:
207207
@click.option(
208208
"--chunk-size",
209209
type=int,
210-
default=65536,
210+
default=32768,
211211
show_default=True,
212-
help="Transfer chunk size in bytes",
212+
help="Transfer chunk size in bytes (32KB, safe for base64 encoding + protocol overhead)",
213213
)
214214
@click.option("--no-verify", is_flag=True, help="Skip checksum verification")
215215
@click.option(

src/pyssm_client/cli/types.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,9 @@ class FileCopyArguments:
167167

168168
# Transfer options
169169
encoding: FileTransferEncoding = FileTransferEncoding.BASE64
170-
chunk_size: int = 65536 # 64KB
170+
chunk_size: int = (
171+
32768 # 32KB (safe for base64 encoding + protocol overhead within 64KB frames)
172+
)
171173
verify_checksum: bool = True
172174
checksum_type: ChecksumType = ChecksumType.MD5
173175

src/pyssm_client/communicator/types.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class WebSocketConfig:
5252
ping_timeout: float = 10.0 # seconds
5353
connect_timeout: float = 30.0 # seconds
5454
max_message_size: int = 1024 * 1024 # 1MB
55+
max_frame_size: int = 128 * 1024 # 128KB frame size limit (generous for base64)
5556
max_queue_size: int = 100
5657
retry_attempts: int = 3
5758
retry_delay: float = 1.0 # seconds

src/pyssm_client/communicator/websocket_channel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ async def _attempt_connection(self) -> None:
126126
connect(
127127
self._config.url,
128128
additional_headers=headers,
129-
max_size=self._config.max_message_size,
129+
max_size=self._config.max_frame_size, # Use frame size limit, not message size
130130
ping_interval=None, # We handle pings manually
131131
ping_timeout=None,
132132
),

0 commit comments

Comments
 (0)