;;; liece-tcp.el --- TCP/IP stream emulation.
;; Copyright (C) 1998-2000 Daiki Ueno

;; Author: Masanobu Umeda <umerin@mse.kyutech.ac.jp>
;;         Daiki Ueno <ueno@unixuser.org>
;; Created: 1999-03-16 renamed from tcp.el
;; Keywords: IRC, liece

;; This file is part of Liece.

;; 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 2, 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 GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Commentary:

;; Notes on TCP package:
;;
;; This package provides a TCP/IP stream emulation for GNU Emacs. If
;; the function `open-network-stream' is not defined in Emacs, but
;; your operating system has a capability of network stream
;; connection, this tcp package can be used for communicating with
;; NNTP server.
;;
;; The tcp package runs inferior process which actually does the role
;; of `open-network-stream'.  The program `tcp' provided with this
;; package can be used for such purpose.  Before loading the package,
;; compile `tcp.c' and install it as `tcp' in a directory in the emacs
;; search path. If you modify `tcp.c', please send diffs to the author
;; of GNUS.  I'll include some of them in the next releases.

;;; Code:

(require 'poe)
(require 'poem)

(eval-when-compile
  (require 'liece-compat)
  (require 'liece-globals))

(defgroup liece-tcp nil
  "TCP/IP Emulation"
  :tag "TCP"
  :prefix "liece-"
  :group 'liece-server)

(defcustom liece-tcp-program "ltcp"
  "The name of the program emulating `open-network-stream' function."
  :type 'file
  :group 'liece-tcp)

(defcustom liece-tcp-default-connection-type 'network
  "TCP/IP Connection type."
  :type '(choice
	  (const :tag "Network" network)
	  (const :tag "Program" program)
	  (const :tag "SSLeay" ssl)
	  (const :tag "rlogin" rlogin))
  :group 'liece-tcp)

(defvar liece-tcp-connection-type liece-tcp-default-connection-type)

(eval-and-compile
  (autoload 'open-ssl-stream "ssl")
  (defvar ssl-program-arguments))

(defcustom liece-tcp-ssl-protocol-version "3"
  "SSL protocol version."
  :type 'integer
  :group 'liece-tcp)

(defcustom liece-tcp-ssl-default-service 993
  "Default SSL service."
  :type 'liece-service-spec
  :group 'liece-tcp)

(defcustom liece-tcp-rlogin-program "rsh"
  "Program used to log in on remote machines.
The default is \"rsh\", but \"ssh\" is a popular alternative."
  :type 'file
  :group 'liece-tcp)

(defcustom liece-tcp-relay-host "localhost"
  "Remote host address."
  :type 'file
  :group 'liece-tcp)

(defcustom liece-tcp-rlogin-parameters '("socket" "-q")
  "Parameters to `liece-tcp-open-rlogin'."
  :type 'list
  :group 'liece-tcp)

(defcustom liece-tcp-rlogin-user-name nil
  "User name on remote system when using the rlogin connect method."
  :type 'string
  :group 'liece-tcp)

(defvar liece-tcp-stream-alist
  '((network open-network-stream)
    (program liece-tcp-open-program-stream)
    (ssl liece-tcp-open-ssl-stream)
    (rlogin liece-tcp-open-rlogin-stream)))


;;;###liece-autoload
(defun liece-open-network-stream (name buffer host service)
  (let ((method
	 (nth 1 (assq liece-tcp-connection-type
		      liece-tcp-stream-alist))))
    (or method
	(error "Invalid stream"))
    (funcall method name buffer host service)))

(defun liece-tcp-open-program-stream (name buffer host service)
  "Open a TCP connection for a service to a host.
Returns a subprocess-object to represent the connection.
Input and output work as for subprocesses; `delete-process' closes it.
Args are NAME BUFFER HOST SERVICE.
NAME is name for process.  It is modified if necessary to make it unique.
BUFFER is the buffer (or `buffer-name') to associate with the process.
 Process output goes at end of that buffer, unless you specify
 an output stream or filter function to handle the output.
 BUFFER may be also nil, meaning that this process is not associated
 with any buffer
Third arg is name of the host to connect to.
Fourth arg SERVICE is name of the service desired, or an integer
 specifying a service number to connect to."
  (let ((proc (start-process name buffer
			     liece-tcp-program
			     host
			     (if (stringp service)
				 service
			       (int-to-string service)))))
    (process-kill-without-query proc)
    ;; Return process
    proc))

(defun liece-tcp-open-ssl-stream-1 (name buffer server service extra-arg)
  (let* ((service (or service liece-tcp-ssl-default-service))
         (ssl-program-arguments (list extra-arg "-connect"
                                      (format "%s:%d" server service)))
         (process (open-ssl-stream name buffer server service)))
    (and process (memq (process-status process) '(open run))
	 process)))

(defun liece-tcp-open-ssl-stream (name buffer server service)
  (if (string-equal liece-tcp-ssl-protocol-version "2")
      (liece-tcp-open-ssl-stream-1
       name buffer server service "-ssl2")
    (or (liece-tcp-open-ssl-stream-1
	 name buffer server service "-ssl3")
	(liece-tcp-open-ssl-stream-1
	 name buffer server service "-ssl2"))))

(defun liece-tcp-open-rlogin-stream (name buffer server service)
  "Open a connection to SERVER using rsh."
  (let* ((service (if (stringp service)
		      service
		    (int-to-string service)))
	 (args `(,liece-tcp-rlogin-program
		 ,@(if liece-tcp-rlogin-user-name
		       (list "-l" liece-tcp-rlogin-user-name))
		 ,liece-tcp-relay-host
		 ,@liece-tcp-rlogin-parameters ,server ,service))
	 (process-connection-type nil))
    (apply #'start-process-shell-command name buffer args)))

(provide 'liece-tcp)

;;; liece-tcp.el ends here
