Changeset 52154 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Jul 23, 2014 6:14:33 PM (11 years ago)
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/socket.c
r51137 r52154 35 35 #include <iphlpapi.h> 36 36 #include <icmpapi.h> 37 #endif 38 39 #if defined(DECLARE_IOVEC) && defined(RT_OS_WINDOWS) 40 AssertCompileMembersSameSizeAndOffset(struct iovec, iov_base, WSABUF, buf); 41 AssertCompileMembersSameSizeAndOffset(struct iovec, iov_len, WSABUF, len); 37 42 #endif 38 43 … … 805 810 sorecvfrom(PNATState pData, struct socket *so) 806 811 { 807 ssize_t ret = 0;808 struct sockaddr_in addr;809 socklen_t addrlen = sizeof(struct sockaddr_in);810 811 812 LogFlowFunc(("sorecvfrom: so = %lx\n", (long)so)); 812 813 … … 823 824 else 824 825 { 826 static uint8_t au8Buf[64 * 1024]; 827 825 828 /* A "normal" UDP packet */ 829 struct sockaddr_in addr; 830 socklen_t addrlen = sizeof(struct sockaddr_in); 831 struct iovec iov[2]; 832 ssize_t nread; 826 833 struct mbuf *m; 827 ssize_t len;828 u_long n = 0;829 int rc = 0;830 static int signalled = 0;831 char *pchBuffer = NULL;832 bool fWithTemporalBuffer = false;833 834 834 835 QSOCKET_LOCK(udb); … … 836 837 QSOCKET_UNLOCK(udb); 837 838 838 /*How many data has been received ?*/839 /*840 * 1. calculate how much we can read841 * 2. read as much as possible842 * 3. attach buffer to allocated header mbuf843 */844 rc = ioctlsocket(so->s, FIONREAD, &n);845 if (rc == -1)846 {847 if ( soIgnorableErrorCode(errno)848 || errno == ENOTCONN)849 return;850 else if (signalled == 0)851 {852 LogRel(("NAT: can't fetch amount of bytes on socket %R[natsock], so message will be truncated.\n", so));853 signalled = 1;854 }855 return;856 }857 858 len = sizeof(struct udpiphdr);859 839 m = m_getjcl(pData, M_NOWAIT, MT_HEADER, M_PKTHDR, slirp_size(pData)); 860 840 if (m == NULL) 841 { 842 SOCKET_UNLOCK(so); 861 843 return; 862 863 len += n; 844 } 845 864 846 m->m_data += ETH_HLEN; 865 847 m->m_pkthdr.header = mtod(m, void *); 848 866 849 m->m_data += sizeof(struct udpiphdr); 867 850 868 pchBuffer = mtod(m, char *); 869 fWithTemporalBuffer = false; 870 /* 871 * Even if amounts of bytes on socket is greater than MTU value 872 * Slirp will able fragment it, but we won't create temporal location 873 * here. 874 */ 875 if (n > (slirp_size(pData) - sizeof(struct udpiphdr))) 876 { 877 pchBuffer = RTMemAlloc((n) * sizeof(char)); 878 if (!pchBuffer) 851 /* small packets will fit without copying */ 852 iov[0].iov_base = mtod(m, char *); 853 iov[0].iov_len = M_TRAILINGSPACE(m); 854 855 /* large packets will spill into a temp buffer */ 856 iov[1].iov_base = au8Buf; 857 iov[1].iov_len = sizeof(au8Buf); 858 859 #if !defined(RT_OS_WINDOWS) 860 { 861 struct msghdr mh; 862 memset(&mh, 0, sizeof(mh)); 863 864 mh.msg_iov = iov; 865 mh.msg_iovlen = 2; 866 mh.msg_name = &addr; 867 mh.msg_namelen = addrlen; 868 869 nread = recvmsg(so->s, &mh, 0); 870 } 871 #else /* RT_OS_WINDOWS */ 872 { 873 DWORD nbytes; /* NB: can't use nread b/c of different size */ 874 DWORD flags; 875 int status; 876 877 flags = 0; 878 status = WSARecvFrom(so->s, iov, 2, &nbytes, &flags, 879 (struct sockaddr *)&addr, &addrlen, 880 NULL, NULL); 881 nread = (status != SOCKET_ERROR) ? nbytes : -1; 882 } 883 #endif 884 if (nread >= 0) 885 { 886 if (nread <= iov[0].iov_len) 887 m->m_len = nread; 888 else 879 889 { 880 m _freem(pData, m);881 return;890 m->m_len = iov[0].iov_len; 891 m_append(pData, m, nread - iov[0].iov_len, iov[1].iov_base); 882 892 } 883 fWithTemporalBuffer = true; 884 } 885 ret = recvfrom(so->s, pchBuffer, n, 0, 886 (struct sockaddr *)&addr, &addrlen); 887 if (fWithTemporalBuffer) 888 { 889 if (ret > 0) 890 { 891 m_copyback(pData, m, 0, ret, pchBuffer); 892 /* 893 * If we've met comporison below our size prediction was failed 894 * it's not fatal just we've allocated for nothing. (@todo add counter here 895 * to calculate how rare we here) 896 */ 897 if(ret < slirp_size(pData) && !m->m_next) 898 Log(("NAT:udp: Expected size(%d) lesser than real(%d) and less minimal mbuf size(%d)\n", 899 n, ret, slirp_size(pData))); 900 } 901 /* we're freeing buffer anyway */ 902 RTMemFree(pchBuffer); 903 } 904 else 905 m->m_len = ret; 906 907 if (ret < 0) 908 { 909 u_char code = ICMP_UNREACH_PORT; 910 911 if (errno == EHOSTUNREACH) 912 code = ICMP_UNREACH_HOST; 913 else if (errno == ENETUNREACH) 914 code = ICMP_UNREACH_NET; 915 916 m_freem(pData, m); 917 if ( soIgnorableErrorCode(errno) 918 || errno == ENOTCONN) 919 { 920 return; 921 } 922 923 Log2((" rx error, tx icmp ICMP_UNREACH:%i\n", code)); 924 icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno)); 925 so->so_m = NULL; 926 } 927 else 928 { 929 Assert((m_length(m,NULL) == ret)); 893 Assert((m_length(m, NULL) == nread)); 894 930 895 /* 931 896 * Hack: domain name lookup will be used the most for UDP, … … 939 904 so->so_expire = curtime + SO_EXPIRE; 940 905 } 906 941 907 /* 942 908 * last argument should be changed if Slirp will inject IP attributes … … 947 913 dnsproxy_answer(pData, so, m); 948 914 949 #if 0950 if (m->m_len == len)951 {952 m_inc(m, MINCSIZE);953 m->m_len = 0;954 }955 #endif956 957 915 /* packets definetly will be fragmented, could confuse receiver peer. */ 958 if ( m_length(m, NULL)> if_mtu)916 if (nread > if_mtu) 959 917 m->m_flags |= M_SKIP_FIREWALL; 918 960 919 /* 961 920 * If this packet was destined for CTL_ADDR, … … 963 922 */ 964 923 udp_output(pData, so, m, &addr); 965 SOCKET_UNLOCK(so); 966 } /* rx error */ 967 } /* if ping packet */ 924 } 925 else 926 { 927 m_freem(pData, m); 928 so->so_m = NULL; 929 930 if (!soIgnorableErrorCode(errno)) 931 { 932 u_char code; 933 if (errno == EHOSTUNREACH) 934 code = ICMP_UNREACH_HOST; 935 else if (errno == ENETUNREACH) 936 code = ICMP_UNREACH_NET; 937 else 938 code = ICMP_UNREACH_PORT; 939 940 Log2((" rx error, tx icmp ICMP_UNREACH:%i\n", code)); 941 icmp_error(pData, so->so_m, ICMP_UNREACH, code, 0, strerror(errno)); 942 } 943 } 944 945 SOCKET_UNLOCK(so); 946 } 968 947 } 969 948 -
trunk/src/VBox/Devices/Network/slirp/socket.h
r44528 r52154 158 158 159 159 #if defined(DECLARE_IOVEC) && !defined(HAVE_READV) 160 # if !defined(RT_OS_WINDOWS) 160 161 struct iovec 161 162 { … … 163 164 size_t iov_len; 164 165 }; 166 # else 167 /* make it congruent with WSABUF */ 168 struct iovec 169 { 170 ULONG iov_len; 171 char *iov_base; 172 }; 173 # endif 165 174 #endif 166 175
Note:
See TracChangeset
for help on using the changeset viewer.