Browse Source

manlink + glibmm

patron 10 months ago
parent
commit
5c8e82c57c

+ 19 - 0
glibmmsockets/Makefile

@@ -0,0 +1,19 @@
+
+CFLAGS=-g -Wall -Wextra $(shell pkg-config --cflags glibmm-2.4) -std=c++17
+CFLAGS+=$(shell pkg-config --cflags giomm-2.4)
+LDFLAGS=$(shell pkg-config --libs glibmm-2.4)
+LDFLAGS+=$(shell pkg-config --libs giomm-2.4)
+
+SRC=SocketHandler.cpp main.cpp
+OBJ=$(SRC:.cpp=.o)
+
+PRJ=test
+
+$(PRJ):	$(OBJ)
+	$(CXX) $(LDFLAGS) -o $@ $^ $(LDFLAGS)
+
+%.o:	%.cpp
+	$(CXX) -o $@ -c $< $(CFLAGS)
+
+clean:	
+	rm *.o $(PRJ)

+ 5 - 0
glibmmsockets/README.md

@@ -0,0 +1,5 @@
+# example
+
+glibmm socket helpers test
+
+

+ 228 - 0
glibmmsockets/SocketHandler.cpp

@@ -0,0 +1,228 @@
+#include <glibmm.h>
+#include <giomm.h>
+#include <list>
+#include <iostream>
+#include "SocketHandler.h"
+#include <cassert>
+
+/*
+   Connections factory
+ */
+
+SocketHandlerFactory* SocketHandlerFactory::m_instance=nullptr;
+/*
+   Creation process
+ */
+SocketHandlerFactory* SocketHandlerFactory::get()
+{
+	if (nullptr==m_instance){
+		m_instance = new SocketHandlerFactory();
+	}
+	return m_instance;
+}
+
+/*
+  fuel 
+ */
+void SocketHandlerFactory::push(std::unique_ptr<SocketHandler>& source)
+{
+	if(m_queue.empty()){
+		Glib::signal_timeout().connect_seconds(sigc::mem_fun(this,&SocketHandlerFactory::patrol),1);
+	}
+	m_queue.push_back(std::move(source));
+}
+
+/*
+   remove_if function
+   remote connection to be destroyed
+ */
+bool on_shut (const std::unique_ptr<SocketHandler>& value)
+{ 
+	return value->toBeDestroyed();
+}
+
+/*
+   cleanup closed connections
+ */
+void SocketHandlerFactory::clean()
+{
+	m_queue.remove_if(on_shut);
+	if(m_queue.empty()){
+		std::cout << "no open connection left." << std::endl;
+	}
+}
+
+bool SocketHandlerFactory::patrol()
+{
+	for(auto &it:m_queue){
+		it->patrol();
+	}
+	return !m_queue.empty();
+}
+/*
+   straight connection
+ */
+SocketHandler::SocketHandler(const Glib::ustring& host,int port)
+	:m_status(CONNECTING),m_garbage(false),m_patrol(-1)
+{
+	connect_to_host_async(host,port,sigc::mem_fun(this,&SocketHandler::on_connect_async_ready));
+}
+
+SocketHandler::~SocketHandler()
+{
+	std::cout << "bye." << std::endl;
+}
+
+SocketHandler::states  SocketHandler::status() const
+{
+	return m_status;
+}
+
+/*
+   patrol counter before 
+   on patrol
+   -1: disable
+ */
+void SocketHandler::setPatrolCounter(ssize_t counter)
+{
+	m_patrol=counter;
+}
+
+void SocketHandler::patrol()
+{
+	if(m_patrol>0){
+		--m_patrol;
+	}
+
+	if(m_patrol==0){
+		onPatrol();
+	}
+}
+
+bool SocketHandler::toBeDestroyed() const
+{
+	return m_garbage;
+}
+
+void SocketHandler::onPatrol()
+{
+}
+
+void SocketHandler::selfDestroy()
+{
+	std::cout << "kill me quick, before I died." << std::endl;
+	m_garbage=true;
+	Glib::signal_idle().connect_once(sigc::mem_fun(SocketHandlerFactory::get(),&SocketHandlerFactory::clean));
+}
+
+bool SocketHandler::error_handler(
+		Glib::IOCondition /*io_condition*/)
+{
+	m_status=ERROR;
+	selfDestroy();
+	/* detach signal */
+	return false;
+}
+
+void SocketHandler::on_connect_async_ready(Glib::RefPtr<Gio::AsyncResult>& result)
+{
+	try{
+		m_socketclient=connect_to_host_finish(result);
+		std::cout << "we r in" << std::endl;
+		m_status=READY;
+	}
+	catch(Glib::Error& e){
+		m_status=ERROR;
+		std::cout << e.what() << std::endl;
+	}
+	/*
+	   callback
+	 */
+	on_connect();
+} 
+
+SingleRequestSocket::SingleRequestSocket(const Glib::ustring& host,int port)
+	:SocketHandler(host,port)
+{}
+
+/*
+   connection callback
+   override
+ */
+void SingleRequestSocket::on_connect()
+{
+	if(m_status==SocketHandler::READY){
+		Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::write_handler), m_socketclient->get_socket(), Glib::IO_OUT);
+		Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::error_handler), m_socketclient->get_socket(), Glib::IO_HUP | Glib::IO_ERR | Glib::IO_NVAL);
+	}
+	else{
+		error_handler(Glib::IOCondition::IO_ERR);
+	}
+}
+
+void SingleRequestSocket::onPatrol()
+{
+	selfDestroy();
+}
+
+/*
+   Sending ready
+ */
+bool SingleRequestSocket::write_handler(
+		Glib::IOCondition /*io_condition*/)
+{
+	/*
+	   send something to remote
+	 */
+	Glib::ustring message = "GET / HTTP/1.1\r\nHost: kikoolaule\r\n\r\n";
+	m_socketclient->get_output_stream()->write (message);
+	/*
+	  received bytes notifications
+	 */
+	Gio::signal_socket().connect(sigc::mem_fun(this,&SingleRequestSocket::read_handler), m_socketclient->get_socket(), Glib::IO_IN);
+	/* one shot write:
+	   detach signal
+	 */
+	return false;
+}
+
+bool SingleRequestSocket::read_handler(Glib::IOCondition io_condition)
+{
+
+	assert(io_condition==Glib::IO_IN);
+	try
+	{
+		auto idata=m_socketclient->get_input_stream();
+
+
+		gsize total=m_socketclient->get_socket()->get_available_bytes();
+
+		if(total>0)
+		{
+			do
+			{
+				std::vector<char>  buf(total);
+				gsize r=idata->read(buf.data(),total);
+				std::string answer(buf.begin(),buf.begin()+r);
+				std::cout << answer << std::flush;
+				total=m_socketclient->get_socket()->get_available_bytes();
+			}while( total<0);
+		}
+		else
+		{
+			m_status=SHUTDOWN;
+		}
+	}
+	catch(Glib::Error& e)
+	{
+		m_status=ERROR;
+		error_handler(io_condition);
+	}
+
+	if(m_status!=READY){
+		selfDestroy();
+	}
+
+	return m_status==READY;
+}
+

+ 74 - 0
glibmmsockets/SocketHandler.h

@@ -0,0 +1,74 @@
+#ifndef SocketHandler_H
+#define SocketHandler_H
+
+#include <glibmm.h>
+#include <giomm.h>
+
+
+class SocketHandler:public Gio::SocketClient
+{
+	public:
+		enum states
+		{
+			CONNECTING,
+			READY,
+			ERROR,
+			SHUTDOWN
+		};
+		virtual ~SocketHandler();
+		SocketHandler(const Glib::ustring& host,int port);
+		void setPatrolCounter(ssize_t counter);
+		states status() const;
+		bool toBeDestroyed() const;
+	protected:
+
+		virtual bool write_handler(Glib::IOCondition io_condition)=0;
+		virtual bool read_handler(Glib::IOCondition io_condition)=0;
+		virtual bool error_handler(Glib::IOCondition io_condition);
+		virtual void on_connect()=0;
+		states m_status;
+		Glib::RefPtr< Gio::SocketConnection > m_socketclient;
+		void selfDestroy();
+
+		friend class SocketHandlerFactory;
+		void  patrol();
+
+	private:
+		virtual void onPatrol();
+		void on_connect_async_ready(Glib::RefPtr<Gio::AsyncResult>& result);
+		bool m_garbage;
+		ssize_t m_patrol;
+
+};
+
+class SingleRequestSocket final:public SocketHandler
+{
+	public:
+		SingleRequestSocket(const Glib::ustring& host,int port);
+		~SingleRequestSocket() =default ;
+	protected:
+		bool write_handler(Glib::IOCondition io_condition);
+		bool read_handler(Glib::IOCondition io_condition);
+		void on_connect();
+	private:
+		void onPatrol();
+};
+
+
+class SocketHandlerFactory
+{
+	public:
+		SocketHandlerFactory(const SocketHandlerFactory&) = delete;
+		SocketHandlerFactory& operator=(const SocketHandlerFactory&) = delete;
+		static SocketHandlerFactory* get();
+		~SocketHandlerFactory()=default;
+		void push(std::unique_ptr<SocketHandler>& source);
+		void clean();
+	private:
+		SocketHandlerFactory() = default;
+		std::list<std::unique_ptr<SocketHandler> > m_queue;
+		static SocketHandlerFactory* m_instance;
+		bool patrol();
+};
+
+#endif

+ 81 - 0
glibmmsockets/main.cpp

@@ -0,0 +1,81 @@
+#include <glibmm.h>
+#include <giomm.h>
+#include <list>
+#include <iostream>
+#include <cassert>
+#include "SocketHandler.h"
+
+Glib::RefPtr<Glib::MainLoop> loop;
+
+using namespace Glib;
+using namespace Gio;
+
+void go()
+{
+	std::unique_ptr<SocketHandler> s=std::make_unique<SingleRequestSocket>("127.0.0.1",5080);
+	s->setPatrolCounter(5);
+	SocketHandlerFactory::get()->push(s);
+}
+
+class client
+{
+	public:
+		client(Glib::RefPtr<Gio::Socket>& l){
+			me=l->accept();
+			std::cout << "new client" << std::endl;
+			Gio::signal_socket().connect(sigc::mem_fun(this,&client::i_handler), me, Glib::IO_IN | Glib::IO_OUT);
+			Gio::signal_socket().connect(sigc::mem_fun(this,&client::o_handler), me, Glib::IO_HUP | Glib::IO_ERR);
+		};
+
+		~client(){};
+		bool i_handler(Glib::IOCondition io_condition)
+		{
+			s=me->receive(buf,1023);
+			buf[s+1]='\0';
+			std::cout << buf;
+			me->send("$",2);
+			return true;
+		}
+		bool o_handler(Glib::IOCondition io_condition)
+		{
+			std::cout << "kill me" << std::endl;
+			return false;
+		}
+	private:
+		Glib::RefPtr<Gio::Socket> me;
+		char buf[1024];
+		gssize s;
+};
+Glib::RefPtr<Gio::Socket> socket_l;
+
+std::list<client> queue;
+bool io_handler(Glib::IOCondition io_condition)
+{
+	queue.emplace_back(socket_l);
+	return true;
+}
+
+int main()
+{
+	Glib::init();
+	Gio::init();
+	setlocale(LC_ALL, "C");
+	std::cout << "local address" << std::endl;
+
+	auto inetAddr=Gio::InetAddress::create 	("127.0.0.1");
+	auto  inetsocket=Gio::InetSocketAddress::create(inetAddr,5012);
+	std::cout << "socket" << std::endl;
+	socket_l=Gio::Socket::create(Gio::SOCKET_FAMILY_IPV4,Gio::SOCKET_TYPE_STREAM
+			,Gio::SOCKET_PROTOCOL_TCP)  ;
+
+	std::cout << "binding to address" << std::endl;
+	socket_l->bind(inetsocket,true);
+	socket_l->listen();
+
+
+	loop = Glib::MainLoop::create();
+	Gio::signal_socket().connect(sigc::ptr_fun(& io_handler), socket_l, Glib::IO_IN | Glib::IO_OUT);
+	Glib::signal_timeout().connect_seconds_once(sigc::ptr_fun(&go),5);
+	loop->run();
+
+}

+ 25 - 0
manlink/LICENSE

@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2020, David Marec
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 7 - 0
manlink/conf/default.php

@@ -0,0 +1,7 @@
+<?php
+/*
+ * Choosing the manpages you want with manlink.
+ */
+$conf['mantarget'] = 'FreeBSD';
+
+//Setup VIM: ex: et ts=2 enc=utf-8 :

+ 6 - 0
manlink/conf/metadata.php

@@ -0,0 +1,6 @@
+<?php
+/*
+ * Metadata statement for the target of the manpage links.
+ */
+$meta['mantarget'] = array('multichoice', '_choices' => array('NetBSD', 'OpenBSD', 'FreeBSD', 'DragonFlyBSD'));
+//Setup VIM: ex: et ts=2 enc=utf-8 :

+ 10 - 0
manlink/plugin.info.txt

@@ -0,0 +1,10 @@
+base   manlink
+author Turtle Crazy 
+email  david@lapinbilly.eu
+date   2020-04-30
+name   Manpage link plugin
+desc   Transforms manpage descriptions to manpage links
+url    https://www.dokuwiki.org/plugin:manlink
+
+
+note	Based on former manlink extension by Julian Fagir

+ 54 - 0
manlink/syntax.php

@@ -0,0 +1,54 @@
+<?php
+/*
+ * Manlinks plugin: convert manpage descriptions to links to the manpages.
+ */
+
+if(!defined('DOKU_INC')) die();
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'syntax.php');
+
+class syntax_plugin_manlink extends DokuWiki_Syntax_Plugin {
+
+	function getType() { return 'substition'; }
+	function getPType() { return 'normal'; }
+	function getSort() { return 361; }
+
+	function connectTo($mode) {
+		$this->Lexer->addSpecialPattern(
+			'\!?[a-zA-Z0-9_.+\[\]-]*\([0-9]\)',
+			$mode,
+			'plugin_manlink');
+	}
+
+	function handle($match, $state, $pos, Doku_Handler $handler){
+		if ($state != DOKU_LEXER_SPECIAL)
+			return false;
+
+		if (substr($match, 0, 1) == "!") {
+			$handler->_addCall('cdata', array(substr($match, 1)), $pos);
+			return true;
+		}
+
+		$mantarget = $this->getconf('mantarget');
+		$manpage = preg_replace('/^([a-zA-Z0-9_+\[\].-]*)\(([0-9])\)$/', '\1', $match);
+		$section = preg_replace('/^([a-zA-Z0-9_+\[\].-]*)\(([0-9])\)$/', '\2', $match);
+
+		if ($mantarget == 'NetBSD')
+			$target = 'http://mdoc.su/n/'.$manpage.'.'.$section;
+		elseif ($mantarget == 'FreeBSD')
+			$target = 'http://mdoc.su/f/'.$manpage.'.'.$section;
+		elseif ($mantarget == 'OpenBSD')
+			$target = 'http://mdoc.su/o/'.$manpage.'.'.$section;
+		elseif ($mantarget == 'DragonFlyBSD')
+			$target = 'http://mdoc.su/d/'.$manpage.'.'.$section;
+
+		$handler->_addCall('externallink', array($target, $match), $pos);
+		return true;
+	}
+
+	function render($format, Doku_Renderer $renderer, $data) {
+		return true;
+	}
+}
+
+?>