static void fdselfpipe(int fd[2]) { fdpipe(fd); fdnoblock(fd[0]); fdnoblock(fd[1]); fdcoe(fd[0]); fdcoe(fd[1]); }
static int usbopen(char *path) { int fd; struct utsname name; if(path != nil){ }else if(uname(&name) < 0){ werrstr("unknown system, cannot determine radio settings"); return -1; }else if(strcmp(name.sysname, "Darwin") == 0){ path = "/dev/cu.usbmodem000001"; }else if(strcmp(name.sysname, "Linux") == 0){ path = "/dev/serial/by-id/usb-Nightscout_subg_rfspy_000002-if00"; }else{ werrstr("no default tty path found for system %s", name.sysname); return -1; } fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY|O_SYNC); if(fd < 0){ werrstr("open %s: %r", path); return -1; } if(ttysetattr(fd, B19200, 0) < 0){ werrstr("%s: %r", path); return -1; } fdnoblock(fd); return fd; }
static int ttyopen(char *path) { int fd; struct utsname name; if(path != nil){ }else if(uname(&name) < 0){ werrstr("unknown system, cannot determine radio settings"); return -1; }else if(strcmp(name.sysname, "Darwin") == 0){ path = "/dev/cu.usbserial-AH03IMYO"; }else if(strcmp(name.sysname, "Linux") == 0){ path = "/dev/ttyAMA0"; }else{ werrstr("no default tty path found for system %s", name.sysname); return -1; } fd = open(path, O_RDWR|O_NOCTTY|O_NDELAY|O_SYNC); if(fd < 0){ werrstr("open %s: %r", path); return -1; } if(ttysetattr(fd, B19200, 0) < 0){ werrstr("%s: %r", path); return -1; } fdnoblock(fd); return fd; }
// 非阻塞的接收新连接 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; }
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; }
// 链接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 netannounce(int istcp, char *server, int port) { int fd, n, proto; struct sockaddr_in sa; socklen_t sn; uint32_t ip; taskstate("netannounce"); // 协议是 tcp 还是 udp proto = istcp ? SOCK_STREAM : SOCK_DGRAM; memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; if(server != nil && strcmp(server, "*") != 0){ // 根据 server 来获取 ip,server 可以是 ip 或者域名 if(netlookup(server, &ip) < 0){ taskstate("netlookup failed"); return -1; } memmove(&sa.sin_addr, &ip, 4); } // 端口转为网络字节序, 忘了是大端还是小端,懒,不想查 sa.sin_port = htons(port); // 设置协议 if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } /* set reuse flag for tcp */ // 设置 resue 选项, 当 time_wait 过多的时候,可以重用端口 if(istcp && getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0){ n = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); } // 绑定监听的地址和端口到 fd if(bind(fd, (struct sockaddr*)&sa, sizeof sa) < 0){ taskstate("bind failed"); close(fd); return -1; } // 如果是 tcp 就开启监听 if(proto == SOCK_STREAM) listen(fd, 16); // 设置为非阻塞 fdnoblock(fd); taskstate("netannounce succeeded"); return fd; }
// 建立一个socket,绑定本地某个端口,且监听 int netannounce(int istcp, char *server, int port) { int fd, n, proto; struct sockaddr_in sa; socklen_t sn; uint32_t ip; taskstate("netannounce"); proto = istcp ? SOCK_STREAM : SOCK_DGRAM; memset(&sa, 0, sizeof sa); sa.sin_family = AF_INET; if(server != nil && strcmp(server, "*") != 0){ if(netlookup(server, &ip) < 0){ taskstate("netlookup failed"); return -1; } memmove(&sa.sin_addr, &ip, 4); } sa.sin_port = htons(port); if((fd = socket(AF_INET, proto, 0)) < 0){ taskstate("socket failed"); return -1; } /* set reuse flag for tcp */ if(istcp && getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0){ n = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); } if(bind(fd, (struct sockaddr*)&sa, sizeof sa) < 0){ taskstate("bind failed"); close(fd); return -1; } if(proto == SOCK_STREAM) listen(fd, 16); fdnoblock(fd); taskstate("netannounce succeeded"); return fd; }
int sockaccept(int fd) { int cfd; struct sockaddr_un sa; socklen_t len; fdwait(fd, 'r'); taskstate("sockaccept"); len = sizeof sa; if((cfd = accept(fd, (void*)&sa, &len)) < 0) { taskstate("accept failed"); return -1; } fdnoblock(cfd); taskstate("sockaccept succeeded"); return cfd; }
void taskmain(int argc, char **argv) { int cfd, fd; int rport; char remote[16]; if(argc != 2){ fprintf(stderr, "usage: tcplongconnection localport \n"); taskexitall(1); } if((fd = netannounce(TCP, 0, atoi(argv[1]))) < 0){ fprintf(stderr, "cannot announce on tcp port %d: %s\n", atoi(argv[1]), strerror(errno)); taskexitall(1); } fdnoblock(fd); while((cfd = netaccept(&fd, remote, &rport)) >= 0){ fprintf(stderr, "connection from %s:%d\n", remote, rport); taskcreate(proxytask, (void*)cfd, STACK); } }
Server *load_server(const char *db_file, const char *server_uuid, Server *old_srv) { int rc = 0; Server *srv = NULL; rc = Config_init_db(db_file); check(rc == 0, "Failed to load config database at %s", db_file); rc = Config_load_settings(); check(rc != -1, "Failed to load global settings."); rc = Config_load_mimetypes(); check(rc != -1, "Failed to load mime types."); srv = Config_load_server(server_uuid); check(srv, "Failed to load server %s from %s", server_uuid, db_file); check(srv->default_host, "No default_host set for server: %s, you need one host named: %s", server_uuid, bdata(srv->default_hostname)); if(old_srv == NULL || old_srv->listen_fd == -1) { srv->listen_fd = netannounce(TCP, bdata(srv->bind_addr), srv->port); check(srv->listen_fd >= 0, "Can't announce on TCP port %d", srv->port); check(fdnoblock(srv->listen_fd) == 0, "Failed to set listening port %d nonblocking.", srv->port); } else { srv->listen_fd = old_srv->listen_fd; } check(Server_start_handlers(srv, old_srv) == 0, "Failed to start handlers."); Config_close_db(); return srv; error: Server_destroy(srv); Config_close_db(); return NULL; }
int netaccept(int fd, char *server, int *port) { int cfd, one; struct sockaddr_in sa; uchar *ip; socklen_t len; Task *t; fdwait(fd, 'r'); /* bv */ t = taskrunning; if (t->signaled) { return -1; } taskstate("netaccept"); len = sizeof sa; if((cfd = accept(fd, (void*)&sa, &len)) < 0){ taskstate("accept failed"); return -1; } if(server){ ip = (uchar*)&sa.sin_addr; snprintf(server, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } if(port) *port = ntohs(sa.sin_port); fdnoblock(cfd); one = 1; setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one); taskstate("netaccept succeeded"); return cfd; }
void main(int argc, char **argv) { int n, top, firstx; fd_set rd, wr, xx; Wsysmsg m; XEvent event; /* * Move the protocol off stdin/stdout so that * any inadvertent prints don't screw things up. */ dup(0, 3); dup(1, 4); close(0); close(1); open("/dev/null", OREAD); open("/dev/null", OWRITE); /* reopens stdout if debugging */ runxevent(0); fmtinstall('W', drawfcallfmt); ARGBEGIN{ case 'D': chatty++; break; default: usage(); }ARGEND /* * Ignore arguments. They're only for good ps -a listings. */ notify(bell); fdin.rp = fdin.wp = fdin.buf; fdin.ep = fdin.buf+sizeof fdin.buf; fdout.rp = fdout.wp = fdout.buf; fdout.ep = fdout.buf+sizeof fdout.buf; fdnoblock(3); fdnoblock(4); firstx = 1; _x.fd = -1; for(;;){ /* set up file descriptors */ FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&xx); /* * Don't read unless there's room *and* we haven't * already filled the output buffer too much. */ if(fdout.wp < fdout.buf+MAXWMSG && fdin.wp < fdin.ep) FD_SET(3, &rd); if(fdout.wp > fdout.rp) FD_SET(4, &wr); FD_SET(3, &xx); FD_SET(4, &xx); top = 4; if(_x.fd >= 0){ if(firstx){ firstx = 0; XSelectInput(_x.display, _x.drawable, Mask); } FD_SET(_x.fd, &rd); FD_SET(_x.fd, &xx); XFlush(_x.display); if(_x.fd > top) top = _x.fd; } if(chatty) fprint(2, "select %d...\n", top+1); /* wait for something to happen */ again: if(select(top+1, &rd, &wr, &xx, NULL) < 0){ if(errno == EINTR) goto again; if(chatty) fprint(2, "select failure\n"); exits(0); } if(chatty) fprint(2, "got select...\n"); { /* read what we can */ n = 1; while(fdin.wp < fdin.ep && (n = read(3, fdin.wp, fdin.ep-fdin.wp)) > 0) fdin.wp += n; if(n == 0){ if(chatty) fprint(2, "eof\n"); exits(0); } if(n < 0 && errno != EAGAIN) sysfatal("reading wsys msg: %r"); /* pick off messages one by one */ while((n = convM2W(fdin.rp, fdin.wp-fdin.rp, &m)) > 0){ /* fprint(2, "<- %W\n", &m); */ runmsg(&m); fdin.rp += n; } /* slide data to beginning of buf */ fdslide(&fdin); } { /* write what we can */ n = 1; while(fdout.rp < fdout.wp && (n = write(4, fdout.rp, fdout.wp-fdout.rp)) > 0) fdout.rp += n; if(n == 0) sysfatal("short write writing wsys"); if(n < 0 && errno != EAGAIN) sysfatal("writing wsys msg: %r"); /* slide data to beginning of buf */ fdslide(&fdout); } { /* * Read an X message if we can. * (XPending actually calls select to make sure * the display's fd is readable and then reads * in any waiting data before declaring whether * there are events on the queue.) */ while(XPending(_x.display)){ XNextEvent(_x.display, &event); runxevent(&event); } } } }