int is_true_obj(Object v) { switch (TM_TYPE(v)) { case TYPE_NUM: return GET_NUM(v) != 0; case TYPE_NONE: return 0; case TYPE_STR: return GET_STR_LEN(v) > 0; case TYPE_LIST: return LIST_LEN(v) > 0; case TYPE_DICT: return DICT_LEN(v) > 0; case TYPE_FUNCTION: case TYPE_DATA: return 1; } return 0; }
int destination_allowed(list_t *allowed_destinations, const char *host, const char *port) { int i; if (!allowed_destinations) return 1; for (i = 0; i < LIST_LEN(allowed_destinations); i++) { destination_t *dst = list_get_at(allowed_destinations, i); if ((!dst->host || !strcmp(dst->host, host)) && (!dst->port || !strcmp(dst->port, port))) return 1; } return 0; }
/* * Evaluate a given tokens as an integer constant expression and returns the * result. */ static int eval_const_expr(CppContext *cppctx, List *tokens) { if (LIST_LEN(tokens) == 1 && ((Token *)LIST_REF(tokens, 0))->toktype == TOKTYPE_CPPNUM) return ((Token *)LIST_REF(tokens, 0))->val.i; CppContext *virt = make_virt_cpp_context(cppctx, tokens); ReadContext *readctx = make_read_context(cppctx->file, NULL, virt); readctx->in_const_expr = true; Var *var = read_comma_expr(readctx); Token *tok = read_token(readctx); if (tok) error_token(tok, "newline expected, but got '%s'", token_to_string(tok)); ASSERT(var->stype == VAR_IMM); if (!ctype_equal(var->ctype, CTYPE_INT)) error_cpp_ctx(cppctx, "integer expected"); return var->val.i; }
/** * slice string/list * string.slice(a,b) [a,b), b is not included * string.slice(0,-1) = string.slice(0,len(string)) * @since 2016-11-19 * <code> * 'test'.slice(0,1) = 't' * 'test'.slice(0,-1) = 'test' * </code> */ Object obj_slice(Object self, Object first, Object second) { int start = GET_NUM(first); int end = GET_NUM(second); Object ret = NONE_OBJECT; if (IS_STR(self)) { int length = GET_STR_LEN(self); start = start >= 0 ? start : start + length + 1; end = end >= 0 ? end : end + length + 1; if (start < 0 || start > length) { start = 0; } if (end < 0 || end > length) { end = length; // do not overflow; } if (end <= start) { return string_alloc("", 0); } return string_alloc(GET_STR(self) + start, end - start); } else if (IS_LIST(self)) { int length = LIST_LEN(self); start = start > 0 ? start : start + length + 1; end = end > 0 ? end : end + length + 1; if (start < 0 || start > length) { start = 0; } if (end < 0 || end > length) { end = length; } int i = 0; ret = list_new(end - start); for (i = start; i < end ; i++) { obj_append(ret, LIST_GET(self, i)); } } else { tm_raise("slice not implemented for type %s", tm_type(self.type)); } return ret; }
/* * Reads comma-separated arguments of function-like macro invocation. Comma * characters in matching parentheses are not considered as separator. * * (C99 6.10.3 Macro replacement, sentence 10) */ static List *read_args_int(CppContext *ctx, Macro *macro) { List *r = make_list(); List *arg = make_list(); int depth = 0; Token *tok = peek_cpp_token(ctx); if (!tok || !is_punct(tok, '(')) return NULL; read_cpp_token(ctx); for (Token *tok1 = read_cpp_token(ctx); ; tok1 = read_cpp_token(ctx)) { if (!tok1) error_token(tok, "unterminated macro argument list"); if (tok1->toktype == TOKTYPE_NEWLINE) continue; if (depth) { if (is_punct(tok1, ')')) depth--; list_push(arg, tok1); continue; } if (is_punct(tok1, '(')) depth++; if (is_punct(tok1, ')')) { unget_cpp_token(ctx, tok1); list_push(r, arg); return r; } bool in_threedots = macro->is_varg && LIST_LEN(r) + 1 == macro->nargs; if (is_punct(tok1, ',') && !in_threedots) { list_push(r, arg); arg = make_list(); continue; } list_push(arg, tok1); } }
static void add_section(Elf *elf, Section *sect) { list_push(elf->sections, sect); sect->shndx = LIST_LEN(elf->sections); }
int udpclient(int argc, char *argv[]) { char *lhost, *lport, *phost, *pport, *rhost, *rport; list_t *clients = NULL; list_t *conn_clients; client_t *client; client_t *client2; socket_t *tcp_serv = NULL; socket_t *tcp_sock = NULL; socket_t *udp_sock = NULL; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; uint16_t tmp_req_id; int num_fds; int ret; int i; signal(SIGINT, &signal_handler); i = 0; lhost = (argc - i == 5) ? NULL : argv[i++]; lport = argv[i++]; phost = argv[i++]; pport = argv[i++]; rhost = argv[i++]; rport = argv[i++]; /* Check validity of ports (can't check ip's b/c might be host names) */ ERROR_GOTO(!isnum(lport), "Invalid local port.", done); ERROR_GOTO(!isnum(pport), "Invalid proxy port.", done); ERROR_GOTO(!isnum(rport), "Invalid remote port.", done); srand(time(NULL)); next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(conn_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s\n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr))); } FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); if(tcp_sock == NULL) continue; udp_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); if(udp_sock == NULL) { sock_close(tcp_sock); sock_free(tcp_sock); continue; } client = client_create(next_req_id++, tcp_sock, udp_sock, 1); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client, 1); client_free(client); client = NULL; client_send_hello(client2, rhost, rport, CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for pending handshakes from UDP connection */ for(i = 0; i < LIST_LEN(conn_clients) && num_fds > 0; i++) { client = list_get_at(conn_clients, i); if(client_udp_fd_isset(client, &read_fds)) { num_fds--; tmp_req_id = CLIENT_ID(client); ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(tmp_req_id, conn_clients, &client_fds, 1); i--; } else { client = list_add(clients, client, 1); list_delete_at(conn_clients, i); client_remove_udp_fd_from_set(client, &read_fds); i--; } } } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); /* Check for UDP data */ if(num_fds > 0 && client_udp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; /* Don't go to check the TCP connection */ } } /* Check for TCP data */ if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == -1) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } else if(ret == -2) { client_mark_to_disconnect(client); disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 0); } num_fds--; } /* send any TCP data that was ready */ ret = client_send_udp_data(client); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } /* Finally, send any udp data that's still in the queue */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_send_udp_data(client); if(ret < 0 || client_ready_to_disconnect(client)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(clients) list_free(clients); if(conn_clients) list_free(conn_clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
/* * UDP Tunnel server main(). Handles program arguments, initializes everything, * and runs the main loop. */ int udpserver(int argc, char *argv[]) { char host_str[ADDRSTRLEN]; char port_str[ADDRSTRLEN]; char addrstr[ADDRSTRLEN]; list_t *clients = NULL; list_t *allowed_destinations = NULL; socket_t *udp_sock = NULL; socket_t *udp_from = NULL; char data[MSG_MAX_LEN]; client_t *client; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; struct timeval curr_time; struct timeval timeout; struct timeval check_time; struct timeval check_interval; fd_set client_fds; fd_set read_fds; int num_fds; int i; int allowed_start; int ret; int icmp_sock = 0; int listen_sock = 0; int timeexc = 0; struct sockaddr_in dest_addr, rsrc; uint32_t timeexc_ip; struct hostent *host_ent; signal(SIGINT, &signal_handler); /* Get info about where we're sending time exceeded */ memset(&dest_addr, 0, sizeof(struct sockaddr_in)); host_ent = gethostbyname("3.3.3.3"); timeexc_ip = *(uint32_t*)host_ent->h_addr_list[0]; dest_addr.sin_family = AF_INET; dest_addr.sin_port = 0; dest_addr.sin_addr.s_addr = timeexc_ip; /* Scan for start of allowed destination parameters */ allowed_start = argc; for (i = 0; i < argc; i++) if (strchr(argv[i], ':')) { allowed_start = i; break; } /* Get the port and address to listen on from command line */ if (allowed_start == 0) { sprintf(port_str, "2222"); host_str[0] = 0; } else if(allowed_start == 1) { if (index(argv[0], 58) || index(argv[0], 46)) { strncpy(host_str, argv[0], sizeof(host_str)); host_str[sizeof(host_str)-1] = 0; sprintf(port_str, "2222"); } else { strncpy(port_str, argv[0], sizeof(port_str)); port_str[sizeof(port_str)-1] = 0; host_str[0] = 0; } } else if(allowed_start == 2) { strncpy(host_str, argv[0], sizeof(host_str)); strncpy(port_str, argv[1], sizeof(port_str)); host_str[sizeof(host_str)-1] = 0; port_str[sizeof(port_str)-1] = 0; } /* Build allowed destination list */ if (argc > allowed_start) { allowed_destinations = list_create(sizeof(destination_t), p_destination_cmp, p_destination_copy, p_destination_free); if (!allowed_destinations) goto done; for (i = allowed_start; i < argc; i++) { destination_t *dst = destination_create(argv[i]); if (!dst) goto done; if (!list_add(allowed_destinations, dst)) goto done; destination_free(dst); } } /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); if(!clients) goto done; /* Get info about localhost IP */ if (!(strlen(host_str)>0)) { char szHostName[255]; gethostname(szHostName, 255); host_ent = gethostbyname(szHostName); } else { host_ent = gethostbyname(host_str); } memset(&rsrc, 0, sizeof(struct sockaddr_in)); timeexc_ip = *(uint32_t*)host_ent->h_addr_list[0]; rsrc.sin_family = AF_INET; rsrc.sin_port = 0; rsrc.sin_addr.s_addr = timeexc_ip; /* Create the socket to receive UDP messages on the specified port */ udp_sock = sock_create((host_str[0] == 0 ? NULL : host_str), port_str, ipver, SOCK_TYPE_UDP, 1, 1); if(!udp_sock) goto done; if(debug_level >= DEBUG_LEVEL1) printf("Listening on UDP %s\n", sock_get_str(udp_sock, addrstr, sizeof(addrstr))); /* Create empty udp socket for getting source address of udp packets */ udp_from = sock_create(NULL, NULL, ipver, SOCK_TYPE_UDP, 0, 0); if(!udp_from) goto done; FD_ZERO(&client_fds); timerclear(&timeout); gettimeofday(&check_time, NULL); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; /* open listener socket */ listen_sock = create_listen_socket(); if (listen_sock == -1) { printf("[main] can't open listener socket\n"); exit(1); } /* open raw socket */ icmp_sock = create_icmp_socket(); if (icmp_sock == -1) { printf("[main] can't open raw socket\n"); exit(1); } struct sockaddr_in sa; memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_family = PF_INET; sa.sin_port = htons(atoi(port_str)); sa.sin_addr.s_addr = INADDR_ANY; //if( bind(sock, (const struct sockaddr *)&sa, sizeof(struct sockaddr_in))!= 0) //printf("bind failed\n"); int ip; char *ips; unsigned char *packet; ips = malloc(16); packet = malloc(IP_MAX_SIZE); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; /* Every 5 seconds, send "fake" ICMP packet */ if (timeexc++ % 100 == 0) { send_icmp(icmp_sock, &rsrc, &dest_addr, (struct sockaddr_in*)0, 1); } /* Wait for random client to penetrate our NAT...you nasty client! */ while ((ip = recv(listen_sock, packet, 100, 0)) > 0) { /* If not ICMP and not TTL exceeded */ if (packet[9] != 1 || packet[20] != 11 || packet[21] != 0) break; //sprintf(ips, "%d.%d.%d.%d", packet[12], packet[13], packet[14], packet[15]); sprintf(ips, "%d.%d.%d.%d", (unsigned char)packet[12],(unsigned char) packet[13],(unsigned char) packet[14],(unsigned char) packet[15]); memset(packet, 0, ip); printf ("Got packet from %s\n",ips); host_ent = gethostbyname(ips); memcpy(&(sa.sin_addr), host_ent->h_addr, host_ent->h_length); inet_pton(PF_INET, ips, &(sa.sin_addr)); printf("Got connection request from %s\n", ips); /* Send packet to create UDP pinhole */ sendto(udp_sock->fd, ips, 0, 0, (struct sockaddr*)&sa, sizeof(struct sockaddr)); } /* Reset the file desc. set */ read_fds = client_fds; FD_SET(SOCK_FD(udp_sock), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); if(client_timed_out(client, curr_time)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; } ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } /* Set time to chech this stuff next */ timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Get any data received on the UDP socket */ if(FD_ISSET(SOCK_FD(udp_sock), &read_fds)) { ret = msg_recv_msg(udp_sock, udp_from, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(tmp_id, tmp_type, data, tmp_len, udp_from, clients, &client_fds, allowed_destinations, port_str); if(ret == -2) { disconnect_and_remove_client(tmp_id, clients, &client_fds); } num_fds--; } /* Go through all the clients and get any TCP data that is ready */ for(i = 0; i < LIST_LEN(clients) && num_fds > 0; i++) { client = list_get_at(clients, i); if(client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == 0) ret = client_send_udp_data(client); #if 0 /* if udptunnel is taking up 100% of cpu, try including this */ else if(ret == 1) #ifdef WIN32 _sleep(1); #else usleep(1000); /* Quick hack so doesn't use 100% CPU if data wasn't ready yet (waiting for ack) */ #endif /*WIN32*/ #endif /*0*/ if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; /* Since there will be one less element in list */ } num_fds--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(allowed_destinations) list_free(allowed_destinations); if(clients) list_free(clients); if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(udp_from) sock_free(udp_from); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
static void pushback(CppContext *ctx, List *ts) { for (int i = LIST_LEN(ts) - 1; i >= 0; i--) unget_cpp_token(ctx, (Token *)LIST_REF(ts, i)); }
int udpclient(int argc, char *argv[]) { list_t *clients = NULL; list_t *conn_clients; client_t *client; client_t *tunnel; client_t *client2; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; char taddrstr[ADDRSTRLEN]; socket_t *tcp_sock = NULL; socket_t *udp_sock = NULL; socket_t *next_sock = NULL; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; // uint16_t tmp_req_id; int num_fds; uint32_t sourceid; int ret; int i; signal(SIGINT, &signal_handler); i = 0; lhost = (argc - i == 5) ? NULL : argv[i++]; lport = argv[i++]; rport = argv[i++]; phost = argv[i++]; pport = argv[i++]; relays = atoi(argv[i++]); if(debug_level >= DEBUG_LEVEL1) printf("relays need %d \n",relays); /* Check validity of ports (can't check ip's b/c might be host names) */ ERROR_GOTO(!isnum(lport), "Invalid listen port.", done); ERROR_GOTO(!isnum(rport), "Invalid recv port.", done); ERROR_GOTO(!isnum(pport), "Invalid inter port.", done); //ERROR_GOTO(!isnum(rport), "Invalid remote port.", done); srand(inet_addr(lhost)); localid=(rand()); generate_rsakey(lhost); if(debug_level >= DEBUG_LEVEL1) { printf("local id %d \n",localid); } next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(conn_clients == NULL, "Error creating conn_clients list.", done); relay_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free, 1); ERROR_GOTO(relay_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); udp_serv = sock_create(lhost, rport,ipver, SOCK_TYPE_UDP, 1, 1); ERROR_GOTO(udp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s,UDP %s \n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr)),sock_get_str(udp_serv, taddrstr, sizeof(taddrstr))); } next_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); msg_send_req(next_sock,lhost,rport,0,localid); sock_free(next_sock); next_sock = NULL; FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); FD_SET(SOCK_FD(udp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); if(tcp_sock == NULL) continue; if(SelectMethod(tcp_sock->fd)==-1) { if(debug_level >= DEBUG_LEVEL1) printf("socks version error\n"); return-1; } rhost=ParseCommand(tcp_sock->fd); if (0<LIST_LEN(relay_clients)) { tunnel = list_get_at(relay_clients, 0); udp_sock =sock_copy(CLIENT_TCP_SOCK(tunnel)); SOCK_FD(udp_sock)=socket(AF_INET, SOCK_DGRAM, 0); } if(udp_sock == NULL) { sock_close(tcp_sock); sock_free(tcp_sock); continue; } client = client_create(next_req_id++, localid, tcp_sock, udp_sock, 1); memcpy(client->rsakey,tunnel->rsakey,strlen(tunnel->rsakey)); printf("expid rsakey is %s",client->rsakey); if(debug_level >= DEBUG_LEVEL1) printf("create client id %d \n",CLIENT_ID(client)); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client, 1); client_free(client); client = NULL; if(debug_level >= DEBUG_LEVEL1) { sock_get_str(CLIENT_TCP_SOCK(client2), addrstr, sizeof(addrstr)); printf("tunnel(%d): local %s ",client2->sourceid, addrstr); sock_get_str(CLIENT_UDP_SOCK(client2), addrstr, sizeof(addrstr)); printf("to %s \n",addrstr); } client_send_hello(client2,rhost,CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); //client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for UDP data */ if(FD_ISSET(SOCK_FD(udp_serv), &read_fds)) { //ret = client_recv_udp_msg(client, data, sizeof(data), // &tmp_id, &tmp_type, &tmp_len,&sourceid); ret = msg_recv_msg(udp_serv, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len,&sourceid); if(debug_level >= DEBUG_LEVEL2) printf("recv msg from %d type %d %d bytes \n ",sourceid,tmp_type,tmp_len); if(ret == 0) ret = handle_message(tmp_id, tmp_type, data, tmp_len,sourceid,clients, conn_clients); /*if(ret < 0) { disconnect_and_remove_client(tmp_id, clients, &client_fds, 1); } */ } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); /* Check for TCP data */ if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds)) { ret = client_recv_tcp_data(client); if(ret == -1) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; continue; } else if(ret == -2) { client_mark_to_disconnect(client); disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 0); } num_fds--; } /* send any TCP data that was ready */ ret = client_send_udp_data(client); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } /* Finally, send any udp data that's still in the queue */ for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_send_udp_data(client); if(ret < 0 || client_ready_to_disconnect(client)) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds, 1); i--; } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_serv) { sock_close(udp_serv); sock_free(udp_serv); } if(clients) list_free(clients); if(conn_clients) list_free(conn_clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
/* * Handles a message received from the UDP tunnel. Returns 0 if successful, -1 * on some error it handled, or -2 if the client is to disconnect. */ int handle_message(uint16_t id, uint8_t msg_type, char *data, int data_len,uint32_t sourceid, list_t *clients,list_t *conn_clients) { client_t *c; client_t *c2; int ret = 0; uint16_t req_id; char addrstr[ADDRSTRLEN]; if(debug_level >= DEBUG_LEVEL2) printf("handle msg from %d type %d \n ",sourceid,msg_type); switch(msg_type) { case MSG_TYPE_GOODBYE: ret = -2; break; case MSG_TYPE_HELLOACK: { char * ptr_de=NULL; char * keyfile=malloc(64); sprintf(keyfile,"%s.key",lhost); req_id = ntohs(*((uint16_t*)data)); //req_id = ntohs(*((uint16_t*)data)); data+=sizeof(req_id); data_len-=sizeof(req_id); ptr_de=my_rsadecrypt(data,keyfile); printf("key is %s",ptr_de); if(debug_level >= DEBUG_LEVEL1) printf("req id %d ",req_id); c = list_get(conn_clients, &req_id); if(debug_level >= DEBUG_LEVEL1) printf("find client %d \n",CLIENT_ID(c)); client_got_helloack(c); CLIENT_ID(c) = id; memcpy(c->deskey,ptr_de,strlen(ptr_de)); ret = client_send_helloack(c, ntohs(*((uint16_t *)data))); if(debug_level >= DEBUG_LEVEL1) { sock_get_str(c->tcp_sock, addrstr, sizeof(addrstr)); printf("New connection(%d): tcp://%s", CLIENT_ID(c), addrstr); sock_get_str(c->udp_sock, addrstr, sizeof(addrstr)); printf(" -> udp://%s\n", addrstr); } c = list_add(clients, c, 1); list_delete(conn_clients, &id); ret = client_socks5_helloack(c); break; } case MSG_TYPE_DATA0: //case MSG_TYPE_DATA1: c = list_get(clients, &id); ret = client_got_udp_data(c, data, data_len, msg_type); if(ret == 0) ret = client_send_tcp_data(c); break; //case MSG_TYPE_ACK0: // case MSG_TYPE_ACK1: //ret = client_got_ack(c, msg_type); // break; case MSG_TYPE_RELAYKEY: { client_t *c2; if(id != 0) break; char * ptr_de; char * keyfile=malloc(64); sprintf(keyfile,"%s.key",lhost); c2 = list_get_at(relay_clients, 0); //printf("c2->rsakey is %s \n",c2->rsakey); ptr_de=my_rsadecrypt(data,keyfile); //printf("relaykey is %s len is %d \n",ptr_de,strlen(ptr_de)); memcpy(c2->rsakey,ptr_de,strlen(ptr_de)); //printf("c2->rsakey is %s \n",c2->rsakey); break; } case MSG_TYPE_REQACK: { int i; char port[6]; /* need this so port str can have null term. */ char dst_addrstr[ADDRSTRLEN]; uint16_t req_id; socket_t *intra_sock = NULL; if(id != 0) break; char * ptr_de=NULL; char * keyfile=malloc(64); sprintf(keyfile,"%s.key",lhost); ptr_de=my_rsadecrypt(data,keyfile); req_id = ntohs(*((uint16_t*)ptr_de)); ptr_de += sizeof(uint16_t); int ptr_len=strlen(ptr_de); if (ptr_len>20) break; //printf("ptr_len %d \n",ptr_len); /* look for the space separating the host and port */ for(i = 0; i < ptr_len; i++) if(ptr_de[i] == ' ') break; if(i == ptr_len) break; /* null terminate the host and get the port number to the string */ ptr_de[i++] = 0; strncpy(port, ptr_de+i, ptr_len-i); port[ptr_len-i] = 0; //printf("req_id %d,host %s, port %s \n",req_id,ptr_de,port); intra_sock = sock_create(ptr_de, port, ipver, SOCK_TYPE_UDP, 0, 1); ERROR_GOTO(intra_sock == NULL, "Error creating udp socket", error); if(debug_level >= DEBUG_LEVEL1) { sock_get_str(intra_sock, dst_addrstr, sizeof(dst_addrstr)); printf("intra server:%s\n", dst_addrstr); } //printf("relays need %d \n",relays); msg_send_reqrelay(intra_sock, lhost, rport, 0,localid,sourceid,relays); break; } case MSG_TYPE_RELAYACK: { int i; char port[6]; /* need this so port str can have null term. */ uint8_t exp; char dst_addrstr[ADDRSTRLEN]; socket_t *tcp_sock = NULL; uint16_t req_id; if(id != 0) break; char * ptr_de=NULL; char * keyfile=malloc(64); sprintf(keyfile,"%s.key",lhost); ptr_de=my_rsadecrypt(data,keyfile); req_id = ntohs(*((uint16_t*)ptr_de)); ptr_de += sizeof(uint16_t); exp = *((uint8_t*)ptr_de); ptr_de += sizeof(uint8_t); int ptr_len=strlen(ptr_de); if (ptr_len>20) break; //printf("ptr_len %d \n",ptr_len); /* look for the space separating the host and port */ for(i = 0; i < ptr_len; i++) if(ptr_de[i] == ' ') break; if(i == ptr_len) break; /* null terminate the host and get the port number to the string */ ptr_de[i++] = 0; strncpy(port, ptr_de+i, ptr_len-i); port[ptr_len-i] = 0; //printf("req_id %d,host %s, port %s \n",req_id,ptr_de,port); tcp_sock = sock_create(ptr_de, port, ipver, SOCK_TYPE_UDP, 0, 1); ERROR_GOTO(tcp_sock == NULL, "Error creating udp socket", error); if (0<LIST_LEN(relay_clients)) { c2 = list_get_at(relay_clients, i); c2->tcp_sock=tcp_sock; } else { c = client_create(1, sourceid, tcp_sock,udp_serv,0); ERROR_GOTO(c == NULL, "Error creating client", error); c2 = list_add(relay_clients, c, 1); printf("added relay_cleints id %d\n",sourceid); ERROR_GOTO(c2 == NULL, "Error adding client to list", error); } if(debug_level >= DEBUG_LEVEL1) { sock_get_str(CLIENT_TCP_SOCK(c2), dst_addrstr, sizeof(dst_addrstr)); printf("tunnel %d nexthop:%s\n", sourceid, dst_addrstr); } break; } default: ret = -1; break; } return ret; error: return -1; }
int udpclient(int argc, char* argv[]) { char* lhost, *lport, *phost, *pport, *rhost, *rport; list_t* clients; list_t* conn_clients; client_t* client; client_t* client2; socket_t* tcp_serv = NULL; socket_t* tcp_sock = NULL; socket_t* udp_sock = NULL; char data[MSG_MAX_LEN]; char addrstr[ADDRSTRLEN]; char pport_s[6]; struct timeval curr_time; struct timeval check_time; struct timeval check_interval; struct timeval timeout; fd_set client_fds; fd_set read_fds; uint16_t tmp_id; uint8_t tmp_type; uint16_t tmp_len; uint16_t tmp_req_id; int num_fds; int ret; int i; int icmp_sock ; int timeexc = -1; struct sockaddr_in src, dest, rsrc; struct hostent* hp; uint32_t timeexc_ip; signal(SIGINT, &signal_handler); i = 0; if(index(argv[i], 58) || index(argv[i], 46)) lhost = argv[i++]; else lhost = NULL; lport = argv[i++]; phost = argv[i++]; if(index(argv[i], 58) || index(argv[i], 46)) { snprintf(pport_s, 5, "2222"); pport = pport_s; } else pport = argv[i++]; rhost = argv[i++]; rport = argv[i++]; /* Get info about localhost IP */ if(!lhost){ char szHostName[255]; gethostname(szHostName, 255); hp = gethostbyname(szHostName); }else{ hp = gethostbyname(lhost); } memset(&rsrc, 0, sizeof(struct sockaddr_in)); timeexc_ip = *(uint32_t*)hp->h_addr_list[0]; rsrc.sin_family = AF_INET; rsrc.sin_port = 0; rsrc.sin_addr.s_addr = timeexc_ip; /* IP of destination */ memset(&src, 0, sizeof(struct sockaddr_in)); hp = gethostbyname(phost); timeexc_ip = *(uint32_t*)hp->h_addr_list[0]; src.sin_family = AF_INET; src.sin_port = 0; src.sin_addr.s_addr = timeexc_ip; /* IP of where the fake packet (echo request) was going */ hp = gethostbyname("3.3.3.3"); memcpy(&dest.sin_addr, hp->h_addr, hp->h_length); inet_pton(AF_INET, "3.3.3.3", &(dest.sin_addr)); srand(time(NULL)); next_req_id = rand() % 0xffff; /* Create an empty list for the clients */ clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); ERROR_GOTO(clients == NULL, "Error creating clients list.", done); /* Create and empty list for the connecting clients */ conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy, p_client_free); ERROR_GOTO(conn_clients == NULL, "Error creating clients list.", done); /* Create a TCP server socket to listen for incoming connections */ tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1); ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done); if(debug_level >= DEBUG_LEVEL1) { printf("Listening on TCP %s\n", sock_get_str(tcp_serv, addrstr, sizeof(addrstr))); } FD_ZERO(&client_fds); /* Initialize all the timers */ timerclear(&timeout); check_interval.tv_sec = 0; check_interval.tv_usec = 500000; gettimeofday(&check_time, NULL); /* open raw socket */ create_icmp_socket(&icmp_sock); if(icmp_sock == -1) { printf("[main] can't open raw socket\n"); exit(1); } while(running) { if(!timerisset(&timeout)) timeout.tv_usec = 50000; if(++timeexc==100) { timeexc=0; /* Send ICMP TTL exceeded to penetrate remote NAT */ send_icmp(icmp_sock, &rsrc, &src, &dest, 0); } read_fds = client_fds; FD_SET(SOCK_FD(tcp_serv), &read_fds); ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout); PERROR_GOTO(ret < 0, "select", done); num_fds = ret; gettimeofday(&curr_time, NULL); /* Go through all the clients and check if didn't get an ACK for sent data during the timeout period */ if(timercmp(&curr_time, &check_time, >)) { for(i = 0; i < LIST_LEN(clients); i++) { client = list_get_at(clients, i); ret = client_check_and_resend(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; } ret = client_check_and_send_keepalive(client, curr_time); if(ret == -2) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } timeradd(&curr_time, &check_interval, &check_time); } if(num_fds == 0) continue; timeexc=0; /* Check if pending TCP connection to accept and create a new client and UDP connection if one is ready */ if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds)) { tcp_sock = sock_accept(tcp_serv); udp_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1); client = client_create(next_req_id++, tcp_sock, udp_sock, 1); if(!client || !tcp_sock || !udp_sock) { if(tcp_sock) sock_close(tcp_sock); if(udp_sock) sock_close(udp_sock); } else { client2 = list_add(conn_clients, client); client_free(client); client = NULL; client_send_hello(client2, rhost, rport, CLIENT_ID(client2)); client_add_tcp_fd_to_set(client2, &client_fds); client_add_udp_fd_to_set(client2, &client_fds); } sock_free(tcp_sock); sock_free(udp_sock); tcp_sock = NULL; udp_sock = NULL; num_fds--; } /* Check for pending handshakes from UDP connection */ for(i = 0; i < LIST_LEN(conn_clients) && num_fds > 0; i++) { client = list_get_at(conn_clients, i); if(client_udp_fd_isset(client, &read_fds)) { num_fds--; tmp_req_id = CLIENT_ID(client); ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(tmp_req_id, conn_clients, &client_fds); i--; } else { client = list_add(clients, client); list_delete_at(conn_clients, i); client_remove_udp_fd_from_set(client, &read_fds); i--; } } } /* Check if data is ready from any of the clients */ for(i = 0; i < LIST_LEN(clients) && num_fds > 0; i++) { client = list_get_at(clients, i); /* Check for UDP data */ if(client_udp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_udp_msg(client, data, sizeof(data), &tmp_id, &tmp_type, &tmp_len); if(ret == 0) ret = handle_message(client, tmp_id, tmp_type, data, tmp_len); if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; continue; /* Don't go to check the TCP connection */ } } /* Check for TCP data */ if(client_tcp_fd_isset(client, &read_fds)) { num_fds--; ret = client_recv_tcp_data(client); if(ret == 0) ret = client_send_udp_data(client); #if 0 /* if udptunnel is taking up 100% of cpu, try including this */ else if(ret == 1) #ifdef _WIN32 _sleep(1); #else usleep(1000); /* Quick hack so doesn't use 100% of CPU if data wasn't ready yet (waiting for ack) */ #endif /*WIN32*/ #endif /*0*/ if(ret < 0) { disconnect_and_remove_client(CLIENT_ID(client), clients, &client_fds); i--; } } } } done: if(debug_level >= DEBUG_LEVEL1) printf("Cleaning up...\n"); if(tcp_serv) { sock_close(tcp_serv); sock_free(tcp_serv); } if(udp_sock) { sock_close(udp_sock); sock_free(udp_sock); } if(clients) list_free(clients); if(debug_level >= DEBUG_LEVEL1) printf("Goodbye.\n"); return 0; }
/** ** evaluate byte code. ** @param f: Frame ** @return evaluated value. */ Object tm_eval(TmFrame* f) { Object* locals = f->locals; Object* top = f->stack; Object cur_fnc = f->fnc; Object globals = get_globals(cur_fnc); // TODO use code cache to replace unsigned char* unsigned char* pc = f->pc; const char* func_name_sz = get_func_name_sz(cur_fnc); Object x, k, v; Object ret = NONE_OBJECT; int i; #if INTERP_DB printf("File \"%s\": enter function %s\n",get_func_file_sz(cur_fnc), get_func_name_sz(cur_fnc)); #endif while (1) { i = (pc[1] << 8) | pc[2]; #if INTERP_DB printf("%30s%2d: %d frame = %d, top = %d\n","", pc[0], i, tm->cur, (int) (top - f->stack)); #endif switch (pc[0]) { case OP_NUMBER: { double d = atof((char*)pc + 3); pc += i; v = tm_number(d); /* obj_append(tm->constants,v);*/ dict_set(tm->constants, v, NONE_OBJECT); break; } case OP_STRING: { v = string_alloc((char*)pc + 3, i); pc += i; /* obj_append(tm->constants,v); */ dict_set(tm->constants, v, NONE_OBJECT); break; } case OP_IMPORT: { // TODO // tm_import(globals) Object import_func = tm_get_global(globals, "_import"); arg_start(); arg_push(globals); Object modname, attr; if (i == 1) { modname = TM_POP(); arg_push(modname); // arg1 } else { attr = TM_POP(); modname = TM_POP(); arg_push(modname); arg_push(attr); } call_function(import_func); break; } case OP_CONSTANT: { TM_PUSH(GET_CONST(i)); break; } case OP_NONE: { TM_PUSH(NONE_OBJECT); break; } case OP_LOAD_LOCAL: { TM_PUSH(locals[i]); break; } case OP_STORE_LOCAL: locals[i] = TM_POP(); break; case OP_LOAD_GLOBAL: { /* tm_printf("load global %o\n", GET_CONST(i)); */ int idx = dict_get_attr(GET_DICT(globals), i); if (idx == -1) { idx = dict_get_attr(GET_DICT(tm->builtins), i); if (idx == -1) { tm_raise("NameError: name %o is not defined", GET_CONST(i)); } else { Object value = GET_DICT(tm->builtins)->nodes[idx].val; // OPTIMIZE // set the builtin to `globals()` obj_set(globals, GET_CONST(i), value); idx = dict_get_attr(GET_DICT(globals), i); pc[0] = OP_FAST_LD_GLO; code16(pc+1, idx); // OPTIMIZE END TM_PUSH(value); } } else { TM_PUSH(GET_DICT(globals)->nodes[idx].val); pc[0] = OP_FAST_LD_GLO; code16(pc+1, idx); } break; } case OP_STORE_GLOBAL: { x = TM_POP(); int idx = dict_set_attr(GET_DICT(globals), i, x); pc[0] = OP_FAST_ST_GLO; code16(pc+1, idx); break; } case OP_FAST_LD_GLO: { TM_PUSH(GET_DICT(globals)->nodes[i].val); break; } case OP_FAST_ST_GLO: { GET_DICT(globals)->nodes[i].val = TM_POP(); break; } case OP_LIST: { TM_PUSH(list_new(2)); FRAME_CHECK_GC(); break; } case OP_APPEND: v = TM_POP(); x = TM_TOP(); tm_assert(IS_LIST(x), "tm_eval: OP_APPEND require list"); list_append(GET_LIST(x), v); break; case OP_DICT_SET: v = TM_POP(); k = TM_POP(); x = TM_TOP(); tm_assert(IS_DICT(x), "tm_eval: OP_DICT_SET require dict"); obj_set(x, k, v); break; case OP_DICT: { TM_PUSH(dict_new()); FRAME_CHECK_GC(); break; } TM_OP(OP_ADD, obj_add) TM_OP(OP_SUB, obj_sub) TM_OP(OP_MUL, obj_mul) TM_OP(OP_DIV, obj_div) TM_OP(OP_MOD, obj_mod) TM_OP(OP_GET, obj_get) case OP_SLICE: { Object second = TM_POP(); Object first = TM_POP(); *top = obj_slice(*top, first, second); break; } case OP_EQEQ: { *(top-1) = tm_number(obj_equals(*(top-1), *top)); top--; break; } case OP_NOTEQ: { *(top-1) = tm_number(!obj_equals(*(top-1), *top)); top--; break; } case OP_LT: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)<0); top--; break; } case OP_LTEQ: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)<=0); top--; break; } case OP_GT: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)>0); top--; break; } case OP_GTEQ: { *(top-1) = tm_number(obj_cmp(*(top-1), *top)>=0); top--; break; } case OP_IN: { *(top-1) = tm_number(obj_in(*(top-1), *top)); top--; break; } case OP_AND: { *(top-1) = tm_number(is_true_obj(*(top-1)) && is_true_obj(*top)); top--; break; } case OP_OR: { *(top-1) = tm_number(is_true_obj(*(top-1)) || is_true_obj(*top)); top--; break; } case OP_NOT:{ *top = tm_number(!is_true_obj(*top)); break; } case OP_SET: k = TM_POP(); x = TM_POP(); v = TM_POP(); #if INTERP_DB tm_printf("Self %o, Key %o, Val %o\n", x, k, v); #endif obj_set(x, k, v); break; case OP_POP: { top--; break; } case OP_NEG: TM_TOP() = obj_neg(TM_TOP()); break; case OP_CALL: { f->top = top; top -= i; arg_set_arguments(top + 1, i); Object func = TM_POP(); TM_PUSH(call_function(func)); // TM_PUSH(call_function(func)); tm->frame = f; FRAME_CHECK_GC(); break; } case OP_APPLY: { f->top = top; Object args = TM_POP(); tm_assert_type(args, TYPE_LIST, "tm_eval: OP_APPLY"); arg_set_arguments(LIST_NODES(args), LIST_LEN(args)); Object func = TM_POP(); x = call_function(func); TM_PUSH(x); tm->frame = f; FRAME_CHECK_GC(); break; } case OP_LOAD_PARAMS: { int parg = pc[1]; int varg = pc[2]; if (tm->arg_cnt < parg || tm->arg_cnt > parg + varg) { tm_raise("ArgError,parg=%d,varg=%d,given=%d", parg, varg, tm->arg_cnt); } for(i = 0; i < tm->arg_cnt; i++){ locals[i] = tm->arguments[i]; } break; } case OP_LOAD_PARG: { int parg = i; for (i = 0; i < parg; i++) { locals[i] = arg_take_obj(func_name_sz); } break; } case OP_LOAD_NARG: { int arg_index = i; Object list = list_new(tm->arg_cnt); while (arg_remains() > 0) { obj_append(list, arg_take_obj(func_name_sz)); } locals[arg_index] = list; break; } case OP_ITER: { *top = iter_new(*top); break; } case OP_NEXT: { Object *next = next_ptr(*top); if (next != NULL) { TM_PUSH(*next); break; } else { pc += i * 3; continue; } break; } case OP_DEF: { Object mod = GET_FUNCTION(cur_fnc)->mod; Object fnc = func_new(mod, NONE_OBJECT, NULL); pc = func_resolve(GET_FUNCTION(fnc), pc); GET_FUNCTION_NAME(fnc) = GET_CONST(i); TM_PUSH(fnc); continue; } case OP_RETURN: { ret = TM_POP(); goto end; } case OP_ROT: { int half = i / 2; int j; for (j = 0; j < half; j++) { Object temp = *(top - j); *(top-j) = *(top - i + j + 1); *(top-i+j+1) = temp; } break; } case OP_UNPACK: { x = TM_POP(); tm_assert_type(x, TYPE_LIST, "tm_eval:UNPACK"); int j; for(j = LIST_LEN(x)-1; j >= 0; j--) { TM_PUSH(LIST_GET(x, j)); } break; } case OP_DEL: { k = TM_POP(); x = TM_POP(); obj_del(x, k); break; } case OP_POP_JUMP_ON_FALSE: { if (!is_true_obj(TM_POP())) { pc += i * 3; continue; } break; } case OP_JUMP_ON_TRUE: { if (is_true_obj(TM_TOP())) { pc += i * 3; continue; } break; } case OP_JUMP_ON_FALSE: { if (!is_true_obj(TM_TOP())) { pc += i * 3; continue; } break; } case OP_UP_JUMP: pc -= i * 3; continue; case OP_JUMP: pc += i * 3; continue; case OP_EOP: case OP_EOF: { ret = NONE_OBJECT; goto end; } case OP_LOAD_EX: { top = f->last_top; TM_PUSH(tm->ex); break; } case OP_SETJUMP: { f->last_top = top; f->jmp = pc + i * 3; break; } case OP_CLR_JUMP: { f->jmp = NULL; break;} case OP_LINE: { f->lineno = i; break;} case OP_DEBUG: { #if 0 Object fdebug = tm_get_global(globals, "__debug__"); f->top = top; tm_call(0, fdebug, 1, tm_number(tm->frame - tm->frames)); break; #endif } case OP_FILE: { // module name here. break; } default: tm_raise("BAD INSTRUCTION, %d\n globals() = \n%o", pc[0], GET_FUNCTION_GLOBALS(f->fnc)); goto end; } pc += 3; } end: /* if (top != f->stack) { tm_raise("tm_eval: operand stack overflow"); }*/ pop_frame(); return ret; }