void sleep(unsigned int seconds) { struct timeval sleeptime; sleeptime.tv_sec = seconds; sleeptime.tv_usec = 0; fdwait(0, 0, 0, &sleeptime, 0); }
int flush_input(int fd) { fd_set read_fds; int err; int ready_fd; struct timeval tv; char buffer[1024]; size_t rcv_cnt; while (1) { bzero((char *)&read_fds, sizeof(read_fds)); FD_SET(fd, &read_fds); tv.tv_sec = 0; tv.tv_usec = 10; err = fdwait(fd + 1, &read_fds, NULL, &tv, &ready_fd); if (err != 0) { return err; } if (!FD_ISSET(fd, &read_fds)) break; else receive(fd, buffer, 1024, &rcv_cnt); } return 0; } // flush_input()
tcpconn tcpdial(const struct sockaddr *addr, socklen_t addrlen) { /* Open a socket. */ int s = socket(AF_INET, SOCK_STREAM, 0); if(s == -1) return NULL; /* Make it non-blocking. */ int opt = fcntl(s, F_GETFL, 0); if (opt == -1) opt = 0; int rc = fcntl(s, F_SETFL, opt | O_NONBLOCK); assert(rc != -1); /* Connect to the remote endpoint. */ rc = connect(s, addr, addrlen); if(rc != 0) { assert(rc == -1); if(errno != EINPROGRESS) return NULL; rc = fdwait(s, FDW_OUT); assert(rc == FDW_OUT); /* TODO: Handle errors. */ } /* Create the object. */ struct tcpconn *conn = malloc(sizeof(struct tcpconn)); assert(conn); conn->fd = s; return conn; }
tcpconn tcpaccept(tcplistener listener) { while(1) { /* Try to get new connection (non-blocking). */ int s = accept(listener->fd, NULL, NULL); if (s >= 0) { /* Put the newly created connection into non-blocking mode. */ int opt = fcntl(s, F_GETFL, 0); if (opt == -1) opt = 0; int rc = fcntl(s, F_SETFL, opt | O_NONBLOCK); assert(rc != -1); /* Create the object. */ struct tcpconn *conn = malloc(sizeof(struct tcpconn)); assert(conn); conn->fd = s; return conn; } assert(s == -1); if(errno != EAGAIN && errno != EWOULDBLOCK) return NULL; /* Wait till new connection is available. */ int rc = fdwait(listener->fd, FDW_IN); assert(rc == FDW_IN); } }
int fdread(int fd, void *buf, int n) { mpass::MessageEndPoint *end_point = &mpass::msg_end_point; mpass::Connection *conn = &end_point->conn_array[fd]; #ifdef maysam_dbg fprintf(stderr,"fdread on fd=%d : before is_empty\n", fd); #endif while(conn->rcv_q->is_empty()) { #ifdef maysam_dbg fprintf(stderr,"fdread on fd=%d: before fdwait\n", fd); #endif fdwait(fd, 'r'); } #ifdef maysam_dbg fprintf(stderr,"fdread on fd=%d: before dequeue\n", fd); #endif mpass::simple_msg msg_buf(buf, n); conn->rcv_q->dequeue(mpass::copy_msg_from_queue, &msg_buf); int size = msg_buf.size; #ifdef maysam_dbg fprintf(stderr,"fdread on fd=%d: after dequeue size is %d\n", fd, size); #endif return size; }
int Dir_stream_file(FileRecord *file, Connection *conn) { ssize_t sent = 0; size_t total = 0; off_t offset = 0; size_t block_size = MAX_SEND_BUFFER; // For the non-sendfile slowpath char *file_buffer = NULL; int nread = 0; int amt = 0; int tempfd = -1; int rc = Dir_send_header(file, conn); check_debug(rc, "Failed to write header to socket."); if(conn->ssl == NULL) { for(total = 0; fdwait(conn->fd, 'w') == 0 && total < file->sb.st_size; total += sent) { sent = Dir_send(conn->fd, file->fd, &offset, block_size); check_debug(sent > 0, "Failed to sendfile on socket: %d from " "file %d", conn->fd, file->fd); } } else { // We have to reopen the file, so we don't get ourselves into seek // position trouble int tempfd = open((const char *)(file->full_path->data), O_RDONLY); check(tempfd >= 0, "Could not reopen open file"); file_buffer = malloc(MAX_SEND_BUFFER); check_mem(file_buffer); while((nread = fdread(tempfd, file_buffer, MAX_SEND_BUFFER)) > 0) { for(amt = 0, sent = 0; sent < nread; sent += amt) { amt = conn->send(conn, file_buffer + sent, nread - sent); check_debug(amt > 0, "Failed to send on socket: %d from " "file %d", conn->fd, tempfd); } total += nread; } free(file_buffer); close(tempfd); tempfd = -1; } check(total <= file->sb.st_size, "Wrote way too much, wrote %d but size was %d", (int)total, (int)file->sb.st_size); check(total == file->sb.st_size, "Sent other than expected, sent: %d, but expected: %d", (int)total, (int)file->sb.st_size); return total; error: if(file_buffer) free(file_buffer); if(tempfd >= 0) close(tempfd); return -1; }
coroutine void collect(chan workers, int back_router) { //int back_router = nn_socket(AF_SP_RAW, NN_REP); //nn_bind(back_router, BACKROUTER); int ready; size_t ready_sz = sizeof (ready); nn_getsockopt(back_router, NN_SOL_SOCKET, NN_RCVFD, &ready, &ready_sz); struct nn_msghdr hdr; char *body = malloc(sizeof(char)*128); while(1){ char *ctrl = malloc(sizeof(char)*64); memset(&hdr, 0, sizeof(hdr)); struct nn_iovec iovec; iovec.iov_base = body; iovec.iov_len = 128; hdr.msg_iov = &iovec; hdr.msg_iovlen = 1; hdr.msg_control = ctrl; hdr.msg_controllen = 64; fdwait(ready, FDW_IN, -1); int rc = nn_recvmsg(back_router, &hdr, NN_DONTWAIT); printf("%.*s\n", hdr.msg_iov->iov_len, (char*) hdr.msg_iov->iov_base); chs(workers, char*, ctrl); } }
int main(void) { unsigned char Frame[MAX_FRAME_LEN]; fd_set readfds; int fd; L2_InitCAM(); L2_PopulateCAM(0x0001, FD_ROUTER, 1); L2_PopulateCAM(0x0002, FD_ROUTER, 2); while (1) { FD_ZERO(&readfds); FD_SET(FD_CRS, &readfds); FD_SET(FD_ROUTER, &readfds); FD_SET(FD_CB3, &readfds); if (fdwait(FD_CB3+1, &readfds, NULL, NULL, NULL) != 0) { continue; } if (FD_ISSET(FD_CRS, &readfds)) { fd = FD_CRS; } else if (FD_ISSET(FD_ROUTER, &readfds)) { fd = FD_ROUTER; } else if (FD_ISSET(FD_CB3, &readfds)) { fd = FD_CB3; } else { continue; } if (L2_RxFrame(fd, Frame)) { L2_ForwardFrame(Frame); } } return(0); }
void sleep(uint32_t usec) { struct timeval t; t.tv_sec = usec / 1000000; t.tv_usec = usec % 1000000; fdwait(1, NULL, NULL, &t, NULL); }
void mfflush(mfile f, int64_t deadline) { if(!f->olen) { errno = 0; return; } char *pos = f->obuf; size_t remaining = f->olen; while(remaining) { ssize_t sz = write(f->fd, pos, remaining); if(sz == -1) { if(errno != EAGAIN && errno != EWOULDBLOCK) return; int rc = fdwait(f->fd, FDW_OUT, deadline); if(rc == 0) { errno = ETIMEDOUT; return; } mill_assert(rc == FDW_OUT); continue; } pos += sz; remaining -= sz; } f->olen = 0; errno = 0; }
void mill_tcpflush_(struct mill_tcpsock *s, int64_t deadline) { if(s->type != MILL_TCPCONN) mill_panic("trying to send to an unconnected socket"); struct mill_tcpconn *conn = (struct mill_tcpconn*)s; if(!conn->olen) { errno = 0; return; } char *pos = conn->obuf; size_t remaining = conn->olen; while(remaining) { ssize_t sz = send(conn->fd, pos, remaining, 0); if(sz == -1) { /* Operating systems are inconsistent w.r.t. returning EPIPE and ECONNRESET. Let's paper over it like this. */ if(errno == EPIPE) { errno = ECONNRESET; return; } if(errno != EAGAIN && errno != EWOULDBLOCK) return; int rc = fdwait(conn->fd, FDW_OUT, deadline); if(rc == 0) { errno = ETIMEDOUT; return; } continue; } pos += sz; remaining -= sz; } conn->olen = 0; errno = 0; }
static ssize_t plain_stream_file(IOBuf *iob, int fd, off_t len) { off_t sent = 0; off_t total = 0; off_t offset = 0; off_t block_size = MAX_SEND_BUFFER; int conn_fd = IOBuf_fd(iob); for(total = 0; fdwait(conn_fd, 'w') == 0 && total < len; total += sent) { block_size = (len - total) > block_size ? block_size : (len - total); sent = IOBuf_sendfile(conn_fd, fd, &offset, block_size); check(Register_write(iob->fd, sent) != -1, "Socket seems to be closed."); check_debug(sent > 0, "Client closed probably during sendfile on socket: %d from " "file %d", conn_fd, fd); } check(total <= len, "Wrote way too much, wrote %d but size was %zd", (int)total, len); check(total == len, "Sent other than expected, sent: %d, but expected: %zd", (int)total, len); return total; error: return -1; }
int fdwrite(int fd, void *msg, int size) { #ifdef maysam_dbg fprintf(stderr,"fdwrite on fd=%d msg=%s size=%d: starting\n", fd, msg, size); #endif void *buf = msg;//malloc(size); #ifdef maysam_dbg fprintf(stderr,"fdwrite 1\n", fd, msg, size); #endif memcpy(buf, msg, size); #ifdef maysam_dbg fprintf(stderr,"fdwrite 2\n", fd, msg, size); #endif mpass::Connection *conn = &mpass::msg_end_point.conn_array[fd]; #ifdef maysam_dbg fprintf(stderr,"fdwrite 3\n", fd, msg, size); #endif mpass::simple_msg to_snd(buf, size); #ifdef maysam_dbg fprintf(stderr,"fdwrite on fd=%d msg=%s size=%d: before fdwait\n", fd, msg, size); #endif while(conn->snd_q->is_full()) fdwait(fd, 'w'); #ifdef maysam_dbg fprintf(stderr,"fdwrite on fd=%d msg=%s size=%d: before enqueue\n", fd, msg, size); #endif conn->snd_q->enqueue(mpass::copy_msg_to_queue, &to_snd); return size; }
int sockdial(char* name) { int fd, len; struct sockaddr_un sa; taskstate("sockdial"); if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { taskstate("socket failed"); return -1; } fdnoblock(fd); /* start connecting */ memset(&sa, 0, sizeof sa); sa.sun_family = AF_UNIX; strcpy(sa.sun_path, name); len = strlen(sa.sun_path) + sizeof(sa.sun_family); if(connect(fd, (struct sockaddr*)&sa, len) < 0 && errno != EINPROGRESS) { taskstate("connect failed"); close(fd); return -1; } fdwait(fd, 'w'); taskstate("connect succeeded"); return fd; }
int getChar(reg_t r) { char c; size_t rx_bytes; int ret = 0; fd_set fdsToWait; struct timeval timeToWait; timeToWait.tv_sec = 1; timeToWait.tv_usec = 0; int readyfds = 0; FD_ZERO(&fdsToWait); FD_SET(0, &fdsToWait); ret = fdwait(1, &fdsToWait, NULL, &timeToWait, &readyfds); if ( (ret != 0) || (readyfds != 1) ) { return (-1); } ret = receive(STDIN, &c, 1, &rx_bytes); if ((ret != 0) || (rx_bytes == 0)) { return (-1); } MOVIM8(r, c); return (0); }
int ready_to_read(void) { fd_set read_fds; int ret; int ready_fd; struct timeval tv; if (buf_offset < buf_read) { return 1; } FD_ZERO(&read_fds); FD_SET(STDIN, &read_fds); tv.tv_sec = 0; tv.tv_usec = 1; ret = fdwait(STDIN + 1, &read_fds, NULL, &tv, &ready_fd); if (ret != 0) { _terminate(1); } if (FD_ISSET(ready_fd, &read_fds)) return 1; return 0; }
unixsock unixaccept(unixsock s, int64_t deadline) { if(s->type != MILL_UNIXLISTENER) mill_panic("trying to accept on a socket that isn't listening"); struct mill_unixlistener *l = (struct mill_unixlistener*)s; while(1) { /* Try to get new connection (non-blocking). */ int as = accept(l->fd, NULL, NULL); if (as >= 0) { mill_unixtune(as); struct mill_unixconn *conn = malloc(sizeof(struct mill_unixconn)); if(!conn) { close(as); errno = ENOMEM; return NULL; } unixconn_init(conn, as); errno = 0; return (unixsock)conn; } mill_assert(as == -1); if(errno != EAGAIN && errno != EWOULDBLOCK) return NULL; /* Wait till new connection is available. */ int rc = fdwait(l->fd, FDW_IN, deadline); if(rc == 0) { errno = ETIMEDOUT; return NULL; } mill_assert(rc == FDW_IN); } }
static void sigio_handler (int sig) { int saved_errno = errno; static timeval ztv = { 0, 0 }; sigio_received = 1; flock (shmfd, LOCK_UN); while (fdwait (rwfd, selread, &ztv) > 0) { /* Note that rwfd is a unix domain socket, not a pipe. Since unix * domain sockets are not specified by POSIX, writes of less than * PIPE_BUF bytes could conceivably not be atomic on some systems, * and a true select for writing might not even guarantee PIPE_BUF * bytes of buffer space. * * We thereforedo a "fullread" here. We know the client is trying * to write sizeof (msg) bytes to us, so we don't need to worry * about blocking. */ aiomsg_t msg; ssize_t n = fullread (rwfd, &msg, sizeof (msg)); if (n != sizeof (msg)) { if (n < 0) fatal ("read: %m\n"); exit (0); } srv->getmsg (msg); } errno = saved_errno; }
// 非阻塞的接收新连接 int netaccept(int fd, char *server, int *port) { int cfd, one; struct sockaddr_in sa; uchar *ip; socklen_t len; // 注册读事件, 出让 cpu 直到事件到来才会重新调度 fdwait(fd, 'r'); taskstate("netaccept"); len = sizeof sa; // accept 新连接 if((cfd = accept(fd, (void*)&sa, &len)) < 0){ taskstate("accept failed"); return -1; } if(server){ ip = (uchar*)&sa.sin_addr; snprint(server, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } if(port) *port = ntohs(sa.sin_port); // 连接 fd 设置为非阻塞 fdnoblock(cfd); one = 1; setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one); taskstate("netaccept succeeded"); return cfd; }
void tcpflush(tcpsock s, int64_t deadline) { if(s->type != MILL_TCPCONN) mill_panic("trying to send to an unconnected socket"); struct mill_tcpconn *conn = (struct mill_tcpconn*)s; if(!conn->olen) { errno = 0; return; } char *pos = conn->obuf; size_t remaining = conn->olen; while(remaining) { ssize_t sz = send(conn->fd, pos, remaining, 0); if(sz == -1) { if(errno != EAGAIN && errno != EWOULDBLOCK) return; int rc = fdwait(conn->fd, FDW_OUT, deadline); if(rc == 0) { errno = ETIMEDOUT; return; } mill_assert(rc == FDW_OUT); continue; } pos += sz; remaining -= sz; } conn->olen = 0; errno = 0; }
/* Like fdread but always calls fdwait before reading. */ int fdread1(int fd, void *buf, int n) { int m; do fdwait(fd, 'r'); while((m = read(fd, buf, n)) < 0 && errno == EAGAIN); return m; }
int fdread(int fd, void *buf, int n) { int m; int b = fdcheckblock(fd); if(b){ while(1){ fdwait(fd,'r'); m = read(fd,buf,n); break; } }else{ while((m=read(fd, buf, n)) < 0 && errno == EAGAIN){ fdwait(fd, 'r'); } } return m; }
size_t mill_tcpsend_(struct mill_tcpsock *s, const void *buf, size_t len, int64_t deadline) { if(s->type != MILL_TCPCONN) mill_panic("trying to send to an unconnected socket"); struct mill_tcpconn *conn = (struct mill_tcpconn*)s; /* If it fits into the output buffer copy it there and be done. */ if(conn->olen + len <= MILL_TCP_BUFLEN) { memcpy(&conn->obuf[conn->olen], buf, len); conn->olen += len; errno = 0; return len; } /* If it doesn't fit, flush the output buffer first. */ tcpflush(s, deadline); if(errno != 0) return 0; /* Try to fit it into the buffer once again. */ if(conn->olen + len <= MILL_TCP_BUFLEN) { memcpy(&conn->obuf[conn->olen], buf, len); conn->olen += len; errno = 0; return len; } /* The data chunk to send is longer than the output buffer. Let's do the sending in-place. */ char *pos = (char*)buf; size_t remaining = len; while(remaining) { ssize_t sz = send(conn->fd, pos, remaining, 0); if(sz == -1) { /* Operating systems are inconsistent w.r.t. returning EPIPE and ECONNRESET. Let's paper over it like this. */ if(errno == EPIPE) { errno = ECONNRESET; return 0; } if(errno != EAGAIN && errno != EWOULDBLOCK) return 0; int rc = fdwait(conn->fd, FDW_OUT, deadline); if(rc == 0) { errno = ETIMEDOUT; return len - remaining; } continue; } pos += sz; remaining -= sz; } errno = 0; return len; }
// 链接server:port,链接成功返回fd int netdial(int istcp, char *server, int port) { int proto, fd, n; uint32_t ip; struct sockaddr_in sa; socklen_t sn; if(netlookup(server, &ip) < 0) return -1; taskstate("netdial"); proto = istcp ? SOCK_STREAM : SOCK_DGRAM; if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } fdnoblock(fd); /* for udp */ if(!istcp){ n = 1; setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof n); } /* start connecting */ memset(&sa, 0, sizeof sa); memmove(&sa.sin_addr, &ip, 4); sa.sin_family = AF_INET; sa.sin_port = htons(port); if(connect(fd, (struct sockaddr*)&sa, sizeof sa) < 0 && errno != EINPROGRESS){ printf(">>>>>>> connect failed \n"); taskstate("connect failed"); close(fd); return -1; } /* wait for finish */ fdwait(fd, 'w'); sn = sizeof sa; if(getpeername(fd, (struct sockaddr*)&sa, &sn) >= 0){ taskstate("connect succeeded"); return fd; } /* report error */ sn = sizeof n; getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&n, &sn); if(n == 0) n = ECONNREFUSED; close(fd); taskstate("connect failed"); errno = n; return -1; }
int main() { /* Create a pair of file descriptors for testing. */ int fds[2]; int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); assert(rc == 0); /* Check for out. */ rc = fdwait(fds[0], FDW_OUT, -1); assert(rc & FDW_OUT); assert(!(rc & ~FDW_OUT)); /* Check with the timeout that doesn't expire. */ rc = fdwait(fds[0], FDW_OUT, now() + 100); assert(rc); assert(rc & FDW_OUT); assert(!(rc & ~FDW_OUT)); /* Check with the timeout that does expire. */ int64_t deadline = now() + 100; rc = fdwait(fds[0], FDW_IN, deadline); assert(rc == 0); int64_t diff = now() - deadline; assert(diff > -20 && diff < 20); /* Check for in. */ ssize_t sz = send(fds[1], "A", 1, 0); assert(sz == 1); rc = fdwait(fds[0], FDW_IN, -1); assert(rc & FDW_IN); assert(!(rc & ~FDW_IN)); /* Check for both in and out. */ rc = fdwait(fds[0], FDW_IN | FDW_OUT, -1); assert(rc & FDW_IN); assert(rc & FDW_OUT); assert(!(rc & ~(FDW_IN | FDW_OUT))); char c; sz = recv(fds[0], &c, 1, 0); assert(sz == 1); /* Check when both timeout and fd signals. */ rc = fdwait(fds[0], FDW_OUT, now() - 10000); assert(rc == 0 || rc == FDW_OUT); /* Two interleaved deadlines. */ int64_t start = now(); go(trigger(fds[0], start + 50)); rc = fdwait(fds[1], FDW_IN, start + 90); assert(rc == FDW_IN); diff = now() - start; assert(diff > 30 && diff < 70); close(fds[0]); close(fds[1]); return 0; }
int fdread(int fd, void *buf, int n) { int m; while((m=read(fd, buf, n)) < 0 && errno == EAGAIN) { if(fdwait(fd, 'r') == -1) { return -1; } } return m; }
int fdrecv(int fd, void *buf, int n) { int m; while((m=recv(fd, buf, n, MSG_NOSIGNAL)) < 0 && errno == EAGAIN) { if(fdwait(fd, 'r') == -1) { return -1; } } return m; }
void receiver(chan ch) { int events = fdwait(signal_pipe[0], FDW_IN, -1); assert(events == FDW_IN); char signo; ssize_t sz = read(signal_pipe[0], &signo, 1); assert(sz == 1); assert(signo == SIGNAL); chs(ch, char, signo); }
int fdread(int fd, void *buf, int n) { int m; while((m=read(fd, buf, n)) < 0 && errno == EAGAIN) { //fprintf(stderr, "read failed on socket %d\n", fd); fdwait(fd, 'r'); } return m; }
int main(void) { char *sp; char input[512]; int bytes_received = 0; fd_set fds; int ready_fds; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 0; int ret; // cgc_read input while (1) { FD_ZERO(&fds); FD_SET(FD_FROM_MAIN, &fds); ret = fdwait(FD_FROM_MAIN + 1, &fds, NULL, &timeout, &ready_fds); bytes_received = receive_until_fd(FD_FROM_MAIN, input, sizeof(input), '\n'); bytes_received = force_newline(input, sizeof(input), bytes_received); if (equals(input, "terminate\n")) { goto EXIT; } if (bytes_received > 0) { char *args[15]; int i = 0; args[i++] = "mailsend"; // parse input char *p = input; while (i < 14) { while(isspace(*p)) p++; if (!*p) break; if (*p && !isspace(*p)) { args[i++] = p; while (*p && !isspace(*p)) p++; *p++ = '\0'; } } // Null terminate argument list args[i] = 0; mailsend(i, args); // Tell main program rsh is done send_all_fd(FD_TO_MAIN, "\0\n", 2); } } EXIT: // cgc_exit return 0; }