diff options
author | Joe <joe@joelightning.com> | 2011-11-10 11:31:23 +0000 |
---|---|---|
committer | Joe <joe@joelightning.com> | 2011-11-10 11:31:23 +0000 |
commit | c40170cb03e41bd1efe775bbd430a50da6cdeea4 (patch) | |
tree | 0cc4c0f5cc41c502a0dff8fdca124cab2bd0dab5 /transport/socat.sh |
First commit, pbot-ng already works.
Diffstat (limited to 'transport/socat.sh')
-rw-r--r-- | transport/socat.sh | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/transport/socat.sh b/transport/socat.sh new file mode 100644 index 0000000..2958708 --- /dev/null +++ b/transport/socat.sh @@ -0,0 +1,184 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +########################################################################### +# # +# envbot - an IRC bot in bash # +# Copyright (C) 2007-2008 Arvid Norlander # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see <http://www.gnu.org/licenses/>. # +# # +########################################################################### +#--------------------------------------------------------------------- +## A transport module using socat +#--------------------------------------------------------------------- + +# A list of features supported +# This is set in transport_check_support +transport_check_support='' + +# Check if all the stuff needed to use this transport is available +# Return status +# 0 Yes +# 1 No +transport_check_support() { + hash socat >/dev/null 2>&1 || { + log_fatal "Can't find socat (needed for this transport)" + return 1 + } + hash mkfifo >/dev/null 2>&1 || { + log_fatal "Can't find mkfifo (needed for this transport)" + return 1 + } + # Build transport_supports + local features="$(socat -V | grep -E 'socat version|define')" + # These seems to always be supported? + transport_supports="nossl bind" + if grep -q WITH_IP4 <<< "$features"; then + transport_supports+=" ipv4" + fi + if grep -q WITH_IP6 <<< "$features"; then + transport_supports+=" ipv6" + fi + if grep -q WITH_OPENSSL <<< "$features"; then + transport_supports+=" ssl" + fi + if [[ -z $config_transport_socat_protocol_family ]]; then + log_fatal "You need to set config_transport_socat_protocol_family in your config to either ipv4 or ipv6." + return 1 + fi + # Check for older version + if grep -q "socat version 1.4" <<< "$features"; then + # SSL + IPv6 is not supported with socat-1.4.x + if [[ $config_server_ssl -ne 0 ]]; then + # list_remove is not yet loaded so we can't use that here... + transport_supports="$(sed "s/ipv6//" <<< "$transport_supports")" + fi + # This is to be sure socat-1.4.x works + # Modules should normally never set config_* in them + # This is an exception. + if [[ -z $config_transport_socat_protocol_family ]]; then + config_transport_socat_protocol_family="ipv4" + fi + # Remember version to find what workaround to use in transport_connect() + transport_socat_is_14="1" + else + transport_socat_is_14="0" + fi + return 0 +} + +# Try to connect +# Parameters +# $1 hostname/IP +# $2 port +# $3 If 1 use SSL. If the module does not support it, just ignore it. +# $4 IP to bind to if any and if supported +# If the module does not support it, just ignore it. +# Return status +# 0 if Ok +# 1 if connection failed +transport_connect() { + transport_tmp_dir_file="$(mktemp -dt envbot.socat.XXXXXXXXXX)" || return 1 + # To keep this simple, from client perspective. + # We WRITE to out and READ from in + mkfifo "${transport_tmp_dir_file}/in" + mkfifo "${transport_tmp_dir_file}/out" + exec 3<&- + exec 4<&- + local addrargs socatnewargs + if [[ $3 -eq 1 ]]; then + addrargs="OPENSSL" + # HACK: Support IPv6 with SSL if socat is new enough. + if [[ $transport_socat_is_14 -eq 0 ]]; then + if [[ $config_transport_socat_protocol_family = "ipv6" ]]; then + socatnewargs=",pf=ip6" + elif [[ $config_transport_socat_protocol_family = "ipv4" ]]; then + socatnewargs=",pf=ip4" + fi + fi + elif [[ $config_transport_socat_protocol_family = "ipv6" ]]; then + addrargs="TCP6" + elif [[ $config_transport_socat_protocol_family = "ipv4" ]]; then + addrargs="TCP4" + fi + # Add in hostname and port. + addrargs+=":${1}:${2}" + # Should we bind an IP? Then lets do that. + if [[ $4 ]]; then + addrargs+=",bind=$4" + fi + # If version 1.5 or later add in extra args + if [[ $transport_socat_is_14 -eq 0 ]]; then + addrargs+="${socatnewargs}" + fi + # If we use SSL check if we should verify. + if [[ $3 -eq 1 && $config_server_ssl_accept_invalid -eq 1 ]]; then + addrargs+=",verify=0" + fi + socat STDIO "$addrargs" < "${transport_tmp_dir_file}/out" > "${transport_tmp_dir_file}/in" & + transport_pid="$!" + echo "$transport_pid" >> "${transport_tmp_dir_file}/pid" + exec 3>"${transport_tmp_dir_file}/out" + exec 4<"${transport_tmp_dir_file}/in" + # To be able to wait for error. + sleep 2 + kill -0 "$transport_pid" >/dev/null 2>&1 || return 1 + time_get_current 'transport_lastvalidtime' +} + +# Called to close connection +# No parameters, no return code check +transport_disconnect() { + # It might not be running. + kill "$(< "${transport_tmp_dir_file}/pid")" >/dev/null 2>&1 + rm -rf "${transport_tmp_dir_file}" + exec 3<&- + exec 4<&- + # To force code to consider this disconnected. + transport_lastvalidtime=0 +} + +# Return status +# 0 If connection is still alive +# 1 If it isn't. +transport_alive() { + kill -0 "$transport_pid" >/dev/null 2>&1 || return 1 + local newtime= + time_get_current 'newtime' + (( newtime - transport_lastvalidtime > 300 )) && return 1 + return 0 +} + +# Return a line in the variable line. +# Return status +# 0 If Ok +# 1 If connection failed +transport_read_line() { + read -ru 4 line + # Fail. + if [[ $? -ne 0 ]]; then + return 1 + else + time_get_current 'transport_lastvalidtime' + fi + line=${line//$'\r'/} +} + +# Send a line +# Parameters +# $* send this +# Return code not checked. +transport_write_line() { + kill -0 "$transport_pid" >/dev/null 2>&1 && echo "$*" >&3 +} |