Changeset 21308 for trunk/src/wsock32/wsock32.cpp
- Timestamp:
- Jun 18, 2009, 6:27:45 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wsock32/wsock32.cpp
r9887 r21308 55 55 #include <winuser32.h> 56 56 #include <wprocess.h> 57 #include <misc.h> 57 #include <dbglog.h> 58 59 #include <sys/types.h> 60 #include <sys/socket.h> 61 #include <net/if.h> 58 62 59 63 #include "wsock32.h" … … 212 216 strcpy(msg, "WSAEHOSTUNREACH"); 213 217 break; 218 case WSAETIMEDOUT: 219 strcpy(msg, "WSAETIMEDOUT"); 220 break; 214 221 default: 215 222 strcpy(msg, "unknown"); … … 663 670 664 671 if(ret == SOCKET_ERROR) { 665 WSASetLastError(wsaErrno()); 666 return SOCKET_ERROR; 672 if(wsaErrno() == WSAEWOULDBLOCK) { 673 struct timeval tv; 674 int optlen = sizeof(tv); 675 ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen); 676 if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) { 677 dprintf(("WSAEWOULDBLOCK: recv timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec)); 678 WSASetLastError(WSAETIMEDOUT); 679 } 680 else WSASetLastError(WSAEWOULDBLOCK); 681 ret = SOCKET_ERROR; 682 } 683 else WSASetLastError(wsaErrno()); 667 684 } 668 685 else … … 684 701 else 685 702 if(state & SS_ISCONNECTED && flags != MSG_PEEK) { 686 dprintf(("recv returned 0, but socket is still connected -> return WSA WOULDBLOCK"));703 dprintf(("recv returned 0, but socket is still connected -> return WSAEWOULDBLOCK")); 687 704 WSASetLastError(WSAEWOULDBLOCK); 688 705 return SOCKET_ERROR; … … 699 716 } 700 717 701 //Reset FD_READ event flag forWSAAsyncSelect thread if one was created for this socket718 //Reset FD_READ event flag for WSAAsyncSelect thread if one was created for this socket 702 719 EnableAsyncEvent(s, FD_READ); 703 720 return ret; … … 732 749 733 750 if(ret == SOCKET_ERROR) { 734 WSASetLastError(wsaErrno()); 751 if(wsaErrno() == WSAEWOULDBLOCK) { 752 struct timeval tv; 753 int optlen = sizeof(tv); 754 ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen); 755 if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) { 756 dprintf(("WSAEWOULDBLOCK: recvfrom timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec)); 757 WSASetLastError(WSAETIMEDOUT); 758 } 759 else WSASetLastError(WSAEWOULDBLOCK); 760 ret = SOCKET_ERROR; 761 } 762 else WSASetLastError(wsaErrno()); 735 763 } 736 764 else { … … 789 817 790 818 if(ret == SOCKET_ERROR) { 791 WSASetLastError(wsaErrno()); 819 if(wsaErrno() == WSAEWOULDBLOCK) { 820 struct timeval tv; 821 int optlen = sizeof(tv); 822 ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen); 823 if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) { 824 dprintf(("WSAEWOULDBLOCK: send timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec)); 825 WSASetLastError(WSAETIMEDOUT); 826 } 827 else WSASetLastError(WSAEWOULDBLOCK); 828 ret = SOCKET_ERROR; 829 } 830 else WSASetLastError(wsaErrno()); 792 831 } 793 832 else WSASetLastError(NO_ERROR); … … 844 883 845 884 if(ret == SOCKET_ERROR) { 846 WSASetLastError(wsaErrno()); 885 if(wsaErrno() == WSAEWOULDBLOCK) { 886 struct timeval tv; 887 int optlen = sizeof(tv); 888 ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen); 889 if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) { 890 dprintf(("WSAEWOULDBLOCK: sendto timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec)); 891 WSASetLastError(WSAETIMEDOUT); 892 } 893 else WSASetLastError(WSAEWOULDBLOCK); 894 ret = SOCKET_ERROR; 895 } 896 else WSASetLastError(wsaErrno()); 847 897 } 848 898 else WSASetLastError(NO_ERROR); … … 906 956 907 957 sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept)); 908 if(readfds ) {958 if(readfds && nrread) { 909 959 memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET)); 910 960 } 911 if(writefds ) {961 if(writefds && nrwrite) { 912 962 memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET)); 913 963 } 914 if(exceptfds ) {964 if(exceptfds && nrexcept) { 915 965 memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET)); 916 966 } … … 940 990 for(i=0;i<nrread;i++) { 941 991 if(socktmp[i] != -1) { 942 readfds->fd_array[i] = socktmp[i]; 992 readfds->fd_array[j] = socktmp[i]; 993 dprintf(("Socket %d read pending", socktmp[i])); 943 994 j++; 944 995 } … … 952 1003 for(i=0;i<nrwrite;i++) { 953 1004 if(socktmp[i] != -1) { 954 writefds->fd_array[i] = socktmp[i]; 1005 writefds->fd_array[j] = socktmp[i]; 1006 dprintf(("Socket %d write pending", socktmp[i])); 955 1007 j++; 956 1008 } … … 963 1015 for(i=0;i<nrexcept;i++) { 964 1016 if(socktmp[i] != -1) { 965 exceptfds->fd_array[ i] = socktmp[i];1017 exceptfds->fd_array[j] = socktmp[i]; 966 1018 j++; 967 1019 } … … 984 1036 return ret; 985 1037 } 1038 #ifdef DEBUG_LOGGING 1039 //****************************************************************************** 1040 //****************************************************************************** 1041 char *debugsockopt(int optname) 1042 { 1043 switch(optname) { 1044 case SO_DONTLINGER: 1045 return "SO_DONTLINGER"; 1046 case SO_LINGER: 1047 return "SO_LINGER"; 1048 case SO_REUSEADDR: 1049 return "SO_REUSEADDR"; 1050 case SO_SNDTIMEO: 1051 return "SO_SNDTIMEO"; 1052 case SO_RCVTIMEO: 1053 return "SO_RCVTIMEO"; 1054 case SO_SNDBUF: 1055 return "SO_SNDBUF"; 1056 case SO_RCVBUF: 1057 return "SO_RCVBUF"; 1058 case SO_BROADCAST: 1059 return "SO_BROADCAST"; 1060 case SO_DEBUG: 1061 return "SO_DEBUG"; 1062 case SO_KEEPALIVE: 1063 return "SO_KEEPALIVE"; 1064 case SO_DONTROUTE: 1065 return "SO_DONTROUTE"; 1066 case SO_OOBINLINE: 1067 return "SO_OOBINLINE"; 1068 case SO_TYPE: 1069 return "SO_TYPE"; 1070 case SO_ERROR: 1071 return "SO_ERROR"; 1072 case SO_SNDLOWAT: 1073 return "SO_SNDLOWAT"; 1074 case SO_RCVLOWAT: 1075 return "SO_RCVLOWAT"; 1076 case SO_USELOOPBACK: 1077 return "SO_USELOOPBACK"; 1078 case SO_ACCEPTCONN: 1079 return "SO_ACCEPTCONN"; 1080 default: 1081 return "unknown option"; 1082 } 1083 } 1084 #endif 986 1085 //****************************************************************************** 987 1086 //****************************************************************************** … … 1064 1163 case SO_SNDTIMEO: 1065 1164 case SO_RCVTIMEO: 1165 { 1166 if(optlen < (int)sizeof(int)) 1167 { 1168 dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small")); 1169 WSASetLastError(WSAEFAULT); 1170 return SOCKET_ERROR; 1171 } 1066 1172 // convert "int" to "struct timeval" 1067 1173 struct timeval tv; 1068 tv.tv_sec = *optval / 1000; 1069 tv.tv_usec = (*optval % 1000) * 1000; 1174 tv.tv_sec = (*(int *)optval) / 1000; 1175 tv.tv_usec = ((*(int *)optval) % 1000) * 1000; 1176 if(optname == SO_SNDTIMEO) { 1177 dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec)); 1178 } 1179 else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec)); 1180 1070 1181 ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) ); 1071 1182 break; 1183 } 1184 1185 case SO_REUSEADDR: 1186 if(optlen < (int)sizeof(int)) { 1187 dprintf(("SO_REUSEADDR, optlen too small")); 1188 WSASetLastError(WSAEFAULT); 1189 return SOCKET_ERROR; 1190 } 1191 dprintf(("option SO_REUSEADDR value %d", *(int *)optval)); 1192 ret = setsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen); 1193 if(ret) { 1194 dprintf(("setsockopt SO_REUSEADDR failed!!")); 1195 } 1196 ret = setsockopt(s, level, SO_REUSEPORT_OS2, (char *)optval, optlen); 1197 if(ret) { 1198 dprintf(("setsockopt SO_REUSEPORT failed!!")); 1199 } 1200 break; 1072 1201 1073 1202 case SO_BROADCAST: … … 1076 1205 case SO_DONTROUTE: 1077 1206 case SO_OOBINLINE: 1078 case SO_REUSEADDR: 1207 case SO_ERROR: 1208 case SO_SNDLOWAT: 1209 case SO_RCVLOWAT: 1210 case SO_ACCEPTCONN: 1211 case SO_USELOOPBACK: 1079 1212 if(optlen < (int)sizeof(int)) { 1080 dprintf((" SOL_SOCKET, SO_REUSEADDR, optlen too small"));1213 dprintf(("%s optlen too small", debugsockopt(optname))); 1081 1214 WSASetLastError(WSAEFAULT); 1082 1215 return SOCKET_ERROR; 1083 1216 } 1217 dprintf(("option %s = %x", debugsockopt(optname), *(int *)optval)); 1084 1218 ret = setsockopt(s, level, optname, (char *)optval, optlen); 1085 1219 break; … … 1153 1287 { 1154 1288 u_int flLoop; 1155 if (optlen < sizeof(u_ char))1289 if (optlen < sizeof(u_int)) 1156 1290 { 1157 1291 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small")); … … 1161 1295 flLoop = (*optval == 0) ? 0 : 1; 1162 1296 dprintf(("IP_MULTICAST_LOOP %d", *optval)); 1163 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);1297 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, sizeof(u_char)); 1164 1298 break; 1165 1299 } … … 1167 1301 case IP_MULTICAST_TTL: 1168 1302 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2): 1169 if (optlen < sizeof(u_ char))1303 if (optlen < sizeof(u_int)) 1170 1304 { 1171 1305 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small")); … … 1173 1307 return SOCKET_ERROR; 1174 1308 } 1175 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen); 1309 dprintf(("IP_MULTICAST_TTL %d", *optval)); 1310 ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, sizeof(u_char)); 1176 1311 break; 1177 1312 … … 1210 1345 dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", val)); 1211 1346 ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&val, optlen); 1347 break; 1348 1349 case IP_DONTFRAGMENT: 1350 case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2): 1351 //MSDN says these options are silently ignored 1352 dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored")); 1353 ret = 0; 1212 1354 break; 1213 1355 … … 1269 1411 break; 1270 1412 1413 case SO_REUSEADDR: 1414 if(optlen == NULL || *optlen < sizeof(int)) { 1415 WSASetLastError(WSAEFAULT); 1416 return SOCKET_ERROR; 1417 } 1418 ret = getsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen); 1419 dprintf(("getsockopt SO_REUSEADDR returned %d", *(int *)optval, optname)); 1420 break; 1421 break; 1422 1423 case SO_SNDTIMEO: 1424 case SO_RCVTIMEO: 1425 { 1426 if(optlen == NULL || *optlen < sizeof(int)) 1427 { 1428 dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small")); 1429 WSASetLastError(WSAEFAULT); 1430 return SOCKET_ERROR; 1431 } 1432 struct timeval tv; 1433 int size = sizeof(tv); 1434 ret = getsockopt(s, level, optname, (char *)&tv, &size ); 1435 1436 // convert "struct timeval" to "int" 1437 *(int *)optval = (tv.tv_sec * 1000) + tv.tv_usec/1000; 1438 if(optname == SO_SNDTIMEO) { 1439 dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec)); 1440 } 1441 else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec)); 1442 1443 break; 1444 } 1445 1271 1446 case SO_SNDBUF: 1272 1447 case SO_RCVBUF: … … 1276 1451 case SO_DONTROUTE: 1277 1452 case SO_OOBINLINE: 1278 case SO_REUSEADDR:1279 1453 case SO_TYPE: 1454 case SO_ERROR: 1455 case SO_SNDLOWAT: 1456 case SO_RCVLOWAT: 1457 case SO_USELOOPBACK: 1280 1458 if(optlen == NULL || *optlen < sizeof(int)) { 1281 1459 WSASetLastError(WSAEFAULT); … … 1283 1461 } 1284 1462 ret = getsockopt(s, level, optname, (char *)optval, optlen); 1463 dprintf(("getsockopt %s returned %d", debugsockopt(optname), *(int *)optval)); 1285 1464 break; 1465 1286 1466 case SO_ACCEPTCONN: 1287 1467 if(optlen == NULL || *optlen < sizeof(int)) { … … 1294 1474 *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN; 1295 1475 *optlen = sizeof(BOOL); 1476 dprintf(("SO_ACCEPTCONN returned %d", *(BOOL *)optval)); 1296 1477 } 1297 1478 break; … … 1357 1538 break; 1358 1539 1540 case IP_MULTICAST_LOOP_WS2: //for buggy applications that intended to call ws_32.getsockopt 1359 1541 case IP_MULTICAST_LOOP: 1360 1542 case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2): 1361 1543 { 1362 if (*optlen < sizeof(u_ char))1544 if (*optlen < sizeof(u_int)) 1363 1545 { 1364 1546 dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small")); … … 1366 1548 return SOCKET_ERROR; 1367 1549 } 1550 memset(optval, 0, *optlen); 1368 1551 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen); 1369 1552 break; … … 1372 1555 case IP_MULTICAST_TTL: 1373 1556 case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2): 1374 if (*optlen < sizeof(u_ char))1557 if (*optlen < sizeof(u_int)) 1375 1558 { 1376 1559 dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small")); … … 1378 1561 return SOCKET_ERROR; 1379 1562 } 1563 memset(optval, 0, *optlen); 1380 1564 ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen); 1565 dprintf(("getsockopt IP_MULTICAST_TTL_OS2 returned %d, size %d", (int)*optval, *optlen)); 1381 1566 break; 1382 1567 … … 1389 1574 return SOCKET_ERROR; 1390 1575 } 1576 memset(optval, 0, *optlen); 1391 1577 ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen); 1392 1578 break; … … 1415 1601 } 1416 1602 break; 1603 1604 case IP_DONTFRAGMENT: 1605 case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2): 1606 //MSDN says these options are silently ignored 1607 if (*optlen < sizeof(u_int)) 1608 { 1609 dprintf(("IP_DONTFRAGMENT, IP_DONTFRAGMENT_WS2, optlen too small")); 1610 WSASetLastError(WSAEFAULT); 1611 return SOCKET_ERROR; 1612 } 1613 dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored")); 1614 *optlen = sizeof(u_int); 1615 *(int *)optval = 0; 1616 ret = 0; 1617 break; 1618 1417 1619 1418 1620 default: … … 1481 1683 // I.e. start ISDNPM without dialing in. gethostbyname will query 1482 1684 // each name server and retry several times (60+ seconds per name server) 1685 // 1686 static struct ws_hostent localhost; 1687 static DWORD localhost_address; 1688 static DWORD localhost_addrlist[2] = {(DWORD)&localhost_address, 0}; 1689 static DWORD localhost_aliaslist[1] = {0}; 1483 1690 //****************************************************************************** 1484 1691 ODINFUNCTION1(ws_hostent *,OS2gethostbyname, … … 1493 1700 1494 1701 dprintf(("gethostbyname %s", name)); 1495 if (gethostname(localhostname, sizeof(localhostname)) == NO_ERROR)1702 if (!gethostname(localhostname, sizeof(localhostname))) 1496 1703 { 1497 if(!strcmp(name, localhostname)) { 1704 /* 1705 * This is a fast non-blocking path for the hostname of this machine. 1706 * It's probably not 100% correct though.. 1707 */ 1708 if (!strcmp(name, localhostname)) 1709 { 1710 /* 1711 * Lookup lan0 address, and move on to lo address if that fails. 1712 */ 1713 sock_init(); /* ??? */ 1714 int s = socket(PF_INET, SOCK_STREAM, 0); 1715 if (s >= 0) 1716 { 1717 struct ifreq ifr = {0}; 1718 strcpy(ifr.ifr_name, "lan0"); 1719 int rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr)); 1720 if (rc == -1) 1721 { 1722 strcpy(ifr.ifr_name, "lo"); 1723 rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr)); 1724 } 1725 soclose(s); 1726 1727 if (rc != -1) 1728 { 1729 /* ASSUMES: family is AF_INET */ 1730 /* Doesn't work with aliases on lan0. */ 1731 struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr; 1732 1733 localhost_address = *(unsigned long *)&addr->sin_addr; 1734 localhost.h_name = "localhost"; /* This is what the old workaround did. */ 1735 localhost.h_addrtype = AF_INET; 1736 localhost.h_length = 4; 1737 localhost.h_addr_list = (char **)&localhost_addrlist[0]; 1738 localhost.h_aliases = (char **)&localhost_aliaslist[0]; 1739 WSASetLastError(NO_ERROR); 1740 return &localhost; 1741 } 1742 } 1743 1744 /* 1745 * bail out.. 1746 */ 1498 1747 strcpy(localhostname, "localhost"); 1499 1748 name = localhostname;
Note:
See TracChangeset
for help on using the changeset viewer.