aboutsummaryrefslogtreecommitdiff
path: root/src/stream/stream_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stream/stream_api.c')
-rw-r--r--src/stream/stream_api.c415
1 files changed, 319 insertions, 96 deletions
diff --git a/src/stream/stream_api.c b/src/stream/stream_api.c
index 9ae34752c..ef0065b22 100644
--- a/src/stream/stream_api.c
+++ b/src/stream/stream_api.c
@@ -696,7 +696,7 @@ ack_task (void *cls,
696 return; 696 return;
697 } 697 }
698 698
699 socket->ack_task_id = 0; 699 socket->ack_task_id = GNUNET_SCHEDULER_NO_TASK;
700 700
701 /* Create the ACK Message */ 701 /* Create the ACK Message */
702 ack_msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_AckMessage)); 702 ack_msg = GNUNET_malloc (sizeof (struct GNUNET_STREAM_AckMessage));
@@ -1562,6 +1562,141 @@ client_handle_transmit_close (void *cls,
1562 1562
1563 1563
1564/** 1564/**
1565 * Generic handler for GNUNET_MESSAGE_TYPE_STREAM_*_CLOSE_ACK messages
1566 *
1567 * @param socket the socket
1568 * @param tunnel connection to the other end
1569 * @param sender who sent the message
1570 * @param message the actual message
1571 * @param atsi performance data for the connection
1572 * @param operation the close operation which is being ACK'ed
1573 * @return GNUNET_OK to keep the connection open,
1574 * GNUNET_SYSERR to close it (signal serious error)
1575 */
1576static int
1577handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket,
1578 struct GNUNET_MESH_Tunnel *tunnel,
1579 const struct GNUNET_PeerIdentity *sender,
1580 const struct GNUNET_STREAM_MessageHeader *message,
1581 const struct GNUNET_ATS_Information *atsi,
1582 int operation)
1583{
1584 struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
1585
1586 shutdown_handle = socket->shutdown_handle;
1587 if (NULL == shutdown_handle)
1588 {
1589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1590 "%x: Received *CLOSE_ACK when shutdown handle is NULL\n",
1591 socket->our_id);
1592 return GNUNET_OK;
1593 }
1594
1595 switch (operation)
1596 {
1597 case SHUT_RDWR:
1598 switch (socket->state)
1599 {
1600 case STATE_CLOSE_WAIT:
1601 if (SHUT_RDWR != shutdown_handle->operation)
1602 {
1603 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1604 "%x: Received CLOSE_ACK when shutdown handle "
1605 "is not for SHUT_RDWR\n",
1606 socket->our_id);
1607 return GNUNET_OK;
1608 }
1609
1610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1611 "%x: Received CLOSE_ACK from %x\n",
1612 socket->our_id,
1613 socket->other_peer);
1614 socket->state = STATE_CLOSED;
1615 break;
1616 default:
1617 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1618 "%x: Received CLOSE_ACK when in it not expected\n",
1619 socket->our_id);
1620 return GNUNET_OK;
1621 }
1622 break;
1623
1624 case SHUT_RD:
1625 switch (socket->state)
1626 {
1627 case STATE_RECEIVE_CLOSE_WAIT:
1628 if (SHUT_RD != shutdown_handle->operation)
1629 {
1630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1631 "%x: Received RECEIVE_CLOSE_ACK when shutdown handle "
1632 "is not for SHUT_RD\n",
1633 socket->our_id);
1634 return GNUNET_OK;
1635 }
1636
1637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1638 "%x: Received RECEIVE_CLOSE_ACK from %x\n",
1639 socket->our_id,
1640 socket->other_peer);
1641 socket->state = STATE_RECEIVE_CLOSED;
1642 break;
1643 default:
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1645 "%x: Received RECEIVE_CLOSE_ACK when in it not expected\n",
1646 socket->our_id);
1647 return GNUNET_OK;
1648 }
1649
1650 break;
1651 case SHUT_WR:
1652 switch (socket->state)
1653 {
1654 case STATE_TRANSMIT_CLOSE_WAIT:
1655 if (SHUT_WR != shutdown_handle->operation)
1656 {
1657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1658 "%x: Received TRANSMIT_CLOSE_ACK when shutdown handle "
1659 "is not for SHUT_WR\n",
1660 socket->our_id);
1661 return GNUNET_OK;
1662 }
1663
1664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1665 "%x: Received TRAMSMIT_CLOSE_ACK from %x\n",
1666 socket->our_id,
1667 socket->other_peer);
1668 socket->state = STATE_TRANSMIT_CLOSED;
1669 break;
1670 default:
1671 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1672 "%x: Received TRANSMIT_CLOSE_ACK when in it not expected\n",
1673 socket->our_id);
1674
1675 return GNUNET_OK;
1676 }
1677 break;
1678 default:
1679 GNUNET_assert (0);
1680 }
1681
1682 if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */
1683 shutdown_handle->completion_cb(shutdown_handle->completion_cls,
1684 operation);
1685 GNUNET_free (shutdown_handle); /* Free shutdown handle */
1686 socket->shutdown_handle = NULL;
1687 if (GNUNET_SCHEDULER_NO_TASK
1688 != shutdown_handle->close_msg_retransmission_task_id)
1689 {
1690 GNUNET_SCHEDULER_cancel
1691 (shutdown_handle->close_msg_retransmission_task_id);
1692 shutdown_handle->close_msg_retransmission_task_id =
1693 GNUNET_SCHEDULER_NO_TASK;
1694 }
1695 return GNUNET_OK;
1696}
1697
1698
1699/**
1565 * Client's message handler for GNUNET_MESSAGE_TYPE_STREAM_TRANSMIT_CLOSE_ACK 1700 * Client's message handler for GNUNET_MESSAGE_TYPE_STREAM_TRANSMIT_CLOSE_ACK
1566 * 1701 *
1567 * @param cls the socket (set from GNUNET_MESH_connect) 1702 * @param cls the socket (set from GNUNET_MESH_connect)
@@ -1583,6 +1718,67 @@ client_handle_transmit_close_ack (void *cls,
1583{ 1718{
1584 struct GNUNET_STREAM_Socket *socket = cls; 1719 struct GNUNET_STREAM_Socket *socket = cls;
1585 1720
1721 return handle_generic_close_ack (socket,
1722 tunnel,
1723 sender,
1724 (const struct GNUNET_STREAM_MessageHeader *)
1725 message,
1726 atsi,
1727 SHUT_WR);
1728}
1729
1730
1731/**
1732 * Generic handler for GNUNET_MESSAGE_TYPE_STREAM_RECEIVE_CLOSE
1733 *
1734 * @param socket the socket
1735 * @param tunnel connection to the other end
1736 * @param sender who sent the message
1737 * @param message the actual message
1738 * @param atsi performance data for the connection
1739 * @return GNUNET_OK to keep the connection open,
1740 * GNUNET_SYSERR to close it (signal serious error)
1741 */
1742static int
1743handle_receive_close (struct GNUNET_STREAM_Socket *socket,
1744 struct GNUNET_MESH_Tunnel *tunnel,
1745 const struct GNUNET_PeerIdentity *sender,
1746 const struct GNUNET_STREAM_MessageHeader *message,
1747 const struct GNUNET_ATS_Information *atsi)
1748{
1749 struct GNUNET_STREAM_MessageHeader *receive_close_ack;
1750
1751 switch (socket->state)
1752 {
1753 case STATE_INIT:
1754 case STATE_LISTEN:
1755 case STATE_HELLO_WAIT:
1756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1757 "%x: Ignoring RECEIVE_CLOSE as it cannot be handled now\n",
1758 socket->our_id);
1759 return GNUNET_OK;
1760 default:
1761 break;
1762 }
1763
1764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1765 "%x: Received RECEIVE_CLOSE from %x\n",
1766 socket->our_id,
1767 socket->other_peer);
1768 receive_close_ack =
1769 GNUNET_malloc (sizeof (struct GNUNET_STREAM_MessageHeader));
1770 receive_close_ack->header.size =
1771 htons (sizeof (struct GNUNET_STREAM_MessageHeader));
1772 receive_close_ack->header.type =
1773 htons (GNUNET_MESSAGE_TYPE_STREAM_RECEIVE_CLOSE_ACK);
1774 queue_message (socket,
1775 receive_close_ack,
1776 &set_state_closed,
1777 NULL);
1778
1779 /* FIXME: Handle the case where write handle is present; the write operation
1780 should be deemed as finised and the write continuation callback
1781 has to be called with the stream status GNUNET_STREAM_SHUTDOWN */
1586 return GNUNET_OK; 1782 return GNUNET_OK;
1587} 1783}
1588 1784
@@ -1609,7 +1805,12 @@ client_handle_receive_close (void *cls,
1609{ 1805{
1610 struct GNUNET_STREAM_Socket *socket = cls; 1806 struct GNUNET_STREAM_Socket *socket = cls;
1611 1807
1612 return GNUNET_OK; 1808 return
1809 handle_receive_close (socket,
1810 tunnel,
1811 sender,
1812 (const struct GNUNET_STREAM_MessageHeader *) message,
1813 atsi);
1613} 1814}
1614 1815
1615 1816
@@ -1635,7 +1836,13 @@ client_handle_receive_close_ack (void *cls,
1635{ 1836{
1636 struct GNUNET_STREAM_Socket *socket = cls; 1837 struct GNUNET_STREAM_Socket *socket = cls;
1637 1838
1638 return GNUNET_OK; 1839 return handle_generic_close_ack (socket,
1840 tunnel,
1841 sender,
1842 (const struct GNUNET_STREAM_MessageHeader *)
1843 message,
1844 atsi,
1845 SHUT_RD);
1639} 1846}
1640 1847
1641 1848
@@ -1659,6 +1866,19 @@ handle_close (struct GNUNET_STREAM_Socket *socket,
1659{ 1866{
1660 struct GNUNET_STREAM_MessageHeader *close_ack; 1867 struct GNUNET_STREAM_MessageHeader *close_ack;
1661 1868
1869 switch (socket->state)
1870 {
1871 case STATE_INIT:
1872 case STATE_LISTEN:
1873 case STATE_HELLO_WAIT:
1874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1875 "%x: Ignoring RECEIVE_CLOSE as it cannot be handled now\n",
1876 socket->our_id);
1877 return GNUNET_OK;
1878 default:
1879 break;
1880 }
1881
1662 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1663 "%x: Received CLOSE from %x\n", 1883 "%x: Received CLOSE from %x\n",
1664 socket->our_id, 1884 socket->our_id,
@@ -1711,69 +1931,6 @@ client_handle_close (void *cls,
1711 1931
1712 1932
1713/** 1933/**
1714 * Generic handler for GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK
1715 *
1716 * @param socket the socket
1717 * @param tunnel connection to the other end
1718 * @param sender who sent the message
1719 * @param message the actual message
1720 * @param atsi performance data for the connection
1721 * @return GNUNET_OK to keep the connection open,
1722 * GNUNET_SYSERR to close it (signal serious error)
1723 */
1724static int
1725handle_close_ack (struct GNUNET_STREAM_Socket *socket,
1726 struct GNUNET_MESH_Tunnel *tunnel,
1727 const struct GNUNET_PeerIdentity *sender,
1728 const struct GNUNET_STREAM_MessageHeader *message,
1729 const struct GNUNET_ATS_Information *atsi)
1730{
1731 struct GNUNET_STREAM_ShutdownHandle *shutdown_handle;
1732
1733 shutdown_handle = socket->shutdown_handle;
1734 switch (socket->state)
1735 {
1736 case STATE_CLOSE_WAIT:
1737 if ( (NULL == shutdown_handle) ||
1738 (SHUT_RDWR != shutdown_handle->operation) )
1739 {
1740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1741 "%x: Received CLOSE_ACK when shutdown handle is NULL or "
1742 "not for SHUT_RDWR\n",
1743 socket->our_id);
1744 return GNUNET_OK;
1745 }
1746
1747 if (GNUNET_SCHEDULER_NO_TASK
1748 != shutdown_handle->close_msg_retransmission_task_id)
1749 {
1750 GNUNET_SCHEDULER_cancel
1751 (shutdown_handle->close_msg_retransmission_task_id);
1752 shutdown_handle->close_msg_retransmission_task_id =
1753 GNUNET_SCHEDULER_NO_TASK;
1754 }
1755
1756 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1757 "%x: Received CLOSE_ACK from %x\n",
1758 socket->our_id,
1759 socket->other_peer);
1760 socket->state = STATE_CLOSED;
1761 if (NULL != shutdown_handle->completion_cb) /* Shutdown completion */
1762 shutdown_handle->completion_cb(shutdown_handle->completion_cls,
1763 SHUT_RDWR);
1764 GNUNET_free (shutdown_handle); /* Free shutdown handle */
1765 break;
1766 default:
1767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1768 "%x: Received CLOSE_ACK when in it not expected\n",
1769 socket->our_id);
1770 break;
1771 }
1772 return GNUNET_OK;
1773}
1774
1775
1776/**
1777 * Client's message handler for GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK 1934 * Client's message handler for GNUNET_MESSAGE_TYPE_STREAM_CLOSE_ACK
1778 * 1935 *
1779 * @param cls the socket (set from GNUNET_MESH_connect) 1936 * @param cls the socket (set from GNUNET_MESH_connect)
@@ -1795,12 +1952,13 @@ client_handle_close_ack (void *cls,
1795{ 1952{
1796 struct GNUNET_STREAM_Socket *socket = cls; 1953 struct GNUNET_STREAM_Socket *socket = cls;
1797 1954
1798 return handle_close_ack (socket, 1955 return handle_generic_close_ack (socket,
1799 tunnel, 1956 tunnel,
1800 sender, 1957 sender,
1801 (const struct GNUNET_STREAM_MessageHeader *) 1958 (const struct GNUNET_STREAM_MessageHeader *)
1802 message, 1959 message,
1803 atsi); 1960 atsi,
1961 SHUT_RDWR);
1804} 1962}
1805 1963
1806/*****************************/ 1964/*****************************/
@@ -2027,7 +2185,13 @@ server_handle_transmit_close_ack (void *cls,
2027{ 2185{
2028 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; 2186 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
2029 2187
2030 return GNUNET_OK; 2188 return handle_generic_close_ack (socket,
2189 tunnel,
2190 sender,
2191 (const struct GNUNET_STREAM_MessageHeader *)
2192 message,
2193 atsi,
2194 SHUT_WR);
2031} 2195}
2032 2196
2033 2197
@@ -2053,7 +2217,12 @@ server_handle_receive_close (void *cls,
2053{ 2217{
2054 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; 2218 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
2055 2219
2056 return GNUNET_OK; 2220 return
2221 handle_receive_close (socket,
2222 tunnel,
2223 sender,
2224 (const struct GNUNET_STREAM_MessageHeader *) message,
2225 atsi);
2057} 2226}
2058 2227
2059 2228
@@ -2079,7 +2248,13 @@ server_handle_receive_close_ack (void *cls,
2079{ 2248{
2080 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; 2249 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
2081 2250
2082 return GNUNET_OK; 2251 return handle_generic_close_ack (socket,
2252 tunnel,
2253 sender,
2254 (const struct GNUNET_STREAM_MessageHeader *)
2255 message,
2256 atsi,
2257 SHUT_RD);
2083} 2258}
2084 2259
2085 2260
@@ -2136,16 +2311,18 @@ server_handle_close_ack (void *cls,
2136{ 2311{
2137 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; 2312 struct GNUNET_STREAM_Socket *socket = *tunnel_ctx;
2138 2313
2139 return handle_close_ack (socket, 2314 return handle_generic_close_ack (socket,
2140 tunnel, 2315 tunnel,
2141 sender, 2316 sender,
2142 (const struct GNUNET_STREAM_MessageHeader *) message, 2317 (const struct GNUNET_STREAM_MessageHeader *)
2143 atsi); 2318 message,
2319 atsi,
2320 SHUT_RDWR);
2144} 2321}
2145 2322
2146 2323
2147/** 2324/**
2148 * Message Handler for mesh 2325 * Handler for DATA_ACK messages
2149 * 2326 *
2150 * @param socket the socket through which the ack was received 2327 * @param socket the socket through which the ack was received
2151 * @param tunnel connection to the other end 2328 * @param tunnel connection to the other end
@@ -2177,6 +2354,8 @@ handle_ack (struct GNUNET_STREAM_Socket *socket,
2177 switch (socket->state) 2354 switch (socket->state)
2178 { 2355 {
2179 case (STATE_ESTABLISHED): 2356 case (STATE_ESTABLISHED):
2357 case (STATE_RECEIVE_CLOSED):
2358 case (STATE_RECEIVE_CLOSE_WAIT):
2180 if (NULL == socket->write_handle) 2359 if (NULL == socket->write_handle)
2181 { 2360 {
2182 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -2284,7 +2463,7 @@ handle_ack (struct GNUNET_STREAM_Socket *socket,
2284 2463
2285 2464
2286/** 2465/**
2287 * Message Handler for mesh 2466 * Handler for DATA_ACK messages
2288 * 2467 *
2289 * @param cls the 'struct GNUNET_STREAM_Socket' 2468 * @param cls the 'struct GNUNET_STREAM_Socket'
2290 * @param tunnel connection to the other end 2469 * @param tunnel connection to the other end
@@ -2311,7 +2490,7 @@ client_handle_ack (void *cls,
2311 2490
2312 2491
2313/** 2492/**
2314 * Message Handler for mesh 2493 * Handler for DATA_ACK messages
2315 * 2494 *
2316 * @param cls the server's listen socket 2495 * @param cls the server's listen socket
2317 * @param tunnel connection to the other end 2496 * @param tunnel connection to the other end
@@ -2855,15 +3034,22 @@ GNUNET_STREAM_listen_close (struct GNUNET_STREAM_ListenSocket *lsocket)
2855 3034
2856 3035
2857/** 3036/**
2858 * Tries to write the given data to the stream 3037 * Tries to write the given data to the stream. The maximum size of data that
3038 * can be written as part of a write operation is (64 * (64000 - sizeof (struct
3039 * GNUNET_STREAM_DataMessage))). If size is greater than this it is not an API
3040 * violation, however only the said number of maximum bytes will be written.
2859 * 3041 *
2860 * @param socket the socket representing a stream 3042 * @param socket the socket representing a stream
2861 * @param data the data buffer from where the data is written into the stream 3043 * @param data the data buffer from where the data is written into the stream
2862 * @param size the number of bytes to be written from the data buffer 3044 * @param size the number of bytes to be written from the data buffer
2863 * @param timeout the timeout period 3045 * @param timeout the timeout period
2864 * @param write_cont the function to call upon writing some bytes into the stream 3046 * @param write_cont the function to call upon writing some bytes into the
3047 * stream
2865 * @param write_cont_cls the closure 3048 * @param write_cont_cls the closure
2866 * @return handle to cancel the operation 3049 *
3050 * @return handle to cancel the operation; if a previous write is pending or
3051 * the stream has been shutdown for this operation then write_cont is
3052 * immediately called and NULL is returned.
2867 */ 3053 */
2868struct GNUNET_STREAM_IOWriteHandle * 3054struct GNUNET_STREAM_IOWriteHandle *
2869GNUNET_STREAM_write (struct GNUNET_STREAM_Socket *socket, 3055GNUNET_STREAM_write (struct GNUNET_STREAM_Socket *socket,
@@ -2891,16 +3077,33 @@ GNUNET_STREAM_write (struct GNUNET_STREAM_Socket *socket,
2891 GNUNET_break (0); 3077 GNUNET_break (0);
2892 return NULL; 3078 return NULL;
2893 } 3079 }
2894 if (!((STATE_ESTABLISHED == socket->state) 3080
2895 || (STATE_RECEIVE_CLOSE_WAIT == socket->state) 3081 switch (socket->state)
2896 || (STATE_RECEIVE_CLOSED == socket->state)))
2897 { 3082 {
2898 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 3083 case STATE_TRANSMIT_CLOSED:
2899 "%x: Attempting to write on a closed (OR) not-yet-established" 3084 case STATE_TRANSMIT_CLOSE_WAIT:
2900 "stream\n", 3085 case STATE_CLOSED:
2901 socket->our_id); 3086 case STATE_CLOSE_WAIT:
3087 if (NULL != write_cont)
3088 write_cont (write_cont_cls, GNUNET_STREAM_SHUTDOWN, 0);
3089 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3090 "%s() END\n", __func__);
3091 return NULL;
3092 case STATE_INIT:
3093 case STATE_LISTEN:
3094 case STATE_HELLO_WAIT:
3095 if (NULL != write_cont)
3096 /* FIXME: GNUNET_STREAM_SYSERR?? */
3097 write_cont (write_cont_cls, GNUNET_STREAM_SYSERR, 0);
3098 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3099 "%s() END\n", __func__);
2902 return NULL; 3100 return NULL;
2903 } 3101 case STATE_ESTABLISHED:
3102 case STATE_RECEIVE_CLOSED:
3103 case STATE_RECEIVE_CLOSE_WAIT:
3104 break;
3105 }
3106
2904 if (GNUNET_STREAM_ACK_BITMAP_BIT_LENGTH * max_payload_size < size) 3107 if (GNUNET_STREAM_ACK_BITMAP_BIT_LENGTH * max_payload_size < size)
2905 size = GNUNET_STREAM_ACK_BITMAP_BIT_LENGTH * max_payload_size; 3108 size = GNUNET_STREAM_ACK_BITMAP_BIT_LENGTH * max_payload_size;
2906 num_needed_packets = (size + (max_payload_size - 1)) / max_payload_size; 3109 num_needed_packets = (size + (max_payload_size - 1)) / max_payload_size;
@@ -2957,14 +3160,18 @@ GNUNET_STREAM_write (struct GNUNET_STREAM_Socket *socket,
2957} 3160}
2958 3161
2959 3162
3163
2960/** 3164/**
2961 * Tries to read data from the stream 3165 * Tries to read data from the stream.
2962 * 3166 *
2963 * @param socket the socket representing a stream 3167 * @param socket the socket representing a stream
2964 * @param timeout the timeout period 3168 * @param timeout the timeout period
2965 * @param proc function to call with data (once only) 3169 * @param proc function to call with data (once only)
2966 * @param proc_cls the closure for proc 3170 * @param proc_cls the closure for proc
2967 * @return handle to cancel the operation 3171 *
3172 * @return handle to cancel the operation; if the stream has been shutdown for
3173 * this type of opeartion then the DataProcessor is immediately
3174 * called with GNUNET_STREAM_SHUTDOWN as status and NULL if returned
2968 */ 3175 */
2969struct GNUNET_STREAM_IOReadHandle * 3176struct GNUNET_STREAM_IOReadHandle *
2970GNUNET_STREAM_read (struct GNUNET_STREAM_Socket *socket, 3177GNUNET_STREAM_read (struct GNUNET_STREAM_Socket *socket,
@@ -2985,6 +3192,22 @@ GNUNET_STREAM_read (struct GNUNET_STREAM_Socket *socket,
2985 3192
2986 GNUNET_assert (NULL != proc); 3193 GNUNET_assert (NULL != proc);
2987 3194
3195 switch (socket->state)
3196 {
3197 case STATE_RECEIVE_CLOSED:
3198 case STATE_RECEIVE_CLOSE_WAIT:
3199 case STATE_CLOSED:
3200 case STATE_CLOSE_WAIT:
3201 proc (proc_cls, GNUNET_STREAM_SHUTDOWN, NULL, 0);
3202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3203 "%x: %s() END\n",
3204 socket->our_id,
3205 __func__);
3206 return NULL;
3207 default:
3208 break;
3209 }
3210
2988 read_handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_IOReadHandle)); 3211 read_handle = GNUNET_malloc (sizeof (struct GNUNET_STREAM_IOReadHandle));
2989 read_handle->proc = proc; 3212 read_handle->proc = proc;
2990 read_handle->proc_cls = proc_cls; 3213 read_handle->proc_cls = proc_cls;