/*  esecannaserver --- pseudo canna server that wraps another IME.
 *  Copyright (C) 1999-2000 Yasuhiro Take
 *
 *  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 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>

#include "constdef.h"
#include "def.h"
#include "vje.h"
#include "misc.h"

vje_request_t vjereq;
int vjeerror = 0;
static struct sockaddr_un unaddr;
static int vjefd;

#define CLEAR_VJEBUF() memset(vjereq.byte, 0, SELECT_LEN)

/* ------------------- vjesocket.c から merge --------------------------*/

/*
 * vje_socket_connect_unix : vjed に AF_UNIX で接続する
 *                         : ファイルディスクリプタを返す
 */

int vje_socket_connect_unix()
{
  if ((vjefd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    return -1;

  unaddr.sun_family = AF_UNIX;
  strcpy(unaddr.sun_path, VJE_UNIX_DOMAIN_PATH);

  if (connect(vjefd, (struct sockaddr *)(&unaddr), sizeof unaddr)) {
    m_msg("Connection to VJE refused.\n");
    close (vjefd);
    return -1;
  }
  
  return 0;
}

/*
 * vje_socket_close_connection: 接続を切る
 */

int vje_socket_close_connection()
{
  if (vjefd >= 0) {
    return close(vjefd);
    vjefd = -1;
  }
  
  return -1;
}

/* ---------------------- vjeproto.c オリジナル --------------------------*/

static int vje_proto_send_request(short proto_no)
{
  int size;
  
  switch (proto_no) {
    case 6: case 8: case 17: case 63: size = SELECT_LEN; break;
    default:                          size = FRAME_LEN;
  }

  vjereq.s_any.funcno = proto_no;

  if (m_socket_write(vjefd, vjereq.byte, size) < 0) {
    m_msg("in vje_prot_send_request: cannot send. Req#=%d\n", proto_no);
    return -1;
  }

  return 0;
}

static int vje_proto_recv_request(short proto_no)
{
  int size;
  
  switch (proto_no) {
    case 6: case 8: case 17: case 63: size = SELECT_LEN; break;
    default:                          size = FRAME_LEN;
  }

  if (m_socket_read(vjefd, vjereq.byte, size) < 0) {
    m_msg("in vje_prot_recv_request: cannot receive. Req#=%d\n", proto_no);
    return -1;
  }
  
  return 0;
}

static int vje_proto_sendrecv_request(short proto_no)
{
  if (vjeerror == TRUE)
    return -1;
  else {
    if (vje_proto_send_request(proto_no) != 0) {
      vjeerror = TRUE;
      return -1;
    }

    if (vje_proto_recv_request(proto_no) != 0) {
      vjeerror = TRUE;
      return -1;
    }
    
    return 0;
  }
}

void vje_proto_clear(short vje_id)
{
  CLEAR_VJEBUF();

  vjereq.s_any.vje_id = vje_id;

  vje_proto_sendrecv_request(1);
}

void vje_proto_setmode(short vje_id, short cnvmode1, short cnvmode2,
		       short rank, short loop_cnt)
{
  CLEAR_VJEBUF();

  vjereq.s_setmode.vje_id = vje_id;
  vjereq.s_setmode.cnvmode1 = cnvmode1;
  vjereq.s_setmode.cnvmode2 = cnvmode2;
  vjereq.s_setmode.rank = rank;
  vjereq.s_setmode.loopcnt = loop_cnt;

  vje_proto_sendrecv_request(4);
}

int vje_proto_sensemode(short vje_id, short *cnvmode1, short *cnvmode2,
			short *rank, short *loop_cnt)
{
  CLEAR_VJEBUF();

  vjereq.s_any.vje_id = vje_id;
  
  if (vje_proto_sendrecv_request(5) != 0)
    return -1;

  *cnvmode1 = vjereq.r_sensemode.cnvmode1;
  *cnvmode2 = vjereq.r_sensemode.cnvmode2;
  *rank = vjereq.r_sensemode.rank;
  *loop_cnt = vjereq.r_sensemode.loopcnt;

  m_msg_dbg("sensemode = %x %x %d %d\n", vjereq.r_sensemode.cnvmode1,
	    vjereq.r_sensemode.cnvmode2, vjereq.r_sensemode.rank,
	    vjereq.r_sensemode.loopcnt);

  return vjereq.r_sensemode.retvalue;
}

int vje_proto25_henkanb(short vje_id, uchar *in_buf, ushort *atr_buf,
			uchar *key_buf, short *mode, short cnvted)
{
  CLEAR_VJEBUF();

  vjereq.s_henkanb25.vje_id = vje_id;
  vjereq.s_henkanb25.mode = *mode;
  vjereq.s_henkanb25.cnvted = cnvted;
  memcpy(vjereq.s_henkanb25.in_buf, in_buf, IN_BUF_SIZE);
  memcpy(vjereq.s_henkanb25.atrbuf, atr_buf, IN_BUF_SIZE * 2);
  memcpy(vjereq.s_henkanb25.keybuf, key_buf, IN_BUF_SIZE);

  if (vje_proto_sendrecv_request(6) != 0)
    return -1;
  
  memcpy(in_buf, vjereq.r_henkanb25.in_buf, IN_BUF_SIZE);
  memcpy(atr_buf, vjereq.r_henkanb25.atrbuf, IN_BUF_SIZE * 2);
  memcpy(key_buf, vjereq.r_henkanb25.keybuf, IN_BUF_SIZE);

  return vjereq.r_henkanb25.retvalue;
}

int vje_proto_toku_henkan()
{
  return 0;
}

int vje_proto25_get_koho_all(short vje_id, buninf25_t *buninf, uchar *buf)
{
  CLEAR_VJEBUF();

  vjereq.s_get_koho_all25.vje_id = vje_id;
  /*
  memcpy(vjereq.s_get_koho_all.buninf, buninf, sizeof(buninf_t));
  memcpy(vjereq.s_get_koho_all.buf, buf, IN_BUF_SIZE);
  */
  
  LEN_OF_OLDBUF(vjereq.s_get_koho_all25.buf) = IN_BUF_SIZE;

  if (vje_proto_sendrecv_request(8) != 0)
    return -1;

  memcpy(buninf, vjereq.r_get_koho_all25.buninf, sizeof(buninf25_t));
  memcpy(buf, vjereq.r_get_koho_all25.buf, IN_BUF_SIZE);

  return vjereq.r_get_koho_all25.retvalue;
}

static int vje_proto_common(short vje_id, short func_no)
{
  CLEAR_VJEBUF();

  vjereq.s_any.vje_id = vje_id;

  if (vje_proto_sendrecv_request(func_no))
    return -1;
  return vjereq.r_any.retvalue;
}

int vje_proto_ji_bunsetu(short vje_id)
{
  int i;
  i = vje_proto_common(vje_id, 9);

  return i;
}

int vje_proto_zen_bunsetu(short vje_id)
{
  int i;
  i = vje_proto_common(vje_id, 10);

  return i;
}


void vje_proto_set_koho_bno(short vje_id, short bno)
{
  CLEAR_VJEBUF();

  vjereq.s_set_koho_bno.vje_id = vje_id;
  vjereq.s_set_koho_bno.bno = bno;

  vje_proto_sendrecv_request(11);
}

short vje_proto_get_koho_bno(short vje_id)
{
  return vje_proto_common(vje_id, 12);
}

/* vje_proto_ji_block() : 0..Failed */

short vje_proto_ji_block(short vje_id)
{
  int ret;
  ret = vje_proto_common(vje_id, 13);
  return ret;
}

/* vje_proto_zen_block() : 0..Failed 1..Success */

short vje_proto_zen_block(short vje_id)
{
  return vje_proto_common(vje_id, 14);
}

void vje_proto_set_koho(short vje_id, short p)
{
  CLEAR_VJEBUF();

  vjereq.s_set_koho.vje_id = vje_id;
  vjereq.s_set_koho.p = p;

  vje_proto_sendrecv_request(15);
}

void vje_proto_get_douon(short vje_id, doubufx_t *douon)
{
  CLEAR_VJEBUF();

  vjereq.s_get_douon.vje_id = vje_id;
  memcpy(vjereq.s_get_douon.doubufx, douon, sizeof(doubufx_t));

  if (vje_proto_sendrecv_request(17))
    return;
  
  memcpy(douon, vjereq.r_get_douon.doubufx, sizeof(doubufx_t));
}

short vje_proto25_saihenkan(short vje_id, uchar *in_buf, short nbun,
			    short len2, short len, short mode)
{
  CLEAR_VJEBUF();

  vjereq.s_saihenkan25.vje_id = vje_id;
  memcpy(vjereq.s_saihenkan25.in_buf, in_buf, IN_BUF_SIZE);
  vjereq.s_saihenkan25.nbun = nbun;
  vjereq.s_saihenkan25.len2 = len2;
  vjereq.s_saihenkan25.len = len;
  vjereq.s_saihenkan25.mode = mode;

  if (vje_proto_sendrecv_request(19))
    return -1;

  memcpy(in_buf, vjereq.r_saihenkan25.in_buf, IN_BUF_SIZE);

  return vjereq.r_saihenkan25.retvalue;
}
  
short vje_proto25_kakutei1(short vje_id, uchar *hira_buf, uchar *key_buf)
{
  CLEAR_VJEBUF();

  vjereq.s_kakutei1_25.vje_id = vje_id;
  memcpy(vjereq.s_kakutei1_25.hira_buf, hira_buf, HIRA_BUF_SIZE);
  memcpy(vjereq.s_kakutei1_25.key_buf, key_buf, KEY_BUF_SIZE);
  LEN_OF_OLDBUF(vjereq.s_kakutei1_25.key_buf) = KEY_BUF_SIZE;

  if (vje_proto_sendrecv_request(20))
    return -1;

  memcpy(hira_buf, vjereq.r_kakutei1_25.hira_buf, HIRA_BUF_SIZE);
  memcpy(key_buf, vjereq.r_kakutei1_25.key_buf, KEY_BUF_SIZE);

  return vjereq.r_kakutei1_25.retvalue;
}

short vje_proto25_kakutei2(short vje_id, uchar *hira_buf, uchar *key_buf)
{
  CLEAR_VJEBUF();

  vjereq.s_kakutei1_25.vje_id = vje_id;
  memcpy(vjereq.s_kakutei1_25.hira_buf, hira_buf, HIRA_BUF_SIZE);
  memcpy(vjereq.s_kakutei1_25.key_buf, key_buf, KEY_BUF_SIZE);
  LEN_OF_OLDBUF(vjereq.s_kakutei1_25.key_buf) = KEY_BUF_SIZE;

  if (vje_proto_sendrecv_request(62))
    return -1;

  memcpy(hira_buf, vjereq.r_kakutei1_25.hira_buf, HIRA_BUF_SIZE);
  memcpy(key_buf, vjereq.r_kakutei1_25.key_buf, KEY_BUF_SIZE);

  return vjereq.r_kakutei1_25.retvalue;
}

void vje_proto_finish_session()
{
  CLEAR_VJEBUF();

  vje_proto_sendrecv_request(32);
}

short vje_proto_vjelibopen()
{
  CLEAR_VJEBUF();

  if (vje_proto_sendrecv_request(45))
    return -1;

  return vjereq.r_any.retvalue;
}

short vje_proto_vjelibclose(short vje_id)
{
  CLEAR_VJEBUF();

  vjereq.s_any.vje_id = vje_id;

  vje_proto_sendrecv_request(46);

  return vjereq.r_any.retvalue;
}

short vje_proto_open_sdic(short vje_id, short dic_id, uchar *dicname,
			  short mode)
{
  CLEAR_VJEBUF();

  vjereq.s_open_sdic.vje_id = vje_id;
  vjereq.s_open_sdic.dic_id = dic_id;
  vjereq.s_open_sdic.mode = mode;
  /* Set string terminater */
  vjereq.s_open_sdic.dicname[DIC_NAME_SIZE - 1] = '\0';
  strncpy(vjereq.s_open_sdic.dicname, dicname, DIC_NAME_SIZE - 1);
  if (vje_proto_sendrecv_request(47))
    return -1;

  return vjereq.r_any.retvalue;
}

short vje_proto_close_sdic(short vje_id, short dic_id)
{
  CLEAR_VJEBUF();

  vjereq.s_close_sdic.vje_id = vje_id;
  vjereq.s_close_sdic.dic_id = dic_id;

  if (vje_proto_sendrecv_request(48))
    return -1;

  return vjereq.r_any.retvalue;
}

short vje_proto_chg_sdic(short vje_id, short dic_id)
{
  CLEAR_VJEBUF();

  vjereq.s_chg_sdic.vje_id = vje_id;
  vjereq.s_chg_sdic.dic_id = dic_id;

  if (vje_proto_sendrecv_request(57))
    return -1;

  return vjereq.r_any.retvalue;
}

void vje_proto_loadcoderange()
{
  CLEAR_VJEBUF();

  vje_proto_sendrecv_request(58);
}

int vje_proto_set_clienthostname(char *name)
{
  uchar hostname[128 + 2];
  int slen;

  CLEAR_VJEBUF();

  if ((slen = strlen(name)) > 128)
    slen = 128;

  memcpy(&(hostname[1]), name, slen);
  LEN_OF_OLDBUF(hostname) = slen;

  memcpy(vjereq.s_set_clienthostname.hostname, hostname, 128 + 2);

  if (vje_proto_sendrecv_request(60)) {
    m_msg_dbg("send recv error\n");
    return -1;
  }

  return vjereq.r_any.retvalue;
}

void vje_proto25_set_kihonbuff(short vje_id, uchar *in_buf, ushort *atrbuf,
			       uchar *keybuf)
{
  CLEAR_VJEBUF();

  vjereq.s_set_kihonbuff25.vje_id = vje_id;
  memcpy(vjereq.s_set_kihonbuff25.in_buf, in_buf, IN_BUF_SIZE);
  memcpy(vjereq.s_set_kihonbuff25.atrbuf, atrbuf, IN_BUF_SIZE * 2);
  memcpy(vjereq.s_set_kihonbuff25.keybuf, keybuf, IN_BUF_SIZE);

  vje_proto_sendrecv_request(63);
}
