ScmObj Scm_SocketAccept(ScmSocket *sock) { Socket newfd; struct sockaddr_storage addrbuf; socklen_t addrlen = sizeof(addrbuf); ScmSocket *newsock; ScmClass *addrClass = Scm_ClassOf(SCM_OBJ(sock->address)); CLOSE_CHECK(sock->fd, "accept from", sock); SCM_SYSCALL(newfd, accept(sock->fd, (struct sockaddr*)&addrbuf, &addrlen)); if (SOCKET_INVALID(newfd)) { if (errno == EAGAIN) { return SCM_FALSE; } else { Scm_SysError("accept(2) failed"); } } newsock = make_socket(newfd, sock->type); newsock->address = SCM_SOCKADDR(Scm_MakeSockAddr(addrClass, (struct sockaddr*)&addrbuf, addrlen)); newsock->status = SCM_SOCKET_STATUS_CONNECTED; return SCM_OBJ(newsock); }
ScmObj Scm_SocketGetPeerName(ScmSocket *sock) { int r; struct sockaddr_storage addrbuf; socklen_t addrlen = sizeof(addrbuf); CLOSE_CHECK(sock->fd, "get the name of", sock); SCM_SYSCALL(r, getpeername(sock->fd, (struct sockaddr*)&addrbuf, &addrlen)); if (r < 0) { Scm_SysError("getpeername(2) failed"); } return SCM_OBJ(Scm_MakeSockAddr(NULL, (struct sockaddr*)&addrbuf, addrlen)); }
ScmObj Scm_SocketRecvFrom(ScmSocket *sock, int bytes, int flags) { int r; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); CLOSE_CHECK(sock->fd, "recv from", sock); char *buf = SCM_NEW_ATOMIC2(char*, bytes); SCM_SYSCALL(r, recvfrom(sock->fd, buf, bytes, flags, (struct sockaddr*)&from, &fromlen)); if (r < 0) { Scm_SysError("recvfrom(2) failed"); } return Scm_Values2(Scm_MakeString(buf, r, r, SCM_STRING_INCOMPLETE), Scm_MakeSockAddr(NULL, (struct sockaddr*)&from, fromlen)); }
ScmObj Scm_SocketBind(ScmSocket *sock, ScmSockAddr *addr) { int r; CLOSE_CHECK(sock->fd, "bind", sock); SCM_SYSCALL(r, bind(sock->fd, &addr->addr, addr->addrlen)); if (r < 0) { Scm_SysError("bind failed to %S", addr); } /* The system may assign different address than <addr>, especially when <addr> contains some 'wild card' (e.g. port=0). We call getsockname to obtain the exact address. Patch provided by ODA Hideo */ ScmSockAddr *naddr = SCM_SOCKADDR( Scm_MakeSockAddr(SCM_CLASS_OF(addr), &addr->addr, addr->addrlen)); SCM_SYSCALL(r, getsockname(sock->fd, &naddr->addr, &naddr->addrlen)); if (r < 0) { Scm_SysError("getsockname failed to %S", addr); } sock->address = naddr; sock->status = SCM_SOCKET_STATUS_BOUND; return SCM_OBJ(sock); }