/* Socket status display code
 * Copyright 1991 Phil Karn, KA9Q
 */
#include "global.h"
#include "commands.h"
#ifdef MSDOS
#include "hardware.h"
#else
#include "mbuf.h"
#include "proc.h"
#endif
#include "lzw.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: sockcmd.c,v 1.16 1997/06/01 22:10:46 root Exp $";
#endif

/* Socket status display command */
int
dosock (argc, argv, p)
int argc;
char *argv[];
void *p OPTIONAL;
{
register struct usock *up;
int s,i;
struct sockaddr fsock;
char const *cp;

	if (argc < 2)	{
		tputs ("S#  Type    PCB       Remote socket        Owner\n");
		for (s = SOCKBASE; s < Nusock + SOCKBASE; s++)	{
			up = itop (s);
			if (up == NULLUSOCK)
				continue;

			i = sizeof (fsock);
			if (getpeername (s, (char *)&fsock, &i) == 0 && i != 0)
				cp = psocket (&fsock);
			else
				cp = "";

			tprintf ("%3d %-8s%-8.8lx %-22s%-8.8lx %-10s\n",
				s, Socktypes[(int)up->type], (uint32) up->cb.p,
				cp, (uint32) up->owner, up->owner->name);
		}
		return 0;
	}
	s = atoi (argv[1]);
	if (s < SOCKBASE || s >= Nusock + SOCKBASE)	{
		tputs ("Number out of range\n");
		return 1;
	}
	up = itop (s);
	if (up == NULLUSOCK){
		tputs ("Socket not in use\n");
		return 0;
	}
	tprintf ("%s %8.8lx %s", 
		Socktypes[(int)up->type], (uint32) up->cb.p,
		(up->flag == SOCK_ASCII) ? "ascii" : "binary");
	if (up->eol[0] != '\0')	{
		tputs (" eol seq:");
		for (i = 0; i < (int)sizeof(up->eol) && up->eol[i] != '\0'; i++)
			tprintf (" %02x", up->eol[i]);
	}
	tprintf ("  Since: %s", ctime (&up->created));
	if (up->cb.p == NULL)
		return 0;
	switch (up->type)	{
		case TYPE_RAW:
		case TYPE_LOCAL_DGRAM:
			tprintf ("Inqlen: %d packets\n", socklen (s, 0));
			tprintf ("Outqlen: %d packets\n", socklen (s, 1));
			break;
		case TYPE_LOCAL_STREAM:
			tprintf ("Inqlen: %d bytes\n", socklen (s, 0));
			tprintf ("Outqlen: %d bytes\n", socklen (s, 1));
			break;
		case TYPE_TCP:
			st_tcp (up->cb.tcb);
			break;
		case TYPE_UDP:
			(void) st_udp (up->cb.udp, 0);
			break;
#ifdef	AX25
		case TYPE_AX25I:
			st_ax25 (up->cb.ax25);
			break;
#endif
#ifdef	NETROM
		case TYPE_NETROML4:
			donrdump (up->cb.nr4);
			break;
#endif
		default:
			break;
	}
#ifdef LZW
	if (up->zout != NULLLZW)
		tprintf ("Compressed %ld bytes. (%s mode - %d/%-d)\n",up->zout->cnt, up->zout->mode ? "fast" : "compact", up->zout->codebits, up->zout->maxbits);
	if (up->zin != NULLLZW)
		tprintf ("Decompressed %ld bytes. (%s mode - %d/%-d)\n",up->zin->cnt, up->zin->mode ? "fast" : "compact", up->zin->codebits, up->zin->maxbits);
#endif
	return 0;
}


/* Kick the session related to a particular socket
 * this is easier then the tcp kick, ax25 kick, etc... commands
 * 920117 - WG7J
 */
int
dokicksocket(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
register struct usock *up;
int s;				/*socket to kick*/
int retval = 0;

	s = atoi (argv[1]);
	if (s < SOCKBASE || s >= Nusock + SOCKBASE)	{
		tputs ("Number out of range\n");
		return 1;
	}
	up = itop (s);
	if (up == NULLUSOCK) {
		tputs ("Socket not in use\n");
		return 0;
	}
	if(up->type == TYPE_TCP)
		retval = kick_tcp (up->cb.tcb);
#ifdef AX25
	if(up->type == TYPE_AX25I)
		retval = kick_ax25 (up->cb.ax25);
#endif
#ifdef NETROM
	if(up->type == TYPE_NETROML4)
		retval = kick_nr4 (up->cb.nr4);
#endif
	if(retval == -1)
		tputs ("Kick not successfull\n");
	return 0;
}


/* Reset (kill) the specified
 */

int
doresetsocket(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
register struct usock *up;
int s;				/*socket to kick*/

	s = atoi (argv[1]);
	if (s < SOCKBASE || s >= Nusock + SOCKBASE)	{
		tputs ("Number out of range\n");
		return 1;
	}
	up = itop (s);
	if (up == NULLUSOCK) {
		tputs ("Socket not in use\n");
		return 0;
	}
	if(up->cb.p == NULLCHAR)
		close_s (s);
	else
		(void) shutdown (s, 2);
	return 0;
}



