Change to use shared process
This commit is contained in:
parent
1f584b19c8
commit
0377be5f81
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
adblock.so
|
adblock.so
|
||||||
cssoutput
|
librun.o
|
||||||
|
wyebab
|
||||||
|
testrun
|
||||||
user.css
|
user.css
|
||||||
|
|
26
README.md
26
README.md
|
@ -3,6 +3,9 @@ An adblock extension for [wyeb](https://github.com/jun7/wyeb), also webkit2gtk b
|
||||||
|
|
||||||
most of code of this are from https://github.com/GNOME/epiphany/tree/master/embed/web-extension
|
most of code of this are from https://github.com/GNOME/epiphany/tree/master/embed/web-extension
|
||||||
|
|
||||||
|
wyebad is shared by clients, So even nowadays, browsers spawn procs for each windows,
|
||||||
|
wyebad keeps single server proc that makes less memory and less cpu times.
|
||||||
|
Don't worry, wyeb wills quit automatically when there is no client and 30 secs past.
|
||||||
|
|
||||||
### usage:
|
### usage:
|
||||||
|
|
||||||
|
@ -14,9 +17,8 @@ copy **easylist.txt** to ~/.config/wyebadblock/
|
||||||
|
|
||||||
wyebadblock only checks 'easylist.txt'
|
wyebadblock only checks 'easylist.txt'
|
||||||
|
|
||||||
|
Testing element hiding is not supported though,
|
||||||
You can check if it works on http://simple-adblock.com/faq/testing-your-adblocker/
|
You can check if it works on http://simple-adblock.com/faq/testing-your-adblocker/
|
||||||
Testing element hiding is not supported though.
|
|
||||||
|
|
||||||
### Disabling
|
### Disabling
|
||||||
|
|
||||||
|
@ -64,10 +66,22 @@ and make link from the dir to the wyebadblock as above.
|
||||||
|
|
||||||
|
|
||||||
## Element Hiding
|
## Element Hiding
|
||||||
Per domain CSS hider rule is not supported and this may crash webkit2gtk.
|
Per domain CSS hider rule is not supported
|
||||||
|
|
||||||
make cssoutput
|
wyebab -css > user.css
|
||||||
./cssoutput > user.css
|
|
||||||
|
|
||||||
And add the user.css to your browser as user css.
|
And add the user.css to your browser as user css.
|
||||||
On wyeb, just copy the user.css to the conf dir.
|
For wyeb, just copy the user.css to the conf dir.
|
||||||
|
|
||||||
|
|
||||||
|
## Shell
|
||||||
|
|
||||||
|
wyebab
|
||||||
|
|
||||||
|
Reads stdin outputs to stdout.
|
||||||
|
blank + enter quits.
|
||||||
|
|
||||||
|
wyebab requst_uri + ' ' + page_uri
|
||||||
|
|
||||||
|
Outputs result
|
||||||
|
Keeps server 30 sec
|
||||||
|
|
|
@ -868,6 +868,7 @@ ephy_uri_tester_new (const char *adblock_data_dir)
|
||||||
return EPHY_URI_TESTER (g_object_new (EPHY_TYPE_URI_TESTER, "adblock-data-dir", adblock_data_dir, NULL));
|
return EPHY_URI_TESTER (g_object_new (EPHY_TYPE_URI_TESTER, "adblock-data-dir", adblock_data_dir, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static void
|
static void
|
||||||
ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
|
ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
|
||||||
char *key,
|
char *key,
|
||||||
|
@ -886,12 +887,13 @@ ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
|
||||||
tester->adblock_loaded = FALSE;
|
tester->adblock_loaded = FALSE;
|
||||||
ephy_uri_tester_load (tester);
|
ephy_uri_tester_load (tester);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ephy_uri_tester_load (EphyUriTester *tester)
|
ephy_uri_tester_load (EphyUriTester *tester)
|
||||||
{
|
{
|
||||||
GTask *task;
|
GTask *task;
|
||||||
char **trash;
|
// char **trash;
|
||||||
|
|
||||||
g_return_if_fail (EPHY_IS_URI_TESTER (tester));
|
g_return_if_fail (EPHY_IS_URI_TESTER (tester));
|
||||||
|
|
||||||
|
@ -920,90 +922,58 @@ ephy_uri_tester_load (EphyUriTester *tester)
|
||||||
|
|
||||||
|
|
||||||
//added
|
//added
|
||||||
#include <webkit2/webkit-web-extension.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
static EphyUriTester *uri_tester;
|
#include <stdbool.h>
|
||||||
static GThread *initt = NULL;
|
|
||||||
static bool tend = false;
|
|
||||||
|
|
||||||
static gboolean reqcb (WebKitWebPage *web_page,
|
#include "wyebrun.h"
|
||||||
WebKitURIRequest *request,
|
|
||||||
WebKitURIResponse *redirected_response,
|
#define EXE "wyebab"
|
||||||
gpointer *p)
|
|
||||||
|
#if DEBUG
|
||||||
|
# define D(f, ...) g_print(#f"\n", __VA_ARGS__);
|
||||||
|
# define DD(a) g_print(#a"\n");
|
||||||
|
#else
|
||||||
|
# define D(f, ...) ;
|
||||||
|
# define DD(a) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ISEXT
|
||||||
|
|
||||||
|
#include <webkit2/webkit-web-extension.h>
|
||||||
|
static bool first = true;
|
||||||
|
static gboolean reqcb(WebKitWebPage *page, WebKitURIRequest *request,
|
||||||
|
WebKitURIResponse *r, gpointer p)
|
||||||
{
|
{
|
||||||
const char *request_uri;
|
const char *request_uri = webkit_uri_request_get_uri(request);
|
||||||
const char *redirected_response_uri;
|
const char *page_uri = webkit_web_page_get_uri(page);
|
||||||
const char *page_uri;
|
|
||||||
char *modified_uri = NULL;
|
|
||||||
EphyUriTestFlags flags = EPHY_URI_TEST_ADBLOCK;
|
|
||||||
request_uri = webkit_uri_request_get_uri (request);
|
|
||||||
page_uri = webkit_web_page_get_uri (web_page);
|
|
||||||
|
|
||||||
redirected_response_uri = redirected_response ?
|
if (first)
|
||||||
webkit_uri_response_get_uri (redirected_response) : NULL;
|
|
||||||
|
|
||||||
if ((flags & EPHY_URI_TEST_ADBLOCK) || (flags & EPHY_URI_TEST_HTTPS_EVERYWHERE)) {
|
|
||||||
char *result;
|
|
||||||
if (initt)
|
|
||||||
{
|
{
|
||||||
SoupMessageHeaders *head = webkit_uri_request_get_http_headers(request);
|
if (webkit_uri_request_get_http_headers(request))
|
||||||
if (head || tend)
|
first = false;
|
||||||
{
|
|
||||||
g_thread_join(initt);
|
|
||||||
initt = NULL;
|
|
||||||
}
|
|
||||||
else //no head is local data. so haven't to block
|
else //no head is local data. so haven't to block
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = ephy_uri_tester_rewrite_uri (uri_tester,
|
|
||||||
modified_uri ? modified_uri : request_uri,
|
|
||||||
page_uri, flags);
|
|
||||||
g_free (modified_uri);
|
|
||||||
|
|
||||||
if (!result) {
|
char *req = g_strconcat(request_uri, " ", page_uri, NULL);
|
||||||
return TRUE;
|
char *res = wyebreq(EXE, req);
|
||||||
}
|
g_free(req);
|
||||||
|
|
||||||
modified_uri = result;
|
if (!res) return true;
|
||||||
} else if (!modified_uri) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_strcmp0 (request_uri, modified_uri) != 0) {
|
if (g_strcmp0(request_uri, res))
|
||||||
webkit_uri_request_set_uri (request, modified_uri);
|
webkit_uri_request_set_uri(request, res);
|
||||||
}
|
|
||||||
g_free (modified_uri);
|
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gpointer inittcb(gpointer data)
|
|
||||||
|
static void pageinit(WebKitWebExtension *ex, WebKitWebPage *wp)
|
||||||
{
|
{
|
||||||
ephy_uri_tester_load(uri_tester);
|
DD(pageinit)
|
||||||
tend = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initex(WebKitWebExtension *ex, WebKitWebPage *wp)
|
|
||||||
{
|
|
||||||
gchar *filter_path = g_build_filename(
|
|
||||||
g_get_user_config_dir(), APPNAME, "easylist.txt", NULL);
|
|
||||||
|
|
||||||
if (g_file_test(filter_path, G_FILE_TEST_EXISTS))
|
|
||||||
{
|
|
||||||
if (!filter_file)
|
|
||||||
{
|
|
||||||
filter_file = g_file_new_for_path(filter_path);
|
|
||||||
uri_tester = ephy_uri_tester_new("/foo/bar");
|
|
||||||
|
|
||||||
initt = g_thread_new("init", inittcb, NULL);
|
|
||||||
}
|
|
||||||
if (wp)
|
|
||||||
g_signal_connect(wp, "send-request", G_CALLBACK(reqcb), NULL);
|
g_signal_connect(wp, "send-request", G_CALLBACK(reqcb), NULL);
|
||||||
}
|
|
||||||
|
|
||||||
g_free(filter_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(
|
G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(
|
||||||
WebKitWebExtension *ex, const GVariant *v)
|
WebKitWebExtension *ex, const GVariant *v)
|
||||||
{
|
{
|
||||||
|
@ -1028,18 +998,101 @@ G_MODULE_EXPORT void webkit_web_extension_initialize_with_user_data(
|
||||||
enable = false;
|
enable = false;
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
g_signal_connect(ex, "page-created", G_CALLBACK(initex), NULL);
|
{
|
||||||
|
wyebloop(EXE, 30, 24);
|
||||||
|
g_signal_connect(ex, "page-created", G_CALLBACK(pageinit), NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static EphyUriTester *tester = NULL;
|
||||||
|
static GThread *initt = NULL;
|
||||||
|
|
||||||
|
static gpointer inittcb(gpointer data)
|
||||||
|
{
|
||||||
|
ephy_uri_tester_load(tester);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void monitorcb(
|
||||||
|
GFileMonitor *m, GFile *f, GFile *o, GFileMonitorEvent e, gpointer p)
|
||||||
|
{
|
||||||
|
if (e == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT ||
|
||||||
|
e == G_FILE_MONITOR_EVENT_DELETED)
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
static void init()
|
||||||
|
{
|
||||||
|
DD(wyebad init)
|
||||||
|
gchar *path = g_build_filename(
|
||||||
|
g_get_user_config_dir(), APPNAME, "easylist.txt", NULL);
|
||||||
|
|
||||||
|
GFile *gf = g_file_new_for_path(path);
|
||||||
|
GFileMonitor *gm = g_file_monitor_file(gf,
|
||||||
|
G_FILE_MONITOR_NONE, NULL, NULL);
|
||||||
|
g_signal_connect(gm, "changed", G_CALLBACK(monitorcb), NULL);
|
||||||
|
g_object_unref(gf);
|
||||||
|
|
||||||
|
if (g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
{
|
||||||
|
filter_file = g_file_new_for_path(path);
|
||||||
|
tester = ephy_uri_tester_new("/foo/bar");
|
||||||
|
|
||||||
|
initt = g_thread_new("init", inittcb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *datafunc(char *req)
|
||||||
|
{
|
||||||
|
if (initt)
|
||||||
|
{
|
||||||
|
g_thread_join(initt);
|
||||||
|
initt = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//req uri + ' ' + page uri
|
||||||
|
gchar **args = g_strsplit(req, " ", 2);
|
||||||
|
|
||||||
|
char *ret = !tester ? g_strdup(args[0]) : ephy_uri_tester_rewrite_uri(tester,
|
||||||
|
args[0], args[1] ?: args[0], EPHY_URI_TEST_ADBLOCK);
|
||||||
|
|
||||||
|
g_strfreev(args);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
initex(NULL, NULL);
|
DD(This bin is compiled with DEBUG=1)
|
||||||
|
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
|
wyebclient(argv[0]);
|
||||||
|
}
|
||||||
|
else if (g_str_has_prefix(argv[1], WYEBPREFIX))
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
wyebsvr(argc, argv, datafunc);
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[1], "-css"))
|
||||||
|
{
|
||||||
|
init();
|
||||||
g_thread_join(initt);
|
g_thread_join(initt);
|
||||||
|
|
||||||
g_print(uri_tester->blockcss->str);
|
g_print(tester->blockcss->str);
|
||||||
g_print("\n\n\n\n{display: none !important}\n\n\n\n");
|
g_print("\n\n\n\n{display: none !important}\n\n\n\n");
|
||||||
// g_print(uri_tester->blockcssprivate->str);
|
//g_print(tester->blockcssprivate->str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wyebuntil(argv[0], 30);
|
||||||
|
g_print("%s", wyebreq(argv[0], argv[1]));
|
||||||
|
}
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
39
makefile
39
makefile
|
@ -4,26 +4,51 @@ CFLAGS += -Wno-deprecated-declarations
|
||||||
EXTENSION_DIR=$(DESTDIR)/usr/lib/wyebrowser
|
EXTENSION_DIR=$(DESTDIR)/usr/lib/wyebrowser
|
||||||
DAPPNAME=-DAPPNAME='"wyebadblock"'
|
DAPPNAME=-DAPPNAME='"wyebadblock"'
|
||||||
|
|
||||||
all: adblock.so
|
ifdef DEBUG
|
||||||
|
DDEBUG=-DDEBUG=${DEBUG}
|
||||||
|
|
||||||
adblock.so: ephy-uri-tester.c ephy-uri-tester.h
|
ifneq ($(DEBUG), 0)
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -shared -fPIC \
|
CFLAGS += -Wall
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: adblock.so wyebab librun.o testrun
|
||||||
|
|
||||||
|
adblock.so: ephy-uri-tester.c ephy-uri-tester.h librun.o makefile
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< librun.o -shared -fPIC \
|
||||||
`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0` \
|
`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0` \
|
||||||
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
|
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
|
||||||
|
$(DDEBUG) $(DAPPNAME) -DISEXT
|
||||||
|
|
||||||
|
wyebab: ephy-uri-tester.c ephy-uri-tester.h librun.o makefile
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< librun.o \
|
||||||
|
`pkg-config --cflags --libs glib-2.0 libsoup-2.4` \
|
||||||
|
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
|
||||||
$(DDEBUG) $(DAPPNAME)
|
$(DDEBUG) $(DAPPNAME)
|
||||||
|
|
||||||
cssoutput: ephy-uri-tester.c ephy-uri-tester.h
|
librun.o: wyebrun.c wyebrun.h makefile
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) -c -o $@ $< -fPIC\
|
||||||
|
`pkg-config --cflags --libs glib-2.0` \
|
||||||
|
-DDEBUG=0
|
||||||
|
|
||||||
|
testrun: wyebrun.c wyebrun.h makefile
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< \
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< \
|
||||||
`pkg-config --cflags --libs gtk+-3.0 glib-2.0 webkit2gtk-4.0` \
|
`pkg-config --cflags --libs glib-2.0` \
|
||||||
-DEXTENSION_DIR=\"$(EXTENSION_DIR)\" \
|
-DDEBUG=1
|
||||||
$(DDEBUG) $(DAPPNAME)
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f adblock.so
|
rm -f adblock.so
|
||||||
|
rm -f wyebab
|
||||||
|
rm -f librun.o
|
||||||
|
rm -f testrun
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
|
install -Dm755 wyebab $(DESTDIR)/usr/bin/wyebab
|
||||||
install -Dm755 adblock.so $(EXTENSION_DIR)/adblock.so
|
install -Dm755 adblock.so $(EXTENSION_DIR)/adblock.so
|
||||||
|
|
||||||
|
re: clean all
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
|
rm -f $(DESTDIR)/usr/bin/wyebab
|
||||||
rm -f $(EXTENSION_DIR)/adblock.so
|
rm -f $(EXTENSION_DIR)/adblock.so
|
||||||
-rmdir $(EXTENSION_DIR)
|
-rmdir $(EXTENSION_DIR)
|
||||||
|
|
541
wyebrun.c
Normal file
541
wyebrun.c
Normal file
|
@ -0,0 +1,541 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 jun7@hush.mail
|
||||||
|
|
||||||
|
This file is part of wyebrun.
|
||||||
|
|
||||||
|
wyebrun is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
wyebrun is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with wyebrun. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
//getpid
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
//flock
|
||||||
|
#include <sys/file.h>
|
||||||
|
|
||||||
|
#include "wyebrun.h"
|
||||||
|
|
||||||
|
#define ROOTNAME "wyebrun"
|
||||||
|
#define PREFIX WYEBPREFIX
|
||||||
|
#define INPUT "wyebinput"
|
||||||
|
#define PING "wyebping"
|
||||||
|
|
||||||
|
#define DUNTIL WYEBDUNTIL
|
||||||
|
#define DPINGTIME 1000
|
||||||
|
|
||||||
|
#define P(f, ...) g_print(#f"\n", __VA_ARGS__);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
static gint64 start;
|
||||||
|
# define D(f, ...) g_print(#f"\n", __VA_ARGS__);
|
||||||
|
# define DD(a) g_print(#a"\n");
|
||||||
|
#else
|
||||||
|
# define D(...) ;
|
||||||
|
# define DD(a) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
//to svr
|
||||||
|
CSuntil = 'u',
|
||||||
|
CSdata = 'd',
|
||||||
|
CSping = 'p',
|
||||||
|
|
||||||
|
//to client
|
||||||
|
CCwoke = 'w',
|
||||||
|
CCret = 'r', //retrun data
|
||||||
|
CClost = 'l', //we lost the req
|
||||||
|
} Com;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//shared
|
||||||
|
static void fatal(int i)
|
||||||
|
{
|
||||||
|
P(\n!!! fatal %d !!!\n, i)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
static void mkdirif(char *path)
|
||||||
|
{
|
||||||
|
char *dir = g_path_get_dirname(path);
|
||||||
|
if (!g_file_test(dir, G_FILE_TEST_EXISTS))
|
||||||
|
g_mkdir_with_parents(dir, 0700);
|
||||||
|
|
||||||
|
g_free(dir);
|
||||||
|
}
|
||||||
|
static char *ipcpath(char *exe, char *name)
|
||||||
|
{
|
||||||
|
return g_build_filename(g_get_user_runtime_dir(),
|
||||||
|
ROOTNAME,exe, name, NULL);
|
||||||
|
}
|
||||||
|
static char *preparepp(char *exe, char *name)
|
||||||
|
{
|
||||||
|
char *path = ipcpath(exe, name);
|
||||||
|
if (!g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
{
|
||||||
|
mkdirif(path);
|
||||||
|
mkfifo(path, 0600);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ipcsend(char *exe, char *name,
|
||||||
|
Com type, char *caller, char *data)
|
||||||
|
{
|
||||||
|
//D(ipcsend exe:%s name:%s, exe, name)
|
||||||
|
char *path = preparepp(exe, name);
|
||||||
|
|
||||||
|
char *esc = g_strescape(data ?: "", "");
|
||||||
|
char *line = g_strdup_printf("%c%s:%s\n", type, caller ?: "", esc);
|
||||||
|
g_free(esc);
|
||||||
|
|
||||||
|
int pp = open(path, O_WRONLY | O_NONBLOCK);
|
||||||
|
|
||||||
|
bool ret = write(pp, line, strlen(line)) != -1;
|
||||||
|
g_free(line);
|
||||||
|
|
||||||
|
close(pp);
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean ipccb(GIOChannel *ch, GIOCondition c, gpointer p);
|
||||||
|
|
||||||
|
static GSource *ipcwatch(char *exe, char *name, GMainContext *ctx) {
|
||||||
|
char *path = preparepp(exe, name);
|
||||||
|
|
||||||
|
GIOChannel *io = g_io_channel_new_file(path, "r+", NULL);
|
||||||
|
GSource *watch = g_io_create_watch(io, G_IO_IN);
|
||||||
|
g_io_channel_unref(io);
|
||||||
|
g_source_set_callback(watch, (GSourceFunc)ipccb, NULL, NULL);
|
||||||
|
g_source_attach(watch, ctx);
|
||||||
|
|
||||||
|
g_free(path);
|
||||||
|
return watch;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//@server
|
||||||
|
static char *svrexe = NULL;
|
||||||
|
static GMainLoop *sloop = NULL;
|
||||||
|
static wyebdataf dataf = NULL;
|
||||||
|
static gboolean quit(gpointer p)
|
||||||
|
{
|
||||||
|
DD(\nsvr quits\n)
|
||||||
|
g_main_loop_quit(sloop);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static void until(int sec)
|
||||||
|
{
|
||||||
|
if (!sloop) return;
|
||||||
|
|
||||||
|
static guint last = 0;
|
||||||
|
if (last)
|
||||||
|
g_source_remove(last);
|
||||||
|
last = g_timeout_add_full(G_PRIORITY_LOW * 2, sec * 1000, quit, NULL, NULL);
|
||||||
|
}
|
||||||
|
static gpointer pingt(gpointer p)
|
||||||
|
{
|
||||||
|
GMainContext *ctx = g_main_context_new();
|
||||||
|
ipcwatch(svrexe, PING, ctx);
|
||||||
|
g_main_loop_run(g_main_loop_new(ctx, true));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wyebwatch(char *exe, char *caller, wyebdataf func)
|
||||||
|
{
|
||||||
|
svrexe = exe;
|
||||||
|
dataf = func;
|
||||||
|
until(DUNTIL);
|
||||||
|
|
||||||
|
g_thread_new("ping", pingt, NULL);
|
||||||
|
ipcwatch(exe, INPUT, g_main_context_default());
|
||||||
|
|
||||||
|
if (!ipcsend(exe, caller, CCwoke, "", NULL))
|
||||||
|
fatal(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean svrinit(char *caller)
|
||||||
|
{
|
||||||
|
wyebwatch(svrexe, caller, dataf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wyebsvr(int argc, char **argv, wyebdataf func)
|
||||||
|
{
|
||||||
|
if (argc < 2 || !g_str_has_prefix(argv[1], PREFIX)) return false;
|
||||||
|
|
||||||
|
svrexe = argv[0];
|
||||||
|
dataf = func;
|
||||||
|
sloop = g_main_loop_new(NULL, false);
|
||||||
|
g_idle_add((GSourceFunc)svrinit, argv[1]);
|
||||||
|
g_main_loop_run(sloop);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getdata(char *caller, char *req)
|
||||||
|
{
|
||||||
|
char *data = dataf(req);
|
||||||
|
if (!ipcsend(svrexe, caller, CCret, "", data))
|
||||||
|
fatal(2);
|
||||||
|
|
||||||
|
g_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//@client
|
||||||
|
static GMutex retm;
|
||||||
|
static GMainLoop *cloop;
|
||||||
|
static GMainContext *wctx = NULL;
|
||||||
|
static char *retdata = NULL;
|
||||||
|
static char *pid()
|
||||||
|
{
|
||||||
|
static char *pid = NULL;
|
||||||
|
if (!pid) pid = g_strdup_printf(PREFIX"%d", getpid());
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spawnsvr(char *exe)
|
||||||
|
{
|
||||||
|
char **argv = g_new0(char*, 2);
|
||||||
|
argv[0] = exe;
|
||||||
|
argv[1] = pid();
|
||||||
|
GError *err = NULL;
|
||||||
|
if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
|
||||||
|
NULL, NULL, NULL, &err))
|
||||||
|
{
|
||||||
|
g_print("err %s", err->message);
|
||||||
|
g_error_free(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(argv);
|
||||||
|
}
|
||||||
|
static gboolean pingloop(gpointer p)
|
||||||
|
{
|
||||||
|
if (!ipcsend((char *)p, PING, CSping, pid(), NULL))
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static char *pppath = NULL;
|
||||||
|
static void removepp()
|
||||||
|
{
|
||||||
|
remove(pppath);
|
||||||
|
}
|
||||||
|
static gpointer watcht(char *exe)
|
||||||
|
{
|
||||||
|
wctx = g_main_context_new();
|
||||||
|
cloop = g_main_loop_new(wctx, true);
|
||||||
|
|
||||||
|
GSource *watch = ipcwatch(exe, pid(), wctx);
|
||||||
|
|
||||||
|
if (!pppath)
|
||||||
|
{
|
||||||
|
pppath = ipcpath(exe, pid());
|
||||||
|
atexit(removepp);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
g_main_loop_run(cloop);
|
||||||
|
|
||||||
|
g_source_unref(watch);
|
||||||
|
g_main_context_unref(wctx);
|
||||||
|
g_main_loop_unref(cloop);
|
||||||
|
cloop = NULL;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
static void watchstart(char *exe)
|
||||||
|
{
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
|
||||||
|
g_thread_new("watch", (GThreadFunc)watcht, exe);
|
||||||
|
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
}
|
||||||
|
static gboolean timeout(gpointer p)
|
||||||
|
{
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GHashTable *lastsec = NULL;
|
||||||
|
static void reuntil(char *exe)
|
||||||
|
{
|
||||||
|
if (!lastsec) return;
|
||||||
|
int sec = GPOINTER_TO_INT(
|
||||||
|
g_hash_table_lookup(lastsec, exe));
|
||||||
|
if (sec)
|
||||||
|
wyebuntil(exe, sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
//don't free
|
||||||
|
static char *request(char *exe, Com type, char *caller, char *req)
|
||||||
|
{
|
||||||
|
g_free(retdata);
|
||||||
|
retdata = NULL;
|
||||||
|
|
||||||
|
if (!cloop) watchstart(exe);
|
||||||
|
|
||||||
|
if (caller)
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
|
||||||
|
if (!ipcsend(exe, INPUT, type, caller, req))
|
||||||
|
{ //svr is not running
|
||||||
|
char *path = ipcpath(exe, "lock");
|
||||||
|
if (!g_file_test(path, G_FILE_TEST_EXISTS))
|
||||||
|
mkdirif(path);
|
||||||
|
|
||||||
|
int lock = open(path, O_RDONLY | O_CREAT, S_IRUSR);
|
||||||
|
g_free(path);
|
||||||
|
|
||||||
|
//retry in single proc
|
||||||
|
if (!ipcsend(exe, INPUT, type, caller, req))
|
||||||
|
{
|
||||||
|
if (!caller)
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
|
||||||
|
GSource *tout = g_timeout_source_new(DUNTIL * 1000);
|
||||||
|
g_source_set_callback(tout, timeout, NULL, NULL);
|
||||||
|
g_source_attach(tout, wctx);
|
||||||
|
|
||||||
|
spawnsvr(exe);
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
|
||||||
|
g_source_destroy(tout);
|
||||||
|
g_source_unref(tout);
|
||||||
|
|
||||||
|
//wyebloop doesn't know svr quits
|
||||||
|
reuntil(exe);
|
||||||
|
|
||||||
|
if (caller)
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
if (!ipcsend(exe, INPUT, type, caller, req))
|
||||||
|
fatal(3); //spawning svr failse is fatal
|
||||||
|
}
|
||||||
|
close(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (caller)
|
||||||
|
{
|
||||||
|
GSource *ping = g_timeout_source_new(DPINGTIME);
|
||||||
|
g_source_set_callback(ping, (GSourceFunc)pingloop, exe, NULL);
|
||||||
|
g_source_attach(ping, wctx); //attach to ping thread
|
||||||
|
|
||||||
|
g_mutex_lock(&retm);
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
|
||||||
|
g_source_destroy(ping);
|
||||||
|
g_source_unref(ping);
|
||||||
|
}
|
||||||
|
|
||||||
|
return retdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *wyebreq(char *exe, char *req)
|
||||||
|
{
|
||||||
|
return request(exe, CSdata, pid(), req);
|
||||||
|
}
|
||||||
|
void wyebuntil(char *exe, int sec)
|
||||||
|
{
|
||||||
|
if (!lastsec)
|
||||||
|
lastsec = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
|
|
||||||
|
g_hash_table_replace(lastsec, exe, GINT_TO_POINTER(sec));
|
||||||
|
|
||||||
|
char *str = g_strdup_printf("%d", sec);
|
||||||
|
request(exe, CSuntil, NULL, str);
|
||||||
|
g_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *exe;
|
||||||
|
int sec;
|
||||||
|
} wyebloopt;
|
||||||
|
static void wlfree(wyebloopt *wl)
|
||||||
|
{
|
||||||
|
g_free(wl->exe);
|
||||||
|
g_free(wl);
|
||||||
|
}
|
||||||
|
static gboolean loopcb(wyebloopt *wl)
|
||||||
|
{
|
||||||
|
wyebuntil(wl->exe, wl->sec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
guint wyebloop(char *exe, int sec, int loopsec)
|
||||||
|
{
|
||||||
|
wyebloopt *wl = g_new(wyebloopt, 1);
|
||||||
|
wl->exe = g_strdup(exe);
|
||||||
|
wl->sec = sec;
|
||||||
|
|
||||||
|
loopcb(wl);
|
||||||
|
return g_timeout_add_full(G_PRIORITY_DEFAULT,
|
||||||
|
loopsec * 1000,
|
||||||
|
(GSourceFunc)loopcb,
|
||||||
|
wl,
|
||||||
|
(GDestroyNotify)wlfree);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean tcinputcb(GIOChannel *ch, GIOCondition c, char *exe)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
g_io_channel_read_line(ch, &line, NULL, NULL, NULL);
|
||||||
|
if (!line) return true;
|
||||||
|
|
||||||
|
g_strstrip(line);
|
||||||
|
if (!strlen(line))
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if (!strcmp(line, "l"))
|
||||||
|
{
|
||||||
|
start = g_get_monotonic_time();
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
|
{
|
||||||
|
char *is = g_strdup_printf("l%d", i);
|
||||||
|
//g_print("loop %d ret %s\n", i, wyebreq(exe, is));
|
||||||
|
wyebreq(exe, is);
|
||||||
|
g_free(is);
|
||||||
|
}
|
||||||
|
gint64 now = g_get_monotonic_time();
|
||||||
|
D(time %f, (now - start) / 1000000.0)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_print("RET is %s\n", wyebreq(exe, line));
|
||||||
|
#else
|
||||||
|
g_print("%s\n", wyebreq(exe, line)); //don't free
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_free(line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static gboolean tcinit(char *exe)
|
||||||
|
{
|
||||||
|
//wyebuntil(exe, 1);
|
||||||
|
wyebloop(exe, 2, 1);
|
||||||
|
|
||||||
|
GIOChannel *io = g_io_channel_unix_new(fileno(stdin));
|
||||||
|
g_io_add_watch(io, G_IO_IN, (GIOFunc)tcinputcb, exe);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void wyebclient(char *exe)
|
||||||
|
{
|
||||||
|
//pid_t getpid(void);
|
||||||
|
sloop = g_main_loop_new(NULL, false);
|
||||||
|
g_idle_add((GSourceFunc)tcinit, exe);
|
||||||
|
g_main_loop_run(sloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//@ipccb
|
||||||
|
static GHashTable *orders = NULL;
|
||||||
|
gboolean ipccb(GIOChannel *ch, GIOCondition c, gpointer p)
|
||||||
|
{
|
||||||
|
if (!orders)
|
||||||
|
orders = g_hash_table_new(g_str_hash, g_str_equal);
|
||||||
|
|
||||||
|
char *line;
|
||||||
|
g_io_channel_read_line(ch, &line, NULL, NULL, NULL);
|
||||||
|
if (!line) return true;
|
||||||
|
g_strchomp(line);
|
||||||
|
|
||||||
|
char *unesc = g_strcompress(line);
|
||||||
|
g_free(line);
|
||||||
|
|
||||||
|
Com type = *unesc;
|
||||||
|
char *id = unesc + 1;
|
||||||
|
char *arg = strstr(unesc, ":");
|
||||||
|
*arg++ = '\0';
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
static int i = 0;
|
||||||
|
D(ipccb%d %c/%s/%s;, i++, type ,id ,arg)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int lastuntil = DUNTIL;
|
||||||
|
switch (type) {
|
||||||
|
//server
|
||||||
|
case CSuntil:
|
||||||
|
until(lastuntil = atoi(arg));
|
||||||
|
break;
|
||||||
|
case CSdata:
|
||||||
|
g_hash_table_add(orders, id);
|
||||||
|
getdata(id, arg);
|
||||||
|
g_hash_table_remove(orders, id);
|
||||||
|
until(lastuntil);
|
||||||
|
break;
|
||||||
|
case CSping:
|
||||||
|
if (!g_hash_table_lookup(orders, id))
|
||||||
|
ipcsend(svrexe, id, CClost, NULL, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
//client
|
||||||
|
case CCret:
|
||||||
|
retdata = g_strdup(arg);
|
||||||
|
case CClost:
|
||||||
|
case CCwoke:
|
||||||
|
//g_main_loop_quit(cloop);
|
||||||
|
g_mutex_unlock(&retm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(unesc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//test
|
||||||
|
#if DEBUG
|
||||||
|
static char *testdata(char *req)
|
||||||
|
{
|
||||||
|
//sleep(9);
|
||||||
|
//g_free(req); //makes crash
|
||||||
|
|
||||||
|
static int i = 0;
|
||||||
|
return g_strdup_printf("%d th dummy data. req is %s", ++i, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
start = g_get_monotonic_time();
|
||||||
|
// gint64 now = g_get_monotonic_time();
|
||||||
|
// D(time %ld %ld, now - start, now)
|
||||||
|
|
||||||
|
//char path[PATH_MAX] = {0};
|
||||||
|
//readlink("/proc/self/exe", path, PATH_MAX);
|
||||||
|
//D(progrname %s, path)
|
||||||
|
|
||||||
|
if (!wyebsvr(argc, argv, testdata))
|
||||||
|
wyebclient(argv[0]);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
#endif
|
47
wyebrun.h
Normal file
47
wyebrun.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 jun7@hush.mail
|
||||||
|
|
||||||
|
This file is part of wyebrun.
|
||||||
|
|
||||||
|
wyebrun is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
wyebrun is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with wyebrun. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _WYEBRUN_H
|
||||||
|
#define _WYEBRUN_H
|
||||||
|
|
||||||
|
#define WYEBPREFIX "-wyeb"
|
||||||
|
#define WYEBDUNTIL 3
|
||||||
|
|
||||||
|
//client
|
||||||
|
//wyebrun spawns the exe if wyebsend failes
|
||||||
|
char *wyebreq( char *exe, char *req);
|
||||||
|
void wyebuntil( char *exe, int sec); //keep alive. default is 10s
|
||||||
|
//loop the wyebuntil. to stop, use g_source_remove
|
||||||
|
guint wyebloop( char *exe, int sec, int loopsec);
|
||||||
|
//send stdin to svr and ret data to stdout
|
||||||
|
//blank and enter exit it
|
||||||
|
void wyebclient(char *exe);
|
||||||
|
|
||||||
|
|
||||||
|
//server
|
||||||
|
typedef char *(*wyebdataf)(char *req);
|
||||||
|
//server is spawned with an arg the caller
|
||||||
|
bool wyebsvr(int argc, char **argv, wyebdataf func);
|
||||||
|
//or if there is own GMainLoop
|
||||||
|
void wyebwatch(char *exe, char *caller, wyebdataf func);
|
||||||
|
//the caller is used to send the res meaning we are ready.
|
||||||
|
//3 sec left or client will die
|
||||||
|
|
||||||
|
#endif //_WYEBRUN_H
|
Loading…
Reference in New Issue
Block a user