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; }
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; }
int32 DatagramChannel::Send(const SocketInetAddress& addr, Buffer* buffer) { char* raw = const_cast<char*>(buffer->GetRawReadBuffer()); uint32 len = buffer->ReadableBytes(); int ret = ::sendto(GetSocketFD(addr.GetDomain()), raw, len, 0, &(addr.GetRawSockAddr()), addr.GetRawSockAddrSize()); if (ret > 0) { buffer->AdvanceReadIndex(len); } return ret; }
int32 DatagramChannel::Receive(SocketInetAddress& addr, Buffer* buffer) { sockaddr& tempaddr = const_cast<sockaddr&>(addr.GetRawSockAddr()); socklen_t socklen = sizeof(sockaddr); memset(&tempaddr, 0, sizeof(struct sockaddr_in)); buffer->EnsureWritableBytes(65536); char* raw = const_cast<char*>(buffer->GetRawWriteBuffer()); int ret = ::recvfrom(GetSocketFD(addr.GetDomain()), raw, buffer->WriteableBytes(), 0, &tempaddr, &socklen); if (ret > 0) { buffer->AdvanceWriteIndex(ret); } return ret; }
bool SocketChannel::DoConnect(Address* remote) { if (NULL == remote) { return false; } SocketInetAddress addr; if (InstanceOf<SocketHostAddress>(remote).OK) { SocketHostAddress* host_addr = static_cast<SocketHostAddress*>(remote); addr = get_inet_address(host_addr->GetHost(), host_addr->GetPort()); } else if (InstanceOf<SocketInetAddress>(remote).OK) { SocketInetAddress* inet_addr = static_cast<SocketInetAddress*>(remote); addr = (*inet_addr); } else if (InstanceOf<SocketUnixAddress>(remote).OK) { SocketUnixAddress* unix_addr = static_cast<SocketUnixAddress*>(remote); addr = get_inet_address(*unix_addr); } else { return false; } int fd = GetSocketFD(addr.GetDomain()); int ret = ::connect(fd, const_cast<sockaddr*>(&(addr.GetRawSockAddr())), addr.GetRawSockAddrSize()); if (ret < 0) { int e = errno; if (((e) == EINTR || (e) == EINPROGRESS)) { //connecting } else { ERROR_LOG("Failed to connect remote server for reason:%s", strerror(e)); return false; } } m_state = SOCK_CONNECTING; //DEBUG_LOG("###Switch to %d", m_state); return true; }
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; }
SocketHostAddress get_host_address(const SocketInetAddress& addr) { return get_host_address(addr.GetRawSockAddr()); }
SocketUnixAddress get_unix_address(const SocketInetAddress& addr) { return get_unix_address(addr.GetRawSockAddr()); }