@@ -213,7 +213,7 @@ namespace pipetap::inject {
213213 strncpy_s (hello.proc_name , sizeof (hello.proc_name ), name.c_str (), _TRUNCATE);
214214 log::printf (" SendHello: pid=%lu exe=%s" , (unsigned long )hello.pid , hello.proc_name );
215215
216- send_control_message (PT_HELLO, & hello, ( uint32_t ) sizeof (hello), nullptr , 0 );
216+ send_control_message (PT_ControlFrame::FromStruct ( PT_HELLO, hello) );
217217 }
218218
219219 void ControlServer::send_error (uint32_t code, const char * what)
@@ -224,7 +224,7 @@ namespace pipetap::inject {
224224 e.code = code;
225225 strncpy_s (e.what , sizeof (e.what ), (what ? what : " err" ), _TRUNCATE);
226226
227- send_control_message (PT_ERROR, &e, ( uint32_t ) sizeof (e), nullptr , 0 );
227+ send_control_message (PT_ControlFrame::FromStruct ( PT_ERROR, e) );
228228 }
229229
230230 void ControlServer::send_pipe_io (uint16_t message_type, HANDLE pipe,
@@ -233,18 +233,12 @@ namespace pipetap::inject {
233233 const char * apiName)
234234 {
235235 if (!connected_.load (std::memory_order_relaxed)) return ;
236- HANDLE hW = atomic_load_handle (ctrl_w_);
237- if (ctrl_broken_.load (std::memory_order_acquire) || !hW || hW == INVALID_HANDLE_VALUE) {
238- connected_.store (false , std::memory_order_release);
239- return ;
240- }
241236
242237 uint8_t is_msg = 0 ;
243238 uint32_t outHint = 0 , inHint = 0 ;
244239 query_pipe_hints (pipe, is_msg, outHint, inHint);
245240
246241 static constexpr uint32_t kMaxSample = 24 * 1024 ;
247- uint32_t sample = (total > kMaxSample ) ? kMaxSample : total;
248242
249243 std::string pipeName = pipe_name_for_handle (pipe);
250244 if (pipeName.size () > 0xFFFE ) pipeName.resize (0xFFFE );
@@ -259,51 +253,27 @@ namespace pipetap::inject {
259253 if (peerImg.size () > 0xFFFE ) peerImg.resize (0xFFFE );
260254 }
261255
262- // Build meta
263- PT_PipeIo meta{};
264- meta.pid = GetCurrentProcessId ();
265- meta.tid = GetCurrentThreadId ();
266- meta.dir = dir;
267- meta.is_message_mode = is_msg;
268- meta.total_size = total;
269- meta.sample_size = sample;
270- meta.out_buf_hint = outHint;
271- meta.in_buf_hint = inHint;
272- meta.op_id = op_id;
273- meta.pipe_len = static_cast <uint16_t >(pipeName.size ());
274- meta.api_len = static_cast <uint16_t >(api.size ());
275- meta.peer_pid = peer.pid ;
276- meta.endpoint_role = peer.role ; // 0=unknown, 1=server-end, 2=client-end
277- meta.image_len = static_cast <uint16_t >(peerImg.size ());
278-
279- const uint32_t meta_len = (uint32_t )sizeof (meta);
280- const uint32_t name_len = meta.pipe_len ;
281- const uint32_t api_len = meta.api_len ;
282- const uint32_t image_len = meta.image_len ;
283- const uint32_t payload_len = sample;
284-
285- std::vector<::pipetap::ControlMessageFragment> fragments;
286- fragments.reserve (1 + (name_len ? 1 : 0 ) + (api_len ? 1 : 0 ) + (image_len ? 1 : 0 ) + ((payload_len && buf) ? 1 : 0 ));
287- fragments.push_back ({ &meta, meta_len });
288- if (name_len) fragments.push_back ({ pipeName.data (), name_len });
289- if (api_len) fragments.push_back ({ api.data (), api_len });
290- if (image_len) fragments.push_back ({ peerImg.data (), image_len });
291- if (payload_len && buf) fragments.push_back ({ buf, payload_len });
292-
293- auto msg = ::pipetap::BuildControlMessage (message_type, fragments);
294-
295- AcquireSRWLockExclusive (&ctrl_lock_);
296- {
297- SuppressHooksGuard _guard;
298- DWORD wrote = 0 ;
299- BOOL ok = WriteFile (hW, msg.data (), (DWORD)msg.size (), &wrote, nullptr );
300- if (!ok || wrote != msg.size ()) {
301- ctrl_broken_.store (true , std::memory_order_release);
302- connected_.store (false , std::memory_order_release);
303- (void )atomic_exchange_handle (ctrl_w_, INVALID_HANDLE_VALUE);
304- }
305- }
306- ReleaseSRWLockExclusive (&ctrl_lock_);
256+ PT_PipeIoEnvelope env{};
257+ env.meta .pid = GetCurrentProcessId ();
258+ env.meta .tid = GetCurrentThreadId ();
259+ env.meta .dir = dir;
260+ env.meta .is_message_mode = is_msg;
261+ env.meta .total_size = total;
262+ env.meta .out_buf_hint = outHint;
263+ env.meta .in_buf_hint = inHint;
264+ env.meta .op_id = op_id;
265+ env.meta .peer_pid = peer.pid ;
266+ env.meta .endpoint_role = peer.role ; // 0=unknown, 1=server-end, 2=client-end
267+
268+ env.pipe_name = pipeName;
269+ env.api_name = api;
270+ env.peer_image = peerImg;
271+ env.payload = static_cast <const uint8_t *>(buf);
272+ env.payload_len = (buf && total) ? total : 0 ;
273+ env.max_sample = kMaxSample ;
274+
275+ auto frame = PT_BuildPipeIoMessage (message_type, env);
276+ send_control_message (frame);
307277 }
308278
309279 void ControlServer::send_proxy_opened (uint64_t session_id,
@@ -319,7 +289,7 @@ namespace pipetap::inject {
319289 r.is_message_mode = is_message_mode;
320290 r.out_buf_hint = out_hint;
321291 r.in_buf_hint = in_hint;
322- send_control_message (PT_EVT_PROXY_OPENED, &r, sizeof (r), nullptr , 0 );
292+ send_control_message (PT_ControlFrame::FromStruct ( PT_EVT_PROXY_OPENED, r) );
323293 }
324294
325295 void ControlServer::send_proxy_closed (uint64_t session_id,
@@ -331,7 +301,7 @@ namespace pipetap::inject {
331301 ev.session_id = session_id;
332302 ev.reason = reason;
333303 ev.win32_error = win32_error;
334- send_control_message (PT_EVT_PROXY_CLOSED, &ev, sizeof (ev), nullptr , 0 );
304+ send_control_message (PT_ControlFrame::FromStruct ( PT_EVT_PROXY_CLOSED, ev) );
335305 }
336306
337307 BOOL ControlServer::wait_for_edit_and_maybe_replace (uint64_t op_id,
@@ -454,9 +424,7 @@ namespace pipetap::inject {
454424 1 , 0 , 256 * 1024 , 0 , nullptr );
455425 }
456426
457- void ControlServer::send_control_message (uint16_t type,
458- const void * meta, uint32_t meta_len,
459- const void * payload, uint32_t payload_len)
427+ void ControlServer::send_control_message (const PT_ControlFrame& frame)
460428 {
461429 if (!connected_.load (std::memory_order_relaxed)) return ;
462430
@@ -466,17 +434,12 @@ namespace pipetap::inject {
466434 return ;
467435 }
468436
469- std::vector<::pipetap::ControlMessageFragment> fragments;
470- if (meta_len && meta) fragments.push_back ({ meta, meta_len });
471- if (payload_len && payload) fragments.push_back ({ payload, payload_len });
472- auto msg = ::pipetap::BuildControlMessage (type, fragments);
473-
474437 AcquireSRWLockExclusive (&ctrl_lock_);
475438 {
476439 SuppressHooksGuard _guard;
477440 DWORD wrote = 0 ;
478- BOOL ok = WriteFile (hW, msg. data (), (DWORD)msg. size (), &wrote, nullptr );
479- if (!ok || wrote != msg. size () ) {
441+ bool ok = :: pipetap::WriteControlFrame (hW, frame, &wrote);
442+ if (!ok) {
480443 ctrl_broken_.store (true , std::memory_order_release);
481444 connected_.store (false , std::memory_order_release);
482445 (void )atomic_exchange_handle (ctrl_w_, INVALID_HANDLE_VALUE);
@@ -498,61 +461,50 @@ namespace pipetap::inject {
498461 }
499462 if (totalAvail < sizeof (PT_ControlMessageHeader)) { Sleep (1 ); continue ; }
500463
501- PT_ControlMessageHeader hdr{} ;
464+ PT_ControlFrame frame ;
502465 {
503466 SuppressHooksGuard _guard;
504- if (!::pipetap::PipeReadExact (h, &hdr, static_cast <DWORD>(sizeof (hdr)))) break ;
505- }
506-
507- if (hdr.length > (512u * 1024u * 1024u )) break ;
508-
509- std::vector<uint8_t > val (hdr.length );
510- if (hdr.length ) {
511- SuppressHooksGuard _guard;
512- if (!::pipetap::PipeReadExact (h, val.data (), hdr.length )) break ;
467+ if (!::pipetap::ReadControlFrame (h, frame)) break ;
513468 }
514469
515470 ctrl_broken_.store (false , std::memory_order_release);
516471 connected_.store (true , std::memory_order_release);
517472
518- switch (hdr .type ) {
473+ switch (frame. header .type ) {
519474 case PT_CMD_SET_EDIT:
520- if (hdr. length >= sizeof (PT_EditFlags)) {
475+ {
521476 PT_EditFlags fl{};
522- std::memcpy (&fl, val.data (), sizeof (fl));
523- edit_req_.store (fl.edit_request ? 1u : 0u , std::memory_order_release);
524- edit_resp_.store (fl.edit_response ? 1u : 0u , std::memory_order_release);
477+ if (frame.TryAs (fl)) {
478+ edit_req_.store (fl.edit_request ? 1u : 0u , std::memory_order_release);
479+ edit_resp_.store (fl.edit_response ? 1u : 0u , std::memory_order_release);
480+ }
525481 }
526482 break ;
527483
528484 case PT_CMD_EDIT_REPLY:
529- if (hdr.length >= sizeof (PT_EditReply)) {
485+ {
486+ PT_ControlFrame::Reader rd = frame.AsReader ();
530487 PT_EditReply rep{};
531- std::memcpy (&rep, val.data (), sizeof (rep));
532- const uint8_t * bytes = nullptr ; uint32_t bsz = 0 ;
533- if (rep.action == 1 ) {
534- size_t off = sizeof (PT_EditReply);
535- if (hdr.length >= off + rep.new_size ) {
536- bytes = val.data () + off;
537- bsz = rep.new_size ;
538- }
488+ if (!rd.Next (rep)) break ;
489+
490+ const uint8_t * bytes = nullptr ;
491+ uint32_t bsz = 0 ;
492+ if (rep.action == 1 && rep.new_size ) {
493+ if (!rd.NextBytes (rep.new_size , bytes)) break ;
494+ bsz = rep.new_size ;
539495 }
540496 complete_pending (rep.op_id , rep.action , bytes, bsz);
541497 }
542498 break ;
543499
544500 case PT_CMD_PROXY_OPEN:
545- if (hdr.length >= sizeof (PT_ProxyOpen)) {
501+ {
502+ PT_ControlFrame::Reader rd = frame.AsReader ();
546503 PT_ProxyOpen op{};
547- std::memcpy (&op, val. data (), sizeof ( op));
504+ if (!rd. Next ( op)) break ;
548505
549- const char * name = nullptr ;
550- if (op.name_len ) {
551- size_t off = sizeof (PT_ProxyOpen);
552- if (hdr.length >= off + op.name_len ) {
553- name = reinterpret_cast <const char *>(val.data () + off);
554- }
555- }
506+ const uint8_t * name = nullptr ;
507+ if (op.name_len && !rd.NextBytes (op.name_len , name)) break ;
556508
557509 uint32_t win32err = ERROR_INVALID_PARAMETER;
558510 bool ok = false ;
@@ -564,7 +516,7 @@ namespace pipetap::inject {
564516 DWORD le = NamedPipeClient::instance ().open_session (
565517 *this ,
566518 op.session_id ,
567- std::string (name, name + op.name_len ),
519+ std::string (reinterpret_cast < const char *>( name), reinterpret_cast < const char *>( name) + op.name_len ),
568520 op.timeout_ms ,
569521 op.wait_for_server != 0 ,
570522 op.set_message_readmode != 0 ,
@@ -588,16 +540,17 @@ namespace pipetap::inject {
588540 break ;
589541
590542 case PT_CMD_PROXY_SEND:
591- if (hdr.length >= sizeof (PT_ProxySend)) {
543+ {
544+ PT_ControlFrame::Reader rd = frame.AsReader ();
592545 PT_ProxySend ps{};
593- std::memcpy (&ps, val.data (), sizeof (ps));
546+ if (!rd.Next (ps)) break ;
547+
594548 const uint8_t * data = nullptr ;
595- if (ps.data_size ) {
596- size_t off = sizeof (PT_ProxySend );
597- if (hdr. length >= off + ps. data_size ) data = val. data () + off ;
549+ if (ps.data_size && !rd. NextBytes (ps. data_size , data) ) {
550+ send_error ( 2001u , " proxy_send_bad_session " );
551+ break ;
598552 }
599-
600- if (!data) {
553+ if (ps.data_size == 0 || !data) {
601554 send_error (2001u , " proxy_send_bad_session" );
602555 break ;
603556 }
@@ -615,11 +568,11 @@ namespace pipetap::inject {
615568 break ;
616569
617570 case PT_CMD_PROXY_CLOSE:
618- if (hdr. length >= sizeof (PT_ProxyClose)) {
571+ {
619572 PT_ProxyClose c{};
620- std::memcpy (&c, val. data (), sizeof ( c));
621-
622- NamedPipeClient::instance (). close_session (c. session_id , /* reason= */ 0u , /* win32err= */ 0u );
573+ if (frame. TryAs ( c)) {
574+ NamedPipeClient::instance (). close_session (c. session_id , /* reason= */ 0u , /* win32err= */ 0u );
575+ }
623576 }
624577 break ;
625578
0 commit comments