25
25
#include <stdlib.h>
26
26
#include <string.h>
27
27
28
- #include "uv.h"
29
- #include "internal.h"
30
28
#include "handle-inl.h"
31
- #include "stream-inl .h"
29
+ #include "internal .h"
32
30
#include "req-inl.h"
31
+ #include "stream-inl.h"
32
+ #include "uv-common.h"
33
+ #include "uv.h"
33
34
34
35
#include <aclapi.h>
35
36
#include <accctrl.h>
@@ -52,19 +53,36 @@ static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
52
53
53
54
/* IPC incoming xfer queue item. */
54
55
typedef struct {
56
+ uv__ipc_socket_xfer_type_t xfer_type ;
55
57
uv__ipc_socket_xfer_info_t xfer_info ;
56
58
QUEUE member ;
57
59
} uv__ipc_xfer_queue_item_t ;
58
60
59
- /* IPC frame types. */
60
- enum { UV__IPC_DATA_FRAME = 0 , UV__IPC_XFER_FRAME = 1 };
61
+ /* IPC frame header flags. */
62
+ /* clang-format off */
63
+ enum {
64
+ UV__IPC_FRAME_HAS_DATA = 0x01 ,
65
+ UV__IPC_FRAME_HAS_SOCKET_XFER = 0x02 ,
66
+ UV__IPC_FRAME_XFER_IS_TCP_CONNECTION = 0x04 ,
67
+ /* These are combinations of the flags above. */
68
+ UV__IPC_FRAME_XFER_FLAGS = 0x06 ,
69
+ UV__IPC_FRAME_VALID_FLAGS = 0x07
70
+ };
71
+ /* clang-format on */
61
72
62
73
/* IPC frame header. */
63
74
typedef struct {
64
- uint32_t type ;
65
- uint32_t payload_length ;
75
+ uint32_t flags ;
76
+ uint32_t reserved1 ; /* Ignored. */
77
+ uint32_t data_length ; /* Must be zero if there is no data. */
78
+ uint32_t reserved2 ; /* Must be zero. */
66
79
} uv__ipc_frame_header_t ;
67
80
81
+ /* To implement the IPC protocol correctly, these structures must have exactly
82
+ * the right size. */
83
+ STATIC_ASSERT (sizeof (uv__ipc_frame_header_t ) == 16 );
84
+ STATIC_ASSERT (sizeof (uv__ipc_socket_xfer_info_t ) == 632 );
85
+
68
86
/* Coalesced write request. */
69
87
typedef struct {
70
88
uv_write_t req ; /* Internal heap-allocated write request. */
@@ -878,7 +896,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) {
878
896
server -> pipe .conn .ipc_xfer_queue_length -- ;
879
897
item = QUEUE_DATA (q , uv__ipc_xfer_queue_item_t , member );
880
898
881
- err = uv__tcp_xfer_import ((uv_tcp_t * ) client , & item -> xfer_info );
899
+ err = uv__tcp_xfer_import (
900
+ (uv_tcp_t * ) client , item -> xfer_type , & item -> xfer_info );
882
901
if (err != 0 )
883
902
return err ;
884
903
@@ -1458,10 +1477,10 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
1458
1477
uv_buf_t stack_bufs [6 ];
1459
1478
uv_buf_t * bufs ;
1460
1479
size_t buf_count , buf_index ;
1461
- uv__ipc_frame_header_t xfer_frame_header ;
1480
+ uv__ipc_frame_header_t frame_header ;
1481
+ uv__ipc_socket_xfer_type_t xfer_type = UV__IPC_SOCKET_XFER_NONE ;
1462
1482
uv__ipc_socket_xfer_info_t xfer_info ;
1463
- uv__ipc_frame_header_t data_frame_header ;
1464
- size_t data_length ;
1483
+ uint64_t data_length ;
1465
1484
size_t i ;
1466
1485
int err ;
1467
1486
@@ -1472,29 +1491,27 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
1472
1491
if (data_length > UINT32_MAX )
1473
1492
return WSAENOBUFS ; /* Maps to UV_ENOBUFS. */
1474
1493
1475
- /* Prepare xfer frame payload. */
1476
- if (send_handle ) {
1494
+ /* Prepare the frame's socket xfer payload. */
1495
+ if (send_handle != NULL ) {
1477
1496
uv_tcp_t * send_tcp_handle = (uv_tcp_t * ) send_handle ;
1478
1497
1479
1498
/* Verify that `send_handle` it is indeed a tcp handle. */
1480
1499
if (send_tcp_handle -> type != UV_TCP )
1481
1500
return ERROR_NOT_SUPPORTED ;
1482
1501
1483
1502
/* Export the tcp handle. */
1484
- err = uv__tcp_xfer_export (
1485
- send_tcp_handle , uv__pipe_get_ipc_remote_pid (handle ), & xfer_info );
1503
+ err = uv__tcp_xfer_export (send_tcp_handle ,
1504
+ uv__pipe_get_ipc_remote_pid (handle ),
1505
+ & xfer_type ,
1506
+ & xfer_info );
1486
1507
if (err != 0 )
1487
1508
return err ;
1488
1509
}
1489
1510
1490
1511
/* Compute the number of uv_buf_t's required. */
1491
- buf_count = 0 ;
1492
- if (send_handle != NULL ) {
1493
- buf_count += 2 ; /* One for the frame header, one for the payload. */
1494
- }
1495
- if (data_buf_count > 0 ) {
1496
- buf_count += 1 + data_buf_count ; /* One extra for the frame header. */
1497
- }
1512
+ buf_count = 1 + data_buf_count ; /* Frame header and data buffers. */
1513
+ if (send_handle != NULL )
1514
+ buf_count += 1 ; /* One extra for the socket xfer information. */
1498
1515
1499
1516
/* Use the on-stack buffer array if it is big enough; otherwise allocate
1500
1517
* space for it on the heap. */
@@ -1509,25 +1526,32 @@ int uv__pipe_write_ipc(uv_loop_t* loop,
1509
1526
}
1510
1527
buf_index = 0 ;
1511
1528
1512
- if (send_handle != NULL ) {
1513
- /* Add xfer frame header. */
1514
- xfer_frame_header .type = UV__IPC_XFER_FRAME ;
1515
- xfer_frame_header .payload_length = sizeof xfer_info ;
1516
- bufs [buf_index ++ ] =
1517
- uv_buf_init ((char * ) & xfer_frame_header , sizeof xfer_frame_header );
1529
+ /* Initialize frame header and add it to the buffers list. */
1530
+ memset (& frame_header , 0 , sizeof frame_header );
1531
+ bufs [buf_index ++ ] = uv_buf_init ((char * ) & frame_header , sizeof frame_header );
1518
1532
1519
- /* Add xfer frame payload. */
1533
+ if (send_handle != NULL ) {
1534
+ /* Add frame header flags. */
1535
+ switch (xfer_type ) {
1536
+ case UV__IPC_SOCKET_XFER_TCP_CONNECTION :
1537
+ frame_header .flags |= UV__IPC_FRAME_HAS_SOCKET_XFER |
1538
+ UV__IPC_FRAME_XFER_IS_TCP_CONNECTION ;
1539
+ break ;
1540
+ case UV__IPC_SOCKET_XFER_TCP_SERVER :
1541
+ frame_header .flags |= UV__IPC_FRAME_HAS_SOCKET_XFER ;
1542
+ break ;
1543
+ default :
1544
+ assert (0 ); // Unreachable.
1545
+ }
1546
+ /* Add xfer info buffer. */
1520
1547
bufs [buf_index ++ ] = uv_buf_init ((char * ) & xfer_info , sizeof xfer_info );
1521
1548
}
1522
1549
1523
1550
if (data_length > 0 ) {
1524
- /* Add data frame header. */
1525
- data_frame_header .type = UV__IPC_DATA_FRAME ;
1526
- data_frame_header .payload_length = (uint32_t ) data_length ;
1527
- bufs [buf_index ++ ] =
1528
- uv_buf_init ((char * ) & data_frame_header , sizeof data_frame_header );
1529
-
1530
- /* Add data buffers. */
1551
+ /* Update frame header. */
1552
+ frame_header .flags |= UV__IPC_FRAME_HAS_DATA ;
1553
+ frame_header .data_length = (uint32_t ) data_length ;
1554
+ /* Add data buffers to buffers list. */
1531
1555
for (i = 0 ; i < data_buf_count ; i ++ )
1532
1556
bufs [buf_index ++ ] = data_bufs [i ];
1533
1557
}
@@ -1601,14 +1625,18 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle,
1601
1625
1602
1626
1603
1627
static void uv__pipe_queue_ipc_xfer_info (
1604
- uv_pipe_t * handle , uv__ipc_socket_xfer_info_t * xfer_info ) {
1628
+ uv_pipe_t * handle ,
1629
+ uv__ipc_socket_xfer_type_t xfer_type ,
1630
+ uv__ipc_socket_xfer_info_t * xfer_info ) {
1605
1631
uv__ipc_xfer_queue_item_t * item ;
1606
1632
1607
1633
item = (uv__ipc_xfer_queue_item_t * ) uv__malloc (sizeof (* item ));
1608
1634
if (item == NULL )
1609
1635
uv_fatal_error (ERROR_OUTOFMEMORY , "uv__malloc" );
1610
1636
1611
- memcpy (& item -> xfer_info , xfer_info , sizeof (item -> xfer_info ));
1637
+ item -> xfer_type = xfer_type ;
1638
+ item -> xfer_info = * xfer_info ;
1639
+
1612
1640
QUEUE_INSERT_TAIL (& handle -> pipe .conn .ipc_xfer_queue , & item -> member );
1613
1641
handle -> pipe .conn .ipc_xfer_queue_length ++ ;
1614
1642
}
@@ -1678,7 +1706,7 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
1678
1706
int err ;
1679
1707
1680
1708
if (* data_remaining > 0 ) {
1681
- /* Read data frame payload. */
1709
+ /* Read frame data payload. */
1682
1710
DWORD bytes_read =
1683
1711
uv__pipe_read_data (loop , handle , * data_remaining , * data_remaining );
1684
1712
* data_remaining -= bytes_read ;
@@ -1687,6 +1715,8 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
1687
1715
} else {
1688
1716
/* Start of a new IPC frame. */
1689
1717
uv__ipc_frame_header_t frame_header ;
1718
+ uint32_t xfer_flags ;
1719
+ uv__ipc_socket_xfer_type_t xfer_type ;
1690
1720
uv__ipc_socket_xfer_info_t xfer_info ;
1691
1721
1692
1722
/* Read the IPC frame header. */
@@ -1695,33 +1725,57 @@ static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) {
1695
1725
if (err )
1696
1726
goto error ;
1697
1727
1698
- if (frame_header .type == UV__IPC_DATA_FRAME ) {
1699
- /* Data frame: capture payload length. Actual data will be read in
1700
- * subsequent call to uv__pipe_read_ipc(). */
1701
- * data_remaining = frame_header .payload_length ;
1728
+ /* Validate that flags are valid. */
1729
+ if ((frame_header .flags & ~UV__IPC_FRAME_VALID_FLAGS ) != 0 )
1730
+ goto invalid ;
1731
+ /* Validate that reserved2 is zero. */
1732
+ if (frame_header .reserved2 != 0 )
1733
+ goto invalid ;
1734
+
1735
+ /* Parse xfer flags. */
1736
+ xfer_flags = frame_header .flags & UV__IPC_FRAME_XFER_FLAGS ;
1737
+ if (xfer_flags & UV__IPC_FRAME_HAS_SOCKET_XFER ) {
1738
+ /* Socket coming -- determine the type. */
1739
+ xfer_type = xfer_flags & UV__IPC_FRAME_XFER_IS_TCP_CONNECTION
1740
+ ? UV__IPC_SOCKET_XFER_TCP_CONNECTION
1741
+ : UV__IPC_SOCKET_XFER_TCP_SERVER ;
1742
+ } else if (xfer_flags == 0 ) {
1743
+ /* No socket. */
1744
+ xfer_type = UV__IPC_SOCKET_XFER_NONE ;
1745
+ } else {
1746
+ /* Invalid flags. */
1747
+ goto invalid ;
1748
+ }
1702
1749
1703
- /* Return number of bytes read. */
1704
- return sizeof frame_header ;
1750
+ /* Parse data frame information. */
1751
+ if (frame_header .flags & UV__IPC_FRAME_HAS_DATA ) {
1752
+ * data_remaining = frame_header .data_length ;
1753
+ } else if (frame_header .data_length != 0 ) {
1754
+ /* Data length greater than zero but data flag not set -- invalid. */
1755
+ goto invalid ;
1756
+ }
1705
1757
1706
- } else if (frame_header .type == UV__IPC_XFER_FRAME ) {
1707
- /* Xfer frame: read the payload. */
1708
- assert (frame_header .payload_length == sizeof xfer_info );
1709
- err =
1710
- uv__pipe_read_exactly (handle -> handle , & xfer_info , sizeof xfer_info );
1711
- if (err )
1712
- goto error ;
1758
+ /* If no socket xfer info follows, return here. Data will be read in a
1759
+ * subsequent invocation of uv__pipe_read_ipc(). */
1760
+ if (xfer_type == UV__IPC_SOCKET_XFER_NONE )
1761
+ return sizeof frame_header ; /* Number of bytes read. */
1713
1762
1714
- /* Store the pending socket info. */
1715
- uv__pipe_queue_ipc_xfer_info (handle , & xfer_info );
1763
+ /* Read transferred socket information. */
1764
+ err = uv__pipe_read_exactly (handle -> handle , & xfer_info , sizeof xfer_info );
1765
+ if (err )
1766
+ goto error ;
1716
1767
1717
- /* Return number of bytes read. */
1718
- return sizeof frame_header + sizeof xfer_info ;
1719
- }
1768
+ /* Store the pending socket info. */
1769
+ uv__pipe_queue_ipc_xfer_info (handle , xfer_type , & xfer_info );
1720
1770
1721
- /* Invalid frame . */
1722
- err = WSAECONNABORTED ; /* Maps to UV_ECONNABORTED. */
1771
+ /* Return number of bytes read . */
1772
+ return sizeof frame_header + sizeof xfer_info ;
1723
1773
}
1724
1774
1775
+ invalid :
1776
+ /* Invalid frame. */
1777
+ err = WSAECONNABORTED ; /* Maps to UV_ECONNABORTED. */
1778
+
1725
1779
error :
1726
1780
uv_pipe_read_error_or_eof (loop , handle , err , uv_null_buf_ );
1727
1781
return 0 ; /* Break out of read loop. */
0 commit comments