int accept(int socket, struct sockaddr *addr, socklen_t *addrlen) { int fd, index, ret; if (fd_get(socket, &fd) == fd_rsocket) { index = fd_open(); if (index < 0) return index; ret = raccept(fd, addr, addrlen); if (ret < 0) { fd_close(index, &fd); return ret; } fd_store(index, ret, fd_rsocket, fd_ready); return index; } else if (fd_gets(socket) == fd_fork_listen) { index = fd_open(); if (index < 0) return index; ret = real.accept(fd, addr, addrlen); if (ret < 0) { fd_close(index, &fd); return ret; } fd_store(index, ret, fd_normal, fd_fork_passive); return index; } else { return real.accept(fd, addr, addrlen); } }
static int server_connect(void) { struct pollfd fds; int ret = 0; set_options(lrs); do { if (use_async) { fds.fd = lrs; fds.events = POLLIN; ret = do_poll(&fds, poll_timeout); if (ret) { perror("rpoll"); return ret; } } rs = raccept(lrs, NULL, 0); } while (rs < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)); if (rs < 0) { perror("raccept"); return rs; } set_options(rs); return ret; }
void vm_process(VM *vm) { int a, b, opcode; opcode = vm->image[vm->ip]; switch(opcode) { case VM_NOP: break; case VM_LIT: vm->sp++; vm->ip++; TOS = vm->image[vm->ip]; break; case VM_DUP: vm->sp++; vm->data[vm->sp] = NOS; break; case VM_DROP: DROP break; case VM_SWAP: a = TOS; TOS = NOS; NOS = a; break; case VM_PUSH: vm->rsp++; TORS = TOS; DROP break; case VM_POP: vm->sp++; TOS = TORS; vm->rsp--; break; case VM_CALL: vm->ip++; vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_JUMP: vm->ip++; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; case VM_RETURN: vm->ip = TORS; vm->rsp--; break; case VM_GT_JUMP: vm->ip++; if(NOS > TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_LT_JUMP: vm->ip++; if(NOS < TOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_NE_JUMP: vm->ip++; if(TOS != NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_EQ_JUMP: vm->ip++; if(TOS == NOS) vm->ip = vm->image[vm->ip] - 1; DROP DROP break; case VM_FETCH: TOS = vm->image[TOS]; break; case VM_STORE: vm->image[TOS] = NOS; DROP DROP break; case VM_ADD: NOS += TOS; DROP break; case VM_SUB: NOS -= TOS; DROP break; case VM_MUL: NOS *= TOS; DROP break; case VM_DIVMOD: a = TOS; b = NOS; TOS = b / a; NOS = b % a; break; case VM_AND: a = TOS; b = NOS; DROP TOS = a & b; break; case VM_OR: a = TOS; b = NOS; DROP TOS = a | b; break; case VM_XOR: a = TOS; b = NOS; DROP TOS = a ^ b; break; case VM_SHL: a = TOS; b = NOS; DROP TOS = b << a; break; case VM_SHR: a = TOS; b = NOS; DROP TOS = b >>= a; break; case VM_ZERO_EXIT: if (TOS == 0) { DROP vm->ip = TORS; vm->rsp--; } break; case VM_INC: TOS += 1; break; case VM_DEC: TOS -= 1; break; case VM_IN: a = TOS; TOS = vm->ports[a]; vm->ports[a] = 0; break; case VM_OUT: vm->ports[0] = 0; vm->ports[TOS] = NOS; DROP DROP break; case VM_WAIT: if (vm->ports[0] == 1) break; /* Input */ if (vm->ports[0] == 0 && vm->ports[1] == 1) { vm->ports[1] = dev_getch(); vm->ports[0] = 1; } /* Output (character generator) */ if (vm->ports[2] == 1) { dev_putch(TOS); DROP vm->ports[2] = 0; vm->ports[0] = 1; } if (vm->ports[4] != 0) { vm->ports[0] = 1; switch (vm->ports[4]) { case 1: vm_save_image(vm, vm->filename); vm->ports[4] = 0; break; case 2: file_add(vm); vm->ports[4] = 0; break; case -1: vm->ports[4] = file_handle(vm); break; case -2: vm->ports[4] = file_readc(vm); break; case -3: vm->ports[4] = file_writec(vm); break; case -4: vm->ports[4] = file_closehandle(vm); break; case -5: vm->ports[4] = file_getpos(vm); break; case -6: vm->ports[4] = file_seek(vm); break; case -7: vm->ports[4] = file_size(vm); break; default: vm->ports[4] = 0; } } /* Capabilities */ if (vm->ports[5] != 0) { vm->ports[0] = 1; switch(vm->ports[5]) { case -1: vm->ports[5] = IMAGE_SIZE; break; case -2: vm->ports[5] = 0; break; case -3: vm->ports[5] = 0; break; case -4: vm->ports[5] = 0; break; case -5: vm->ports[5] = vm->sp; break; case -6: vm->ports[5] = vm->rsp; break; case -7: vm->ports[5] = 0; break; case -8: vm->ports[5] = time(NULL); break; case -9: vm->ports[5] = 0; vm->ip = IMAGE_SIZE; break; default: vm->ports[5] = 0; } } if (vm->ports[8] != 0) { vm->ports[0] = 1; switch (vm->ports[8]) { case -1: rsocket(vm); vm->ports[8] = 0; break; case -2: rbind(vm); vm->ports[8] = 0; break; case -3: rlisten(vm); vm->ports[8] = 0; break; case -4: raccept(vm); vm->ports[8] = 0; break; case -5: rclose(vm); vm->ports[8] = 0; break; case -6: rsend(vm); vm->ports[8] = 0; break; case -7: rrecv(vm); vm->ports[8] = 0; break; case -8: rconnect(vm); vm->ports[8] = 0; break; default: vm->ports[8] = 0; } vm->ports[8] = 0; } break; default: vm->rsp++; TORS = vm->ip; vm->ip = vm->image[vm->ip] - 1; if (vm->ip < 0) vm->ip = IMAGE_SIZE; else { if (vm->image[vm->ip+1] == 0) vm->ip++; if (vm->image[vm->ip+1] == 0) vm->ip++; } break; } vm->ports[3] = 1; }
/* * The server will start listening for the new connection, then send a * message to the active side when the listen is ready. This does leave * fork unsupported in the following case: the server is nonblocking and * calls select/poll waiting to receive data from the client. */ static void fork_passive(int socket) { struct sockaddr_in6 sin6; sem_t *sem; int lfd, sfd, dfd, ret, param; socklen_t len; uint32_t msg; sfd = fd_getd(socket); len = sizeof sin6; ret = real.getsockname(sfd, (struct sockaddr *) &sin6, &len); if (ret) goto out; sin6.sin6_flowinfo = sin6.sin6_scope_id = 0; memset(&sin6.sin6_addr, 0, sizeof sin6.sin6_addr); sem = sem_open("/rsocket_fork", O_CREAT | O_RDWR, S_IRWXU | S_IRWXG, 1); if (sem == SEM_FAILED) { ret = -1; goto out; } lfd = rsocket(sin6.sin6_family, SOCK_STREAM, 0); if (lfd < 0) { ret = lfd; goto sclose; } param = 1; rsetsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, ¶m, sizeof param); sem_wait(sem); ret = rbind(lfd, (struct sockaddr *) &sin6, sizeof sin6); if (ret) goto lclose; ret = rlisten(lfd, 1); if (ret) goto lclose; msg = 0; len = real.write(sfd, &msg, sizeof msg); if (len != sizeof msg) goto lclose; dfd = raccept(lfd, NULL, NULL); if (dfd < 0) { ret = dfd; goto lclose; } set_rsocket_options(dfd); copysockopts(dfd, sfd, &rs, &real); real.shutdown(sfd, SHUT_RDWR); real.close(sfd); fd_store(socket, dfd, fd_rsocket, fd_ready); lclose: rclose(lfd); sem_post(sem); sclose: sem_close(sem); out: if (ret) fd_store(socket, sfd, fd_normal, fd_ready); }