@@ -71,6 +71,8 @@ static int ngx_stream_lua_socket_udp_close(lua_State *L);
7171static ngx_int_t ngx_stream_lua_socket_udp_resume (ngx_stream_lua_request_t * r );
7272static void ngx_stream_lua_udp_resolve_cleanup (void * data );
7373static void ngx_stream_lua_udp_socket_cleanup (void * data );
74+ static ssize_t ngx_stream_lua_udp_sendmsg (ngx_connection_t * c ,
75+ ngx_iovec_t * vec );
7476
7577
7678enum {
@@ -786,6 +788,8 @@ ngx_stream_lua_socket_udp_send(lua_State *L)
786788 int type ;
787789 const char * msg ;
788790 ngx_str_t query ;
791+ ngx_iovec_t vec ;
792+ struct iovec iovs [1 ];
789793
790794 ngx_stream_lua_socket_udp_upstream_t * u ;
791795 ngx_stream_lua_loc_conf_t * llcf ;
@@ -921,9 +925,16 @@ ngx_stream_lua_socket_udp_send(lua_State *L)
921925
922926 dd ("sending query %.*s" , (int ) query .len , query .data );
923927
924- n = ngx_udp_send (u -> udp_connection .connection , query .data , query .len );
928+ vec .iovs = iovs ;
929+ vec .nalloc = 1 ;
930+ vec .count = 1 ;
931+ iovs [0 ].iov_base = query .data ;
932+ iovs [0 ].iov_len = query .len ;
933+ vec .size = query .len ;
934+ n = ngx_stream_lua_udp_sendmsg (u -> udp_connection .connection , & vec );
925935
926- dd ("ngx_udp_send returns %d (query len %d)" , (int ) n , (int ) query .len );
936+ dd ("ngx_stream_lua_udp_sendmsg returns %d (query len %d)" ,
937+ (int ) n , (int ) query .len );
927938
928939 if (n == NGX_ERROR || n == NGX_AGAIN ) {
929940 u -> socket_errno = ngx_socket_errno ;
@@ -1797,4 +1808,142 @@ ngx_stream_lua_req_socket_udp(lua_State *L)
17971808}
17981809
17991810
1811+ static ssize_t
1812+ ngx_stream_lua_udp_sendmsg (ngx_connection_t * c , ngx_iovec_t * vec )
1813+ {
1814+ ssize_t n ;
1815+ ngx_err_t err ;
1816+ struct msghdr msg ;
1817+
1818+ #if (NGX_HAVE_MSGHDR_MSG_CONTROL )
1819+
1820+ #if (NGX_HAVE_IP_SENDSRCADDR )
1821+ u_char msg_control [CMSG_SPACE (sizeof (struct in_addr ))];
1822+ #elif (NGX_HAVE_IP_PKTINFO )
1823+ u_char msg_control [CMSG_SPACE (sizeof (struct in_pktinfo ))];
1824+ #endif
1825+
1826+ #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO )
1827+ u_char msg_control6 [CMSG_SPACE (sizeof (struct in6_pktinfo ))];
1828+ #endif
1829+
1830+ #endif
1831+
1832+ ngx_memzero (& msg , sizeof (struct msghdr ));
1833+
1834+ if (c -> socklen ) {
1835+ msg .msg_name = c -> sockaddr ;
1836+ msg .msg_namelen = c -> socklen ;
1837+ }
1838+
1839+ msg .msg_iov = vec -> iovs ;
1840+ msg .msg_iovlen = vec -> count ;
1841+
1842+ #if (NGX_HAVE_MSGHDR_MSG_CONTROL )
1843+
1844+ if (c -> listening && c -> listening -> wildcard && c -> local_sockaddr ) {
1845+
1846+ #if (NGX_HAVE_IP_SENDSRCADDR )
1847+
1848+ if (c -> local_sockaddr -> sa_family == AF_INET ) {
1849+ struct cmsghdr * cmsg ;
1850+ struct in_addr * addr ;
1851+ struct sockaddr_in * sin ;
1852+
1853+ msg .msg_control = & msg_control ;
1854+ msg .msg_controllen = sizeof (msg_control );
1855+
1856+ cmsg = CMSG_FIRSTHDR (& msg );
1857+ cmsg -> cmsg_level = IPPROTO_IP ;
1858+ cmsg -> cmsg_type = IP_SENDSRCADDR ;
1859+ cmsg -> cmsg_len = CMSG_LEN (sizeof (struct in_addr ));
1860+
1861+ sin = (struct sockaddr_in * ) c -> local_sockaddr ;
1862+
1863+ addr = (struct in_addr * ) CMSG_DATA (cmsg );
1864+ * addr = sin -> sin_addr ;
1865+ }
1866+
1867+ #elif (NGX_HAVE_IP_PKTINFO )
1868+
1869+ if (c -> local_sockaddr -> sa_family == AF_INET ) {
1870+ struct cmsghdr * cmsg ;
1871+ struct in_pktinfo * pkt ;
1872+ struct sockaddr_in * sin ;
1873+
1874+ msg .msg_control = & msg_control ;
1875+ msg .msg_controllen = sizeof (msg_control );
1876+
1877+ cmsg = CMSG_FIRSTHDR (& msg );
1878+ cmsg -> cmsg_level = IPPROTO_IP ;
1879+ cmsg -> cmsg_type = IP_PKTINFO ;
1880+ cmsg -> cmsg_len = CMSG_LEN (sizeof (struct in_pktinfo ));
1881+
1882+ sin = (struct sockaddr_in * ) c -> local_sockaddr ;
1883+
1884+ pkt = (struct in_pktinfo * ) CMSG_DATA (cmsg );
1885+ ngx_memzero (pkt , sizeof (struct in_pktinfo ));
1886+ pkt -> ipi_spec_dst = sin -> sin_addr ;
1887+ }
1888+
1889+ #endif
1890+
1891+ #if (NGX_HAVE_INET6 && NGX_HAVE_IPV6_RECVPKTINFO )
1892+
1893+ if (c -> local_sockaddr -> sa_family == AF_INET6 ) {
1894+ struct cmsghdr * cmsg ;
1895+ struct in6_pktinfo * pkt6 ;
1896+ struct sockaddr_in6 * sin6 ;
1897+
1898+ msg .msg_control = & msg_control6 ;
1899+ msg .msg_controllen = sizeof (msg_control6 );
1900+
1901+ cmsg = CMSG_FIRSTHDR (& msg );
1902+ cmsg -> cmsg_level = IPPROTO_IPV6 ;
1903+ cmsg -> cmsg_type = IPV6_PKTINFO ;
1904+ cmsg -> cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo ));
1905+
1906+ sin6 = (struct sockaddr_in6 * ) c -> local_sockaddr ;
1907+
1908+ pkt6 = (struct in6_pktinfo * ) CMSG_DATA (cmsg );
1909+ ngx_memzero (pkt6 , sizeof (struct in6_pktinfo ));
1910+ pkt6 -> ipi6_addr = sin6 -> sin6_addr ;
1911+ }
1912+
1913+ #endif
1914+ }
1915+
1916+ #endif
1917+
1918+ eintr :
1919+
1920+ n = sendmsg (c -> fd , & msg , 0 );
1921+
1922+ ngx_log_debug4 (NGX_LOG_DEBUG_EVENT , c -> log , 0 ,
1923+ "sendto: fd:%d %z of %uz to \"%V\"" ,
1924+ c -> fd , n , vec -> size , & c -> addr_text );
1925+ if (n == -1 ) {
1926+ err = ngx_errno ;
1927+
1928+ switch (err ) {
1929+ case NGX_EAGAIN :
1930+ ngx_log_debug0 (NGX_LOG_DEBUG_EVENT , c -> log , err ,
1931+ "sendmsg() not ready" );
1932+ return NGX_AGAIN ;
1933+
1934+ case NGX_EINTR :
1935+ ngx_log_debug0 (NGX_LOG_DEBUG_EVENT , c -> log , err ,
1936+ "sendmsg() was interrupted" );
1937+ goto eintr ;
1938+
1939+ default :
1940+ c -> write -> error = 1 ;
1941+ ngx_connection_error (c , err , "sendmsg() failed" );
1942+ return NGX_ERROR ;
1943+ }
1944+ }
1945+
1946+ return n ;
1947+ }
1948+
18001949/* vi:set ft=c ts=4 sw=4 et fdm=marker: */
0 commit comments