tcpsock tcpattach(int fd, int listening) { if(listening == 0) { struct mill_tcpconn *conn = malloc(sizeof(struct mill_tcpconn)); if(!conn) { errno = ENOMEM; return NULL; } tcpconn_init(conn, fd); errno = 0; return (tcpsock)conn; } /* It's a listening socket. Find out the port it is listening on. */ ipaddr addr; socklen_t sz = sizeof(ipaddr); int rc = getsockname(fd, (struct sockaddr*)&addr, &sz); if(rc == -1) return NULL; struct mill_tcplistener *l = malloc(sizeof(struct mill_tcplistener)); if(!l) { errno = ENOMEM; return NULL; } l->sock.type = MILL_TCPLISTENER; l->fd = fd; l->port = mill_ipport(addr); errno = 0; return &l->sock; }
tcpsock tcplisten(ipaddr addr, int backlog) { /* Open the listening socket. */ int s = socket(mill_ipfamily(addr), SOCK_STREAM, 0); if(s == -1) return NULL; mill_tcptune(s); /* Start listening. */ int rc = bind(s, (struct sockaddr*)&addr, mill_iplen(addr)); if(rc != 0) return NULL; rc = listen(s, backlog); if(rc != 0) return NULL; /* If the user requested an ephemeral port, retrieve the port number assigned by the OS now. */ int port = mill_ipport(addr); if(!port == 0) { ipaddr baddr; socklen_t len = sizeof(ipaddr); rc = getsockname(s, (struct sockaddr*)&baddr, &len); if(rc == -1) { int err = errno; fdclean(s); close(s); errno = err; return NULL; } port = mill_ipport(baddr); } /* Create the object. */ struct mill_tcplistener *l = malloc(sizeof(struct mill_tcplistener)); if(!l) { fdclean(s); close(s); errno = ENOMEM; return NULL; } l->sock.type = MILL_TCPLISTENER; l->fd = s; l->port = port; errno = 0; return &l->sock; }
struct mill_udpsock *mill_udplisten_(ipaddr addr) { /* Open the listening socket. */ int s = socket(mill_ipfamily(addr), SOCK_DGRAM, 0); if(s == -1) return NULL; mill_udptune(s); /* Start listening. */ int rc = bind(s, (struct sockaddr*)&addr, mill_iplen(addr)); if(rc != 0) return NULL; /* If the user requested an ephemeral port, retrieve the port number assigned by the OS now. */ int port = mill_ipport(addr); if(port) { ipaddr baddr; socklen_t len = sizeof(ipaddr); rc = getsockname(s, (struct sockaddr*)&baddr, &len); if(rc == -1) { int err = errno; fdclean(s); close(s); errno = err; return NULL; } port = mill_ipport(baddr); } /* Create the object. */ struct mill_udpsock *us = malloc(sizeof(struct mill_udpsock)); if(!us) { fdclean(s); close(s); errno = ENOMEM; return NULL; } us->fd = s; us->port = port; errno = 0; return us; }
int tcpport(tcpsock s) { if(s->type == MILL_TCPCONN) { struct mill_tcpconn *c = (struct mill_tcpconn*)s; return mill_ipport(c->addr); } else if(s->type == MILL_TCPLISTENER) { struct mill_tcplistener *l = (struct mill_tcplistener*)s; return l->port; } mill_assert(0); }