#include "precompile.h" #include "sockutil.h" #include "strutil.h" #include "dbgutil.h" //define replaced by cmake synatx // #if defined(_MSC_VER) #include #pragma comment(lib, "ws2_32.lib") #endif //_MSC_VER TOOLKIT_API int winsock_init() { WSADATA wsaData; return WSAStartup(0x0202, &wsaData); } TOOLKIT_API int winsock_term() { return WSACleanup(); } /* 1:require 0:option -1:forbid */ static int is_legal_ip(char* content) { int len = 0; if (content == NULL) { return -1; } len = strlen(content); if (len < strlen("0.0.0.0")) { return -1; } //99开头行内办公网,10开头行内业务网。规范出自《招商银行总行网络规范汇编(2017年版).pdf》 if (strstr(content, "99.") == content || strstr(content, "10.") == content) { return 1; } if (strcmp(content, "127.0.0.1") == 0 /*sipphone*/ || strcmp(content, "2.0.0.1") == 0 /*ConnecotrFSM*/ || strstr(content, "198.168.") == content /*sipphone 双网卡*/ ) { return -1; } return 0; } TOOLKIT_API int toolkit_getlocalip(char* buf, int len_of_buf) { char bak_buf[64]; #if defined(_MSC_VER) memset(bak_buf, 0, 64); struct hostent* ent = gethostbyname(NULL); if (ent && ent->h_addr_list[0] != NULL) { int i = 0; for (; ent->h_addr_list[i] != NULL; ++i) { char tmp[64]; int r; struct in_addr* in = (struct in_addr*)ent->h_addr_list[i]; memset(tmp, 0, 64); sprintf_s(tmp, 64, "%d.%d.%d.%d", in->S_un.S_un_b.s_b1, in->S_un.S_un_b.s_b2, in->S_un.S_un_b.s_b3, in->S_un.S_un_b.s_b4); r = is_legal_ip(tmp); if (r == 1) { memset(buf, 0, len_of_buf * sizeof(char)); strcpy(buf, tmp); return 0; } else if (r == 0 && strlen(bak_buf) == 0) { strcpy(bak_buf, tmp); } } #else // Same implements with: // * DeviceSimulator // * SipPhone // int sockfd = -1; struct ifconf ifconf; struct ifreq* ifreq = NULL; char strbuf[256] = { 0 }; int i; memset(bak_buf, 0, 64); ifconf.ifc_len = 256; ifconf.ifc_buf = strbuf; if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { if (ioctl(sockfd, SIOCGIFCONF, &ifconf) >= 0) { //get all socket info for (i = (ifconf.ifc_len / sizeof(struct ifreq)); i > 0; i--) { ifreq = (struct ifreq*)&ifconf.ifc_req[i]; if (ifreq->ifr_addr.sa_family == AF_INET) { //for ipv4 struct sockaddr_in* addr = (struct sockaddr_in*)&ifreq->ifr_addr; char tmp[INET_ADDRSTRLEN]; int r = 0; memset(tmp, 0, sizeof(tmp)); inet_ntop(AF_INET, &addr->sin_addr, tmp, INET_ADDRSTRLEN); r = is_legal_ip(tmp); if (r == 1) { memset(buf, 0, len_of_buf * sizeof(char)); strcpy(buf, tmp); close(sockfd); return 0; } else if (r == 0 && strlen(bak_buf) == 0) { strcpy(bak_buf, tmp); } } } } close(sockfd); #endif //_MSC_VER if (strlen(bak_buf) > 0) { memset(buf, 0, len_of_buf * sizeof(char)); strcpy(buf, bak_buf); return 0; } } return -1; } // < 0 : error // < n : timeout // ==n : ok TOOLKIT_API int tsend_n(int fd, const char *buf, int n, long timeout/* = -1 */) { struct timeval _tm; struct timeval *tm; int offset = 0; int left = n; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); while (left > 0 && (timeout == -1 || timeout > 0)) { int t = send(fd, buf+offset, left, 0); if (t == 0) { return offset; } else if (t < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set wr_fs; fd_set ex_fs; FD_ZERO(&wr_fs); FD_ZERO(&ex_fs); FD_SET(fd, &wr_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, NULL, &wr_fs, &ex_fs, tm); if (rc < 0) return -1; if (rc == 0) return offset; if (FD_ISSET(fd, &ex_fs)) return -1; TOOLKIT_ASSERT(FD_ISSET(fd, &wr_fs)); } else { return -1; } } else { // (t > 0) offset += t; left -= t; } } return offset; } TOOLKIT_API int trecv_n(int fd, char *buf, size_t n, long timeout/* = -1*/) { struct timeval _tm; struct timeval *tm; int offset = 0; int left = n; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); while (left > 0 && (timeout == -1 || timeout > 0)) { int t = recv(fd, buf+offset, left, 0); if (t == 0) { return offset; } else if (t < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set rd_fs; fd_set ex_fs; FD_ZERO(&rd_fs); FD_ZERO(&ex_fs); FD_SET(fd, &rd_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, &rd_fs, NULL, &ex_fs, tm); if (rc < 0) return -1; if (rc == 0) return offset; if (FD_ISSET(fd, &ex_fs)) return -1; TOOLKIT_ASSERT(FD_ISSET(fd, &rd_fs)); } else { return -1; } } else { offset += t; left -= t; } } return offset; } TOOLKIT_API int trecv_until(int fd, char *buf, int n, const char *delimer, int *header_len, long timeout) { struct timeval _tm; struct timeval *tm; int offset = 0; int left = n; DWORD dwLast; TOOLKIT_ASSERT(delimer); *header_len = 0; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); while (left > 0 && (timeout == -1 || timeout > 0)) { int t = recv(fd, buf+offset, left, 0); if (t == 0) { *header_len = 0; return offset; } else if (t < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set rd_fs; fd_set ex_fs; FD_ZERO(&rd_fs); FD_ZERO(&ex_fs); FD_SET(fd, &rd_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, &rd_fs, NULL, &ex_fs, tm); if (rc < 0) return -1; if (rc == 0) return offset; if (FD_ISSET(fd, &ex_fs)) return -1; TOOLKIT_ASSERT(FD_ISSET(fd, &rd_fs)); } else { return -1; } } else { const char *p; offset += t; left -= t; p = memstr(buf, offset, delimer); if (p) { p += strlen(delimer); *header_len = p - buf; return offset; } } } return offset; } TOOLKIT_API int tsend_until(int fd, const char *buf, int n, const char *delimer, long timeout) { const char *p; TOOLKIT_ASSERT(delimer); p = memstr(buf, n, delimer); if (!p) return -1; p += strlen(delimer); return tsend_n(fd, buf, p - buf, timeout); } #ifndef SIO_UDP_CONNRESET #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12) #endif TOOLKIT_API int disable_udp_connreset(SOCKET so) { DWORD dwBytesReturned = 0; BOOL bNewBehavior = FALSE; return WSAIoctl(so, SIO_UDP_CONNRESET, &bNewBehavior, sizeof(bNewBehavior), NULL, 0, &dwBytesReturned, NULL, NULL); } TOOLKIT_API int tsend_n_v(int fd, LPWSABUF lpBuffers, DWORD dwBufferCount, long timeout) { struct timeval _tm; struct timeval *tm; int sendedbufs = 0; int leftbufs = (int)dwBufferCount; int offset = 0; int sendedbytes = 0; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); while (leftbufs > 0 && (timeout == -1 || timeout > 0)) { DWORD dwSent = 0; int rc = WSASend(fd, lpBuffers+sendedbufs, leftbufs, &dwSent, 0, NULL, NULL); if (rc < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set wr_fs; fd_set ex_fs; FD_ZERO(&wr_fs); FD_ZERO(&ex_fs); FD_SET(fd, &wr_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, NULL, &wr_fs, &ex_fs, tm); if (rc < 0) return -1; if (rc == 0) return sendedbytes; if (FD_ISSET(fd, &ex_fs)) return -1; TOOLKIT_ASSERT(FD_ISSET(fd, &wr_fs)); } else { return -1; } } else { // (t > 0) if (dwSent == 0) return sendedbytes; sendedbytes += dwSent; while (dwSent > 0) { if (dwSent >= (lpBuffers[sendedbufs].len-offset)) { dwSent -= lpBuffers[sendedbufs].len-offset; sendedbufs++; leftbufs--; offset = 0; } else { lpBuffers[sendedbufs].buf += dwSent; lpBuffers[sendedbufs].len -= dwSent; dwSent = 0; } } } } return sendedbytes; } TOOLKIT_API int trecv_n_v(int fd, LPWSABUF lpBuffers, DWORD dwBufferCount, long timeout) { struct timeval _tm; struct timeval *tm; int recvedbufs = 0; int leftbufs = (int)dwBufferCount; int offset = 0; int recvedbytes = 0; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); while (leftbufs > 0 && (timeout == -1 || timeout > 0)) { DWORD dwRecv = 0; int rc = WSARecv(fd, lpBuffers+recvedbufs, leftbufs, &dwRecv, 0, NULL, NULL); if (rc < 0) { if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set rd_fs; fd_set ex_fs; FD_ZERO(&rd_fs); FD_ZERO(&ex_fs); FD_SET(fd, &rd_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, &rd_fs, NULL, &ex_fs, tm); if (rc < 0) return -1; if (rc == 0) return recvedbytes; if (FD_ISSET(fd, &ex_fs)) return -1; TOOLKIT_ASSERT(FD_ISSET(fd, &rd_fs)); } else { return -1; } } else { // (t > 0) if (dwRecv == 0) return recvedbytes; recvedbytes += dwRecv; while (dwRecv > 0) { if (dwRecv >= (lpBuffers[recvedbufs].len-offset)) { dwRecv -= lpBuffers[recvedbufs].len-offset; recvedbufs++; leftbufs--; offset = 0; } else { lpBuffers[recvedbufs].buf += dwRecv; lpBuffers[recvedbufs].len -= dwRecv; dwRecv = 0; } } } } return recvedbytes; } TOOLKIT_API int tsendto(int fd, const char *buf, int n, const struct sockaddr* to, int tolen, long timeout) { struct timeval _tm; struct timeval *tm; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); do { int rc = sendto(fd, buf, n, 0, to, tolen); if (rc >= 0) return rc; if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set wr_fs; fd_set ex_fs; FD_ZERO(&wr_fs); FD_ZERO(&ex_fs); FD_SET(fd, &wr_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, NULL, &wr_fs, &ex_fs, tm); if (rc <= 0) break; if (FD_ISSET(fd, &ex_fs)) break; TOOLKIT_ASSERT(FD_ISSET(fd, &wr_fs)); } else { break; } } while (timeout == -1 || timeout > 0); return -1; } TOOLKIT_API int trecvfrom(int fd, char *buf, int n, struct sockaddr* fromaddr, int *fromlen, long timeout) { struct timeval _tm; struct timeval *tm; DWORD dwLast; tm = (timeout >= 0) ? &_tm : NULL; if (tm) dwLast = GetTickCount(); do { int rc = recvfrom(fd, buf, n, 0, fromaddr, fromlen); if (rc >= 0) return rc; if (WSAGetLastError() == WSAEWOULDBLOCK) { int rc; fd_set rd_fs; fd_set ex_fs; FD_ZERO(&rd_fs); FD_ZERO(&ex_fs); FD_SET(fd, &rd_fs); FD_SET(fd, &ex_fs); if (tm) { DWORD dwNow = GetTickCount(); long diff = (long)(dwNow - dwLast); if (timeout >= diff) { timeout -= diff; } else { timeout = 0; } tm->tv_sec = timeout/1000; tm->tv_usec = timeout%1000; dwLast = dwNow; } rc = select(1, &rd_fs, NULL, &ex_fs, tm); if (rc <= 0) break; if (FD_ISSET(fd, &ex_fs)) break; TOOLKIT_ASSERT(FD_ISSET(fd, &rd_fs)); } else { break; } } while (timeout == -1 || timeout > 0); return -1; }