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; }
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; }