Vault  4.1
vsocket_platform.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved.
00003 This file is part of the Code Vault version 4.1
00004 http://www.bombaydigital.com/
00005 License: MIT. See LICENSE.md in the Vault top level directory.
00006 */
00007 
00010 #include "vsocket.h"
00011 
00012 #include "vexception.h"
00013 
00014 #include <signal.h>
00015 
00016 #ifdef sun
00017 #include <sys/proc.h>
00018 #endif
00019 
00020 #include <sys/ioctl.h>
00021 #include <ifaddrs.h>
00022 
00023 // static
00024 bool VSocket::_platform_staticInit() {
00025     //lint -e421 -e923 " Caution -- function 'signal(int, void (*)(int))' is considered dangerous [MISRA Rule 123]"
00026     ::signal(SIGPIPE, SIG_IGN);
00027 
00028     // Should log the error if the call failed.
00029 
00030     return true;
00031 }
00032 
00033 // static
00034 VNetworkInterfaceList VSocket::_platform_enumerateNetworkInterfaces() {
00035     VNetworkInterfaceList interfaces;
00036     struct ifaddrs* interfacesDataPtr = NULL;
00037     int result = ::getifaddrs(&interfacesDataPtr);
00038     if (result != 0) {
00039         throw VStackTraceException(VSystemError::getSocketError(), VSTRING_FORMAT("VSocket::enumerateNetworkInterfaces: getifaddrs() failed with result %d.", result));
00040     }
00041 
00042     struct ifaddrs* intfPtr = interfacesDataPtr;
00043     while (intfPtr != NULL) {
00044         if (intfPtr->ifa_addr != NULL) {
00045             VNetworkInterfaceInfo info;
00046             info.mFamily = intfPtr->ifa_addr->sa_family;
00047             info.mName.copyFromCString(intfPtr->ifa_name);
00048             // AF_INET6 will work just fine here, too. But hold off until we can verify callers can successfully use IPV6 address strings to listen, connect, etc.
00049             if ((info.mFamily == AF_INET) && (info.mName != "lo0")) { // Internet interfaces only, and skip the loopback address.
00050                 info.mAddress.preflight(255);
00051                 char* buffer = info.mAddress.buffer();
00052                 ::inet_ntop(intfPtr->ifa_addr->sa_family, &((struct sockaddr_in*) intfPtr->ifa_addr)->sin_addr, buffer, 255);
00053                 info.mAddress.postflight((int) ::strlen(buffer));
00054 
00055                 // Check for "lo0" above should filter out 127.x.x.x (loopback addresses), but in case it doesn't, check it.
00056                 if (! info.mAddress.startsWith("127.")) {
00057                     interfaces.push_back(info);
00058                 }
00059             }
00060         }
00061 
00062         intfPtr = intfPtr->ifa_next;
00063     }
00064 
00065     ::freeifaddrs(interfacesDataPtr);
00066     return interfaces;
00067 }
00068 
00069 static const int MAX_ADDRSTRLEN = V_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN);
00070 // static
00071 VString VSocket::_platform_addrinfoToIPAddressString(const VString& hostName, const struct addrinfo* info) {
00072     void* addr;
00073     if (info->ai_family == AF_INET) {
00074         addr = (void*) &(((struct sockaddr_in*)info->ai_addr)->sin_addr);
00075     } else if (info->ai_family == AF_INET6) {
00076         addr = (void*) &(((struct sockaddr_in6*)info->ai_addr)->sin6_addr);
00077     } else {
00078         // We don't know how to access the addr for other family types. They could conceivably be added.
00079         throw VException(VSTRING_FORMAT("VSocket::_platform_addrinfoToIPAddressString(%s): An invalid family (%d) other than AF_INET or AF_INET6 was specified.", hostName.chars(), info->ai_family));
00080     }
00081 
00082     VString result;
00083     result.preflight(MAX_ADDRSTRLEN);
00084     const char* buf = ::inet_ntop(info->ai_family, addr, result.buffer(), MAX_ADDRSTRLEN);
00085     if (buf == NULL) {
00086         throw VException(VSystemError::getSocketError(), VSTRING_FORMAT("VSocket::_platform_addrinfoToIPAddressString(%s): inet_ntop() failed.", hostName.chars()));
00087     }
00088     result.postflight((int) ::strlen(buf));
00089 
00090     return result;
00091 }
00092 
00093 // static
00094 bool VSocket::_platform_isSocketIDValid(VSocketID socketID) {
00095     // On Unix:
00096     // -1 is typical error return value from ::socket()
00097     // Also, FD_SETSIZE is max num open sockets, sockid over that is sign of a big problem, and would cause FD_SET() during read() to fail.
00098     return (socketID >= 0) && (socketID <= FD_SETSIZE);
00099 }
00100 
00101 int VSocket::_platform_available() {
00102     int numBytesAvailable = 0;
00103 
00104     int result = ::v_ioctlsocket(mSocketID, FIONREAD, &numBytesAvailable);
00105 
00106     if (result == -1) {
00107         throw VStackTraceException(VSystemError::getSocketError(), VSTRING_FORMAT("VSocket[%s] available: v_ioctlsocket() failed.", mSocketName.chars()));
00108     }
00109 
00110     return numBytesAvailable;
00111 }
00112 

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.