const Address* SocketChannel::GetLocalAddress() { if (NULL == m_localAddr) { try { // SocketHostAddress local = getHostAddress(m_fd); // NEW(m_localAddr, SocketHostAddress(local)); SocketInetAddress inet = get_socket_inet_address(m_fd); if (inet.IsUnix()) { SocketUnixAddress local = get_unix_address(inet); NEW(m_localAddr, SocketUnixAddress(local)); } else { SocketHostAddress local = get_host_address(inet); NEW(m_localAddr, SocketHostAddress(local)); } } catch (...) { } } return m_localAddr; }
const Address* SocketChannel::GetRemoteAddress() { if (NULL == m_remoteAddr) { try { SocketInetAddress inet = get_remote_inet_address(m_fd); if (inet.IsUnix()) { SocketUnixAddress remote = get_unix_address(inet); NEW(m_remoteAddr, SocketUnixAddress(remote)); } else { SocketHostAddress remote = get_host_address(inet); NEW(m_remoteAddr, SocketHostAddress(remote)); } } catch (...) { } } return m_remoteAddr; }
bool SocketChannel::DoBind(Address* local) { if (NULL == local) { return false; } SocketInetAddress addr; if (InstanceOf<SocketHostAddress>(local).OK) { SocketHostAddress* host_addr = static_cast<SocketHostAddress*>(local); addr = get_inet_address(host_addr->GetHost(), host_addr->GetPort()); } else if (InstanceOf<SocketInetAddress>(local).OK) { SocketInetAddress* inet_addr = static_cast<SocketInetAddress*>(local); addr = (*inet_addr); } else if (InstanceOf<SocketUnixAddress>(local).OK) { SocketUnixAddress* unix_addr = (SocketUnixAddress*) local; unlink(unix_addr->GetPath().c_str()); // in case it already exists addr = get_inet_address(*unix_addr); } else { return false; } if (addr.IsUnix()) { struct sockaddr_un* pun = (struct sockaddr_un*) &(addr.GetRawSockAddr()); DEBUG_LOG("Bind on %s", pun->sun_path); } int fd = GetSocketFD(addr.GetDomain()); if (0 == ::bind(fd, &(addr.GetRawSockAddr()), addr.GetRawSockAddrSize())) { return true; } int e = errno; ERROR_LOG("Failed to bind address for reason:%s", strerror(e)); return false; }
bool ServerSocketChannel::DoBind(Address* local) { if (m_fd > 0) { return true; } int on = 1; SocketInetAddress addr; if (InstanceOf<SocketHostAddress>(local).OK) { SocketHostAddress* host_addr = (SocketHostAddress*) local; addr = get_inet_address(host_addr->GetHost(), host_addr->GetPort()); } else if (InstanceOf<SocketInetAddress>(local).OK) { SocketInetAddress* inet_addr = (SocketInetAddress*) local; addr = (*inet_addr); } else if (InstanceOf<SocketUnixAddress>(local).OK) { SocketUnixAddress* unix_addr = (SocketUnixAddress*) local; int ret = unlink(unix_addr->GetPath().c_str()); // in case it already exists if (ret == -1) { int e = errno; ERROR_LOG( "unlink %s failed:%s", unix_addr->GetPath().c_str(), strerror(e)); } addr = get_inet_address(*unix_addr); } else { return false; } int family = addr.GetRawSockAddr().sa_family; int fd = ::socket(family, SOCK_STREAM, 0); if (fd < 0) { return false; } if (make_fd_nonblocking(fd) < 0) { ::close(fd); return false; } if (!addr.IsUnix()) { if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { ::close(fd); return false; } } else { struct sockaddr_un* pun = (struct sockaddr_un*) &(addr.GetRawSockAddr()); DEBUG_LOG("Bind on %s", pun->sun_path); // int nZero = 0; // setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &nZero, sizeof(nZero)); // setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &nZero, sizeof(int)); } //setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*) &on, sizeof(on)); if (::bind(fd, (struct sockaddr*) &(addr.GetRawSockAddr()), addr.GetRawSockAddrSize()) == -1) { int e = errno; ERROR_LOG("Failed to bind address for reason:%s", strerror(e)); ::close(fd); return false; } if (::listen(fd, 511) == -1) { /* the magic 511 constant is from nginx */ int e = errno; ERROR_LOG("Failed to listen for reason:%s", strerror(e)); ::close(fd); return false; } if (aeCreateFileEvent(GetService().GetRawEventLoop(), fd, AE_READABLE, Channel::IOEventCallback, this) == AE_ERR) { ::close(fd); return false; } m_fd = fd; return true; }