y_nnn : change learn_to_drive and add some bash print
This commit is contained in:
@@ -130,6 +130,7 @@ struct print_params * create_print_params(float scale_x, float scale_y, struct
|
||||
pprint->delay = delay;
|
||||
pprint->string_space = malloc(LOG_LENTH+1);
|
||||
pthread_mutex_init(&(pprint->mut_printed), NULL);
|
||||
pprint->go_on = 1;
|
||||
|
||||
int i;
|
||||
for( i=0; i<LOG_LENTH; ++i)
|
||||
@@ -204,6 +205,15 @@ void free_delay_params (struct delay_params *dly_p){
|
||||
free(dly_p);
|
||||
}
|
||||
|
||||
int check_go_on_print_params(struct print_params *pprint){
|
||||
int ret=0;
|
||||
pthread_mutex_lock(&(pprint->mut_printed));
|
||||
ret=pprint->go_on;
|
||||
pthread_mutex_unlock(&(pprint->mut_printed));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_print_params (struct print_params *pprint){
|
||||
free(pprint->string_space);
|
||||
pthread_mutex_destroy(&(pprint->mut_printed));
|
||||
@@ -388,15 +398,15 @@ void learn_to_drive(struct RL_agent * rlAgent){
|
||||
//struct print_params * pprint = rlAgent->pprint;
|
||||
char msg[100];
|
||||
|
||||
pthread_t threadPrint;
|
||||
pthread_create(&threadPrint, NULL, runPrint, (void*)rlAgent);
|
||||
////pthread_t threadPrint;
|
||||
////pthread_create(&threadPrint, NULL, runPrint, (void*)rlAgent);
|
||||
|
||||
// while(true){
|
||||
for(size_t index_episode = 0; index_episode < qlParams->number_episodes; ++index_episode){
|
||||
reset(car);
|
||||
qlStatus->nb_training_after_updated_weight_in_target = 0;
|
||||
qlStatus->index_episode = index_episode;
|
||||
while(true){
|
||||
while(!is_ending(qlStatus) /*true*/){
|
||||
++(qlStatus->nb_episodes);
|
||||
++(qlStatus->nb_training_after_updated_weight_in_target);
|
||||
action = select_action(rlAgent);
|
||||
@@ -435,6 +445,6 @@ void learn_to_drive(struct RL_agent * rlAgent){
|
||||
pthread_mutex_unlock(qlStatus->mut_ending);
|
||||
// }
|
||||
|
||||
pthread_join(threadPrint, NULL);
|
||||
////pthread_join(threadPrint, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
//float d_reLU(float x);
|
||||
|
||||
extern char *action_name[8];
|
||||
|
||||
struct qlearning_params {
|
||||
float gamma;
|
||||
@@ -67,8 +68,11 @@ struct print_params {
|
||||
float scale_y;
|
||||
struct delay_params *delay;
|
||||
char *string_space;//[LOG_LENTH];
|
||||
int go_on;
|
||||
};
|
||||
|
||||
int check_go_on_print_params(struct print_params *pprint);
|
||||
|
||||
struct networks_qlearning {
|
||||
config_layers *config;
|
||||
neurons_TYPE_FLOAT *main_net;
|
||||
@@ -136,5 +140,9 @@ void train_qlearning(struct RL_agent * rlAgent,
|
||||
// long reward;
|
||||
|
||||
void learn_to_drive(struct RL_agent * rlAgent);
|
||||
int is_ending(struct status_qlearning *qlStatus);
|
||||
|
||||
///char *fileNameDateScore(char * pre, char* post,size_t score);
|
||||
///int select_action(struct RL_agent * rlAgent);
|
||||
|
||||
#endif /* __LEARNING_VEHICLE__C_H____ */
|
||||
|
||||
@@ -370,7 +370,8 @@ void goto_xy(int x, int y)
|
||||
}
|
||||
|
||||
|
||||
static struct winsize w;
|
||||
//static
|
||||
struct winsize w;
|
||||
|
||||
void init_win(){
|
||||
ioctl(1, TIOCGWINSZ, &w);
|
||||
|
||||
@@ -130,4 +130,8 @@ float distance2_coordinate(coordinate *c0, coordinate *c1);
|
||||
void print2D_blocks(struct blocks *blk, float scale_x, float scale_y, char pad);
|
||||
void print2D_blocks_withPoint(struct blocks *blk, float scale_x, float scale_y, char pad, coordinate *coordPoint);
|
||||
|
||||
extern struct winsize w;
|
||||
void init_win();
|
||||
struct blocks * block_neighbord_Point(coordinate *coord, float *radius );
|
||||
|
||||
#endif /* __VEHICLE__C_H__ */
|
||||
|
||||
@@ -4,10 +4,26 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "learn_to_drive.h"
|
||||
|
||||
#include "y_net_neur_net/y_nnn_screen_manager.h"
|
||||
|
||||
#include "y_socket_t/y_socket_t.h"
|
||||
|
||||
void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg);
|
||||
|
||||
struct arg_run_qlearn_bprint{
|
||||
struct arg_bash *bash_arg;
|
||||
struct RL_agent *rlAgent;
|
||||
};
|
||||
|
||||
struct arg_run_qlearn_bprint * create_arg_run_qlearn_bprint(
|
||||
struct arg_bash *bash_arg,
|
||||
struct RL_agent *rlAgent
|
||||
);
|
||||
|
||||
void free_arg_run_qlearn_bprint(struct arg_run_qlearn_bprint *arg);
|
||||
|
||||
void* runBashPrint(void *arg);
|
||||
|
||||
#endif /* Y_NETWORK_NEURAL_NETWORK__MANAGER__H_C */
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "list_t/list_t.h"
|
||||
|
||||
#include "vehicle.h"
|
||||
|
||||
GENERATE_LIST_ALL(pid_t)
|
||||
|
||||
#define SIZE_LOCAL_BUF 300
|
||||
@@ -23,6 +25,16 @@ GENERATE_LIST_ALL(pid_t)
|
||||
#define GOTO_TOP_LEFT "\x1B[0;0f"
|
||||
#define LEN_GOTO_TOP_LEFT 6
|
||||
|
||||
#define BASH_WRITE_IF_EXIST(bash,buf,len_buf) \
|
||||
do{\
|
||||
if(bash_arg->fd_new_bash_pid>0){\
|
||||
write(bash_arg->fd_new_bash_pid, buf, len_buf);\
|
||||
}\
|
||||
if(bash_arg->fd_current_bash_pid>0){\
|
||||
write(bash_arg->fd_current_bash_pid, buf, len_buf);\
|
||||
}\
|
||||
} while(0);
|
||||
|
||||
//#include "y_socket_t/y_list_var_tool.h"
|
||||
|
||||
pid_t pidof(char *target, struct main_list_pid_t *m_pid_t);
|
||||
@@ -56,6 +68,7 @@ void free_arg_bash(struct arg_bash *arg);
|
||||
|
||||
int write_duplicate_bash(int fd, char *content, size_t size_content);
|
||||
|
||||
int new_bash_exist(struct arg_bash *bash_arg);
|
||||
|
||||
void* run_newbash(void *arg);
|
||||
void* wait_newbash(void *arg);
|
||||
@@ -69,4 +82,8 @@ void* launch_new_bash(void *arg);
|
||||
void* launch_wait_bash(void *arg);
|
||||
void* launch_sleep_wait_bash(void *arg);
|
||||
|
||||
void bash_print_vehicle_n_path(struct vehicle *v, float scale_x, float scale_y, struct arg_bash *bash_arg);
|
||||
void bash_print2D_blocks_indexOne_withPoint(struct blocks *blk, float scale_x, float scale_y, coordinate *coordPoint, struct arg_bash *bash_arg);
|
||||
|
||||
|
||||
#endif /* Y_NETWORK_NEURAL_NETWORK__SCREEN_MANAGER__H_C */
|
||||
|
||||
@@ -2,18 +2,36 @@
|
||||
|
||||
#include "y_net_neur_net/y_nnn_manager.h"
|
||||
|
||||
struct arg_run_qlearn_bprint * create_arg_run_qlearn_bprint(
|
||||
struct arg_bash *bash_arg,
|
||||
struct RL_agent *rlAgent
|
||||
){
|
||||
struct arg_run_qlearn_bprint *r_arg=malloc(sizeof(struct arg_run_qlearn_bprint));
|
||||
r_arg->bash_arg = bash_arg;
|
||||
r_arg->rlAgent = rlAgent;
|
||||
|
||||
return r_arg;
|
||||
}
|
||||
|
||||
void free_arg_run_qlearn_bprint(struct arg_run_qlearn_bprint *arg){
|
||||
free_RL_agent(arg->rlAgent);
|
||||
free_arg_bash(arg->bash_arg);
|
||||
free(arg);
|
||||
}
|
||||
|
||||
void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg){
|
||||
//struct arg_bash *bash_arg=(struct arg_bash*)arg;
|
||||
struct arg_run_qlearn_bprint *run_arg=(struct arg_run_bash_print*)arg;
|
||||
struct arg_bash *bash_arg=run_arg->bash_arg;
|
||||
|
||||
if(arg && (len_buf>0)){
|
||||
|
||||
printf("debug: %s #%d (%d)\n",buf,len_buf,((struct arg_bash*)arg)->old_bash_pid);
|
||||
printf("debug: %s #%d (%d)\n",buf,len_buf,(bash_arg)->old_bash_pid);
|
||||
if(strncmp(buf,"newbash",7)==0){
|
||||
run_newbash(arg);
|
||||
run_newbash(bash_arg);
|
||||
}else if(strncmp(buf,"waitbash",8)==0){
|
||||
launch_sleep_wait_bash(arg);
|
||||
launch_sleep_wait_bash(bash_arg);
|
||||
}else if(strncmp(buf,"killbash",8)==0){
|
||||
kill_all_bash(arg);
|
||||
kill_all_bash(bash_arg);
|
||||
}else{
|
||||
printf("debug: %s is not handle\n",buf);
|
||||
}
|
||||
@@ -22,3 +40,69 @@ void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg){
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void* runBashPrint(void *arg){
|
||||
struct arg_run_bash_print *arg_run=(struct arg_run_bash_print*)arg;
|
||||
struct RL_agent *rlAgent = arg_run->rlAgent;
|
||||
struct arg_bash *bash_arg = arg_run->bash_arg;
|
||||
|
||||
struct status_qlearning *qlStatus = rlAgent->status;
|
||||
struct print_params * pprint = rlAgent->pprint;
|
||||
struct vehicle *car = rlAgent->car;
|
||||
size_t count_print = 0;
|
||||
char buf[SIZE_LOCAL_BUF];
|
||||
int len_buf;
|
||||
while((new_bash_exist(bash_arg)) && check_go_on_print_params(pprint) && !is_ending(qlStatus)){
|
||||
if(/*(qlStatus->nb_episodes %125 == 0) &&*/ pprint->printed){
|
||||
//pthread_mutex_lock(&(pprint->mut_printed));
|
||||
pthread_mutex_lock(&(car->mut_coord));
|
||||
bash_print_vehicle_n_path(car, pprint->scale_x, pprint->scale_y,bash_arg);
|
||||
pthread_mutex_unlock(&(car->mut_coord));
|
||||
//pthread_mutex_unlock(&(pprint->mut_printed));
|
||||
////printf("%s ",pprint->string_space);
|
||||
len_buf=sprintf(buf,"%s ",pprint->string_space);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
|
||||
////printf("ep: %ld\n",qlStatus->index_episode);
|
||||
len_buf=sprintf(buf,"ep: %ld\n",qlStatus->index_episode);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
neurons_TYPE_FLOAT * net_main = rlAgent->networks->main_net;
|
||||
neurons_TYPE_FLOAT * net_target = rlAgent->networks->target_net;
|
||||
for(size_t i=0; (i<net_main->output->dim->rank) && (new_bash_exist(bash_arg)); ++i) {
|
||||
////printf("{sensro[%s]:%f "" vs oldsens[%s]: %f}\n",action_name[i%COUNT_ACTION],net_target->output->x[i],
|
||||
len_buf = sprintf(buf,"{sensro[%s]:%f "" vs oldsens[%s]: %f}\n",action_name[i%COUNT_ACTION],net_target->output->x[i],action_name[i%COUNT_ACTION],net_main->output->x[i]);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
|
||||
}
|
||||
////printf("\n< %5.2f > ( %s ) \n", car->direction, action_name[qlStatus->action % COUNT_ACTION]);
|
||||
len_buf=sprintf(buf,"\n< %5.2f > ( %s ) \n", car->direction, action_name[qlStatus->action % COUNT_ACTION]);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
//print_weight_in_neurons_TYPE_FLOAT(net_main, "net_main_wei");
|
||||
//PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, weight_in, "net_main_we_in");
|
||||
///PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, output, "net_main_out");
|
||||
//PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_target, output, "net_target_out");
|
||||
//PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, input, "net_main_input");
|
||||
////printf(" action : %d , factor : %f nb_episodes : %ld \n",qlStatus->action,rlAgent->qlearnParams->exploration_factor, rlAgent->status->nb_episodes);
|
||||
len_buf=sprintf(buf," action : %d , factor : %f nb_episodes : %ld \n",qlStatus->action,rlAgent->qlearnParams->exploration_factor, rlAgent->status->nb_episodes);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
|
||||
FOR_LIST_FORM_BEGIN(TYPE_L_INT, qlStatus->progress_best_cumul){
|
||||
////printf(" | %ld |,",(qlStatus->progress_best_cumul)->current_list->value);
|
||||
len_buf=sprintf(buf," | %ld |,",(qlStatus->progress_best_cumul)->current_list->value);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
}
|
||||
////printf("[%ld] %s ", rlAgent->car->status->cumulative_reward, pprint->string_space);
|
||||
len_buf=sprintf(buf,"[%ld] %s ", rlAgent->car->status->cumulative_reward, pprint->string_space);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)
|
||||
|
||||
}
|
||||
Sleep(pprint->delay->delay_between_games);
|
||||
++count_print;
|
||||
if(count_print > 20){
|
||||
count_print = 0;
|
||||
clear_screen();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -133,6 +133,10 @@ void free_arg_bash(struct arg_bash *arg){
|
||||
free(arg);
|
||||
}
|
||||
|
||||
int new_bash_exist(struct arg_bash *bash_arg){
|
||||
return ((bash_arg->fd_new_bash_pid>0) || (bash_arg->fd_current_bash_pid));
|
||||
}
|
||||
|
||||
/* run new bash terminal graphic, can be called directly or in a thread */
|
||||
void* run_newbash(void* argg){
|
||||
struct arg_bash *arg=(struct arg_bash*)argg;
|
||||
@@ -339,4 +343,89 @@ void* launch_wait_bash(void *b_arg){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define __BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)\
|
||||
if(bash_arg->fd_new_bash_pid>0){\
|
||||
write(bash_arg->fd_new_bash_pid, buf , len_buf);\
|
||||
}\
|
||||
if(bash_arg->fd_current_bash_pid>0){\
|
||||
write(bash_arg->fd_current_bash_pid, buf, len_buf);\
|
||||
}\
|
||||
|
||||
|
||||
void bash_print_vehicle_n_path(struct vehicle *v, float scale_x, float scale_y, struct arg_bash *bash_arg){
|
||||
static bool first = true;
|
||||
if(first){
|
||||
first = false;
|
||||
init_win();
|
||||
char pad[w.ws_col+1];
|
||||
int i=0;
|
||||
for(i=0; i<w.ws_col+1; ++i) pad[i]=' ';
|
||||
pad[i]='\0';
|
||||
for(i=0; i<w.ws_row / 2 ; ++i) printf("%s\n",pad);;
|
||||
|
||||
}
|
||||
//goto_xy(0,w.ws_row - lines);
|
||||
////goto_xy(0,0);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, GOTO_TOP_LEFT, LEN_GOTO_TOP_LEFT);
|
||||
//printf("lines : %d , row : %d : diff: %d\n",lines, w.ws_row , w.ws_row - lines);
|
||||
bash_print2D_blocks_indexOne_withPoint(v->path, scale_x, scale_y, v->coord, bash_arg);
|
||||
//printf("lines print : %d\n",lines);
|
||||
char loggg[SIZE_LOCAL_BUF];
|
||||
int len_loggg=sprintf(loggg,"\nlog : %s \n",v->status->log);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, loggg, len_loggg);
|
||||
}
|
||||
|
||||
|
||||
void bash_print2D_blocks_indexOne_withPoint(struct blocks *blk, float scale_x, float scale_y, coordinate *coordPoint, struct arg_bash *bash_arg){
|
||||
if(blk->dimension_size == 2){
|
||||
update_bounds_limits_blocks(blk);
|
||||
coordinate ** bounds_coord = blk->bounds_all_blocks;
|
||||
|
||||
coordinate * coord = create_coordinate(2);
|
||||
|
||||
float *radius = malloc(2 * sizeof(float));
|
||||
radius[0]=scale_x;
|
||||
radius[1]=scale_y;
|
||||
char buf[SIZE_LOCAL_BUF];
|
||||
int len_buf;
|
||||
struct blocks * blk_point = block_neighbord_Point(coordPoint, radius);
|
||||
for(coord->x[1] = bounds_coord[1]->x[1]; coord->x[1] > bounds_coord[0]->x[1]; coord->x[1]-=scale_y ){
|
||||
for(coord->x[0] = bounds_coord[0]->x[0]; coord->x[0] < bounds_coord[1]->x[0]; coord->x[0]+=scale_x ){
|
||||
if(is_in_blocks(blk_point, coord)){
|
||||
////printf("\033[0;31m"); // red
|
||||
BASH_WRITE_IF_EXIST(bash_arg, "\033[0;31m", 7);
|
||||
}
|
||||
int in = is_in_blocks(blk,coord);
|
||||
if(in){
|
||||
if(in>9){
|
||||
int div=in%10;
|
||||
////printf("%d",div);
|
||||
len_buf=sprintf(buf,"%d",div);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf);
|
||||
}else{
|
||||
////printf("%d",in);
|
||||
len_buf=sprintf(buf,"%d",in);
|
||||
BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf);
|
||||
}
|
||||
}else{
|
||||
////printf("."); //printf(" ");
|
||||
BASH_WRITE_IF_EXIST(bash_arg, ".", 1);
|
||||
}
|
||||
|
||||
////printf("\033[0;37m"); // white
|
||||
BASH_WRITE_IF_EXIST(bash_arg, "\033[0;37m", 7); // white
|
||||
}
|
||||
///printf("\n");
|
||||
BASH_WRITE_IF_EXIST(bash_arg,"\n",1);
|
||||
}
|
||||
|
||||
|
||||
free_coordinate(coord);
|
||||
|
||||
free_blocks(blk_point);
|
||||
free(radius);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ void *func_bash(void* b_arg){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if 0
|
||||
TEST(try_y_socket_manager){
|
||||
struct arg_bash *bash_arg= create_arg_bash();
|
||||
struct arg_var_ * var = create_arg_var_(y_nnn_manager_handle_input, bash_arg);
|
||||
@@ -239,6 +240,7 @@ TEST(try_y_socket_manager){
|
||||
free_arg_bash(bash_arg);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
|
||||
|
||||
@@ -55,11 +55,11 @@ struct arg_var_{
|
||||
struct main_list_y_ptr_HEADER_T *m_ok_head_l_t;
|
||||
pthread_mutex_t *mut_var;
|
||||
pthread_cond_t *cond_var;
|
||||
void* bash_arg;
|
||||
void* extern_arg;
|
||||
void (*extern_socket_handler)(char*,int, void*);
|
||||
};
|
||||
|
||||
struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void* bash_arg);
|
||||
struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void* extern_arg);
|
||||
void set_up_arg_var_init_(struct arg_var_ *var, struct y_socket_t * argSock, struct main_list_TYPE_PTR * list_arg, struct argExecTasQ *argx , struct main_list_y_ptr_HEADER_T *m_ok_head_l_t);
|
||||
void free_arg_var_(struct arg_var_ *var);
|
||||
void wait_var_set_up_value_not_equal(struct arg_var_ *var, int value_set_up);
|
||||
|
||||
@@ -12,7 +12,7 @@ void handle_input_cmd(char * buf, int buf_len, struct arg_var_ *var);
|
||||
//struct y_socket_t * argSock, struct main_list_TYPE_PTR * list_arg, struct argExecTasQ *argx , struct main_list_y_ptr_HEADER_T *m_ok_head_l_t);
|
||||
|
||||
|
||||
struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void *bash_arg){
|
||||
struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void *extern_arg){
|
||||
struct arg_var_ * new_var=malloc(sizeof(struct arg_var_));
|
||||
new_var->set_up = 0;
|
||||
new_var->mut_var = malloc(sizeof(pthread_mutex_t));
|
||||
@@ -26,7 +26,7 @@ struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*
|
||||
new_var->m_ok_head_l_t = NULL;
|
||||
|
||||
new_var->extern_socket_handler = extern_socket_handler;
|
||||
new_var->bash_arg=bash_arg;
|
||||
new_var->extern_arg=extern_arg;
|
||||
|
||||
return new_var;
|
||||
}
|
||||
@@ -602,7 +602,7 @@ if(buf_len>6){
|
||||
}else{
|
||||
printf("debug: call 1 extern_socket_handler\n");
|
||||
if(var->extern_socket_handler){
|
||||
var->extern_socket_handler(buf,buf_len,var->bash_arg);
|
||||
var->extern_socket_handler(buf,buf_len,var->extern_arg);
|
||||
}else{
|
||||
printf("debug: No extern_socket_handler in var\n");
|
||||
}
|
||||
@@ -616,7 +616,7 @@ if(buf_len>6){
|
||||
}else{
|
||||
printf("debug: call 2 extern_socket_handler\n");
|
||||
if(var->extern_socket_handler){
|
||||
var->extern_socket_handler(buf,buf_len,var->bash_arg);
|
||||
var->extern_socket_handler(buf,buf_len,var->extern_arg);
|
||||
}else{
|
||||
printf("debug: No extern_socket_handler in var\n");
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user