// ===================================================
// Листинг 4. Сервер IPX
//
// Файл ipxserv.c
//
// (C) A. Frolov, 1993
// ===================================================

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <mem.h>
#include <string.h>
#include "ipx.h"

#define BUFFER_SIZE 512

void main(void) {

// Используем сокет 0x4567

	static unsigned Socket = 0x4567;

// Этот ECB мы будем использовать и для приема
// пакетов, и для их передачи.

	struct ECB RxECB;

// Заголовки принимаемых и передаваемых пакетов

	struct IPX_HEADER RxHeader, TxHeader;

// Буфера для принимаемых и передаваемых пакетов

	unsigned char RxBuffer[BUFFER_SIZE];
	unsigned char TxBuffer[BUFFER_SIZE];

	printf("\n*Сервер IPX*, (C) Фролов А., 1993\n\n");

// Проверяем наличие драйвера IPX и определяем
// адрес точки входа его API

	if(ipx_init() != 0xff) {
		printf("IPX не загружен!\n"); exit(-1);
	}

// Открываем сокет, на котором мы будем
// принимать пакеты

	if(IPXOpenSocket(SHORT_LIVED, &Socket)) {
		printf("Ошибка при открытии сокета\n");
		exit(-1);
	};

// Подготавливаем ECB для приема пакета

	memset(&RxECB, 0, sizeof(RxECB));
	RxECB.Socket            = IntSwap(Socket);
	RxECB.FragmentCnt       = 2;
	RxECB.Packet[0].Address = &RxHeader;
	RxECB.Packet[0].Size    = sizeof(RxHeader);
	RxECB.Packet[1].Address = RxBuffer;
	RxECB.Packet[1].Size    = BUFFER_SIZE;

	IPXListenForPacket(&RxECB);

	printf("Ожидание запроса от клиента\n");
	printf("Для отмены нажмите любую клавишу\n");

	while(RxECB.InUse) {
		IPXRelinquishControl();
		if(kbhit()) {
			getch();
			RxECB.CCode = 0xfe;
			break;
		}
	}
	if(RxECB.CCode == 0) {
		printf("Принят запрос от клиента '%s'\n", RxBuffer);
		printf("Для продолжения нажмите любую клавишу\n");
		getch();

// Подготавливаем ECB для передачи пакета
// Поле ImmAddress не заполняем, так как там
// уже находится адрес станции клиента.
// Это потому, что мы только что приняли от клиента
// пакет данных и при этом в ECB установился
// непосредственный адрес станции, которая
// отправила пакет

		RxECB.Socket            = IntSwap(Socket);
		RxECB.FragmentCnt       = 2;
		RxECB.Packet[0].Address = &TxHeader;
		RxECB.Packet[0].Size    = sizeof(TxHeader);
		RxECB.Packet[1].Address = TxBuffer;
		RxECB.Packet[1].Size    = BUFFER_SIZE;

// Подготавливаем заголовок пакета

		TxHeader.PacketType = 4;
		memset(TxHeader.DestNetwork, 0, 4);
		memcpy(TxHeader.DestNode, RxECB.ImmAddress, 6);
		TxHeader.DestSocket = IntSwap(Socket);

// Подготавливаем передаваемые данные

		strcpy(TxBuffer, "SERVER *DEMO*");

// Передаем пакет обратно клиенту

		IPXSendPacket(&RxECB);
	}

// Закрываем сокет

	IPXCloseSocket(&Socket);
	exit(0);
}