📄 libproxyfish.c
字号:
fd_set w_set; //可写 //要发送的验证信息 gchar *message = "GET http://www.kernel.org/ HTTP/1.1\r\n" "Host: www.kernel.org\r\n" "User-Agent: ProxyFish\r\n" "Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*\r\n" "Keep-Alive: 300\r\n" "Proxy-Connection: keep-alive\r\n" "\r\n"; //网站关键字 gchar *key_word = "Linux Kernel"; gchar *key_word_1 = "HTTP/1.1 200"; //网站返回的缓冲 char buf[BUFFER_2048]; memset(buf, 0, sizeof(buf)); fd = socket(AF_INET, SOCK_STREAM, 0); if(fd < 0){ perror("socket"); exit(1); } if (strlen(timeout) >0) timeo.tv_sec = atoi(timeout); int savefl = fcntl(fd,F_GETFL); fcntl(fd, F_SETFL, savefl | O_NONBLOCK); //设置为非阻塞 addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(host); addr.sin_port = htons(atoi(port)); if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) { DBG("connected..1\n"); goto SEND; } if (errno != EINPROGRESS) { DBG("connect..2"); b_result = FALSE; close(fd); return b_result; } FD_ZERO(&w_set); FD_SET(fd, &w_set); //检测 fd retval = select(fd + 1, NULL, &w_set, NULL, &timeo); if (retval == -1) { close(fd); perror("select"); b_result = FALSE; return b_result; } else if(retval == 0) { DBG("timeout\n"); b_result = FALSE; close(fd); return b_result; } if(FD_ISSET (fd,&w_set)) { int error = 0; socklen_t len = sizeof (error); if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { DBG ("getsockopt fail,connected fail\n"); b_result = FALSE; close(fd); return b_result; } if (error == ETIMEDOUT) { DBG ("connected timeout\n"); b_result = FALSE; close(fd); return b_result; } if(error == ECONNREFUSED) { DBG("No one listening on the remote address.\n"); b_result = FALSE; close(fd); return b_result; } } DBG ("connected .. 3\n"); //发送数据SEND: //设置为阻塞方式 fcntl(fd, F_SETFL, savefl); //设置超时时间为5秒 struct timeval timeo_test = {5,0}; //为recv设置超时, setsockopt可为阻塞模式设置超时 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_test, sizeof(timeo_test)); send_count = send(fd, message, strlen(message), 0); if (send_count < 0) { DBG("socket send error"); close(fd); return FALSE; } /*信号量锁*/ g_mutex_lock(m_flaw_send_count); app->env.flaw_send_total += send_count; g_mutex_unlock(m_flaw_send_count); // fcntl(fd, F_SETFL, savefl | O_NONBLOCK); //设置为非阻塞 rec_cout = recv(fd, buf, sizeof(buf), 0); if ( rec_cout < 0) { DBG("socket recv error"); close(fd); return FALSE; } /*信号锁*/ g_mutex_lock(m_flaw_rec_count); app->env.flaw_rec_total += rec_cout; g_mutex_unlock(m_flaw_rec_count); DBG("%s\n", buf); if (strlen(buf) > 0) { if(proxy_fish_check_key_string(buf, key_word_1) \ ||proxy_fish_check_key_string(buf, key_word) ) { DBG("Yes, contain the key word\n"); b_result = TRUE; } } close (fd); return b_result;}/** * 描述: 线程运行函数 * 返回: 无 * 参数: * data: 提交的需要处理的数据 * user_data: 线程池创建时候传递的数据 * */static void proxy_fish_thread_run (gchar* data, gpointer user_data){ gchar* ip = NULL; gchar* port = NULL; gchar* symbol_lookfor = ":"; gchar* invector = NULL; struct timeval start_ck_tv; /** 开始验证的时间 */ struct timeval end_ck_tv; /** 结束验证的时间 */ struct timezone tz; /** 记录时区,当前还没有用到 */ gint second_t = 0; /*秒*/ guint32 u_second_t = 0; /*微秒*/ ///如果是ip:port格式,则拆分出IP和端口 if (find_ip_port_in_content(data)) { invector = get_content_symbol(data, symbol_lookfor); g_assert(invector != NULL); ip = g_malloc0(invector - data + 1); port = g_malloc0(strlen(data) - (invector -data) + 1); memcpy(ip, data, (invector -data)); memcpy(port, invector + 1, strlen(data) - (invector -data)); DBG("ip = %s port = %s\n", ip, port); /** 如果port格式不是数字,则不予检验 */ if (!check_digital(ip)) { g_free(ip); g_free(port); g_free(data); ///释放传送给线程的数据 return; } ///记录开始检验的时间 gettimeofday (&start_ck_tv, &tz); /*信号量上锁*/ g_mutex_lock(treeview_window_main_textview); gdk_threads_enter(); GString* tmp_1_1 = g_string_new(NULL); g_string_printf(tmp_1_1, _("Checking %-15s:%s"), ip, port); log_proxy_fish_info(tmp_1_1->str); g_string_free(tmp_1_1, TRUE); gdk_threads_leave(); /*信号量解锁*/ g_mutex_unlock(treeview_window_main_textview); ///开始检验 if (proxy_fish_check_port(ip, port, "6")) { DBG("host %s ::::: %s is a proxy\n", ip, port); ///添加到列表中 GtkWidget* treeview_window_main_proxy_list = lookup_widget(GTK_WIDGET(app->gui.window_main), \ "treeview_window_main_proxy_list"); GtkWidget* statusbar_window_main_1 = lookup_widget(GTK_WIDGET(app->gui.window_main), "statusbar_window_main_1"); GString* u_second_c = g_string_new(NULL); GString* time_delay = g_string_new(NULL); /** 时间差*/ GString* pf_info_message = g_string_new(NULL); GString* proxy_useable_total_c = g_string_new(NULL); g_assert(statusbar_window_main_1 != NULL); g_assert(treeview_window_main_proxy_list != NULL); ///记录结束检验的时间 gettimeofday (&end_ck_tv, &tz); /* 计算时间 */ if (end_ck_tv.tv_usec < start_ck_tv.tv_usec) { /*下面的 -1 是借位*/ second_t = (int)(end_ck_tv.tv_sec - start_ck_tv.tv_sec - 1); u_second_t = (guint32)(1.0e+6 + end_ck_tv.tv_usec - start_ck_tv.tv_usec); } else { second_t = (int)(end_ck_tv.tv_sec - start_ck_tv.tv_sec); u_second_t = (guint32)(end_ck_tv.tv_usec - start_ck_tv.tv_usec); } g_string_printf(u_second_c, "%u", u_second_t); g_string_set_size(u_second_c, 2); g_string_printf(time_delay, "%d.%s", second_t, u_second_c->str); /* 信号量上锁 */ g_mutex_lock(treeview_window_main_proxy_list_mutex); gdk_threads_enter(); /*添加到"可用链表"中*/ append_proxy_to_list(treeview_window_main_proxy_list, ip, port, time_delay->str); /*计数*/ app->env.proxy_useable_total ++; g_string_printf(proxy_useable_total_c, _("total find %u proxy useable"), \ app->env.proxy_useable_total); g_string_printf(pf_info_message, _("IP %-15s: %s is useable"), \ ip, port); update_statusbar(statusbar_window_main_1, proxy_useable_total_c->str); log_proxy_fish_info(pf_info_message->str); gdk_threads_leave(); /* 信号量解锁 */ g_mutex_unlock(treeview_window_main_proxy_list_mutex); g_string_free(proxy_useable_total_c, TRUE); g_string_free(u_second_c, TRUE); g_string_free(time_delay, TRUE); g_string_free(pf_info_message, TRUE); } else { /*不可用代理计数*/ /* 信号量上锁 */ g_mutex_lock(unuseable_proxy_count); app->env.proxy_unuseable_total ++; /* 信号量解锁 */ g_mutex_unlock(unuseable_proxy_count); } g_free(port); g_free(ip); g_free(data); ///释放传送给线程的数据 } ///否则的话应该是超级链接 else { GString* info = g_string_new(_("Now parsing:")); ///如果没有"http://"前缀则加上"/"前缀 if (!filter_file_has_prefix(data, "http://")) { GString* tmp = g_string_new(data); tmp = g_string_prepend(tmp, "/"); parse_url_content(tmp->str, get_proxy); g_string_free(tmp, TRUE); info = g_string_append(info, data); } else if (!strcmp(data, DEFAULT_URL)) { info = g_string_append(info, DEFAULT_URL); /*如果是首页*/ parse_url_content(data, get_child_url); } else { /*如果是子链接*/ parse_url_content(data, get_proxy); info = g_string_append(info, data); } /*记录*/ /*信号量上锁*/ g_mutex_lock(treeview_window_main_textview); gdk_threads_enter(); log_proxy_fish_info(info->str); gdk_threads_leave(); /*信号量解锁*/ g_mutex_unlock(treeview_window_main_textview); g_string_free(info, TRUE); }}/** * 销毁线程池 */static void proxy_fish_thread_pool_exit (void){ if (app->env.thread_pool) g_thread_pool_free(app->env.thread_pool, TRUE, FALSE);}/** * 释放信号量 */static void proxy_fish_free_mutex (void){ g_mutex_free(treeview_window_main_proxy_list_mutex); g_mutex_free(treeview_window_main_textview); g_mutex_free(unuseable_proxy_count); g_mutex_free(m_flaw_send_count); g_mutex_free(m_flaw_rec_count);}/** * 线程池初始化 */GThreadPool* proxy_fish_thread_pool_init (void){ gint l_max_thread_num = 10; ///最大线程数 GThreadPool* thread_pool = NULL; thread_pool = g_thread_pool_new ((GFunc)proxy_fish_thread_run, //线程执行函数 (gpointer)NULL, //执行函数的参数user_data l_max_thread_num, //最大线程数 FALSE, //是否独占 NULL); //存放错误 if (!thread_pool) { perror("create thread pool error"); exit(1); } DBG("thread pool create successed\n"); /* 初始化信号量 */ treeview_window_main_proxy_list_mutex = g_mutex_new(); treeview_window_main_textview = g_mutex_new(); unuseable_proxy_count = g_mutex_new(); m_flaw_send_count = g_mutex_new(); m_flaw_rec_count = g_mutex_new(); /* 请先释放信号量,再释放线程池 */ g_atexit(proxy_fish_free_mutex); g_atexit(proxy_fish_thread_pool_exit); return thread_pool;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -