commit
e8c65d39ba
@ -1,47 +0,0 @@
|
||||
#! /bin/sh -e
|
||||
# /usr/lib/emacsen-common/packages/install/libsntl
|
||||
|
||||
# Written by Jim Van Zandt <jrv@debian.org>, borrowing heavily
|
||||
# from the install scripts for gettext by Santiago Vila
|
||||
# <sanvila@ctv.es> and octave by Dirk Eddelbuettel <edd@debian.org>.
|
||||
|
||||
FLAVOR=$1
|
||||
PACKAGE=libsntl
|
||||
|
||||
if [ ${FLAVOR} = emacs ]; then exit 0; fi
|
||||
|
||||
echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR}
|
||||
|
||||
#FLAVORTEST=`echo $FLAVOR | cut -c-6`
|
||||
#if [ ${FLAVORTEST} = xemacs ] ; then
|
||||
# SITEFLAG="-no-site-file"
|
||||
#else
|
||||
# SITEFLAG="--no-site-file"
|
||||
#fi
|
||||
FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile"
|
||||
|
||||
ELDIR=/usr/share/emacs/site-lisp/${PACKAGE}
|
||||
ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE}
|
||||
ELRELDIR=../../../emacs/site-lisp/${PACKAGE}
|
||||
|
||||
# Install-info-altdir does not actually exist.
|
||||
# Maybe somebody will write it.
|
||||
if test -x /usr/sbin/install-info-altdir; then
|
||||
echo install/${PACKAGE}: install Info links for ${FLAVOR}
|
||||
install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/share/info/${PACKAGE}.info.gz
|
||||
fi
|
||||
|
||||
install -m 755 -d ${ELCDIR}
|
||||
cd ${ELDIR}
|
||||
FILES=`echo *.el`
|
||||
cd ${ELCDIR}
|
||||
ln -sf ${ELRELDIR}/*.el .
|
||||
|
||||
cat << EOF > path.el
|
||||
(debian-pkg-add-load-path-item ".")
|
||||
(setq byte-compile-warnings nil)
|
||||
EOF
|
||||
${FLAVOR} ${FLAGS} ${FILES}
|
||||
rm -f path.el
|
||||
|
||||
exit 0
|
@ -1,15 +0,0 @@
|
||||
#!/bin/sh -e
|
||||
# /usr/lib/emacsen-common/packages/remove/libsntl
|
||||
|
||||
FLAVOR=$1
|
||||
PACKAGE=libsntl
|
||||
|
||||
if [ ${FLAVOR} != emacs ]; then
|
||||
if test -x /usr/sbin/install-info-altdir; then
|
||||
echo remove/${PACKAGE}: removing Info links for ${FLAVOR}
|
||||
install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/share/info/libsntl.info.gz
|
||||
fi
|
||||
|
||||
echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR}
|
||||
rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE}
|
||||
fi
|
@ -1,27 +0,0 @@
|
||||
;; -*-emacs-lisp-*-
|
||||
;;
|
||||
;; Emacs startup file, e.g. /etc/emacs/site-start.d/50libsntl.el
|
||||
;; for the Debian libsntl package
|
||||
;;
|
||||
;; Originally contributed by Nils Naumann <naumann@unileoben.ac.at>
|
||||
;; Modified by Dirk Eddelbuettel <edd@debian.org>
|
||||
;; Adapted for dh-make by Jim Van Zandt <jrv@debian.org>
|
||||
|
||||
;; The libsntl package follows the Debian/GNU Linux 'emacsen' policy and
|
||||
;; byte-compiles its elisp files for each 'emacs flavor' (emacs19,
|
||||
;; xemacs19, emacs20, xemacs20...). The compiled code is then
|
||||
;; installed in a subdirectory of the respective site-lisp directory.
|
||||
;; We have to add this to the load-path:
|
||||
(let ((package-dir (concat "/usr/share/"
|
||||
(symbol-name debian-emacs-flavor)
|
||||
"/site-lisp/libsntl")))
|
||||
;; If package-dir does not exist, the libsntl package must have
|
||||
;; removed but not purged, and we should skip the setup.
|
||||
(when (file-directory-p package-dir)
|
||||
(if (fboundp 'debian-pkg-add-load-path-item)
|
||||
(debian-pkg-add-load-path-item package-dir)
|
||||
(setq load-path (cons package-dir load-path)))
|
||||
(autoload 'libsntl-mode "libsntl-mode"
|
||||
"Major mode for editing libsntl files." t)
|
||||
(add-to-list 'auto-mode-alist '("\\.libsntl$" . libsntl-mode))))
|
||||
|
@ -1,2 +1,2 @@
|
||||
libsntl-dev_0.2.1_amd64.deb libdevel extra
|
||||
libsntl_0.2.1_amd64.deb libs extra
|
||||
libsntl-dev_0.3.0_amd64.deb libdevel extra
|
||||
libsntl_0.3.0_amd64.deb libs extra
|
||||
|
@ -1,2 +1,4 @@
|
||||
usr/lib
|
||||
usr/include
|
||||
usr/share/man
|
||||
usr/share/man/man3
|
@ -0,0 +1,10 @@
|
||||
man/sxmsg_rreply.3
|
||||
man/connections_create.3
|
||||
man/connections_destroy.3
|
||||
man/connections_free.3
|
||||
man/connections_init.3
|
||||
man/sntl_init.3
|
||||
man/connections_setsslserts.3
|
||||
man/connections_set_priv.3
|
||||
man/connections_get_priv.3
|
||||
man/connections_set_ondestroy.3
|
@ -1,2 +1,2 @@
|
||||
shlibs:Depends=libc6 (>= 2.3.2), libsexpr, libssl1.0.0 (>= 1.0.1), libtdata, libuuid1 (>= 2.20.1)
|
||||
shlibs:Depends=libc6 (>= 2.2.5), libsexpr, libssl1.0.0 (>= 1.0.1), libtdata, libuuid1 (>= 2.20.1)
|
||||
misc:Depends=
|
||||
|
@ -1,56 +0,0 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.\" (C) Copyright 2014 Alexander Vdolainen <vdo@daze>,
|
||||
.\"
|
||||
.\" First parameter, NAME, should be all caps
|
||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||
.\" other parameters are allowed: see man(7), man(1)
|
||||
.TH LIBSNTL SECTION "November 24, 2014"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
libsntl \- program to do something
|
||||
.SH SYNOPSIS
|
||||
.B libsntl
|
||||
.RI [ options ] " files" ...
|
||||
.br
|
||||
.B bar
|
||||
.RI [ options ] " files" ...
|
||||
.SH DESCRIPTION
|
||||
This manual page documents briefly the
|
||||
.B libsntl
|
||||
and
|
||||
.B bar
|
||||
commands.
|
||||
.PP
|
||||
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
|
||||
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
|
||||
.\" respectively.
|
||||
\fBlibsntl\fP is a program that...
|
||||
.SH OPTIONS
|
||||
These programs follow the usual GNU command line syntax, with long
|
||||
options starting with two dashes (`-').
|
||||
A summary of options is included below.
|
||||
For a complete description, see the Info files.
|
||||
.TP
|
||||
.B \-h, \-\-help
|
||||
Show summary of options.
|
||||
.TP
|
||||
.B \-v, \-\-version
|
||||
Show version of program.
|
||||
.SH SEE ALSO
|
||||
.BR bar (1),
|
||||
.BR baz (1).
|
||||
.br
|
||||
The programs are documented fully by
|
||||
.IR "The Rise and Fall of a Fooish Bar" ,
|
||||
available via the Info system.
|
@ -1,154 +0,0 @@
|
||||
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
|
||||
|
||||
<!-- Process this file with docbook-to-man to generate an nroff manual
|
||||
page: `docbook-to-man manpage.sgml > manpage.1'. You may view
|
||||
the manual page with: `docbook-to-man manpage.sgml | nroff -man |
|
||||
less'. A typical entry in a Makefile or Makefile.am is:
|
||||
|
||||
manpage.1: manpage.sgml
|
||||
docbook-to-man $< > $@
|
||||
|
||||
|
||||
The docbook-to-man binary is found in the docbook-to-man package.
|
||||
Please remember that if you create the nroff version in one of the
|
||||
debian/rules file targets (such as build), you will need to include
|
||||
docbook-to-man in your Build-Depends control field.
|
||||
|
||||
-->
|
||||
|
||||
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
|
||||
<!ENTITY dhfirstname "<firstname>FIRSTNAME</firstname>">
|
||||
<!ENTITY dhsurname "<surname>SURNAME</surname>">
|
||||
<!-- Please adjust the date whenever revising the manpage. -->
|
||||
<!ENTITY dhdate "<date>November 24, 2014</date>">
|
||||
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
|
||||
allowed: see man(7), man(1). -->
|
||||
<!ENTITY dhsection "<manvolnum>SECTION</manvolnum>">
|
||||
<!ENTITY dhemail "<email>vdo@daze</email>">
|
||||
<!ENTITY dhusername "Alexander Vdolainen">
|
||||
<!ENTITY dhucpackage "<refentrytitle>LIBSEXPR</refentrytitle>">
|
||||
<!ENTITY dhpackage "libsntl">
|
||||
|
||||
<!ENTITY debian "<productname>Debian</productname>">
|
||||
<!ENTITY gnu "<acronym>GNU</acronym>">
|
||||
<!ENTITY gpl "&gnu; <acronym>GPL</acronym>">
|
||||
]>
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<address>
|
||||
&dhemail;
|
||||
</address>
|
||||
<author>
|
||||
&dhfirstname;
|
||||
&dhsurname;
|
||||
</author>
|
||||
<copyright>
|
||||
<year>2003</year>
|
||||
<holder>&dhusername;</holder>
|
||||
</copyright>
|
||||
&dhdate;
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
&dhucpackage;
|
||||
|
||||
&dhsection;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>&dhpackage;</refname>
|
||||
|
||||
<refpurpose>program to do something</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
|
||||
<arg><option>-e <replaceable>this</replaceable></option></arg>
|
||||
|
||||
<arg><option>--example <replaceable>that</replaceable></option></arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1>
|
||||
<title>DESCRIPTION</title>
|
||||
|
||||
<para>This manual page documents briefly the
|
||||
<command>&dhpackage;</command> and <command>bar</command>
|
||||
commands.</para>
|
||||
|
||||
<para>This manual page was written for the &debian; distribution
|
||||
because the original program does not have a manual page.
|
||||
Instead, it has documentation in the &gnu;
|
||||
<application>Info</application> format; see below.</para>
|
||||
|
||||
<para><command>&dhpackage;</command> is a program that...</para>
|
||||
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>OPTIONS</title>
|
||||
|
||||
<para>These programs follow the usual &gnu; command line syntax,
|
||||
with long options starting with two dashes (`-'). A summary of
|
||||
options is included below. For a complete description, see the
|
||||
<application>Info</application> files.</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-h</option>
|
||||
<option>--help</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Show summary of options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option>
|
||||
<option>--version</option>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>Show version of program.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>SEE ALSO</title>
|
||||
|
||||
<para>bar (1), baz (1).</para>
|
||||
|
||||
<para>The programs are documented fully by <citetitle>The Rise and
|
||||
Fall of a Fooish Bar</citetitle> available via the
|
||||
<application>Info</application> system.</para>
|
||||
</refsect1>
|
||||
<refsect1>
|
||||
<title>AUTHOR</title>
|
||||
|
||||
<para>This manual page was written by &dhusername; &dhemail; for
|
||||
the &debian; system (and may be used by others). Permission is
|
||||
granted to copy, distribute and/or modify this document under
|
||||
the terms of the &gnu; General Public License, Version 2 any
|
||||
later version published by the Free Software Foundation.
|
||||
</para>
|
||||
<para>
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in /usr/share/common-licenses/GPL.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
<!-- Keep this comment at the end of the file
|
||||
Local variables:
|
||||
mode: sgml
|
||||
sgml-omittag:t
|
||||
sgml-shorttag:t
|
||||
sgml-minimize-attributes:nil
|
||||
sgml-always-quote-attributes:t
|
||||
sgml-indent-step:2
|
||||
sgml-indent-data:t
|
||||
sgml-parent-document:nil
|
||||
sgml-default-dtd-file:nil
|
||||
sgml-exposed-tags:nil
|
||||
sgml-local-catalogs:nil
|
||||
sgml-local-ecat-files:nil
|
||||
End:
|
||||
-->
|
@ -1,291 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
|
||||
<!--
|
||||
|
||||
`xsltproc -''-nonet \
|
||||
-''-param man.charmap.use.subset "0" \
|
||||
-''-param make.year.ranges "1" \
|
||||
-''-param make.single.year.ranges "1" \
|
||||
/usr/share/xml/docbook/stylesheet/docbook-xsl/manpages/docbook.xsl \
|
||||
manpage.xml'
|
||||
|
||||
A manual page <package>.<section> will be generated. You may view the
|
||||
manual page with: nroff -man <package>.<section> | less'. A typical entry
|
||||
in a Makefile or Makefile.am is:
|
||||
|
||||
DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl
|
||||
XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
|
||||
|
||||
manpage.1: manpage.xml
|
||||
$(XP) $(DB2MAN) $<
|
||||
|
||||
The xsltproc binary is found in the xsltproc package. The XSL files are in
|
||||
docbook-xsl. A description of the parameters you can use can be found in the
|
||||
docbook-xsl-doc-* packages. Please remember that if you create the nroff
|
||||
version in one of the debian/rules file targets (such as build), you will need
|
||||
to include xsltproc and docbook-xsl in your Build-Depends control field.
|
||||
Alternatively use the xmlto command/package. That will also automatically
|
||||
pull in xsltproc and docbook-xsl.
|
||||
|
||||
Notes for using docbook2x: docbook2x-man does not automatically create the
|
||||
AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
|
||||
<refsect1> ... </refsect1>.
|
||||
|
||||
To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
|
||||
read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
|
||||
found in the docbook-xsl-doc-html package.
|
||||
|
||||
Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
|
||||
|
||||
General documentation about man-pages and man-page-formatting:
|
||||
man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
|
||||
|
||||
-->
|
||||
|
||||
<!-- Fill in your name for FIRSTNAME and SURNAME. -->
|
||||
<!ENTITY dhfirstname "FIRSTNAME">
|
||||
<!ENTITY dhsurname "SURNAME">
|
||||
<!-- dhusername could also be set to "&dhfirstname; &dhsurname;". -->
|
||||
<!ENTITY dhusername "Alexander Vdolainen">
|
||||
<!ENTITY dhemail "vdo@daze">
|
||||
<!-- SECTION should be 1-8, maybe w/ subsection other parameters are
|
||||
allowed: see man(7), man(1) and
|
||||
http://www.tldp.org/HOWTO/Man-Page/q2.html. -->
|
||||
<!ENTITY dhsection "SECTION">
|
||||
<!-- TITLE should be something like "User commands" or similar (see
|
||||
http://www.tldp.org/HOWTO/Man-Page/q2.html). -->
|
||||
<!ENTITY dhtitle "libsntl User Manual">
|
||||
<!ENTITY dhucpackage "LIBSEXPR">
|
||||
<!ENTITY dhpackage "libsntl">
|
||||
]>
|
||||
|
||||
<refentry>
|
||||
<refentryinfo>
|
||||
<title>&dhtitle;</title>
|
||||
<productname>&dhpackage;</productname>
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>&dhfirstname;</firstname>
|
||||
<surname>&dhsurname;</surname>
|
||||
<contrib>Wrote this manpage for the Debian system.</contrib>
|
||||
<address>
|
||||
<email>&dhemail;</email>
|
||||
</address>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<copyright>
|
||||
<year>2007</year>
|
||||
<holder>&dhusername;</holder>
|
||||
</copyright>
|
||||
<legalnotice>
|
||||
<para>This manual page was written for the Debian system
|
||||
(and may be used by others).</para>
|
||||
<para>Permission is granted to copy, distribute and/or modify this
|
||||
document under the terms of the GNU General Public License,
|
||||
Version 2 or (at your option) any later version published by
|
||||
the Free Software Foundation.</para>
|
||||
<para>On Debian systems, the complete text of the GNU General Public
|
||||
License can be found in
|
||||
<filename>/usr/share/common-licenses/GPL</filename>.</para>
|
||||
</legalnotice>
|
||||
</refentryinfo>
|
||||
<refmeta>
|
||||
<refentrytitle>&dhucpackage;</refentrytitle>
|
||||
<manvolnum>&dhsection;</manvolnum>
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname>&dhpackage;</refname>
|
||||
<refpurpose>program to do something</refpurpose>
|
||||
</refnamediv>
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
<!-- These are several examples, how syntaxes could look -->
|
||||
<arg choice="plain"><option>-e <replaceable>this</replaceable></option></arg>
|
||||
<arg choice="opt"><option>--example=<parameter>that</parameter></option></arg>
|
||||
<arg choice="opt">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-e</option></arg>
|
||||
<arg choice="plain"><option>--example</option></arg>
|
||||
</group>
|
||||
<replaceable class="option">this</replaceable>
|
||||
</arg>
|
||||
<arg choice="opt">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-e</option></arg>
|
||||
<arg choice="plain"><option>--example</option></arg>
|
||||
</group>
|
||||
<group choice="req">
|
||||
<arg choice="plain"><replaceable>this</replaceable></arg>
|
||||
<arg choice="plain"><replaceable>that</replaceable></arg>
|
||||
</group>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>&dhpackage;</command>
|
||||
<!-- Normally the help and version options make the programs stop
|
||||
right after outputting the requested information. -->
|
||||
<group choice="opt">
|
||||
<arg choice="plain">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-h</option></arg>
|
||||
<arg choice="plain"><option>--help</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
<arg choice="plain">
|
||||
<group choice="req">
|
||||
<arg choice="plain"><option>-v</option></arg>
|
||||
<arg choice="plain"><option>--version</option></arg>
|
||||
</group>
|
||||
</arg>
|
||||
</group>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
<refsect1 id="description">
|
||||
<title>DESCRIPTION</title>
|
||||
<para>This manual page documents briefly the
|
||||
<command>&dhpackage;</command> and <command>bar</command>
|
||||
commands.</para>
|
||||
<para>This manual page was written for the Debian distribution
|
||||
because the original program does not have a manual page.
|
||||
Instead, it has documentation in the GNU <citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> format; see below.</para>
|
||||
<para><command>&dhpackage;</command> is a program that...</para>
|
||||
</refsect1>
|
||||
<refsect1 id="options">
|
||||
<title>OPTIONS</title>
|
||||
<para>The program follows the usual GNU command line syntax,
|
||||
with long options starting with two dashes (`-'). A summary of
|
||||
options is included below. For a complete description, see the
|
||||
<citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> files.</para>
|
||||
<variablelist>
|
||||
<!-- Use the variablelist.term.separator and the
|
||||
variablelist.term.break.after parameters to
|
||||
control the term elements. -->
|
||||
<varlistentry>
|
||||
<term><option>-e <replaceable>this</replaceable></option></term>
|
||||
<term><option>--example=<replaceable>that</replaceable></option></term>
|
||||
<listitem>
|
||||
<para>Does this and that.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--help</option></term>
|
||||
<listitem>
|
||||
<para>Show summary of options.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--version</option></term>
|
||||
<listitem>
|
||||
<para>Show version of program.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="files">
|
||||
<title>FILES</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><filename>/etc/foo.conf</filename></term>
|
||||
<listitem>
|
||||
<para>The system-wide configuration file to control the
|
||||
behaviour of <application>&dhpackage;</application>. See
|
||||
<citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry> for further details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><filename>${HOME}/.foo.conf</filename></term>
|
||||
<listitem>
|
||||
<para>The per-user configuration file to control the
|
||||
behaviour of <application>&dhpackage;</application>. See
|
||||
<citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry> for further details.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="environment">
|
||||
<title>ENVIRONMENT</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><envar>FOO_CONF</envar></term>
|
||||
<listitem>
|
||||
<para>If used, the defined file is used as configuration
|
||||
file (see also <xref linkend="files"/>).</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
<refsect1 id="diagnostics">
|
||||
<title>DIAGNOSTICS</title>
|
||||
<para>The following diagnostics may be issued
|
||||
on <filename class="devicefile">stderr</filename>:</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><errortext>Bad configuration file. Exiting.</errortext></term>
|
||||
<listitem>
|
||||
<para>The configuration file seems to contain a broken configuration
|
||||
line. Use the <option>--verbose</option> option, to get more info.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para><command>&dhpackage;</command> provides some return codes, that can
|
||||
be used in scripts:</para>
|
||||
<segmentedlist>
|
||||
<segtitle>Code</segtitle>
|
||||
<segtitle>Diagnostic</segtitle>
|
||||
<seglistitem>
|
||||
<seg><errorcode>0</errorcode></seg>
|
||||
<seg>Program exited successfully.</seg>
|
||||
</seglistitem>
|
||||
<seglistitem>
|
||||
<seg><errorcode>1</errorcode></seg>
|
||||
<seg>The configuration file seems to be broken.</seg>
|
||||
</seglistitem>
|
||||
</segmentedlist>
|
||||
</refsect1>
|
||||
<refsect1 id="bugs">
|
||||
<!-- Or use this section to tell about upstream BTS. -->
|
||||
<title>BUGS</title>
|
||||
<para>The program is currently limited to only work
|
||||
with the <package>foobar</package> library.</para>
|
||||
<para>The upstreams <acronym>BTS</acronym> can be found
|
||||
at <ulink url="http://bugzilla.foo.tld"/>.</para>
|
||||
</refsect1>
|
||||
<refsect1 id="see_also">
|
||||
<title>SEE ALSO</title>
|
||||
<!-- In alpabetical order. -->
|
||||
<para><citerefentry>
|
||||
<refentrytitle>bar</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>, <citerefentry>
|
||||
<refentrytitle>baz</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry>, <citerefentry>
|
||||
<refentrytitle>foo.conf</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry></para>
|
||||
<para>The programs are documented fully by <citetitle>The Rise and
|
||||
Fall of a Fooish Bar</citetitle> available via the <citerefentry>
|
||||
<refentrytitle>info</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</citerefentry> system.</para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
@ -1,2 +0,0 @@
|
||||
?package(libsntl):needs="X11|text|vc|wm" section="Applications/see-menu-manual"\
|
||||
title="libsntl" command="/usr/bin/libsntl"
|
@ -1 +1 @@
|
||||
libsntl 0.2.0 libsntl (>> 0.2.0), libsntl (<< 0.2.99)
|
||||
libsntl 0.3.0 libsntl (>> 0.3.0), libsntl (<< 0.3.99)
|
||||
|
@ -1 +1 @@
|
||||
nobase_include_HEADERS = sntl/pth_queue.h sntl/connection.h
|
||||
nobase_include_HEADERS = sntl/sntllv2.h sntl/errno.h sntl/limits.h
|
||||
|
@ -1,312 +0,0 @@
|
||||
/*
|
||||
* File: connection.h
|
||||
* Author: vdo
|
||||
*
|
||||
* Created on September 24, 2014, 2:36 AM
|
||||
*/
|
||||
|
||||
#ifndef __ESXC_CONNECTION_H_
|
||||
#define __ESXC_CONNECTION_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <tdata/idx_allocator.h>
|
||||
#include <sexpr/sexp.h>
|
||||
#include <sexpr/faststack.h>
|
||||
|
||||
#include <sntl/pth_queue.h>
|
||||
|
||||
/* error codes */
|
||||
#define ESXOREPLYREQ 44 /* protocol require reply with expression,
|
||||
* or expression return for the request */
|
||||
#define ESXOTIMEDOUT 45 /* timedout */
|
||||
#define ESXRCBADPROT 46 /* invalid protocol */
|
||||
#define ESXNOCONNECT 47 /* connection is lost */
|
||||
#define ESXNOCHANSUP 48
|
||||
#define ESXRAPIDREPLY 49
|
||||
|
||||
#define VERIFY_DEPTH 1 /* FIXME: */
|
||||
|
||||
#define MAX_CONNECTIONS 32768
|
||||
#define MAX_CHANNELS 4096
|
||||
#define MAX_RPC_LIST 2048
|
||||
#define MAX_MULTI 12
|
||||
#define MAX_PENDINGMSG 16384
|
||||
#define MAX_MSGINDEX ((MAX_PENDINGMSG) * (MAX_MULTI))
|
||||
|
||||
typedef struct __perm_context_type {
|
||||
char *login;
|
||||
char *passwd;
|
||||
ulong_t certid;
|
||||
ulong_t uid;
|
||||
ulong_t gid;
|
||||
ulong_t *gids;
|
||||
int n_gids;
|
||||
int p_attr;
|
||||
struct in_addr *addr;
|
||||
void *priv;
|
||||
} perm_ctx_t;
|
||||
|
||||
#define CXCONN_MASTER (1 << 1)
|
||||
#define CXCONN_SLAVE (1 << 2)
|
||||
#define CXCONN_ESTABL (1 << 3)
|
||||
#define CXCONN_BROKEN (1 << 4)
|
||||
|
||||
|
||||
struct __connections_subsys_type;
|
||||
/*
|
||||
* älä jätä kommentteja omalla kielellä! yksinkertaisia englanti sijaan!
|
||||
* i found somebody who write comments and messages in non-english,
|
||||
* itäs a fucking practice - forget it.
|
||||
*/
|
||||
typedef struct __connection_t {
|
||||
struct __connections_subsys_type *ssys; /* < connections subsystem */
|
||||
char *uuid; /** < uuid of the connection */
|
||||
idx_allocator_t *idx_ch; /** < index allocation for channels */
|
||||
usrtc_t *chnl_tree; /** < search tree of all channels */
|
||||
usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */
|
||||
SSL_CTX *ctx; /** < SSL context */
|
||||
SSL *ssl; /** < SSL connection */
|
||||
int ssl_data_index; /** < SSL index for the custom data */
|
||||
perm_ctx_t *pctx; /** < higher layer authentification context */
|
||||
pthread_t cthread; /** < thread for listening the connection socket */
|
||||
pthread_t rmsgthread; /** < thread for message queue (1) */
|
||||
pthread_t msgthread; /** < thread for message queue (2) */
|
||||
pth_queue_t *mqueue; /** < message queue (2) */
|
||||
pth_queue_t *rqueue; /** < message queue (1) */
|
||||
pth_dqtpoll_t *tpoll; /** < thread poll for rpc requests */
|
||||
pthread_mutex_t oplock; /** < mutex used to sync operations on connection */
|
||||
pthread_rwlock_t chnl_lock; /** < rwlock used to sync ops with channels */
|
||||
int flags; /** < flags of the connection */
|
||||
usrtc_node_t csnode; /** < node to store the connection within list */
|
||||
} conn_t;
|
||||
|
||||
struct __connection_rpc_list_type;
|
||||
struct __message_t;
|
||||
|
||||
#define ESXCHAN_PENDING (1 << 1)
|
||||
#define ESXCHAN_CLOSURE (1 << 2)
|
||||
|
||||
typedef struct __channel_t {
|
||||
ulong_t cid; /** < ID of the channel */
|
||||
char *uuid; /** < UUID of the channel, used in advanced implementation
|
||||
* of the complex distributed systems */
|
||||
conn_t *connection; /** < pointer to the parent connection */
|
||||
idx_allocator_t *idx_msg; /** < index allocation for messages */
|
||||
usrtc_t *msgs_tree; /** < search tree of the existing messages */
|
||||
struct __message_t *sysmsg; /** < system message used to operate with channel */
|
||||
struct __connection_rpc_list_type *rpc_list; /** < rpc functions list */
|
||||
pthread_mutex_t oplock; /** < operation ops lock */
|
||||
pthread_rwlock_t msglock; /** < rwlock used to operate with messages */
|
||||
usrtc_node_t node; /** < node for connection search tree */
|
||||
int use_count; /** < use count */
|
||||
int flags; /** < flags of the channel */
|
||||
} chnl_t;
|
||||
|
||||
typedef struct __sexp_payload_t {
|
||||
char *cstr;
|
||||
sexp_t *sx;
|
||||
} sxpayload_t;
|
||||
|
||||
#define ESX_SYSMSG_SIZE 512
|
||||
|
||||
#define ESXMSG_SYS (1 << 1)
|
||||
#define ESXMSG_USR (1 << 2)
|
||||
#define ESXMSG_PENDING (1 << 3)
|
||||
#define ESXMSG_NOWAY (1 << 4)
|
||||
#define ESXMSG_TIMEDOUT (1 << 5)
|
||||
#define ESXMSG_PULSE (1 << 6) /* obsolete flag */
|
||||
#define ESXMSG_NOWAIT (1 << 7)
|
||||
#define ESXMSG_ISREPLY (1 << 8)
|
||||
#define ESXMSG_CLOSURE (1 << 9)
|
||||
#define ESXMSG_RMONRETR (1 << 10)
|
||||
#define ESXMSG_KILLTHRD (1 << 11)
|
||||
#define ESXMSG_ISRAPID (1 << 12)
|
||||
|
||||
/**
|
||||
* \brief Message used in sntl message passing
|
||||
*
|
||||
* This structure used to manage a message within a channel
|
||||
* of the sntl structure stack.
|
||||
*/
|
||||
typedef struct __message_t {
|
||||
chnl_t *pch; /** < channel of the message(if applicable) */
|
||||
ulong_t mid; /** < unique ID within connection context */
|
||||
char *uuid; /** < UUID of the message, used for special messages */
|
||||
usrtc_node_t pendingq_node; /** < node for the pending queue */
|
||||
pthread_mutex_t wait; /** < special wait mutex, used for sync */
|
||||
void *payload; /** < payload */
|
||||
sexp_t *initial_sx;
|
||||
int opcode; /** < opcode for system and pulse messages */
|
||||
int flags; /** < flags of the message (type, state etc ...)*/
|
||||
int use_count; /** < use count */
|
||||
} sxmsg_t;
|
||||
|
||||
typedef struct __connection_rpc_entry_type {
|
||||
char *name;
|
||||
int (*rpcf)(void *, sexp_t *);
|
||||
usrtc_node_t node;
|
||||
} cx_rpc_t;
|
||||
|
||||
typedef struct __connection_rpc_list_type {
|
||||
usrtc_t *rpc_tree; /** < search tree for the rpc lookup */
|
||||
char *opt_version; /** < reserved for future implementations */
|
||||
} cx_rpc_list_t;
|
||||
|
||||
/**
|
||||
* \brief Connection subsystem structure.
|
||||
*
|
||||
* This structure used for management and control a set of a
|
||||
* determined connections with the same RPC lists and the same
|
||||
* mode (server, client).
|
||||
*
|
||||
*/
|
||||
typedef struct __connections_subsys_type {
|
||||
usrtc_t *connections;
|
||||
pth_queue_t *ioq; /** < general messages queue */
|
||||
pth_queue_t *ioqueue; /** < system messages queue */
|
||||
/* system threads */
|
||||
pthread_t iog_thread; /** < general io queue */
|
||||
pthread_t ios_thread; /** < system io queue */
|
||||
pthread_rwlock_t rwlock;
|
||||
char *rootca, *certpem, *certkey; /* path name to the certificates */
|
||||
cx_rpc_list_t *system_rpc;
|
||||
/* special functions pointers */
|
||||
int (*validate_sslpem)(conn_t *); /** < this function used to validate SSL certificate while SSL handshake */
|
||||
int (*secure_check)(conn_t *); /** < this function authorize user to login,
|
||||
* and also should check SSL cert and user, and already made sessions */
|
||||
usrtc_t* (*get_rpc_typed_list_tree)(conn_t *); /** < this function is used to set RPC list of the functions */
|
||||
int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback
|
||||
* during setting up a typed channel */
|
||||
void (*on_destroy)(conn_t *); /** < callback on connection destroy */
|
||||
void *priv;
|
||||
} conn_sys_t;
|
||||
|
||||
typedef struct __rpc_typed_list_type {
|
||||
int type_id;
|
||||
char *description;
|
||||
cx_rpc_list_t *rpc_list;
|
||||
usrtc_node_t lnode;
|
||||
} rpc_typed_list_t;
|
||||
|
||||
/* General API */
|
||||
/* subsystem */
|
||||
|
||||
extern conn_sys_t *conn_sys; /* an old obsolete method */
|
||||
/* old API from 0.1.xx */
|
||||
#define connections_subsystem_init() { conn_sys = (conn_sys_t *)malloc(sizeof(conn_sys_t)); connections_init(conn_sys); }
|
||||
|
||||
#define connections_subsystem_setsslserts(a, b, c) connections_setsslserts(conn_sys, a, b, c)
|
||||
|
||||
#define connections_subsystem_setrpclist_function(a) connections_setrpclist_function(conn_sys, a)
|
||||
|
||||
#define connections_set_priv(c, p) (c)->priv = (void *)p
|
||||
|
||||
#define connections_get_priv(c) (c)->priv
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** call this function before use sntl related functions */
|
||||
int sntl_init(void);
|
||||
|
||||
/* new */
|
||||
int connections_init(conn_sys_t *ssys);
|
||||
|
||||
int connections_setsslserts(conn_sys_t *ssys, const char *rootca,
|
||||
const char *certpem, const char *certkey);
|
||||
|
||||
int connections_setrpclist_function(conn_sys_t *ssys,
|
||||
usrtc_t* (*get_rpc_typed_list_tree)(conn_t *));
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define connections_subsystem_set_securecheck(c, fuu) (c)->secure_check = fuu
|
||||
#define connections_subsystem_set_sslvalidator(c, fuu) (c)->validate_sslpem = fuu
|
||||
#define connections_subsystem_set_rpctlist_call(c, fuu) (c)->set_typed_list_callback = fuu
|
||||
#define connections_subsystem_set_on_destroy(c, fuu) (c)->on_destroy = fuu
|
||||
|
||||
/* connection - compatibility (old versions) macros */
|
||||
#define connection_create(c, s) connection_create_fapi((c), (s), NULL)
|
||||
#define connection_initiate(c, h, p, s, p1) connection_initiate_m(conn_sys, c, h, p, s, p1)
|
||||
#define connection_create_fapi(c, s, a) connection_create_fapi_m(conn_sys, c, s, a)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* new */
|
||||
int connection_initiate_m(conn_sys_t *ssys, conn_t *co, const char *host,
|
||||
int port, const char *SSL_cert, perm_ctx_t *pctx);
|
||||
|
||||
int connection_create_fapi_m(conn_sys_t *ssys, conn_t *co, int sck,
|
||||
struct in_addr *addr);
|
||||
|
||||
int connection_close(conn_t *co);
|
||||
|
||||
/* channels */
|
||||
int channel_open(conn_t *co, chnl_t **ch, int type);
|
||||
|
||||
int channel_close(chnl_t *chnl);
|
||||
|
||||
/* message passing */
|
||||
int msg_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg);
|
||||
|
||||
int msg_send_timed(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio);
|
||||
|
||||
int msg_return(sxmsg_t *msg, int opcode);
|
||||
|
||||
int msg_reply(sxmsg_t *msg, sexp_t *sx);
|
||||
|
||||
int msg_reply_timed(sxmsg_t *msg, sexp_t *sx, struct timespec *tio);
|
||||
|
||||
/* reply with S expression without confirmation of delivery and applying */
|
||||
int msg_reply_rapid(sxmsg_t *msg, sexp_t *sx);
|
||||
|
||||
/* this is required to clean the message in case if it's a rapid message */
|
||||
int msg_rapid_clean(sxmsg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* additional functions */
|
||||
#define sntl_msg_get_secctx(m) (m)->pch->connection->pctx
|
||||
|
||||
/* RPC List API */
|
||||
#define SNTL_FILTER_INC 0xa
|
||||
#define SNTL_FILTER_EXC 0xb
|
||||
#define SNTL_FILTER_END -1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int sntl_rpclist_init(usrtc_t *tree);
|
||||
|
||||
int sntl_rpclist_add(usrtc_t *tree, int type, const char *description,
|
||||
const char *version);
|
||||
|
||||
int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name,
|
||||
int (*rpcf)(void *, sexp_t *));
|
||||
|
||||
int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* for DEBUG purposes */
|
||||
#define __DBGLINE fprintf(stderr, "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#endif /* __ESXC_CONNECTION_H_ */
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SNTL_ERRNO_H__
|
||||
#define __SNTL_ERRNO_H__
|
||||
|
||||
#define __SNTL_EPREFIX 200
|
||||
|
||||
#define SNE_SUCCESS 200
|
||||
#define SNE_FAILED 201
|
||||
#define SNE_ENOMEM 202
|
||||
#define SNE_BADPROTO 203
|
||||
#define SNE_ENORPC 204
|
||||
#define SNE_EPERM 205
|
||||
#define SNE_TOOLONG 206
|
||||
#define SNE_EBUSY 207
|
||||
#define SNE_WOULDBLOCK 208
|
||||
#define SNE_LINKERROR 209
|
||||
#define SNE_NOSUCHMSG 210
|
||||
#define SNE_NOSUCHCHAN 211
|
||||
#define SNE_ETIMEDOUT 212
|
||||
#define SNE_IGNORED 213
|
||||
#define SNE_REPLYREQ 214
|
||||
#define SNE_RAPIDMSG 215
|
||||
#define SNE_ESSL 216
|
||||
#define SNE_NOCHANNELS 217
|
||||
#define SNE_MCHANNELS 218
|
||||
#define SNE_MMESSAGES 219
|
||||
#define SNE_LINKBROKEN 220
|
||||
#define SNE_INVALINDEX 221
|
||||
|
||||
/* some old errors for compatibility */
|
||||
#define ESXOREPLYREQ SNE_REPLYREQ /* protocol require reply with expression,
|
||||
* or expression return for the request */
|
||||
#define ESXOTIMEDOUT SNE_ETIMEDOUT /* timedout */
|
||||
#define ESXRCBADPROT SNE_BADPROTO /* invalid protocol */
|
||||
#define ESXNOCONNECT SNE_LINKERROR /* connection is lost */
|
||||
#define ESXNOCHANSUP SNE_NOSUCHCHAN
|
||||
#define ESXRAPIDREPLY SNE_RAPIDMSG
|
||||
|
||||
const char *sntll_errno2cstr(int);
|
||||
|
||||
#endif /* __SNTL_ERRNO_H__ */
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SNTL_LIMITS_H__
|
||||
#define __SNTL_LIMITS_H__
|
||||
|
||||
#define MAX_RPC_LIST 512
|
||||
|
||||
#define MAX_RBBUF_LEN (65536 - sizeof(sntllv2_head_t))
|
||||
|
||||
#endif /* __SNTL_LIMITS_H__ */
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) 2013 Copyright Askele, inc. <http://askele.com>
|
||||
* (c) 2013 Copyright Askele Ingria, inc. <http://askele-ingria.com>
|
||||
* (c) 2014 Copyright Confident, inc. (granted permission to use in commercial software)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file pth_queue.h
|
||||
* @author Alexander Vdolainen
|
||||
* @date 4 Nov 2013, 20 Dec 2014 (dynamic polls)
|
||||
* @brief queue implementation for threads intercommunication
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PTH_QUEUE_H__
|
||||
#define __PTH_QUEUE_H__
|
||||
|
||||
#include <pthread.h>
|
||||
#include <tdata/idx_allocator.h>
|
||||
|
||||
/* possible message types, ones with POLL_ prefix valid on for pth_dqtpoll_* */
|
||||
#define SYS_MSG 0x0f0affee
|
||||
#define USR_MSG 0x0afeeffe
|
||||
#define POLL_DECREASE 0x0afafafe
|
||||
#define POLL_INCREASE 0x0afaffff
|
||||
#define NIL_MSG 0x0
|
||||
#define END_MSG 0xdead0000
|
||||
|
||||
/* max amount of threads within the poll */
|
||||
#define MAX_POLL_VALUE 32
|
||||
|
||||
typedef struct pth_msg_s {
|
||||
void *data; /** < message payload */
|
||||
unsigned int msgtype; /** < message type ID */
|
||||
unsigned int qlength; /** < current queue length (actual on add moment),
|
||||
* it makes no sense with few readers */
|
||||
usrtc_node_t node;
|
||||
} pth_msg_t;
|
||||
|
||||
typedef struct pth_queue_s {
|
||||
unsigned int length;
|
||||
/* sync */
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
/* queue data */
|
||||
usrtc_t qtree;
|
||||
/* cache */
|
||||
usrtc_t msgcache;
|
||||
} pth_queue_t;
|
||||
|
||||
int pth_queue_init(pth_queue_t *queue);
|
||||
|
||||
int pth_queue_add(pth_queue_t *queue, void *data, unsigned int msgtype);
|
||||
|
||||
int pth_queue_get(pth_queue_t *queue, const struct timespec *timeout,
|
||||
pth_msg_t *msg);
|
||||
|
||||
unsigned int pth_queue_length(pth_queue_t *queue);
|
||||
|
||||
int pth_queue_destroy(pth_queue_t *queue, int freedata,
|
||||
void (*free_msg)(void *));
|
||||
|
||||
/* dynamic queue thread poll ... bbrrr .... ok, ok with beer
|
||||
* Dynamic queue thread poll is a queue like pth_queue,
|
||||
* but also it has itäs own mamagement for threads - that's
|
||||
* why dynamic.
|
||||
* Ideally, the model is trying to achieve the following:
|
||||
* 1. one thread in queue while no or very small amount of jobs in the queue
|
||||
* 2. grow until max threads is reached while too many requests
|
||||
* 3. gently slide down volume of threads after job heat
|
||||
* 4. minimal additional drawbacks (i hate something periodically running,
|
||||
* it's bad practice)
|
||||
* The model is quite simple, we should make spurious wakeups equal to zero,
|
||||
* if no - decrease poll value, and, if we don't have thread available -
|
||||
* create it.
|
||||
*/
|
||||
typedef struct pth_dqtpoll_s {
|
||||
pth_queue_t *queue; /** < Job queue */
|
||||
pthread_t *poll; /** < Thread descriptors */
|
||||
int (*jobdata_callback)(void *); /** < Callback to have a deal with data */
|
||||
int flags; /** < Flags */
|
||||
idx_allocator_t *idx; /** < index allocator for the poll threads */
|
||||
pthread_rwlock_t stats_lock; /** < rwlock for stats data */
|
||||
unsigned long spurious_wakeups; /** < amount of spurios wakeups */
|
||||
int poll_value; /** < value of the poll (totally) */
|
||||
struct timeval sched_time;
|
||||
int msgop;
|
||||
} pth_dqtpoll_t;
|
||||
|
||||
/* flags for poll */
|
||||
#define DQTPOLL_RUNNING (1 << 1) /* poll is running */
|
||||
#define DQTPOLL_DEADSTAGE (1 << 2) /* poll in the stage of destroy */
|
||||
|
||||
/* keep it stupid */
|
||||
#define DQTPOLL_DELTAMS 500000
|
||||
#define DQTPOLL_DELTASE 0
|
||||
|
||||
/* init poll, structure must be allocated */
|
||||
int pth_dqtpoll_init(pth_dqtpoll_t*, int (*jobdata_callback)(void *));
|
||||
|
||||
/* run poll: poll */
|
||||
int pth_dqtpoll_run(pth_dqtpoll_t*);
|
||||
|
||||
/* add the job to the queue: poll, job data, message type */
|
||||
int pth_dqtpoll_add(pth_dqtpoll_t*, void*, unsigned int);
|
||||
|
||||
/* destroy the poll: poll, force flag
|
||||
* if force flag is set (!= 0), give up
|
||||
* about jobs, if no, do the job, but don't
|
||||
* accept the new ones, and destroy all poll
|
||||
* with last thread.
|
||||
*/
|
||||
int pth_dqtpoll_destroy(pth_dqtpoll_t*, int);
|
||||
|
||||
#endif /* __PTH_QUEUE_H__ */
|
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SNTL_SNTLLV2_H__
|
||||
#define __SNTL_SNTLLV2_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <tdata/idx_allocator.h>
|
||||
#include <tdata/list.h>
|
||||
#include <sexpr/sexp.h>
|
||||
#include <sexpr/faststack.h>
|
||||
|
||||
#include <sntl/errno.h>
|
||||
|
||||
#define VERIFY_DEPTH 1 /* FIXME: */
|
||||
|
||||
typedef struct __perm_context_type {
|
||||
char *login;
|
||||
char *passwd;
|
||||
uint64_t certid;
|
||||
struct in_addr *addr;
|
||||
void *priv;
|
||||
} perm_ctx_t;
|
||||
|
||||
/* 8 byte header */
|
||||
typedef struct __sntllv2_head_type {
|
||||
uint16_t msgid;
|
||||
uint16_t payload_length;
|
||||
uint8_t attr;
|
||||
uint8_t opcode;
|
||||
uint16_t reserve;
|
||||
}__attribute__((packed)) sntllv2_head_t;
|
||||
|
||||
struct __connections_subsys_type;
|
||||
struct __channel_t;
|
||||
struct __message_t;
|
||||
|
||||
/* flags for the connection link */
|
||||
#define SNSX_BATCHMODE (1 << 1)
|
||||
#define SNSX_MESSAGINGMODE (1 << 2)
|
||||
#define SNSX_ALIVE (1 << 3)
|
||||
#define SNSX_CLOSED (1 << 4)
|
||||
|
||||
/*
|
||||
* älä jätä kommentteja omalla kielellä! yksinkertaisia englanti sijaan!
|
||||
* i found somebody who write comments and messages in non-english,
|
||||
* it's a fucking practice - forget it.
|
||||
*/
|
||||
typedef struct __connection_t {
|
||||
/* General section */
|
||||
struct __connections_subsys_type *ssys; /* < connections subsystem */
|
||||
char *uuid; /** < uuid of the connection */
|
||||
/* Channels section */
|
||||
idx_allocator_t idx_ch; /** < index allocation for channels */
|
||||
pthread_mutex_t idx_ch_lock; /** < mutex for allocating and deallocating channels */
|
||||
struct __channel_t **channels; /** < channels O(1) storage */
|
||||
/* RPC section */
|
||||
usrtc_t *rpc_list; /** < search tree of possible RPC typed lists */
|
||||
/* SSL related section */
|
||||
SSL_CTX *ctx; /** < SSL context */
|
||||
SSL *ssl; /** < SSL connection */
|
||||
int ssl_data_index; /** < SSL index for the custom data */
|
||||
pthread_mutex_t sslinout[2]; /** < SSL related locks for in and out */
|
||||
/* Security section */
|
||||
perm_ctx_t *pctx; /** < higher layer authentification context */
|
||||
/* Messages section */
|
||||
struct __message_t **messages; /** < messages O(1) storage */
|
||||
idx_allocator_t idx_msg;
|
||||
pthread_mutex_t idx_msg_lock;
|
||||
list_head_t write_pending; /** < list of messages waiting for write */
|
||||
pthread_mutex_t write_pending_lock;
|
||||
volatile uint8_t pending_messages; /** < pending message count */
|
||||
/* Other stuff */
|
||||
pthread_t thrd_poll[8];
|
||||
volatile uint8_t flags; /** < flags of the connection */
|
||||
volatile uint8_t usecount;
|
||||
usrtc_node_t csnode; /** < node to store the connection within list */
|
||||
} conn_t;
|
||||
|
||||
struct __connection_rpc_list_type;
|
||||
struct __message_t;
|
||||
|
||||
typedef struct __pp_msg_type {
|
||||
struct __message_t *msg;
|
||||
list_node_t node;
|
||||
} ppmsg_t;
|
||||
|
||||
typedef struct __channel_t {
|
||||
uint16_t cid; /** < ID of the channel */
|
||||
conn_t *connection; /** < pointer to the parent connection */
|
||||
struct __connection_rpc_list_type *rpc_list; /** < rpc functions list */
|
||||
int flags; /** < flags of the channel */
|
||||
} chnl_t;
|
||||
|
||||
/* message flags */
|
||||
#define SXMSG_OPEN (1 << 1)
|
||||
#define SXMSG_CLOSED (1 << 2)
|
||||
#define SXMSG_PROTO (1 << 3)
|
||||
#define SXMSG_LINK (1 << 4)
|
||||
#define SXMSG_REPLYREQ (1 << 5)
|
||||
#define SXMSG_PULSE (1 << 6)
|
||||
#define SXMSG_TIMEDOUT (1 << 7)
|
||||
|
||||
/**
|
||||
* \brief Message used in sntl message passing
|
||||
*
|
||||
* This structure used to manage a message within a channel
|
||||
* of the sntl structure stack.
|
||||
*/
|
||||
typedef struct __message_t {
|
||||
chnl_t *pch; /** < channel of the message(if applicable) */
|
||||
pthread_mutex_t wait; /** < special wait mutex, used for pending list and sync */
|
||||
sntllv2_head_t mhead;
|
||||
void *payload; /** < payload */
|
||||
} sxmsg_t;
|
||||
|
||||
#define sxmsg_payload(m) (m)->payload
|
||||
#define sxmsg_datalen(m) (m)->mhead.payload_length
|
||||
#define sxmsg_rapidbuf(m) (m)->payload
|
||||
#define sxmsg_retcode(m) (m)->mhead.opcode
|
||||
#define sxmsg_waitlock(m) pthread_mutex_lock(&((m)->wait))
|
||||
#define sxmsg_waitunlock(m) pthread_mutex_unlock(&((m)->wait))
|
||||
|
||||
typedef struct __connection_rpc_entry_type {
|
||||
char *name;
|
||||
int (*rpcf)(void *, sexp_t *);
|
||||
usrtc_node_t node;
|
||||
} cx_rpc_t;
|
||||
|
||||
typedef struct __connection_rpc_list_type {
|
||||
usrtc_t *rpc_tree; /** < search tree for the rpc lookup */
|
||||
char *opt_version; /** < reserved for future implementations */
|
||||
} cx_rpc_list_t;
|
||||
|
||||
#define MAX_CONNECTIONS 32768
|
||||
|
||||
/**
|
||||
* \brief Connection subsystem structure.
|
||||
*
|
||||
* This structure used for management and control a set of a
|
||||
* determined connections with the same RPC lists and the same
|
||||
* mode (server, client).
|
||||
*
|
||||
*/
|
||||
typedef struct __connections_subsys_type {
|
||||
usrtc_t *connections;
|
||||
pthread_rwlock_t rwlock;
|
||||
char *rootca, *certpem, *certkey; /* path name to the certificates */
|
||||
cx_rpc_list_t *system_rpc;
|
||||
/* special functions pointers */
|
||||
int (*validate_sslpem)(conn_t *); /** < this function used to validate SSL certificate while SSL handshake */
|
||||
int (*secure_check)(conn_t *); /** < this function authorize user to login,
|
||||
* and also should check SSL cert and user, and already made sessions */
|
||||
usrtc_t* (*get_rpc_typed_list_tree)(conn_t *); /** < this function is used to set RPC list of the functions */
|
||||
int (*set_typed_list_callback)(conn_t *, int, char *); /** < this function is a callback
|
||||
* during setting up a typed channel */
|
||||
void (*on_destroy)(conn_t *); /** < callback on connection destroy */
|
||||
void (*on_pulse)(conn_t *, sexp_t *); /** < callback on pulse emit */
|
||||
void *priv;
|
||||
} conn_sys_t;
|
||||
|
||||
#define connections_set_sslvalidate(c, f) (c)->validate_sslpem = (f)
|
||||
#define connections_set_authcheck(c, f) (c)->secure_check = (f)
|
||||
#define connections_set_rpcvalidator(c, f) (c)->get_rpc_typed_list_tree = (f)
|
||||
#define connections_set_channelcall(c, f) (c)->set_typed_list_callback = (f)
|
||||
#define connections_set_ondestroy(c, f) (c)->on_destroy = (f)
|
||||
#define connections_set_onpulse(c, f) (c)->on_pulse = (f)
|
||||
#define connections_set_priv(c, p) (c)->priv = (p)
|
||||
#define connections_get_priv(c) (c)->priv
|
||||
|
||||
typedef struct __rpc_typed_list_type {
|
||||
int type_id;
|
||||
char *description;
|
||||
cx_rpc_list_t *rpc_list;
|
||||
usrtc_node_t lnode;
|
||||
} rpc_typed_list_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* API */
|
||||
int sntl_init(void);
|
||||
|
||||
int connections_init(conn_sys_t *ssys);
|
||||
|
||||
conn_sys_t *connections_create(void);
|
||||
|
||||
int connections_destroy(conn_sys_t *ssys);
|
||||
|
||||
int connections_free(conn_sys_t *ssys);
|
||||
|
||||
int connections_setsslserts(conn_sys_t *ssys, const char *rootca,
|
||||
const char *certpem, const char *certkey);
|
||||
|
||||
/* create links */
|
||||
conn_t *connection_master_link(conn_sys_t *ssys, int sck, struct in_addr *addr);
|
||||
conn_t *connection_link(conn_sys_t *ssys, const char *host,
|
||||
int port, const char *SSL_cert, const char *login,
|
||||
const char *passwd);
|
||||
int connection_close(conn_t *co);
|
||||
|
||||
/* channels */
|
||||
chnl_t *sxchannel_open(conn_t *co, int type);
|
||||
int sxchannel_close(chnl_t *channel);
|
||||
|
||||
/* messages */
|
||||
/*
|
||||
* creates a message with a payload.
|
||||
* Will return a error code, and, if applicable, pointer to message
|
||||
*/
|
||||
int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg);
|
||||
/* the same - postponed message i.e. will be written to the queue - not to write immendatly */
|
||||
int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **msg);
|
||||
/* send a pulse message */
|
||||
int sxmsg_pulse(conn_t *co, const char *data, size_t datalen);
|
||||
int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen);
|
||||
int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen);
|
||||
int sxmsg_rreply(sxmsg_t *msg, size_t datalen);
|
||||
int sxmsg_return(sxmsg_t *msg, int opcode);
|
||||
int sxmsg_return_pp(sxmsg_t *msg, int opcode);
|
||||
void sxmsg_clean(sxmsg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* RPC List API */
|
||||
#define SNTL_FILTER_INC 0xa
|
||||
#define SNTL_FILTER_EXC 0xb
|
||||
#define SNTL_FILTER_END -1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int sntl_rpclist_init(usrtc_t *tree);
|
||||
|
||||
int sntl_rpclist_add(usrtc_t *tree, int type, const char *description,
|
||||
const char *version);
|
||||
|
||||
int sntl_rpclist_add_function(usrtc_t *tree, int type, const char *fu_name,
|
||||
int (*rpcf)(void *, sexp_t *));
|
||||
|
||||
int sntl_rpclist_filter(usrtc_t *source, usrtc_t **dest, int flag, int *filter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define blub(txt) fprintf(stderr, "%s:%d in %s > %s\n", __FILE__, __LINE__, __FUNCTION__, txt)
|
||||
|
||||
#define dumphead(head) fprintf(stderr, "id: %d, opcode: %d, attr: %d, len = %d\n", head->msgid, head->opcode, head->attr, head->payload_length)
|
||||
|
||||
#endif /* __SNTL_SNTLLV2_H__ */
|
||||
|
||||
|
@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library implementation.
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/connection.h>
|
||||
|
||||
extern char *__generate_uuid(void);
|
||||
|
||||
extern void __destroy_msg(sxmsg_t *msg);
|
||||
|
||||
extern int __create_sys_msg(sxmsg_t **msg, char *uuid, chnl_t *ch,
|
||||
sxpayload_t *data);
|
||||
|
||||
static long __cmp_ulong(const void *a, const void *b)
|
||||
{
|
||||
return (long)(*(ulong_t *)a - *(ulong_t *)b);
|
||||
}
|
||||
|
||||
int __alloc_channel(ulong_t cid, conn_t *co, rpc_typed_list_t *rlist, chnl_t **channel)
|
||||
{
|
||||
int r = 0;
|
||||
chnl_t *ch = malloc(sizeof(chnl_t));
|
||||
usrtc_t *msg_tree = malloc(sizeof(usrtc_t));
|
||||
idx_allocator_t *idx_msg = malloc(sizeof(idx_allocator_t));
|
||||
|
||||
if(!idx_msg) goto __fin_enomem;
|
||||
else if(idx_allocator_init(idx_msg, MAX_MSGINDEX, 0)) goto __fin_enomem;
|
||||
|
||||
if(!ch || !msg_tree) {
|
||||
__fin_up2:
|
||||
idx_allocator_destroy(idx_msg);
|
||||
__fin_enomem:
|
||||
r = ENOMEM;
|
||||
goto __fin_up;
|
||||
} else {
|
||||
usrtc_init(msg_tree, USRTC_REDBLACK, MAX_PENDINGMSG, __cmp_ulong);
|
||||
ch->cid = cid;
|
||||
ch->flags = ch->use_count = 0;
|
||||
ch->uuid = NULL;
|
||||
usrtc_node_init(&ch->node, ch);
|
||||
if(rlist) ch->rpc_list = rlist->rpc_list;
|
||||
else ch->rpc_list = NULL;
|
||||
/* init locks */
|
||||
if(pthread_rwlock_init(&(ch->msglock), NULL)) {
|
||||
r = ENOMEM;
|
||||
goto __fin_up2;
|
||||
}
|
||||
if(pthread_mutex_init(&(ch->oplock), NULL)) {
|
||||
pthread_rwlock_destroy(&(ch->msglock));
|
||||
r = ENOMEM;
|
||||
goto __fin_up2;
|
||||
}
|
||||
/* assign all the stuff */
|
||||
ch->idx_msg = idx_msg;
|
||||
ch->msgs_tree = msg_tree;
|
||||
ch->connection = co;
|
||||
}
|
||||
|
||||
__fin_up:
|
||||
if(r) {
|
||||
if(idx_msg) free(idx_msg);
|
||||
if(ch) free(ch);
|
||||
if(msg_tree) free(msg_tree);
|
||||
return r;
|
||||
} else {
|
||||
*channel = ch;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* channels */
|
||||
int channel_open(conn_t *co, chnl_t **ch, int type)
|
||||
{
|
||||
chnl_t *nch = NULL;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
int r = 0;
|
||||
char *uuid_;
|
||||
sxpayload_t *pl;
|
||||
ulong_t cid;
|
||||
rpc_typed_list_t *rpclist = NULL;
|
||||
usrtc_node_t *node = NULL;
|
||||
sxmsg_t *sms;
|
||||
|
||||
if(!(co->flags & CXCONN_ESTABL)) {
|
||||
return ESXNOCONNECT;
|
||||
}
|
||||
|
||||
uuid_ = __generate_uuid();
|
||||
pl = malloc(sizeof(sxpayload_t));
|
||||
node = usrtc_lookup(co->rpc_list, &type);
|
||||
|
||||
if(node) rpclist = (rpc_typed_list_t *)usrtc_node_getdata(node);
|
||||
|
||||
if(!uuid_) {
|
||||
if(pl) free(pl);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if(!pl) {
|
||||
__ffail:
|
||||
if(uuid_) free(uuid_);
|
||||
return ENOMEM;
|
||||
} else {
|
||||
pl->sx = NULL;
|
||||
if(!(pl->cstr = malloc(sizeof(char)*ESX_SYSMSG_SIZE))) {
|
||||
free(pl); goto __ffail;
|
||||
} else memset(pl->cstr, 0, sizeof(char)*ESX_SYSMSG_SIZE);
|
||||
}
|
||||
|
||||
pthread_rwlock_wrlock(&(co->chnl_lock));
|
||||
cid = idx_allocate(co->idx_ch);
|
||||
pthread_rwlock_unlock(&(co->chnl_lock));
|
||||
if(cid == IDX_INVAL) {
|
||||
r = ENOMEM;
|
||||
goto __fini_op;
|
||||
}
|
||||
|
||||
if((r = __alloc_channel(cid, co, rpclist, &nch))) {
|
||||
goto __fini_op;
|
||||
} else nch->flags |= ESXCHAN_PENDING;
|
||||
|
||||
nch->uuid = uuid_;
|
||||
|
||||
/* ok now we're ready to create a message and push channel to the list */
|
||||
if((r = __create_sys_msg(&sms, uuid_, nch, pl))) {
|
||||
__fail_chan:
|
||||
/* destroy the channel*/
|
||||
goto __fini_op;
|
||||
} else {
|
||||
/* put the channel to the channels search tree */
|
||||
pthread_rwlock_wrlock(&(co->chnl_lock));
|
||||
//printf("inserting cid = %d\n", nch->cid);
|
||||
usrtc_insert(co->chnl_tree, &nch->node, &nch->cid);
|
||||
pthread_rwlock_unlock(&(co->chnl_lock));
|
||||
|
||||
/* put system message to the run queue */
|
||||
/* first form the message */
|
||||
snprintf(pl->cstr, sizeof(char)*ESX_SYSMSG_SIZE,
|
||||
"(ch-open ((:id %ld)(:uuid %s)(:type %d)))", nch->cid, nch->uuid, type);
|
||||
nch->sysmsg = sms; /* assign system message to the channel */
|
||||
/* put it */
|
||||
if((r = pth_queue_add(ssys->ioqueue, (void *)sms, SYS_MSG))) {
|
||||
__fail_chan_r:
|
||||
/* remove it from the search tree */
|
||||
pthread_rwlock_wrlock(&(co->chnl_lock));
|
||||
usrtc_delete(co->chnl_tree, &nch->node);
|
||||
pthread_rwlock_unlock(&(co->chnl_lock));
|
||||
goto __fail_chan;
|
||||
}
|
||||
if(!(sms->flags & ESXMSG_PENDING)) {
|
||||
/* was processed too fast */
|
||||
goto __process_smsg;
|
||||
} else pthread_mutex_lock(&(sms->wait)); /* will sleep until got a reply */
|
||||
__process_smsg:
|
||||
if(sms->opcode) {
|
||||
r = sms->opcode;
|
||||
goto __fail_chan_r;
|
||||
} else r = 0;
|
||||
nch->flags &= ~ESXCHAN_PENDING; /* mark it as established */
|
||||
free(pl->cstr);
|
||||
free(pl);
|
||||
__destroy_msg(nch->sysmsg);
|
||||
}
|
||||
|
||||
__fini_op:
|
||||
if(r) {
|
||||
if(uuid_) free(uuid_);
|
||||
if(pl) {
|
||||
if(pl->cstr) free(pl->cstr);
|
||||
free(pl);
|
||||
}
|
||||
pthread_rwlock_wrlock(&(co->chnl_lock));
|
||||
idx_free(co->idx_ch, nch->cid);
|
||||
pthread_rwlock_unlock(&(co->chnl_lock));
|
||||
idx_allocator_destroy(nch->idx_msg);
|
||||
free(nch->idx_msg);
|
||||
free(nch->msgs_tree);
|
||||
pthread_mutex_destroy(&(nch->oplock));
|
||||
pthread_rwlock_destroy(&(nch->msglock));
|
||||
|
||||
free(nch);
|
||||
} else *ch = nch;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int channel_close(chnl_t *chnl)
|
||||
{
|
||||
char *uuid_;
|
||||
usrtc_node_t *node = NULL;
|
||||
int r = 0;
|
||||
conn_t *co = chnl->connection;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
sxmsg_t *sms;
|
||||
sxpayload_t *pl;
|
||||
|
||||
if(!(co->flags & CXCONN_ESTABL)) {
|
||||
return ESXNOCONNECT;
|
||||
}
|
||||
|
||||
pthread_rwlock_rdlock(&(co->chnl_lock));
|
||||
node = usrtc_lookup(co->chnl_tree, &chnl->cid);
|
||||
pthread_rwlock_unlock(&(co->chnl_lock));
|
||||
if(!node) {
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
pthread_rwlock_wrlock(&(chnl->msglock));
|
||||
/* check unprocessed messages */
|
||||
if(!usrtc_isempty(chnl->msgs_tree)) { /* messages on the queue */
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
uuid_ = __generate_uuid();
|
||||
pl = malloc(sizeof(sxpayload_t));
|
||||
if(!pl || !uuid_) {
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
if(pl) free(pl);
|
||||
if(uuid_) free(uuid_);
|
||||
return ENOMEM;
|
||||
}
|
||||
if(__create_sys_msg(&sms, uuid_, chnl, pl)) {
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
free(pl);
|
||||
free(uuid_);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
pl->sx = NULL;
|
||||
if(!(pl->cstr = malloc(sizeof(char) * ESX_SYSMSG_SIZE))) {
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
free(pl);
|
||||
free(uuid_);
|
||||
return ENOMEM;
|
||||
}
|
||||
memset(pl->cstr, 0, sizeof(char) * ESX_SYSMSG_SIZE);
|
||||
|
||||
/* put system message to the run queue */
|
||||
/* first form the message */
|
||||
snprintf(pl->cstr, sizeof(char) * ESX_SYSMSG_SIZE,
|
||||
"(ch-close (:id %ld))", chnl->cid);
|
||||
chnl->sysmsg = sms; /* assign system message to the channel */
|
||||
/* put it */
|
||||
if((r = pth_queue_add(ssys->ioqueue, (void *)sms, SYS_MSG))) {
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
return r;
|
||||
}
|
||||
if(!(sms->flags & ESXMSG_PENDING)) {
|
||||
/* was processed too fast */
|
||||
goto __process_smsg;
|
||||
} else pthread_mutex_lock(&(sms->wait)); /* will sleep until got a reply */
|
||||
|
||||
__process_smsg:
|
||||
if(sms->opcode) {
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
r = sms->opcode;
|
||||
return r;
|
||||
} else r = 0;
|
||||
chnl->flags &= ~ESXCHAN_PENDING; /* mark it as established */
|
||||
/* remove channel from the search tree */
|
||||
pthread_rwlock_wrlock(&(chnl->connection->chnl_lock));
|
||||
usrtc_delete(chnl->connection->chnl_tree, &chnl->node);
|
||||
/* free index */
|
||||
idx_free(co->idx_ch, chnl->cid);
|
||||
pthread_rwlock_unlock(&(chnl->connection->chnl_lock));
|
||||
|
||||
pthread_rwlock_unlock(&(chnl->msglock));
|
||||
|
||||
__destroy_msg(chnl->sysmsg);
|
||||
free(uuid_);
|
||||
|
||||
free(pl->cstr);
|
||||
free(pl);
|
||||
free(chnl->uuid);
|
||||
idx_allocator_destroy(chnl->idx_msg);
|
||||
free(chnl->idx_msg);
|
||||
free(chnl->msgs_tree);
|
||||
pthread_mutex_destroy(&(chnl->oplock));
|
||||
pthread_rwlock_destroy(&(chnl->msglock));
|
||||
|
||||
free(chnl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#define EBADE 1
|
||||
#define NETDB_SUCCESS 0
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
/* locally used functions */
|
||||
uint8_t _channel_open(conn_t *co, uint16_t *chid)
|
||||
{
|
||||
chnl_t *chan;
|
||||
int typeid = *chid; /* our type */
|
||||
uint16_t chidx;
|
||||
usrtc_t *rpc_list = co->rpc_list;
|
||||
usrtc_node_t *node;
|
||||
rpc_typed_list_t *rlist;
|
||||
cx_rpc_list_t *rpclist;
|
||||
|
||||
node = usrtc_lookup(rpc_list, &typeid);
|
||||
if(!node) return SNE_EPERM;
|
||||
else rlist = (rpc_typed_list_t *)usrtc_node_getdata(node);
|
||||
|
||||
if(rlist) rpclist = rlist->rpc_list;
|
||||
else return SNE_FAILED;
|
||||
|
||||
chan = malloc(sizeof(chnl_t));
|
||||
if(!chan) return SNE_ENOMEM;
|
||||
|
||||
/* init channel */
|
||||
chan->connection = co;
|
||||
chan->rpc_list = rpclist;
|
||||
chan->flags = 0;
|
||||
|
||||
pthread_mutex_lock(&co->idx_ch_lock);
|
||||
chidx = idx_allocate(&co->idx_ch);
|
||||
pthread_mutex_unlock(&co->idx_ch_lock);
|
||||
|
||||
if(chidx == IDX_INVAL) {
|
||||
free(chan);
|
||||
return SNE_MCHANNELS;
|
||||
}
|
||||
|
||||
chan->cid = chidx;
|
||||
co->channels[chidx] = chan;
|
||||
*chid = chidx;
|
||||
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t _channel_close(conn_t *co, uint16_t chid)
|
||||
{
|
||||
chnl_t *chan;
|
||||
ulong_t chidx = chid;
|
||||
|
||||
if(chid > 512) return SNE_INVALINDEX;
|
||||
else chan = co->channels[chidx];
|
||||
|
||||
if(!chan) return SNE_NOSUCHCHAN;
|
||||
|
||||
pthread_mutex_lock(&co->idx_ch_lock);
|
||||
idx_free(&co->idx_ch, chidx);
|
||||
co->channels[chidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_ch_lock);
|
||||
|
||||
free(chan);
|
||||
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
chnl_t *sxchannel_open(conn_t *co, int type)
|
||||
{
|
||||
chnl_t *chan = NULL;
|
||||
sxmsg_t *msg = NULL;
|
||||
sntllv2_head_t *head;
|
||||
int msgidx, r, ccid;
|
||||
|
||||
if(!co) {
|
||||
r = SNE_FAILED;
|
||||
goto __reterr;
|
||||
}
|
||||
|
||||
if(!(chan = malloc(sizeof(chnl_t)))) {
|
||||
__enomem:
|
||||
if(chan) free(chan);
|
||||
r = SNE_ENOMEM;
|
||||
goto __reterr;
|
||||
}
|
||||
if(!(msg = malloc(sizeof(sxmsg_t)))) goto __enomem;
|
||||
|
||||
/* early init for the channel */
|
||||
chan->connection = co;
|
||||
chan->flags = 0;
|
||||
|
||||
/* early init for the message */
|
||||
pthread_mutex_init(&msg->wait, NULL);
|
||||
pthread_mutex_lock(&msg->wait);
|
||||
msg->pch = chan;
|
||||
msg->payload = NULL;
|
||||
memset(&msg->mhead, 0, sizeof(sntllv2_head_t));
|
||||
head = &msg->mhead;
|
||||
|
||||
/* form a header */
|
||||
head->attr = SXMSG_PROTO | SXMSG_REPLYREQ | SXMSG_OPEN;
|
||||
head->payload_length = 0;
|
||||
head->reserve = (uint16_t)type;
|
||||
|
||||
/* try to alloc a message */
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
msgidx = idx_allocate(&co->idx_msg);
|
||||
if(msgidx != IDX_INVAL) co->messages[msgidx] = msg;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; }
|
||||
else head->msgid = msgidx;
|
||||
|
||||
/* now we're ready to write it */
|
||||
r = _sntll_writemsg(co, msg);
|
||||
if(r == SNE_SUCCESS) pthread_mutex_lock(&msg->wait);
|
||||
else goto __reterr3;
|
||||
|
||||
/* we will wakeup on return */
|
||||
if(msg->mhead.opcode != SNE_SUCCESS) { r = msg->mhead.opcode; goto __reterr3; }
|
||||
|
||||
/* ok all is fine */
|
||||
chan->cid = msg->mhead.reserve;
|
||||
ccid = chan->cid;
|
||||
pthread_mutex_lock(&co->idx_ch_lock);
|
||||
idx_reserve(&co->idx_ch, ccid);
|
||||
co->channels[ccid] = chan;
|
||||
pthread_mutex_unlock(&co->idx_ch_lock);
|
||||
|
||||
/* destroy a message */
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, msgidx);
|
||||
co->messages[msgidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
/* free allocated resources */
|
||||
pthread_mutex_unlock(&msg->wait);
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
free(msg);
|
||||
|
||||
return chan;
|
||||
|
||||
__reterr3:
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, msgidx);
|
||||
co->messages[msgidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
__reterr2:
|
||||
pthread_mutex_unlock(&msg->wait);
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
__reterr:
|
||||
if(chan) free(chan);
|
||||
if(msg) free(msg);
|
||||
errno = r;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int sxchannel_close(chnl_t *channel)
|
||||
{
|
||||
int r = SNE_SUCCESS;
|
||||
sxmsg_t *msg;
|
||||
sntllv2_head_t *head;
|
||||
conn_t *co;
|
||||
int msgidx = 0, chidx = 0;
|
||||
|
||||
/* check channel validity */
|
||||
if(!channel) return SNE_FAILED;
|
||||
else if(!(co = channel->connection)) return SNE_FAILED;
|
||||
if(channel->cid > 512) return SNE_IGNORED;
|
||||
else chidx = channel->cid;
|
||||
if(channel != co->channels[chidx]) return SNE_IGNORED;
|
||||
|
||||
if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM;
|
||||
head = &msg->mhead;
|
||||
memset(head, 0, sizeof(sntllv2_head_t));
|
||||
|
||||
/* setup head */
|
||||
head->attr = SXMSG_PROTO | SXMSG_REPLYREQ; /* close channel */
|
||||
head->reserve = channel->cid;
|
||||
|
||||
/* setup message */
|
||||
pthread_mutex_init(&msg->wait, NULL);
|
||||
pthread_mutex_lock(&msg->wait);
|
||||
msg->pch = channel;
|
||||
|
||||
/* allocate it */
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
msgidx = idx_allocate(&co->idx_msg);
|
||||
if(msgidx != IDX_INVAL) co->messages[msgidx] = msg;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __reterr2; }
|
||||
else head->msgid = msgidx;
|
||||
|
||||
r = _sntll_writemsg(co, msg);
|
||||
if(r == SNE_SUCCESS) {
|
||||
pthread_mutex_lock(&msg->wait);
|
||||
r = head->opcode;
|
||||
|
||||
/* we will free this anyway */
|
||||
pthread_mutex_lock(&co->idx_ch_lock);
|
||||
idx_free(&co->idx_ch, chidx);
|
||||
co->channels[chidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_ch_lock);
|
||||
free(channel);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, msgidx);
|
||||
co->messages[msgidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
__reterr2:
|
||||
pthread_mutex_unlock(&msg->wait);
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
free(msg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#define EBADE 1
|
||||
#define NETDB_SUCCESS 0
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
static int __insert_rpc_function(usrtc_t *tree, const char *name, int (*rpcf)(void *, sexp_t *))
|
||||
{
|
||||
cx_rpc_t *ent = malloc(sizeof(cx_rpc_t));
|
||||
usrtc_node_t *node;
|
||||
|
||||
if(!ent) return ENOMEM;
|
||||
else node = &ent->node;
|
||||
|
||||
if(!(ent->name = strdup(name))) {
|
||||
free(ent);
|
||||
return ENOMEM;
|
||||
} else ent->rpcf = rpcf;
|
||||
|
||||
usrtc_node_init(node, ent);
|
||||
usrtc_insert(tree, node, ent->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __destroy_rpc_list_tree(usrtc_t *tree)
|
||||
{
|
||||
usrtc_node_t *node;
|
||||
cx_rpc_t *ent;
|
||||
|
||||
for(node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
|
||||
ent = (cx_rpc_t *)usrtc_node_getdata(node);
|
||||
usrtc_delete(tree, node);
|
||||
free(ent->name);
|
||||
free(ent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* negotiation functions */
|
||||
/**
|
||||
* Proto: (auth-set-credentials "<login>" "<password>")
|
||||
* Return - message return; opcode as a return of this function.
|
||||
* in batch mode message with 0 index used always
|
||||
*/
|
||||
static int __set_credentials(void *cctx, sexp_t *sx)
|
||||
{
|
||||
register int idx;
|
||||
conn_t *co = (conn_t *)cctx;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
sexp_t *isx;
|
||||
char *login = NULL;
|
||||
char *passwd = NULL;
|
||||
|
||||
/* take a deal with S-exp */
|
||||
SEXP_ITERATE_LIST(sx, isx, idx) {
|
||||
if(isx->ty == SEXP_LIST) return SNE_BADPROTO;
|
||||
|
||||
if(idx > 0 && isx->aty != SEXP_DQUOTE) return SNE_BADPROTO;
|
||||
if(idx == 1) login = isx->val;
|
||||
else if(idx == 2) passwd = isx->val;
|
||||
else if(idx > 2) return SNE_BADPROTO;
|
||||
}
|
||||
|
||||
if(!login || !passwd) return SNE_BADPROTO;
|
||||
|
||||
co->pctx->login = strdup(login);
|
||||
co->pctx->passwd = strdup(passwd);
|
||||
if(!co->pctx->login || !co->pctx->passwd) {
|
||||
if(co->pctx->login) free(co->pctx->login);
|
||||
if(co->pctx->passwd) free(co->pctx->passwd);
|
||||
return SNE_ENOMEM;
|
||||
}
|
||||
|
||||
if(ssys->secure_check) return ssys->secure_check(co);
|
||||
else return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static int __get_channels_list(void *cctx, sexp_t *sx)
|
||||
{
|
||||
conn_t *co = (conn_t *)cctx;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
sxmsg_t *msg = co->messages[0];
|
||||
char *buf = msg->payload;
|
||||
usrtc_node_t *node;
|
||||
rpc_typed_list_t *list_ent;
|
||||
size_t maxlen = 65535 - sizeof(sntllv2_head_t);
|
||||
size_t ulen = 0;
|
||||
|
||||
/* we will avoid S-exp scanning here */
|
||||
|
||||
/* call the function */
|
||||
if(ssys->get_rpc_typed_list_tree)
|
||||
co->rpc_list = ssys->get_rpc_typed_list_tree(co);
|
||||
if(!co->rpc_list) return SNE_EPERM;
|
||||
//buf += sizeof(sntllv2_head_t);
|
||||
ulen += snprintf(buf + ulen, maxlen - ulen, "(set-channels-list ");
|
||||
for(node = usrtc_first(co->rpc_list); node != NULL;
|
||||
node = usrtc_next(co->rpc_list, node)) { /* fill the list */
|
||||
list_ent = (rpc_typed_list_t *)usrtc_node_getdata(node);
|
||||
ulen += snprintf(buf + ulen, maxlen - ulen, "(:%d \"%s\")",
|
||||
list_ent->type_id, list_ent->description);
|
||||
}
|
||||
ulen += snprintf(buf + ulen, maxlen - ulen, ")");
|
||||
msg->mhead.payload_length = ulen + sizeof(sntllv2_head_t);
|
||||
|
||||
/* we're ready for messaging mode */
|
||||
co->flags |= SNSX_MESSAGINGMODE;
|
||||
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static int __set_channels_list(void *cctx, sexp_t *sx)
|
||||
{
|
||||
register int idx;
|
||||
conn_t *co = (conn_t *)cctx;
|
||||
conn_sys_t *ssys = co->ssys;
|
||||
sexp_t *isx, *iisx;
|
||||
int id, r;
|
||||
|
||||
SEXP_ITERATE_LIST(sx, isx, idx) {
|
||||
if(!idx) continue;
|
||||
|
||||
if(isx->ty != SEXP_LIST) return SNE_BADPROTO;
|
||||
if(sexp_list_length(isx) != 2) return SNE_BADPROTO;
|
||||
|
||||
/* get id */
|
||||
sexp_list_car(isx, &iisx);
|
||||
if(iisx->ty == SEXP_LIST) return SNE_BADPROTO;
|
||||
if(iisx->aty != SEXP_BASIC) return SNE_BADPROTO;
|
||||
if(iisx->val[0] != ':') return SNE_BADPROTO;
|
||||
id = atoi(iisx->val + sizeof(char));
|
||||
|
||||
/* get short description */
|
||||
sexp_list_cdr(isx, &iisx);
|
||||
if(iisx->ty == SEXP_LIST) return SNE_BADPROTO;
|
||||
if(iisx->aty != SEXP_DQUOTE) return SNE_BADPROTO;
|
||||
|
||||
/* ok, here we go */
|
||||
if(ssys->set_typed_list_callback) {
|
||||
r = ssys->set_typed_list_callback(co, id, iisx->val);
|
||||
if(r != SNE_SUCCESS) return r;
|
||||
}
|
||||
}
|
||||
|
||||
/* we're ready for messaging mode */
|
||||
co->flags |= SNSX_MESSAGINGMODE;
|
||||
co->flags &= ~SNSX_BATCHMODE;
|
||||
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static int __init_systemrpc_tree(usrtc_t *rtree)
|
||||
{
|
||||
/* batch mode negotiation context functions */
|
||||
if(__insert_rpc_function(rtree, "auth-set-credentials", __set_credentials)) goto __fail;
|
||||
if(__insert_rpc_function(rtree, "get-channels-list", __get_channels_list)) goto __fail;
|
||||
if(__insert_rpc_function(rtree, "set-channels-list", __set_channels_list)) goto __fail;
|
||||
|
||||
return 0;
|
||||
|
||||
__fail:
|
||||
__destroy_rpc_list_tree(rtree);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
static long __cmp_cstr(const void *a, const void *b)
|
||||
{
|
||||
return (long)strcmp((const char *)a, (const char *)b);
|
||||
}
|
||||
|
||||
int connections_init(conn_sys_t *ssys)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if(!ssys) return EINVAL;
|
||||
else memset(ssys, 0, sizeof(conn_sys_t));
|
||||
|
||||
if(!(ssys->connections = malloc(sizeof(usrtc_t)))) return ENOMEM;
|
||||
|
||||
/* init connections list */
|
||||
usrtc_init(ssys->connections, USRTC_REDBLACK, MAX_CONNECTIONS,
|
||||
__cmp_cstr);
|
||||
if((r = pthread_rwlock_init(&(ssys->rwlock), NULL)))
|
||||
goto __fini;
|
||||
|
||||
/* init RPC list related functions */
|
||||
if(!(ssys->system_rpc = malloc(sizeof(cx_rpc_list_t)))) {
|
||||
r = ENOMEM;
|
||||
goto __lfini;
|
||||
} else {
|
||||
if(!(ssys->system_rpc->rpc_tree = malloc(sizeof(usrtc_t)))) {
|
||||
r = ENOMEM;
|
||||
goto __lfini;
|
||||
}
|
||||
usrtc_init(ssys->system_rpc->rpc_tree, USRTC_SPLAY, 256, __cmp_cstr);
|
||||
r = __init_systemrpc_tree(ssys->system_rpc->rpc_tree);
|
||||
if(r) {
|
||||
free(ssys->system_rpc->rpc_tree);
|
||||
goto __lfini;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
__lfini:
|
||||
if(ssys->system_rpc) free(ssys->system_rpc);
|
||||
pthread_rwlock_destroy(&(ssys->rwlock));
|
||||
__fini:
|
||||
if(ssys->connections) free(ssys->connections);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
conn_sys_t *connections_create(void)
|
||||
{
|
||||
int r = 0;
|
||||
conn_sys_t *nsys = malloc(sizeof(conn_sys_t));
|
||||
|
||||
if(!nsys) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = connections_init(nsys);
|
||||
if(r) {
|
||||
errno = r;
|
||||
free(nsys);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nsys;
|
||||
}
|
||||
|
||||
int connections_setsslserts(conn_sys_t *ssys, const char *rootca,
|
||||
const char *certpem, const char *certkey)
|
||||
{
|
||||
int r = ENOMEM;
|
||||
|
||||
if(!ssys) return EINVAL;
|
||||
/* simply copying */
|
||||
if(!(ssys->rootca = strdup(rootca))) return ENOMEM;
|
||||
if(!(ssys->certkey = strdup(certkey))) goto __fail;
|
||||
if(!(ssys->certpem = strdup(certpem))) goto __fail;
|
||||
|
||||
r = 0;
|
||||
return 0;
|
||||
__fail:
|
||||
if(ssys->rootca) free(ssys->rootca);
|
||||
if(ssys->certkey) free(ssys->certkey);
|
||||
if(ssys->certpem) free(ssys->certpem);
|
||||
|
||||
return r;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
#ifndef __SNTLL_INTERNAL_H__
|
||||
#define __SNTLL_INTERNAL_H__
|
||||
|
||||
/* link related */
|
||||
int _sntll_writemsg(conn_t *co, sxmsg_t *msg);
|
||||
|
||||
/* channel operations */
|
||||
uint8_t _channel_open(conn_t *co, uint16_t *chid);
|
||||
uint8_t _channel_close(conn_t *co, uint16_t chid);
|
||||
|
||||
/* messages */
|
||||
void _message_process(sxmsg_t *msg);
|
||||
|
||||
#endif /* __SNTLL_INTERNAL_H__ */
|
@ -1,286 +0,0 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library implementation.
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/connection.h>
|
||||
|
||||
void __destroy_msg(sxmsg_t *msg)
|
||||
{
|
||||
chnl_t *ch = msg->pch;
|
||||
|
||||
if(msg->flags & ESXMSG_USR) {
|
||||
pthread_mutex_lock(&(ch->oplock));
|
||||
idx_free(ch->idx_msg, msg->mid);
|
||||
pthread_mutex_unlock(&(ch->oplock));
|
||||
} else if(msg->flags & ESXMSG_SYS) {
|
||||
//if(msg->uuid) free(msg->uuid);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&(msg->wait));
|
||||
pthread_mutex_destroy(&(msg->wait));
|
||||
free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
sxmsg_t *__allocate_msg(int *res)
|
||||
{
|
||||
sxmsg_t *msg = malloc(sizeof(sxmsg_t));
|
||||
int r = 0;
|
||||
|
||||
if(!msg) {
|
||||
*res = ENOMEM;
|
||||
return NULL;
|
||||
} else {
|
||||
memset(msg, 0, sizeof(sxmsg_t));
|
||||
if((r = pthread_mutex_init(&(msg->wait), NULL))) {
|
||||
free(msg);
|
||||
*res = r;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usrtc_node_init(&(msg->pendingq_node), msg);
|
||||
}
|
||||
|
||||
*res = 0;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
int __create_reg_msg(sxmsg_t **msg, chnl_t *ch)
|
||||
{
|
||||
int r = 0;
|
||||
sxmsg_t *sm = __allocate_msg(&r);
|
||||
|
||||
if(r) return r;
|
||||
else {
|
||||
sm->pch = ch;
|
||||
sm->flags = (ESXMSG_USR | ESXMSG_PENDING);
|
||||
|
||||
/* ok allocate message ID */
|
||||
pthread_mutex_lock(&(ch->oplock));
|
||||
sm->mid = idx_allocate(ch->idx_msg);
|
||||
pthread_mutex_unlock(&(ch->oplock));
|
||||
|
||||
pthread_mutex_lock(&(sm->wait));
|
||||
*msg = sm;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __create_sys_msg(sxmsg_t **msg, char *uuid, chnl_t *ch, sxpayload_t *data)
|
||||
{
|
||||
int r = 0;
|
||||
sxmsg_t *m = __allocate_msg(&r);
|
||||
|
||||
if(r) return r;
|
||||
else {
|
||||
/* fill values */
|
||||
m->pch = ch;
|
||||
m->uuid = uuid;
|
||||
m->payload = data;
|
||||
/* set the right flags */
|
||||
m->flags = (ESXMSG_SYS | ESXMSG_PENDING);
|
||||
/* we need to lock the wait mutex */
|
||||
pthread_mutex_lock(&(m->wait));
|
||||
|
||||
*msg = m;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* message passing */
|
||||
|
||||
/*
|
||||
* How message sending works:
|
||||
* 1. Create a message structure assigned to the channel,
|
||||
* 2. Put S-expression context to it
|
||||
* 3. Put the message to the queue
|
||||
* 4. expect the result waiting on the lock mutex
|
||||
*/
|
||||
static int __message_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio)
|
||||
{
|
||||
int r = 0;
|
||||
sxmsg_t *m = NULL;
|
||||
conn_t *co = ch->connection;
|
||||
|
||||
if(!(co->flags & CXCONN_ESTABL)) {
|
||||
destroy_sexp(sx);
|
||||
return ESXNOCONNECT;
|
||||
}
|
||||
|
||||
*msg = NULL;
|
||||
|
||||
r = __create_reg_msg(&m, ch);
|
||||
if(r) return r;
|
||||
else {
|
||||
/* put the message to the search tree */
|
||||
pthread_rwlock_wrlock(&(ch->msglock));
|
||||
usrtc_insert(ch->msgs_tree, &(m->pendingq_node), &(m->mid));
|
||||
pthread_rwlock_unlock(&(ch->msglock));
|
||||
|
||||
/* message assign */
|
||||
m->opcode = 0;
|
||||
m->payload = (void *)sx;
|
||||
/* assign initial sx */
|
||||
m->initial_sx = sx;
|
||||
|
||||
/* put the message to the run queue */
|
||||
r = pth_queue_add(co->mqueue, (void *)m, USR_MSG);
|
||||
if(r) return r; /* FIXME: better give up */
|
||||
|
||||
if(m->flags & ESXMSG_PENDING) {
|
||||
if(!tio) pthread_mutex_lock(&(m->wait));
|
||||
else pthread_mutex_timedlock(&(m->wait), tio);
|
||||
}
|
||||
if(tio && (m->flags & ESXMSG_PENDING))
|
||||
return ESXOTIMEDOUT;
|
||||
if(!m->payload) {
|
||||
r = m->opcode;
|
||||
/* first remove the message from tree */
|
||||
pthread_rwlock_wrlock(&(ch->msglock));
|
||||
usrtc_delete(ch->msgs_tree, &(m->pendingq_node));
|
||||
pthread_rwlock_unlock(&(ch->msglock));
|
||||
/* destroy s expression */
|
||||
destroy_sexp(m->initial_sx);
|
||||
/* destroy */
|
||||
__destroy_msg(m);
|
||||
} else {
|
||||
*msg = m;
|
||||
if(m->opcode == ESXNOCONNECT || m->opcode == ESXRAPIDREPLY)
|
||||
r = m->opcode;
|
||||
else r = ESXOREPLYREQ;
|
||||
/* FIXME: remove ugly code */
|
||||
if(m->opcode == ESXRAPIDREPLY) {
|
||||
/* first remove the message from tree */
|
||||
pthread_rwlock_wrlock(&(ch->msglock));
|
||||
usrtc_delete(ch->msgs_tree, &(m->pendingq_node));
|
||||
pthread_rwlock_unlock(&(ch->msglock));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int msg_send(chnl_t *ch, sexp_t *sx, sxmsg_t **msg)
|
||||
{
|
||||
return __message_send(ch, sx, msg, NULL);
|
||||
}
|
||||
|
||||
int msg_send_timed(chnl_t *ch, sexp_t *sx, sxmsg_t **msg, struct timespec *tio)
|
||||
{
|
||||
return __message_send(ch, sx, msg, tio);
|
||||
}
|
||||
|
||||
static int __msg_reply(sxmsg_t *msg, sexp_t *sx, struct timespec *tio, int opcode,
|
||||
int israpid)
|
||||
{
|
||||
int r = 0;
|
||||
chnl_t *ch = msg->pch;
|
||||
conn_t *co = ch->connection;
|
||||
|
||||
if(!(co->flags & CXCONN_ESTABL)) {
|
||||
destroy_sexp(sx);
|
||||
return ESXNOCONNECT;
|
||||
}
|
||||
|
||||
if(msg->flags & ESXMSG_ISREPLY)
|
||||
destroy_sexp((sexp_t *)msg->payload);
|
||||
|
||||
msg->payload = sx;
|
||||
msg->opcode = opcode;
|
||||
msg->flags |= ESXMSG_PENDING; /* pending */
|
||||
msg->flags |= ESXMSG_ISREPLY; /* this is a reply */
|
||||
if(israpid) msg->flags |= ESXMSG_ISRAPID; /* message is a rapid message */
|
||||
|
||||
if(!sx || israpid) msg->flags &= ~ESXMSG_PENDING;
|
||||
else msg->flags |= ESXMSG_RMONRETR;
|
||||
|
||||
/* put the message to the queue */
|
||||
r = pth_queue_add(co->mqueue, (void *)msg, USR_MSG);
|
||||
if(r) return r; /* FIXME: better give up */
|
||||
if(!sx || israpid) {
|
||||
/* wait for write */
|
||||
//pthread_mutex_lock(&(msg->wait));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(msg->flags & ESXMSG_PENDING) {
|
||||
if(!tio) pthread_mutex_lock(&(msg->wait));
|
||||
else pthread_mutex_timedlock(&(msg->wait), tio);
|
||||
}
|
||||
|
||||
if(tio && (msg->flags & ESXMSG_PENDING)) {
|
||||
msg->flags &= ~ESXMSG_PENDING; /* we will not wait for it */
|
||||
return ESXOTIMEDOUT;
|
||||
}
|
||||
|
||||
r = msg->opcode;
|
||||
|
||||
if(msg->flags & ESXMSG_CLOSURE) {
|
||||
__destroy_msg(msg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int msg_return(sxmsg_t *msg, int opcode)
|
||||
{
|
||||
return __msg_reply(msg, NULL, NULL, opcode, 0);
|
||||
}
|
||||
|
||||
int msg_reply(sxmsg_t *msg, sexp_t *sx)
|
||||
{
|
||||
return __msg_reply(msg, sx, NULL, 0, 0);
|
||||
}
|
||||
|
||||
int msg_reply_timed(sxmsg_t *msg, sexp_t *sx, struct timespec *tio)
|
||||
{
|
||||
return __msg_reply(msg, sx, tio, 0, 0);
|
||||
}
|
||||
|
||||
int msg_reply_rapid(sxmsg_t *msg, sexp_t *sx)
|
||||
{
|
||||
return __msg_reply(msg, sx, NULL, 0, 1);
|
||||
}
|
||||
|
||||
int msg_rapid_clean(sxmsg_t *msg)
|
||||
{
|
||||
destroy_sexp(msg->initial_sx);
|
||||
if(msg->payload) destroy_sexp(msg->payload);
|
||||
__destroy_msg(msg);
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <tdata/list.h>
|
||||
#include <sexpr/sexp.h>
|
||||
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
void _message_process(sxmsg_t *msg)
|
||||
{
|
||||
chnl_t *chan = msg->pch;
|
||||
sexp_t *sx, *isx;
|
||||
usrtc_t *listrpc = chan->rpc_list->rpc_tree;
|
||||
usrtc_node_t *node;
|
||||
cx_rpc_t *rpcc;
|
||||
int r;
|
||||
|
||||
sx = parse_sexp(msg->payload, msg->mhead.payload_length);
|
||||
if(!sx) sxmsg_return(msg, SNE_BADPROTO);
|
||||
|
||||
sexp_list_car(sx, &isx);
|
||||
if(!isx) { r = SNE_BADPROTO; goto __return_err; }
|
||||
if(isx->ty == SEXP_LIST) { r = SNE_BADPROTO; goto __return_err; }
|
||||
if(isx->aty != SEXP_BASIC) { r = SNE_BADPROTO; goto __return_err; }
|
||||
|
||||
node = usrtc_lookup(listrpc, (void *)isx->val);
|
||||
if(!node) { r = SNE_ENORPC; goto __return_err; }
|
||||
else rpcc = (cx_rpc_t *)usrtc_node_getdata(node);
|
||||
|
||||
rpcc->rpcf((void *)msg, sx);
|
||||
|
||||
destroy_sexp(sx);
|
||||
|
||||
return;
|
||||
|
||||
__return_err:
|
||||
destroy_sexp(sx);
|
||||
sxmsg_return(msg, r);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int __sxmsg_send(chnl_t *channel, const char *data, size_t datalen,
|
||||
sxmsg_t **omsg, int pp)
|
||||
{
|
||||
conn_t *co;
|
||||
sxmsg_t *msg;
|
||||
sntllv2_head_t *head;
|
||||
ppmsg_t *ppm;
|
||||
int msgidx, r;
|
||||
|
||||
if(!channel) return SNE_FAILED;
|
||||
if(!data || !datalen) return SNE_FAILED;
|
||||
|
||||
if(!(msg = malloc(sizeof(sxmsg_t)))) return SNE_ENOMEM;
|
||||
else memset(msg, 0, sizeof(sxmsg_t));
|
||||
|
||||
co = channel->connection;
|
||||
head = &msg->mhead;
|
||||
/* form a head */
|
||||
head->attr = SXMSG_OPEN | SXMSG_REPLYREQ;
|
||||
head->reserve = channel->cid;
|
||||
head->payload_length = datalen;
|
||||
/* init message itself */
|
||||
pthread_mutex_init(&msg->wait, NULL);
|
||||
pthread_mutex_lock(&msg->wait);
|
||||
msg->pch = channel;
|
||||
msg->payload = (void *)data;
|
||||
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
msgidx = idx_allocate(&co->idx_msg);
|
||||
if(msgidx != IDX_INVAL) co->messages[msgidx] = msg;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
if(msgidx == IDX_INVAL) { r = SNE_MMESSAGES; goto __freemsg; }
|
||||
else head->msgid = (uint16_t)msgidx;
|
||||
|
||||
/* ready to send it */
|
||||
if(!pp) {
|
||||
r = _sntll_writemsg(co, msg);
|
||||
if(r != SNE_SUCCESS) goto __closemsg;
|
||||
} else { /* postponed */
|
||||
if(!(ppm = malloc(sizeof(ppmsg_t)))) { r = SNE_ENOMEM; goto __closemsg; }
|
||||
list_init_node(&ppm->node);
|
||||
ppm->msg = msg;
|
||||
|
||||
/* under locking here */
|
||||
pthread_mutex_lock(&co->write_pending_lock);
|
||||
co->pending_messages++;
|
||||
list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */
|
||||
pthread_mutex_unlock(&co->write_pending_lock);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&msg->wait); /* we will sleep here */
|
||||
|
||||
if(head->payload_length) {
|
||||
*omsg = msg;
|
||||
return head->opcode;
|
||||
} else r = head->opcode;
|
||||
|
||||
__closemsg:
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, msgidx);
|
||||
co->messages[msgidx] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
__freemsg:
|
||||
/* free resources for message */
|
||||
pthread_mutex_unlock(&msg->wait);
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
free(msg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sxmsg_send(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **omsg)
|
||||
{
|
||||
return __sxmsg_send(channel, data, datalen, omsg, 0);
|
||||
}
|
||||
|
||||
/* the same - postponed message i.e. will be written to the queue - not to write immendatly */
|
||||
int sxmsg_send_pp(chnl_t *channel, const char *data, size_t datalen, sxmsg_t **omsg)
|
||||
{
|
||||
return __sxmsg_send(channel, data, datalen, omsg, 1);
|
||||
}
|
||||
|
||||
/* send a pulse message */
|
||||
int sxmsg_pulse(conn_t *co, const char *data, size_t datalen)
|
||||
{
|
||||
sxmsg_t *msg = malloc(sizeof(sxmsg_t));
|
||||
sntllv2_head_t *head;
|
||||
int r;
|
||||
|
||||
/* a little bit of paranoid tests */
|
||||
if(!msg) return SNE_ENOMEM;
|
||||
else memset(msg, 0, sizeof(sxmsg_t));
|
||||
|
||||
/* prepare it */
|
||||
head = &msg->mhead;
|
||||
head->attr = 0;
|
||||
head->attr = SXMSG_PULSE | SXMSG_LINK;
|
||||
head->opcode = SNE_RAPIDMSG;
|
||||
head->payload_length = datalen;
|
||||
msg->payload = (void *)data;
|
||||
|
||||
r = _sntll_writemsg(co, msg);
|
||||
|
||||
free(msg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int __sxmsg_reply(sxmsg_t *msg, const char *data,
|
||||
size_t datalen, int pp)
|
||||
{
|
||||
chnl_t *ch;
|
||||
conn_t *co;
|
||||
sntllv2_head_t *head;
|
||||
ppmsg_t *ppm;
|
||||
int r, i;
|
||||
pthread_t self = pthread_self();
|
||||
|
||||
/* a little bit of paranoid tests */
|
||||
if(!msg) return SNE_FAILED;
|
||||
if(!(ch = msg->pch)) return SNE_FAILED;
|
||||
if(!(co = ch->connection)) return SNE_FAILED;
|
||||
|
||||
/* test for blocking */
|
||||
for(i = 0; i < 8; i++)
|
||||
if(pthread_equal(self, co->thrd_poll[i])) return SNE_WOULDBLOCK;
|
||||
|
||||
/* prepare it */
|
||||
head = &msg->mhead;
|
||||
head->attr = 0;
|
||||
head->attr |= SXMSG_REPLYREQ;
|
||||
head->opcode = SNE_REPLYREQ;
|
||||
head->payload_length = datalen;
|
||||
msg->payload = (void *)data;
|
||||
|
||||
if(!pp) {
|
||||
r = _sntll_writemsg(co, msg);
|
||||
if(r != SNE_SUCCESS) return r;
|
||||
} else {
|
||||
if(!(ppm = malloc(sizeof(ppmsg_t)))) return SNE_ENOMEM;
|
||||
list_init_node(&ppm->node);
|
||||
ppm->msg = msg;
|
||||
|
||||
/* under locking here */
|
||||
pthread_mutex_lock(&co->write_pending_lock);
|
||||
co->pending_messages++;
|
||||
list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */
|
||||
pthread_mutex_unlock(&co->write_pending_lock);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&msg->wait); /* wait */
|
||||
|
||||
r = head->opcode;
|
||||
|
||||
if((head->attr & SXMSG_CLOSED) && !head->payload_length) { /* dialog closed and no data exists */
|
||||
pthread_mutex_unlock(&msg->wait); /* we able to invalidate it */
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sxmsg_reply(sxmsg_t *msg, const char *data, size_t datalen)
|
||||
{
|
||||
return __sxmsg_reply(msg, data, datalen, 0);
|
||||
}
|
||||
|
||||
int sxmsg_reply_pp(sxmsg_t *msg, const char *data, size_t datalen)
|
||||
{
|
||||
return __sxmsg_reply(msg, data, datalen, 1);
|
||||
}
|
||||
|
||||
int sxmsg_rreply(sxmsg_t *msg, size_t datalen)
|
||||
{
|
||||
chnl_t *ch;
|
||||
conn_t *co;
|
||||
sntllv2_head_t *head;
|
||||
int r, mid;
|
||||
|
||||
/* a little bit of paranoid tests */
|
||||
if(!msg) return SNE_FAILED;
|
||||
if(!(ch = msg->pch)) return SNE_FAILED;
|
||||
if(!(co = ch->connection)) return SNE_FAILED;
|
||||
|
||||
/* prepare it */
|
||||
head = &msg->mhead;
|
||||
head->attr = 0;
|
||||
head->attr |= SXMSG_CLOSED;
|
||||
head->opcode = SNE_RAPIDMSG;
|
||||
head->payload_length = datalen;
|
||||
|
||||
mid = head->msgid;
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, mid);
|
||||
co->messages[mid] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
r = _sntll_writemsg(co, msg);
|
||||
|
||||
pthread_mutex_unlock(&msg->wait); /* we able to invalidate it */
|
||||
pthread_mutex_destroy(&msg->wait);
|
||||
free(msg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int __sxmsg_return(sxmsg_t *msg, int opcode, int pp)
|
||||
{
|
||||
chnl_t *ch;
|
||||
conn_t *co;
|
||||
sntllv2_head_t *head;
|
||||
ppmsg_t *ppm;
|
||||
int r, mid;
|
||||
|
||||
/* a little bit of paranoid tests */
|
||||
if(!msg) return SNE_FAILED;
|
||||
if(!(ch = msg->pch)) return SNE_FAILED;
|
||||
if(!(co = ch->connection)) return SNE_FAILED;
|
||||
|
||||
head = &msg->mhead;
|
||||
head->attr = 0;
|
||||
head->attr |= SXMSG_CLOSED;
|
||||
head->opcode = opcode;
|
||||
head->payload_length = 0;
|
||||
mid = head->msgid;
|
||||
|
||||
if(!pp) {
|
||||
/* free index */
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, mid);
|
||||
co->messages[mid] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
|
||||
r = _sntll_writemsg(co, msg);
|
||||
} else {
|
||||
if(!(ppm = malloc(sizeof(ppmsg_t)))) return SNE_ENOMEM;
|
||||
else { /* remove it */
|
||||
pthread_mutex_lock(&co->idx_msg_lock);
|
||||
idx_free(&co->idx_msg, mid);
|
||||
co->messages[mid] = NULL;
|
||||
pthread_mutex_unlock(&co->idx_msg_lock);
|
||||
}
|
||||
|
||||
list_init_node(&ppm->node);
|
||||
ppm->msg = msg;
|
||||
|
||||
/* under locking here */
|
||||
pthread_mutex_lock(&co->write_pending_lock);
|
||||
co->pending_messages++;
|
||||
list_add2tail(&co->write_pending, &ppm->node); /* push it to the FIFO */
|
||||
pthread_mutex_unlock(&co->write_pending_lock);
|
||||
|
||||
r = SNE_SUCCESS;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int sxmsg_return(sxmsg_t *msg, int opcode)
|
||||
{
|
||||
return __sxmsg_return(msg, opcode, 0);
|
||||
}
|
||||
|
||||
int sxmsg_return_pp(sxmsg_t *msg, int opcode)
|
||||
{
|
||||
return __sxmsg_return(msg, opcode, 1);
|
||||
}
|
||||
|
||||
void sxmsg_clean(sxmsg_t *msg)
|
||||
{
|
||||
free(msg->payload);
|
||||
free(msg);
|
||||
return;
|
||||
}
|
@ -1,465 +0,0 @@
|
||||
/*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
*
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
/**/
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#else
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#endif
|
||||
|
||||
/**/
|
||||
// #include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
|
||||
#include <sntl/pth_queue.h>
|
||||
|
||||
#define MAX_QUEUE_SIZE 4096
|
||||
#define MAX_QUEUE_POOL 256
|
||||
|
||||
static long __cmp_uint(const void *a, const void *b)
|
||||
{
|
||||
return (long)(*(unsigned int *)a - *(unsigned int *)b);
|
||||
}
|
||||
|
||||
static inline pth_msg_t *__get_newmsg(pth_queue_t *queue)
|
||||
{
|
||||
usrtc_t *tree = &queue->msgcache;
|
||||
usrtc_node_t *node;
|
||||
pth_msg_t *tmp;
|
||||
|
||||
if(usrtc_count(tree)) {
|
||||
node = usrtc_first(tree);
|
||||
tmp = (pth_msg_t *)usrtc_node_getdata(node);
|
||||
usrtc_delete(tree, node);
|
||||
} else {
|
||||
tmp = malloc(sizeof(pth_msg_t));
|
||||
tree = &queue->qtree;
|
||||
node = &tmp->node;
|
||||
usrtc_node_init(node, tmp);
|
||||
}
|
||||
/* insert it */
|
||||
tree = &queue->qtree;
|
||||
tmp->qlength = usrtc_count(tree);
|
||||
usrtc_insert(tree, node, (void *)(&tmp->qlength));
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static inline void __release_msg(pth_queue_t *queue, pth_msg_t *msg)
|
||||
{
|
||||
usrtc_node_t *node = &msg->node;
|
||||
usrtc_t *tree = &queue->qtree;
|
||||
|
||||
tree = &queue->qtree; /* remove from queue */
|
||||
usrtc_delete(tree, node);
|
||||
|
||||
tree = &queue->msgcache;
|
||||
|
||||
if(usrtc_count(tree) >= MAX_QUEUE_POOL)
|
||||
free(msg);
|
||||
else {
|
||||
msg->data = NULL;
|
||||
msg->msgtype = NIL_MSG;
|
||||
usrtc_insert(tree, node, (void *)&msg->qlength);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int pth_queue_init(pth_queue_t *queue)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
memset(queue, 0, sizeof(pth_queue_t));
|
||||
if((r = pthread_cond_init(&queue->cond, NULL)))
|
||||
return r;
|
||||
|
||||
if((r = pthread_mutex_init(&queue->mutex, NULL))) {
|
||||
pthread_cond_destroy(&queue->cond);
|
||||
return r;
|
||||
}
|
||||
|
||||
usrtc_init(&queue->qtree, USRTC_AVL, MAX_QUEUE_SIZE, __cmp_uint);
|
||||
usrtc_init(&queue->msgcache, USRTC_AVL, MAX_QUEUE_POOL, __cmp_uint);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int pth_queue_add(pth_queue_t *queue, void *data, unsigned int msgtype)
|
||||
{
|
||||
pth_msg_t *newmsg;
|
||||
|
||||
pthread_mutex_lock(&queue->mutex);
|
||||
newmsg = __get_newmsg(queue);
|
||||
if (newmsg == NULL) {
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
newmsg->data = data;
|
||||
newmsg->msgtype = msgtype;
|
||||
|
||||
if(queue->length == 0)
|
||||
pthread_cond_broadcast(&queue->cond);
|
||||
queue->length++;
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pth_queue_get(pth_queue_t *queue, const struct timespec *timeout, pth_msg_t *msg)
|
||||
{
|
||||
usrtc_t *tree;
|
||||
usrtc_node_t *node = NULL;
|
||||
pth_msg_t *tmp;
|
||||
int r = 0;
|
||||
struct timespec abstimeout;
|
||||
|
||||
if (queue == NULL || msg == NULL)
|
||||
return EINVAL;
|
||||
else
|
||||
tree = &queue->qtree;
|
||||
|
||||
if (timeout) { /* setup timeout */
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
abstimeout.tv_sec = now.tv_sec + timeout->tv_sec;
|
||||
abstimeout.tv_nsec = (now.tv_usec * 1000) + timeout->tv_nsec;
|
||||
if (abstimeout.tv_nsec >= 1000000000) {
|
||||
abstimeout.tv_sec++;
|
||||
abstimeout.tv_nsec -= 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&queue->mutex);
|
||||
|
||||
/* Will wait until awakened by a signal or broadcast */
|
||||
while ((node = usrtc_first(tree)) == NULL && r != ETIMEDOUT) { /* Need to loop to handle spurious wakeups */
|
||||
if (timeout)
|
||||
r = pthread_cond_timedwait(&queue->cond, &queue->mutex, &abstimeout);
|
||||
else
|
||||
pthread_cond_wait(&queue->cond, &queue->mutex);
|
||||
}
|
||||
if (r == ETIMEDOUT) {
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
return r;
|
||||
}
|
||||
|
||||
tmp = (pth_msg_t *)usrtc_node_getdata(node);
|
||||
queue->length--;
|
||||
|
||||
msg->data = tmp->data;
|
||||
msg->msgtype = tmp->msgtype;
|
||||
msg->qlength = tmp->qlength; /* we will hold the msg id instead of size here */
|
||||
|
||||
__release_msg(queue, tmp);
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pth_queue_destroy(pth_queue_t *queue, int freedata, void (*free_msg)(void *))
|
||||
{
|
||||
int r = 0;
|
||||
usrtc_t *tree = &queue->qtree;
|
||||
usrtc_node_t *node = NULL;
|
||||
pth_msg_t *msg;
|
||||
|
||||
if (queue == NULL) return EINVAL;
|
||||
|
||||
pthread_mutex_lock(&queue->mutex);
|
||||
|
||||
for (node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
|
||||
usrtc_delete(tree, node);
|
||||
msg = (pth_msg_t *)usrtc_node_getdata(node);
|
||||
|
||||
if(freedata) free(msg->data);
|
||||
else if(free_msg) free_msg(msg->data);
|
||||
|
||||
free(msg);
|
||||
}
|
||||
/* free cache */
|
||||
tree = &queue->msgcache;
|
||||
for (node = usrtc_first(tree); node != NULL; node = usrtc_first(tree)) {
|
||||
usrtc_delete(tree, node);
|
||||
free(usrtc_node_getdata(node));
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
r = pthread_mutex_destroy(&queue->mutex);
|
||||
pthread_cond_destroy(&queue->cond);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
unsigned int pth_queue_length(pth_queue_t *queue)
|
||||
{
|
||||
unsigned int c;
|
||||
|
||||
pthread_mutex_lock(&queue->mutex);
|
||||
c = queue->length;
|
||||
pthread_mutex_unlock(&queue->mutex);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* dynamic queue thread poll */
|
||||
|
||||
struct __pthrd_data {
|
||||
pth_dqtpoll_t *pthrd;
|
||||
int myid;
|
||||
};
|
||||
|
||||
static void *__poll_thread(void *poll)
|
||||
{
|
||||
int r = 0;
|
||||
struct __pthrd_data *thrdata = (struct __pthrd_data *)poll;
|
||||
struct __pthrd_data *npoll = NULL;
|
||||
pth_msg_t msgbuf, sysbuf;
|
||||
pth_dqtpoll_t *p = thrdata->pthrd;
|
||||
pth_queue_t *q = p->queue;
|
||||
ulong_t myid = thrdata->myid;
|
||||
struct timeval now;
|
||||
int resched = 0;
|
||||
long tusec, si, mdrate;
|
||||
|
||||
while(1) {
|
||||
resched = 0;
|
||||
r = pth_queue_get(q, NULL, &msgbuf);
|
||||
pthread_rwlock_wrlock(&(p->stats_lock));
|
||||
if(p->flags & DQTPOLL_DEADSTAGE) { /* poll going to be killed */
|
||||
pthread_rwlock_unlock(&(p->stats_lock));
|
||||
idx_free(p->idx, myid);
|
||||
p->poll_value--;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* now get the time */
|
||||
gettimeofday(&now, NULL);
|
||||
if((now.tv_sec >= p->sched_time.tv_sec) &&
|
||||
(now.tv_usec >= p->sched_time.tv_usec)) {
|
||||
resched = 1;
|
||||
/* set the new schedule time */
|
||||
si = 0;
|
||||
tusec = DQTPOLL_DELTAMS + now.tv_usec;
|
||||
if(tusec > 1000000) {
|
||||
tusec -= 1000000;
|
||||
si++;
|
||||
}
|
||||
p->sched_time.tv_sec += si + DQTPOLL_DELTASE;
|
||||
p->sched_time.tv_usec = tusec;
|
||||
}
|
||||
|
||||
if(resched) { /* ok now we need to resched and descrease/increase thread poll volume */
|
||||
if(p->msgop) mdrate = ((DQTPOLL_DELTASE*1000000) + DQTPOLL_DELTAMS)/p->msgop;
|
||||
else mdrate = 0;
|
||||
if((mdrate > p->poll_value) && (p->poll_value < MAX_POLL_VALUE)) { /* increase ! */
|
||||
if((npoll = malloc(sizeof(struct __pthrd_data)))) {
|
||||
npoll->myid = idx_allocate(p->idx);
|
||||
npoll->pthrd = p;
|
||||
p->poll_value++;
|
||||
/* create thread here */
|
||||
if(pthread_create(&(p->poll[npoll->myid]), NULL, __poll_thread, npoll)) {
|
||||
idx_free(p->idx, npoll->myid);
|
||||
p->poll_value--;
|
||||
free(npoll);
|
||||
}
|
||||
}
|
||||
} else if((p->poll_value > 2) && (mdrate < p->poll_value)) /* decrease */ {
|
||||
memset(&sysbuf, 0, sizeof(pth_msg_t));
|
||||
pth_queue_add(p->queue, &sysbuf, POLL_DECREASE);
|
||||
}
|
||||
|
||||
/* init all other stuff */
|
||||
p->msgop = 0;
|
||||
}
|
||||
|
||||
if(r) {
|
||||
pthread_rwlock_unlock(&(p->stats_lock));
|
||||
continue;
|
||||
} else p->msgop++;
|
||||
pthread_rwlock_unlock(&(p->stats_lock));
|
||||
|
||||
switch(msgbuf.msgtype) {
|
||||
case USR_MSG:
|
||||
/* do the job */
|
||||
p->jobdata_callback(msgbuf.data);
|
||||
break;
|
||||
case POLL_DECREASE:
|
||||
pthread_rwlock_rdlock(&(p->stats_lock));
|
||||
if(p->poll_value > 2) r = 1; /* exit now */
|
||||
pthread_rwlock_unlock(&(p->stats_lock));
|
||||
if(r) {
|
||||
pthread_rwlock_wrlock(&(p->stats_lock));
|
||||
idx_free(p->idx, myid);
|
||||
p->poll_value--;
|
||||
pthread_rwlock_unlock(&(p->stats_lock));
|
||||
free(poll);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* TODO: do something ... */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init poll, structure must be allocated */
|
||||
int pth_dqtpoll_init(pth_dqtpoll_t *tpoll, int (*jobdata_callback)(void *))
|
||||
{
|
||||
int r = 0;
|
||||
pth_queue_t *queue = malloc(sizeof(pth_queue_t));
|
||||
pthread_t *poll = malloc(sizeof(pthread_t)*MAX_POLL_VALUE);
|
||||
idx_allocator_t *idx = malloc(sizeof(idx_allocator_t));
|
||||
struct __pthrd_data *ndata = malloc(sizeof(struct __pthrd_data));
|
||||
|
||||
/* check it for allocation */
|
||||
if(!ndata) goto __enomem;
|
||||
if(!idx) goto __enomem;
|
||||
if(!queue) goto __enomem;
|
||||
if(!poll) goto __enomem;
|
||||
|
||||
/* init all the stuff */
|
||||
if(idx_allocator_init(idx, MAX_POLL_VALUE*16, 0)) {
|
||||
__enomem:
|
||||
r = ENOMEM;
|
||||
goto __finish;
|
||||
}
|
||||
if(pth_queue_init(queue)) goto __enomem; /* init queue */
|
||||
if(pthread_rwlock_init(&(tpoll->stats_lock), NULL)) goto __enomem;
|
||||
|
||||
/* set parameters */
|
||||
memset(poll, 0, sizeof(pthread_t)*MAX_POLL_VALUE);
|
||||
tpoll->flags = 0;
|
||||
tpoll->idx = idx;
|
||||
tpoll->poll = poll;
|
||||
tpoll->queue = queue;
|
||||
tpoll->poll_value = 2;
|
||||
tpoll->spurious_wakeups = 0;
|
||||
tpoll->msgop = 0;
|
||||
tpoll->jobdata_callback = jobdata_callback;
|
||||
|
||||
/* first thread initiation */
|
||||
idx_reserve(idx, 0);
|
||||
ndata->myid = 0;
|
||||
ndata->pthrd = tpoll;
|
||||
if(pthread_create(&(poll[0]), NULL, __poll_thread, ndata)) {
|
||||
__eadd:
|
||||
pthread_rwlock_destroy(&(tpoll->stats_lock));
|
||||
goto __enomem;
|
||||
}
|
||||
/* second thread initiation */
|
||||
ndata = malloc(sizeof(struct __pthrd_data));
|
||||
if(!ndata) goto __eadd;
|
||||
idx_reserve(idx, 1);
|
||||
ndata->myid = 1;
|
||||
ndata->pthrd = tpoll;
|
||||
if(pthread_create(&(poll[1]), NULL, __poll_thread, ndata)) {
|
||||
pthread_rwlock_destroy(&(tpoll->stats_lock));
|
||||
goto __enomem;
|
||||
}
|
||||
|
||||
gettimeofday(&(tpoll->sched_time), NULL);
|
||||
|
||||
__finish:
|
||||
if(r) {
|
||||
if(ndata) free(ndata);
|
||||
if(idx) free(idx);
|
||||
if(queue) {
|
||||
pth_queue_destroy(queue, 0, NULL);
|
||||
free(queue);
|
||||
}
|
||||
if(poll) free(poll);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* run poll: poll */
|
||||
int pth_dqtpoll_run(pth_dqtpoll_t *tpoll)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
pthread_rwlock_wrlock(&(tpoll->stats_lock));
|
||||
if((tpoll->flags & DQTPOLL_RUNNING) || (tpoll->flags & DQTPOLL_DEADSTAGE)) r = EINVAL;
|
||||
else {
|
||||
tpoll->flags |= DQTPOLL_RUNNING;
|
||||
}
|
||||
pthread_rwlock_unlock(&(tpoll->stats_lock));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* add the job to the queue: poll, job data, message type */
|
||||
int pth_dqtpoll_add(pth_dqtpoll_t *tpoll, void *job, unsigned int type)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = pth_queue_add(tpoll->queue, job, type);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* destroy the poll: poll, force flag
|
||||
* if force flag is set (!= 0), give up
|
||||
* about jobs, if no, do the job, but don't
|
||||
* accept the new ones, and destroy all poll
|
||||
* with last thread.
|
||||
*/
|
||||
int pth_dqtpoll_destroy(pth_dqtpoll_t *tpoll, int force)
|
||||
{
|
||||
int r = 0;
|
||||
pth_msg_t tmpmsg;
|
||||
|
||||
pthread_rwlock_wrlock(&(tpoll->stats_lock));
|
||||
tpoll->flags |= DQTPOLL_DEADSTAGE;
|
||||
pthread_rwlock_unlock(&(tpoll->stats_lock));
|
||||
|
||||
/* now we need to wait */
|
||||
while(1) {
|
||||
pthread_rwlock_rdlock(&(tpoll->stats_lock));
|
||||
if(!tpoll->poll_value) {
|
||||
pthread_rwlock_unlock(&(tpoll->stats_lock));
|
||||
break;
|
||||
} else {
|
||||
pthread_rwlock_unlock(&(tpoll->stats_lock));
|
||||
pth_queue_add(tpoll->queue, &tmpmsg, 0); /* spurious */
|
||||
}
|
||||
usleep(100); /* just to sleep and free timeslice to others */
|
||||
}
|
||||
|
||||
/* free all */
|
||||
pth_queue_destroy(tpoll->queue, 0, NULL);
|
||||
idx_allocator_destroy(tpoll->idx);
|
||||
pthread_rwlock_destroy(&(tpoll->stats_lock));
|
||||
|
||||
free(tpoll->poll);
|
||||
free(tpoll->queue);
|
||||
free(tpoll->idx);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,3 @@
|
||||
man_MANS = sxmsg_rreply.3 connections_create.3 connections_init.3 connections_destroy.3 connections_free.3 \
|
||||
sntl_init.3 connections_setsslserts.3 connections_set_priv.3 connections_get_priv.3 \
|
||||
connections_set_ondestroy.3
|
@ -0,0 +1,80 @@
|
||||
.TH CONNECTIONS_CREATE 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
connections_create \- Allocate and initialize connections system
|
||||
.br
|
||||
connections_init \- Initialize connections system
|
||||
.br
|
||||
connections_destroy \- Destroy connections system
|
||||
.br
|
||||
connections_free \- Free all stuff allocated for connections system
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.sp
|
||||
conn_sys_t *connections_create(void);
|
||||
|
||||
int connections_init(conn_sys_t *ssys);
|
||||
|
||||
int connections_destroy(conn_sys_t *ssys);
|
||||
|
||||
int connections_free(conn_sys_t *ssys);
|
||||
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
.B connections_create
|
||||
will create a separate connections set used for handling creation and initialization of the connection links.
|
||||
.B connections_init
|
||||
will do the same, but it will take an already preallocated pointer.
|
||||
.br
|
||||
.B connections_destroy
|
||||
will deallocate all related to the connections set, include pointer
|
||||
.BI ssys
|
||||
, but
|
||||
.B connections_free
|
||||
will not free this pointer consider it will be deallocated by user.
|
||||
.br
|
||||
.SH RETURN VALUE
|
||||
Upon successful completion, the function
|
||||
.B connections_create
|
||||
will return a valid pointer to the connections set.
|
||||
.B connections_init
|
||||
will return
|
||||
.B 0
|
||||
.br
|
||||
Otherwise NULL will be returned and errno will be set, or error will be returned, in case of
|
||||
.B connections_init
|
||||
use.
|
||||
.SH ERRORS
|
||||
.B connections_init
|
||||
will return,
|
||||
.B connection_create will set
|
||||
.B errno
|
||||
to:
|
||||
.br
|
||||
.B ENOMEM
|
||||
Not enough memory to allocate all required stuff.
|
||||
.br
|
||||
.B EINVAL
|
||||
Returned if invalid pointer given.
|
||||
.br
|
||||
.SH BUGS
|
||||
Not known yet.
|
||||
.SH EXAMPLE
|
||||
None.
|
||||
.SH APPLICATION USAGE
|
||||
None.
|
||||
.SH RATIONALE
|
||||
Connection link destroy function might be used carefully, the logic of there functions is a
|
||||
send a special link layer message that will close the connection link on the master side.
|
||||
The reason to care about is a delivery of all messages, channels and other stuff, because
|
||||
when this functions called all pending messages are drops.
|
||||
.SH SEE ALSO
|
||||
.BI connections_setsslserts(3)
|
||||
,
|
||||
.BI sntl_init(3)
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
@ -0,0 +1 @@
|
||||
connections_create.3
|
@ -0,0 +1 @@
|
||||
connections_create.3
|
@ -0,0 +1 @@
|
||||
connections_set_priv.3
|
@ -0,0 +1 @@
|
||||
connections_create.3
|
@ -0,0 +1,48 @@
|
||||
.TH CONNECTIONS_ON_DESTROY 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
connections_on_destroy \- Set callback for the connection links based on the connections set, called in case of link destroying
|
||||
.br
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.sp
|
||||
#define connections_set_ondestroy(c, f)
|
||||
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
This macro should be used if you want to setup callback function fired upon a connection is closed or broken.
|
||||
.br
|
||||
This macro will set on
|
||||
.B c
|
||||
connections link set callback
|
||||
.B f
|
||||
which is a function pointer of the type:
|
||||
.br
|
||||
.sp
|
||||
.B typedef void (*ondestroy_t)(conn_t *);
|
||||
.br
|
||||
.sp
|
||||
This function will be called if connection link failed, broken etc. It will pass a pointer to the failed connection.
|
||||
.SH RETURN VALUE
|
||||
None.
|
||||
.SH ERRORS
|
||||
None.
|
||||
.SH BUGS
|
||||
None known yet.
|
||||
.SH EXAMPLE
|
||||
None.
|
||||
.SH APPLICATION USAGE
|
||||
None.
|
||||
.SH RATIONALE
|
||||
None.
|
||||
.SH SEE ALSO
|
||||
.BI connections_set_priv(3)
|
||||
,
|
||||
.BI connections_get_priv(3)
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
||||
|
@ -0,0 +1,58 @@
|
||||
.TH CONNECTIONS_SET_PRIV 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
connections_set_priv \- Set a private pointer to the connection links set
|
||||
.br
|
||||
connections_get_priv \- Get a private pointer of the connection links set
|
||||
.br
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.sp
|
||||
#define connections_set_priv(c, p)
|
||||
.br
|
||||
#define connections_get_priv(c)
|
||||
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
There macros should be used in case if you want set and get back your private pointer for something.
|
||||
.br
|
||||
Pointer is a
|
||||
.B void*
|
||||
i.e. it might be anything you pointed in the memory.
|
||||
.br
|
||||
.B connections_set_priv
|
||||
will set a pointer
|
||||
.B p
|
||||
to connections set
|
||||
.B c
|
||||
.br
|
||||
.B connections_get_priv
|
||||
will return your pointer set to
|
||||
.B c
|
||||
connection set.
|
||||
.br
|
||||
.SH RETURN VALUE
|
||||
None in case of
|
||||
.B connections_set_priv
|
||||
, a private pointer set in case of
|
||||
.B connections_get_priv
|
||||
.br
|
||||
.SH ERRORS
|
||||
None.
|
||||
.br
|
||||
.SH BUGS
|
||||
None known yet.
|
||||
.SH EXAMPLE
|
||||
None.
|
||||
.SH APPLICATION USAGE
|
||||
None.
|
||||
.SH RATIONALE
|
||||
None.
|
||||
.SH SEE ALSO
|
||||
.BI connections_set_ondestroy(3)
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
@ -0,0 +1,63 @@
|
||||
.TH CONNECTIONS_SETSSLSERTS 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
connections_setsslserts \- Setup root public certificate to check up, and also setups key and public certificate used for connections set
|
||||
.br
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.sp
|
||||
int connections_setsslserts(conn_sys_t *ssys, const char *rootca,
|
||||
const char *certpem, const char *certkey);
|
||||
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
.B connections_setsslserts
|
||||
will setup root public certificate and private key and public certificate used to run connections set.
|
||||
This is required always, see below for more information.
|
||||
.br
|
||||
.sp
|
||||
This function just set a pathname of the certificates for
|
||||
.BI ssys
|
||||
where
|
||||
.BI rootca
|
||||
is a pathname to the public X.509 certificate
|
||||
.BI certpem
|
||||
is a your own X.509 certificate and
|
||||
.BI certkey
|
||||
is a your own key for this certificate. Therefore,
|
||||
.BI certpem
|
||||
and
|
||||
.BI certkey
|
||||
might be a single file.
|
||||
.br
|
||||
.SH RETURN VALUE
|
||||
Will return 0 on success or errors below.
|
||||
.br
|
||||
.SH ERRORS
|
||||
.B EINVAL
|
||||
Invalid pointer given.
|
||||
.br
|
||||
.B ENOMEM
|
||||
There are no available memory for operation.
|
||||
.br
|
||||
.SH BUGS
|
||||
None known yet, but name is historically wrong it should be called connections_setsslcerts, btw there are many
|
||||
code was written with this mistake.
|
||||
.SH EXAMPLE
|
||||
None.
|
||||
.SH APPLICATION USAGE
|
||||
Call this function *always* before linking a connection. Non master link will always avoid non-root certificate and key,
|
||||
since you will required to pass it via call.
|
||||
.SH RATIONALE
|
||||
None.
|
||||
.SH SEE ALSO
|
||||
.BI connection_link(3)
|
||||
,
|
||||
.BI connection_link_master(3)
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
||||
|
@ -0,0 +1,45 @@
|
||||
.TH SNTL_INIT 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
sntl_init \- Initialize all required globals to run sntl library functions
|
||||
.br
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.sp
|
||||
int *sntl_init(void);
|
||||
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
.B sntl_init
|
||||
will initialize all globals required to run sntl related functions, it mostly about
|
||||
openssl library initialization.
|
||||
.br
|
||||
.SH RETURN VALUE
|
||||
Always returns
|
||||
.B 0
|
||||
since we cannot track openssl global initialization routines.
|
||||
.br
|
||||
.SH ERRORS
|
||||
None errors might be returned.
|
||||
.SH BUGS
|
||||
None known yet.
|
||||
.SH EXAMPLE
|
||||
None.
|
||||
.SH APPLICATION USAGE
|
||||
Call this function from the main thread before using sntl library. Otherwise it will not works. There are also
|
||||
useful to know if you are using other openssl functionality there are no need to initialize globals for it.
|
||||
.SH RATIONALE
|
||||
None.
|
||||
.SH SEE ALSO
|
||||
.BI connections_create(3)
|
||||
,
|
||||
.BI connections_destroy(3)
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
||||
|
||||
|
||||
|
@ -0,0 +1,59 @@
|
||||
.TH SXMSG_RREPLY 3 "20 July 2015" "SNTLLv2" "SNTL Library Manual"
|
||||
.SH NAME
|
||||
sxmsg_rreply \- Function used to send a rapid reply without confirmation
|
||||
.SH SYNOPSIS
|
||||
.B #include <sntl/sntllv2.h>
|
||||
.br
|
||||
.B #include <sntl/limits.h>
|
||||
.sp
|
||||
int sxmsg_rreply(sxmsg_t
|
||||
.BI *msg
|
||||
, size_t
|
||||
.BI datalen
|
||||
);
|
||||
.br
|
||||
.sp
|
||||
.SH DESCRIPTION
|
||||
.B sxmsg_rreply
|
||||
Will reply rapidly to the message using already allocated buffer, which must be
|
||||
retrieved via
|
||||
.B sxmsg_rapidbuf().
|
||||
This function will write desired message as soon
|
||||
as possible. It will not wait any write or delivery confirmation. It will close
|
||||
message dialog if message is valid.
|
||||
.br
|
||||
.SH RETURN VALUE
|
||||
Upon successful completion, the function shall rapidly send a message reply and close
|
||||
the message dialog returning
|
||||
.B SNE_SUCCESS
|
||||
Othrewise other error code will be returned.
|
||||
.SH ERRORS
|
||||
.B SNE_FAILED
|
||||
returns if message has invalid index, channel or message pointer is NULL.
|
||||
.br
|
||||
.B SNE_ESSL
|
||||
returns if write was failed i.e. connection link was broken, or SSL error occurs.
|
||||
.br
|
||||
.B SNE_SUCCESS
|
||||
returns on success.
|
||||
.br
|
||||
.SH BUGS
|
||||
Not known yet.
|
||||
.SH EXAMPLE
|
||||
.B Reply rapidly from the RPC function call.
|
||||
.RS
|
||||
.nf
|
||||
.if t .ft CW
|
||||
char *buf = sxmsg_rapidbuf(msg);
|
||||
int ln = snprintf(buf, MAX_RBBUF_LEN, "(is-done)");
|
||||
return sxmsg_rreply(msg, str, ln);
|
||||
.SH APPLICATION USAGE
|
||||
This function will be useful in RPC functions required to reply ASAP i.e. for getting some data. It RPC function takes a lot of time it's better to use other functions and postponed message processing.
|
||||
.SH RATIONALE
|
||||
Use for lightweight RPC functions, this method may be used only in RPC call i.e. within SNTL thread context.
|
||||
.SH COPYRIGHT
|
||||
This is a proprietary software. See COPYING for further details.
|
||||
.br
|
||||
(c) Askele Group 2013-2015 <http://askele.com>
|
||||
.SH AUTHOR
|
||||
Alexander Vdolainen (vdo@askele.com)
|
@ -0,0 +1,37 @@
|
||||
## AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \
|
||||
-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
|
||||
-DPACKAGE_DATA_DIR=\""$(pkgdatadir)"\" \
|
||||
-DCNFPATH=\""$(prefix)/etc"\" \
|
||||
-I../include \
|
||||
-I../lib
|
||||
|
||||
AM_CFLAGS = -Wall -g
|
||||
|
||||
# where to find libsntl
|
||||
libsntl = ../lib/.libs/libsntl.la
|
||||
|
||||
if !BUILD_WIN32
|
||||
|
||||
bin_PROGRAMS = lv2sd lv2sc
|
||||
|
||||
lv2sd_SOURCES = lv2sd.c
|
||||
lv2sd_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \
|
||||
$(LIBUUID_LIBS) $(libsntl)
|
||||
|
||||
lv2sc_SOURCES = lv2sc.c
|
||||
lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \
|
||||
$(LIBUUID_LIBS) $(libsntl)
|
||||
|
||||
else BUILD_WIN32
|
||||
|
||||
bin_PROGRAMS = lv2sc
|
||||
|
||||
lv2sc_SOURCES = lv2sc.c
|
||||
lv2sc_LDADD = $(LIBTDATA_LIBS) $(LIBSEXPR_LIBS) $(OPENSSL_LIBS) \
|
||||
$(LIBUUID_LIBS) $(libsntl) -lws2_32
|
||||
|
||||
endif BUILD_WIN32
|
||||
|
@ -0,0 +1,30 @@
|
||||
1. lv2ftp isn's serious, just a test and benchmark of the sntllv2
|
||||
2. there are few stages:
|
||||
2.1 Simple v.1
|
||||
This protocol is enough to donwload a directory subtree with files.
|
||||
2.1.1 Directory workout
|
||||
* Open directory stream: (dir-open "<dir-name>")
|
||||
* Return: error, or rapidly replies with (dir-stream <id>)
|
||||
* Read directory entry: (dir-read <id>)
|
||||
* Return: error, or rapidly replies with the following:
|
||||
* (dir-end <id>)
|
||||
* (dir-entry "<filename>" "<filetype>"), where filetype the following:
|
||||
* regular - regular file
|
||||
* directory - directory
|
||||
* block - block device
|
||||
* char - char device
|
||||
* fifo - named pipe
|
||||
* link - symbolic link
|
||||
* socket - socket
|
||||
* unknown - unknown file type
|
||||
* Close directory entry: (dir-close <id>)
|
||||
* Return: error or SNE_SUCCESS
|
||||
2.1.2 File workout
|
||||
* Open file: (file-open "<file-name>")
|
||||
* Return: error, or rapidly replies with (file-id <id>)
|
||||
* Get simple stat: (file-stat <id>)
|
||||
* Return error, or rapidle replies with (file-stat <id> <size>)
|
||||
* Read file data: (file-read <id> <offset>)
|
||||
* Return error, or rapidly replies with 30k(raw data, in base64 it will be more) (file-data <id> <offset> "<B64encoded data>")
|
||||
* Close file: (file-close <id>)
|
||||
* Return error or SNE_SUCCESS
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,282 @@
|
||||
#include <stdio.h>
|
||||
#define __USE_GNU
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#include <signal.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/resource.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <execinfo.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
#include <sntl/sntllv2.h>
|
||||
#include <sntl/limits.h>
|
||||
|
||||
/* define a little bit */
|
||||
#define DEFAULT_PORT 13133
|
||||
#define CHANNEL_COUNT 200
|
||||
#define CLIENT_COUNT 256
|
||||
#define MESSAGES_PER_SESSION 10000
|
||||
#define ITERATION_COUNT 1000
|
||||
|
||||
#define FAILS_ONLY
|
||||
|
||||
struct testdata {
|
||||
int uc;
|
||||
pthread_mutex_t ulock;
|
||||
conn_t *co;
|
||||
};
|
||||
|
||||
static int __init_testdata(struct testdata *t, conn_t *co)
|
||||
{
|
||||
t->uc = 0;
|
||||
pthread_mutex_init(&t->ulock, NULL);
|
||||
t->co = co;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __wait_completion(struct testdata *t)
|
||||
{
|
||||
pthread_mutex_lock(&t->ulock);
|
||||
if(t->uc) {
|
||||
pthread_mutex_lock(&t->ulock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int __set_typed_list_callback(conn_t *co, int ch, char *desc)
|
||||
{
|
||||
printf("allowed channel %d (%s)\n", ch, desc);
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
static void *__addsthrd(void *a)
|
||||
{
|
||||
struct testdata *t = a;
|
||||
conn_t *co = t->co;
|
||||
chnl_t *mch;
|
||||
sxmsg_t *msg;
|
||||
char mmbuf[1024];
|
||||
size_t ln;
|
||||
int mr, i;
|
||||
|
||||
pthread_mutex_lock(&t->ulock);
|
||||
t->uc++;
|
||||
pthread_mutex_unlock(&t->ulock);
|
||||
|
||||
/* here we go */
|
||||
mch = sxchannel_open(co, 12);
|
||||
|
||||
if(!mch) {
|
||||
fprintf(stderr, "Failed to openchannel with %d\n", errno);
|
||||
goto __fini;
|
||||
}
|
||||
|
||||
for(i = 0; i < MESSAGES_PER_SESSION; i++) {
|
||||
ln = snprintf(mmbuf, 1024, "(ar-add (10 10))");
|
||||
mr = sxmsg_send(mch, mmbuf, ln, &msg);
|
||||
switch(mr) {
|
||||
case SNE_RAPIDMSG:
|
||||
//fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg));
|
||||
sxmsg_clean(msg);
|
||||
break;
|
||||
case SNE_REPLYREQ:
|
||||
if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n",
|
||||
(char *)sxmsg_payload(msg));
|
||||
mr = sxmsg_return(msg, SNE_SUCCESS);
|
||||
fprintf(stderr, "mr = %d\n", mr);
|
||||
break;
|
||||
case SNE_SUCCESS:
|
||||
fprintf(stdout, "Success.\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR: %d\n", mr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sxchannel_close(mch);
|
||||
|
||||
__fini:
|
||||
t->uc--;
|
||||
if(t->uc <= 1) pthread_mutex_unlock(&t->ulock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *rootca = NULL, *cert = NULL;
|
||||
int port = DEFAULT_PORT;
|
||||
char *addr = NULL, *login = NULL, *password = NULL;
|
||||
int opt;
|
||||
conn_sys_t *ssys;
|
||||
conn_t *co;
|
||||
|
||||
while((opt = getopt(argc, argv, "p:r:a:u:l:w:")) != -1) {
|
||||
switch(opt) {
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
rootca = strdup(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
addr = strdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
cert = strdup(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
login = strdup(optarg);
|
||||
break;
|
||||
case 'w':
|
||||
password = strdup(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [-p <PORTNUM>] -r <PATH to Root CA> -a <Server ip address> -u <PATH"
|
||||
" to SSL certificate> -l <User login> -w <User password>\n", argv[0]);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if(!rootca) {
|
||||
fprintf(stderr, "Root CA not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if(!addr) {
|
||||
fprintf(stderr, "Server address not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if(!cert) {
|
||||
fprintf(stderr, "User certificate not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if(!login) {
|
||||
fprintf(stderr, "User login not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if(!password) {
|
||||
fprintf(stderr, "User password not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
sntl_init();
|
||||
/* all is fine let's init connection subsystem */
|
||||
ssys = connections_create();
|
||||
if(!ssys) {
|
||||
fprintf(stderr, "Subsystem init failed: %d\n", errno);
|
||||
return errno;
|
||||
}
|
||||
/* set working certificates */
|
||||
opt = connections_setsslserts(ssys, rootca, cert, cert);
|
||||
if(opt) {
|
||||
fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt);
|
||||
return opt;
|
||||
}
|
||||
|
||||
/* Tests */
|
||||
struct timeval beg, end;
|
||||
/* try to open connection */
|
||||
connections_set_channelcall(ssys, __set_typed_list_callback);
|
||||
|
||||
gettimeofday(&beg, NULL);
|
||||
co = connection_link(ssys, addr, port, cert, login, password);
|
||||
|
||||
if(!co) {
|
||||
fprintf(stderr, "Failed to connection with %d\n", errno);
|
||||
return errno;
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
if((end.tv_sec - beg.tv_sec) > 0) {
|
||||
printf("Seconds: %ld ", end.tv_sec - beg.tv_sec);
|
||||
printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec));
|
||||
} else printf("µS: %ld\n", end.tv_usec - beg.tv_usec);
|
||||
|
||||
/* ok now we should open a channel */
|
||||
chnl_t *testchannel = sxchannel_open(co, 12);
|
||||
|
||||
if(!testchannel) {
|
||||
fprintf(stderr, "Failed to openchannel with %d\n", errno);
|
||||
return errno;
|
||||
}
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
if((end.tv_sec - beg.tv_sec) > 0) {
|
||||
printf("Seconds: %ld ", end.tv_sec - beg.tv_sec);
|
||||
printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec));
|
||||
} else printf("µS: %ld\n", end.tv_usec - beg.tv_usec);
|
||||
|
||||
/* ok, send a message */
|
||||
char mmbuf[1024];
|
||||
sxmsg_t *msg;
|
||||
size_t ln;
|
||||
ln = snprintf(mmbuf, 1024, "(ar-add (10 10))");
|
||||
int mr = sxmsg_send(testchannel, mmbuf, ln, &msg);
|
||||
switch(mr) {
|
||||
case SNE_RAPIDMSG:
|
||||
fprintf(stdout, "Rapidly replied: %s\n", (char *)sxmsg_payload(msg));
|
||||
sxmsg_clean(msg);
|
||||
break;
|
||||
case SNE_REPLYREQ:
|
||||
if(sxmsg_datalen(msg)) fprintf(stdout, "Replied (confirmation required): %s\n",
|
||||
(char *)sxmsg_payload(msg));
|
||||
mr = sxmsg_return(msg, SNE_SUCCESS);
|
||||
fprintf(stderr, "mr = %d\n", mr);
|
||||
break;
|
||||
case SNE_SUCCESS:
|
||||
fprintf(stdout, "Success.\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR: %d\n", mr);
|
||||
break;
|
||||
}
|
||||
|
||||
int ee = sxchannel_close(testchannel);
|
||||
printf("ee = %d\n", ee);
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
if((end.tv_sec - beg.tv_sec) > 0) {
|
||||
printf("Seconds: %ld ", end.tv_sec - beg.tv_sec);
|
||||
printf("µS: %ld\n", end.tv_usec + (1000000 - beg.tv_usec));
|
||||
} else printf("µS: %ld\n", end.tv_usec - beg.tv_usec);
|
||||
sleep(10);
|
||||
/* ok, now we need to create many threads */
|
||||
struct testdata trd;
|
||||
pthread_t thrd;
|
||||
int i;
|
||||
__init_testdata(&trd, co);
|
||||
|
||||
for(i = 0; i < 256; i++) pthread_create(&thrd, NULL, __addsthrd, &trd);
|
||||
|
||||
__wait_completion(&trd);
|
||||
|
||||
connection_close(co);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Secure Network Transport Layer Library v2 implementation.
|
||||
* (sntllv2) it superseed all versions before due to the:
|
||||
* - memory consumption
|
||||
* - new features such as pulse emitting
|
||||
* - performance optimization
|
||||
*
|
||||
* This is a proprietary software. See COPYING for further details.
|
||||
*
|
||||
* (c) Askele Group 2013-2015 <http://askele.com>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#define __USE_GNU
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#include <signal.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/select.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/resource.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <execinfo.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <tdata/usrtc.h>
|
||||
#include <sexpr/sexp.h>
|
||||
#include <sntl/limits.h>
|
||||
#include <sntl/sntllv2.h>
|
||||
|
||||
#include <pthread.h>
|
||||
// #include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* helper functions */
|
||||
int __openlistener(int port)
|
||||
{
|
||||
int sd;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
sd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
bzero(&addr, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 ) {
|
||||
perror("can't bind port");
|
||||
abort();
|
||||
}
|
||||
if ( listen(sd, 10) != 0 ) {
|
||||
perror("Can't configure listening port");
|
||||
abort();
|
||||
}
|
||||
|
||||
return sd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Validation of the SSL certificate
|
||||
* this function must be exist.
|
||||
*/
|
||||
static int __validate_sslpem(conn_t *co)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* validate - authorize user with password
|
||||
*/
|
||||
static int __secure_check(conn_t *co)
|
||||
{
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* typed list callback
|
||||
*/
|
||||
static int __set_typed_list_callback(conn_t *co, int ch, char *desc)
|
||||
{
|
||||
printf("allowed channel %d (%s)\n", ch, desc);
|
||||
return SNE_SUCCESS;
|
||||
}
|
||||
|
||||
/* list of rpc calls functions */
|
||||
usrtc_t *fulist;
|
||||
|
||||
/* our fake */
|
||||
usrtc_t *__rettlist(conn_t *c)
|
||||
{
|
||||
return fulist;
|
||||
}
|
||||
|
||||
/* RPC functions implementation */
|
||||
static int __ar_add(void *m, sexp_t *sx)
|
||||
{
|
||||
sexp_t *lsx = NULL, *sx_iter;
|
||||
sxmsg_t *msg = (sxmsg_t *)m;
|
||||
char *buf;
|
||||
int idx;
|
||||
size_t ln = 0;
|
||||
|
||||
if(sexp_list_cdr(sx, &lsx)) {
|
||||
printf("Invalid protocol\n");
|
||||
return sxmsg_return(msg, SNE_BADPROTO);
|
||||
}
|
||||
|
||||
long int sum = 0;
|
||||
SEXP_ITERATE_LIST(lsx, sx_iter, idx) {
|
||||
if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) {
|
||||
fprintf(stderr, "Invalid value type\n");
|
||||
return sxmsg_return(msg, SNE_BADPROTO);
|
||||
}
|
||||
sum += atoi(sx_iter->val);
|
||||
}
|
||||
|
||||
buf = sxmsg_rapidbuf(msg);
|
||||
ln = snprintf(buf, MAX_RBBUF_LEN, "(add-result %ld)", sum);
|
||||
|
||||
return sxmsg_rreply(msg, ln);
|
||||
}
|
||||
|
||||
static int __ar_multiply(void *data, sexp_t *sx)
|
||||
{
|
||||
sexp_t *lsx = NULL;
|
||||
sxmsg_t *msg = (sxmsg_t *)data;
|
||||
char *buf;
|
||||
int idx;
|
||||
sexp_t *sx_iter;
|
||||
size_t ln;
|
||||
|
||||
if(sexp_list_cdr(sx, &lsx)) {
|
||||
printf("Invalid protocol\n");
|
||||
return sxmsg_return(msg, SNE_BADPROTO);
|
||||
}
|
||||
|
||||
long int mult = 0;
|
||||
SEXP_ITERATE_LIST(lsx, sx_iter, idx) {
|
||||
if(!SEXP_IS_TYPE(sx_iter, SEXP_BASIC)) {
|
||||
printf("Invalid value type\n");
|
||||
return sxmsg_return(msg, SNE_BADPROTO);
|
||||
}
|
||||
mult *= atoi(sx_iter->val);
|
||||
}
|
||||
|
||||
buf = sxmsg_rapidbuf(msg);
|
||||
ln = snprintf(buf, MAX_RBBUF_LEN, "(multiply-result %ld)", mult);
|
||||
|
||||
return sxmsg_rreply(msg, ln);
|
||||
}
|
||||
|
||||
/* define a little bit */
|
||||
#define DEFAULT_PORT 13133
|
||||
|
||||
static void sigpipe_handler(int a)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *rootca = NULL, *cert = NULL;
|
||||
conn_sys_t *ssys = connections_create();
|
||||
int port = DEFAULT_PORT;
|
||||
int opt;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
while((opt = getopt(argc, argv, "p:r:u:")) != -1) {
|
||||
switch(opt) {
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
rootca = strdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
cert = strdup(optarg);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "usage: %s [-p <PORTNUM>] -r <PATH to Root CA> -u <PATH"
|
||||
" to SSL certificate>\n", argv[0]);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if(!rootca) {
|
||||
fprintf(stderr, "Root CA not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if(!cert) {
|
||||
fprintf(stderr, "User certificate not pointed.\n Failure.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
sntl_init();
|
||||
/* all is fine let's init connection subsystem */
|
||||
if(!ssys) {
|
||||
fprintf(stderr, "Subsystem init failed: %d\n", opt);
|
||||
return 2;
|
||||
}
|
||||
/* set wroking certificates */
|
||||
opt = connections_setsslserts(ssys, rootca, cert, cert);
|
||||
if(opt) {
|
||||
fprintf(stderr, "Subsystem init failed (set SSL x.509 pems): %d\n", opt);
|
||||
return opt;
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
free(rootca);
|
||||
free(cert);
|
||||
|
||||
/* set important callbacks to do the security checking */
|
||||
connections_set_authcheck(ssys, __secure_check);
|
||||
connections_set_sslvalidate(ssys, __validate_sslpem);
|
||||
/* set a callback, it's optional and doesn't required in server side apps */
|
||||
connections_set_channelcall(ssys, __set_typed_list_callback);
|
||||
|
||||
/* ok, now we need to construct RPC lists (channels) */
|
||||
if(!(fulist = malloc(sizeof(usrtc_t)))) {
|
||||
fprintf(stderr, "Cannot allocate memory for RPC lists\n Failure.\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
opt = sntl_rpclist_init(fulist);
|
||||
if(opt) {
|
||||
fprintf(stderr, "Failed to init rpc list\n Failure.\n");
|
||||
return opt;
|
||||
}
|
||||
|
||||
/* we will add one channel with type id 12 "Demo rpc list" */
|
||||
opt = sntl_rpclist_add(fulist, 12, "Demo RPC list", NULL);
|
||||
if(opt) {
|
||||
fprintf(stderr, "Failed to add typed RPC channel\n Failure.\n");
|
||||
return opt;
|
||||
}
|
||||
/* ok, let's add two functions */
|
||||
opt = sntl_rpclist_add_function(fulist, 12, "ar-add", __ar_add);
|
||||
if(opt) {
|
||||
__fail:
|
||||
fprintf(stderr, "Failed to add functions to typed RPC channel\n Failure.\n");
|
||||
return opt;
|
||||
}
|
||||
opt = sntl_rpclist_add_function(fulist, 12, "ar-multiply", __ar_multiply);
|
||||
if(opt) goto __fail;
|
||||
|
||||
/* ok, setup it */
|
||||
connections_set_rpcvalidator(ssys, __rettlist);
|
||||
|
||||
/* now we're ready to run the listen process */
|
||||
int srv = __openlistener(port);
|
||||
while(1) {
|
||||
struct sockaddr_in addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
conn_t *co;
|
||||
|
||||
int client = accept(srv, (struct sockaddr*)&addr, &len); /* accept connection as usual */
|
||||
co = connection_master_link(ssys, client, NULL); /* create connection, that's all */
|
||||
if(!co) {
|
||||
fprintf(stderr, "Cannot create connetion (%d)\n", opt);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue