Протокол SPX и использование драйвера Novell Netware
Добавлено: Вс мар 30, 2025 8:24 am
Hello, world!
Ранее я описал протокол IPX, использование драйвера Novell Netware для работы с протоколом IPX. В этой статье опишу протокол SPX и опишу функции драйвера для работы с ним, также напишу простую систему клиент - сервер на языке ассемблера.
SPX является протоколом сеансового уровня и также "надстройкой" для протокола IPX. Для передачи данных необходимо сначала создать канал связи, а затем уже передавать данные, канал связи даёт гарантию того, что данные дойдут до адресата, в отличии от датаграмм.
Структура пакета SPX
Структура пакета SPX схожа со структурой пакета IPX, но имеет дополнительные поля (см. картинку):
Поля ConnControl и DataStreamType можно рассматривать числа, обозначающие состояние передачи данных:
1. ConnControl:
01h-08h Зарезервировано
10h End-of-Message. Этот бит может использоваться программой для сигнализации окончания передачи данных.
Драйвер SPX передает этот бит программе в неизменном виде, причем сам драйвер протокола SPX этот бит
игнорирует
20h Attention. Этот бит игнорируется драйвером SPX и передается в неизменном виде программе
40h Acknowledgement Required. Бит используется драйвером SPX. Вам не следует модифицировать его значение
80h System Packet. Этот бит устанавливается драйвером SPX при передаче системных пакетов, которые
используются самим драйвером и не передаются в программу пользователя
2. DataStreamType:
00h-FDh Эти значения игнорируются драйвером SPX и могут быть использованы программой произвольным образом
FEh End-of-Connection. Когда программа вызывает функцию, закрывающую SPX-канал, драйвер SPX посылает
партнеру по связи последний пакет, в поле DataStreamType которого записано значение FEh. Это служит
требованием завершить связь и закрыть канал
FFh End-of-Connection-Acknowledgement. Это значение отмечает пакет, подтверждающий завершение связи. Такой
пакет является системным и не передается в программу пользователя
Поле SourceConnID содержит номер канала связи, присвоенный драйвером SPX.
Поле SeqNumber содержит количество пакетов, переданных по каналу связи.
Поле AckNumber содержит номер следующего пакета.
Поле AllocNumber содержит количество областей памяти, выделенных для приема пакетов.
Использование драйвера IPX/SPX
В статье про использование драйвера IPX упоминалась структура ECB (event control block), для использования драйвера SPX используется точно такая же структура.
Т.к. драйвер у Novell Netware служит для использования протоколов IPX/SPX, то и использование драйвера для передачи данных по протоколу SPX абсолютно такое же, отличается лишь логическая часть, я расскажу об этом ниже.
Описание функций SPX
SPXCheckInstallation
На входе:
BX = 10h
AL = 00h
На выходе:
AL = Код завершения:
00h - SPX не установлен;
FFh - SPX установлен.
BH = Верхний номер версии SPX.
BL = Нижний номер версии SPX.
CX = Максимальное количество каналов SPX, поддерживаемых драйвером SPX.
DX = Количество доступных каналов SPX.
SPXListenForConnection
На входе:
BX = 12h.
AL = Счетчик повторов попыток создать канал связи.
AH = Флаг включения системы периодической проверки связи.
ES:SI = Адрес блока ECB.
Эта функция используется для создания канала связи, ожидает пакета от функции SPXEstablishConnection.
Программа-сервер вызывает SPXListenForConnection, передавая ей адрес блока ECB. Этот блок будет использован для образования канала связи.
В блоке ECB необходимо определить значение поля ESRAddress и указать номер сокета. Для каждого сокета можно создать несколько каналов.
После образования канала связи, когда в поле InUse будет записано нулевое значение, поле CCode блока ECB будет содержать код завершения:
00 канал связи создан, ошибок нет;
FFh указанный в ECB сокет не был открыт;
FCh запрос SPXListenForConnection был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
EFh переполнилась внутренняя таблица номеров каналов связи; до тех пор, пока какой-нибудь канал не будет закрыт, вы не сможете образовать новые каналы.
SPXEstablishConnection
На входе:
BX = 11h.
AL = Счетчик повторов попыток создать канал связи.
AH = Флаг включения системы периодической проверки связи.
ES:SI = Адрес блока ECB.
На выходе:
AL = Промежуточный код завершения:
00h - выполняется попытка создать канал;
FFh - указанный в блоке ECB сокет закрыт;
FDh - сбойный пакет: либо счетчик фрагментов не равен 1, либо размер фрагмента не равен 42;
EFh - переполнение локальной таблицы номеров каналов связи.
DX = Присвоенный номер канала.
Функция устанавливает канал связи с программой, вызвавшей функцию SPXListenForConnection.
Для функции необходимо подготовить блок ECB и пакет в формате SPX, состоящий из одного заголовка. В блоке ECB необходимо заполнить поля ESRAddress, Socket, счетчик количества фрагментов (нужен один фрагмент) и указатель на фрагмент размером 42 байта. В заголовке SPX-пакета необходимо заполнить поля DestNetwork, DestNode, DestSocket.
Кроме того, перед вызовом функции SPXListenForConnection программа должна выделить хотя бы один ECB для приема SPX-пакета. Это нужно сделать при помощи функции SPXListenForSequencedPacket
Если по каким-либо причинам канал создать не удалось, в поле CCode будет записан код ошибки:
00h канал связи создан, ошибок нет;
FCh запрос SPXListenForConnection был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
FDh сбойный пакет: либо счетчик фрагментов не равен единице, либо размер фрагмента не равен 42;
FFh указанный в ECB сокет не был открыт;
EFh переполнилась внутренняя таблица номеров каналов связи; до тех пор, пока какой-нибудь канал не будет закрыт, вы не сможете образовать новые каналы;
EDh адресат не отвечает или сообщает, что он не может создать канал; этот код может возникнуть либо как результат неисправности сетевого аппаратного обеспечения, либо если функция SPXEstablishConnection была отменена при помощи функции SPXAbortConnection.
SPXListenForSequencedPacket
На входе:
BX = 17h
ES:SI = Адрес блока ECB.
Функция обеспечивает прием пакетов средствами протокола SPX.Функция обеспечивает прием пакетов средствами протокола SPX. Используемый блок ECB ставится в очередь на приём, а функция возвращает управление вашей программе.
Перед вызовом функции необходимо заполнить в структуре ECB поля ESRAddress, Socket, счетчик фрагментов и адреса и размеры фрагментов. Необходимо также открыть используемый сокет при помощи функции IPXOpenSocket.
После того как пакет будет принят, в поле InUse блока ECB устанавливается нулевое значение, а в поле CCode - код завершения:
00h пакет принят без ошибок;
FCh запрос SPXListenForSequencedPacket был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
FDh переполнение пакета - принятый пакет имеет длину, которая превосходит размер буферов, указанных в дескрипторах фрагментов;
EDh система периодической проверки связи обнаружила разрыв канала, номер разрушенного канала записан в первых двух байтах поля IPXWorkspace блока ECB;
FFh указанный в ECB сокет не был открыт.
SPXSendSequencedPacket
На входе:
BX = 16h
ES:SI = Адрес блока ECB.
DX = Номер канала связи.
Перед вызовом функции программа должна заполнить поле ESRAddress, счетчик фрагментов и адреса и размеры фрагментов блока ECB, а также бит End-Of-Message в поле ConnControl и поле DataStreamType в заголовке передаваемого пакета.
Если партнер не успевает принимать передаваемые пакеты, они ставятся в очередь на передачу, чем обеспечивается правильная последовательность доставки пакетов.
После завершения передачи пакета поле InUse блока ECB имеет нулевое значение. Если определена программа ESR, она вызывается. В поле CCode находится код завершения:
00h пакет был передан и успешно принят партнером;
FCh указанный в ECB сокет был закрыт, программа ESR не вызывается;
FDh сбойный пакет: либо счетчик фрагментов равен нулю, либо размер первого фрагмента меньше 42 байт, либо размер всего пакета больше 576 байт;
EEh неправильное значение в регистре DX;
EDh либо система периодической проверки связи обнаружила разрыв канала, либо канал был уничтожен функцией SPXAbortConnection (номер разрушенного канала записан в первых двух байтах поля IPXWorkspace блока ECB);
ECh удаленный партнер закрыл канал без подтверждения приема этого пакета, при этом SPX не может гарантировать, что переданный пакет был успешно принят партнером перед тем, как канал был закрыт.
Простая система клиент - сервер
Алгоритм:
Определяем наличие драйвера IPX и SPX, аналогично серверу IPX из предыдущей статьи. Затем открывается сокет для протокола IPX, подготавливается ECB для приема пакета от клиента (да, сначала надо обменяться пакетами по протоколу IPX, чтобы знать сетевые адреса клиента и сервера!). Программа сервер ожидает широковещательного пакета от клиента, клиент посылает широковещательный пакет.
После того, как сервер примет пакет, он копирует адрес клиента из поля ImmAddress структуры ECB и отправляет ответный IPX пакет клиенту, затем клиент копирует адрес сервера из поля ImmAddress структуры ECB, теперь клиент и сервер знают адреса друг друга.
После этого сервер и клиент открывают ещё один сокет, который будет использоваться для протокола SPX (для протокола SPX и IPX необходимо выделять разные сокеты).
Когда сервер и клиент знают адреса друг друга, сокеты для работы с протоколами IPX и SPX открыты, сервер подготавливает структуру ECB для приема пакета SPX от клиента, заполняя необходимые поля, затем вызывается функция SPXListenForSequencedPacket.
Программа - сервер подготавливает ещё один блок ECB для создания канала и вызывает функцию SPXListenForConnection.
Программа - клиент подготавливает блок ECB для отправки запроса на создание канала и вызывает функцию SPXEstablishConnection.
После того, как канал создан, сервер и клиент завершают свою работу (не забываем закрывать сокеты, я использую короткоживущие сокеты).
Сервер:
Клиент:
Была использована версия компилятора MASM 6.11 в контексте операционной системы MS DOS 6.22, а также драйверы Novell Netware!
Спасибо за внимание!
С уважением, push0ret!
Ранее я описал протокол IPX, использование драйвера Novell Netware для работы с протоколом IPX. В этой статье опишу протокол SPX и опишу функции драйвера для работы с ним, также напишу простую систему клиент - сервер на языке ассемблера.
SPX является протоколом сеансового уровня и также "надстройкой" для протокола IPX. Для передачи данных необходимо сначала создать канал связи, а затем уже передавать данные, канал связи даёт гарантию того, что данные дойдут до адресата, в отличии от датаграмм.
Структура пакета SPX
Структура пакета SPX схожа со структурой пакета IPX, но имеет дополнительные поля (см. картинку):
Поля ConnControl и DataStreamType можно рассматривать числа, обозначающие состояние передачи данных:
1. ConnControl:
01h-08h Зарезервировано
10h End-of-Message. Этот бит может использоваться программой для сигнализации окончания передачи данных.
Драйвер SPX передает этот бит программе в неизменном виде, причем сам драйвер протокола SPX этот бит
игнорирует
20h Attention. Этот бит игнорируется драйвером SPX и передается в неизменном виде программе
40h Acknowledgement Required. Бит используется драйвером SPX. Вам не следует модифицировать его значение
80h System Packet. Этот бит устанавливается драйвером SPX при передаче системных пакетов, которые
используются самим драйвером и не передаются в программу пользователя
2. DataStreamType:
00h-FDh Эти значения игнорируются драйвером SPX и могут быть использованы программой произвольным образом
FEh End-of-Connection. Когда программа вызывает функцию, закрывающую SPX-канал, драйвер SPX посылает
партнеру по связи последний пакет, в поле DataStreamType которого записано значение FEh. Это служит
требованием завершить связь и закрыть канал
FFh End-of-Connection-Acknowledgement. Это значение отмечает пакет, подтверждающий завершение связи. Такой
пакет является системным и не передается в программу пользователя
Поле SourceConnID содержит номер канала связи, присвоенный драйвером SPX.
Поле SeqNumber содержит количество пакетов, переданных по каналу связи.
Поле AckNumber содержит номер следующего пакета.
Поле AllocNumber содержит количество областей памяти, выделенных для приема пакетов.
Использование драйвера IPX/SPX
В статье про использование драйвера IPX упоминалась структура ECB (event control block), для использования драйвера SPX используется точно такая же структура.
Т.к. драйвер у Novell Netware служит для использования протоколов IPX/SPX, то и использование драйвера для передачи данных по протоколу SPX абсолютно такое же, отличается лишь логическая часть, я расскажу об этом ниже.
Описание функций SPX
SPXCheckInstallation
На входе:
BX = 10h
AL = 00h
На выходе:
AL = Код завершения:
00h - SPX не установлен;
FFh - SPX установлен.
BH = Верхний номер версии SPX.
BL = Нижний номер версии SPX.
CX = Максимальное количество каналов SPX, поддерживаемых драйвером SPX.
DX = Количество доступных каналов SPX.
SPXListenForConnection
На входе:
BX = 12h.
AL = Счетчик повторов попыток создать канал связи.
AH = Флаг включения системы периодической проверки связи.
ES:SI = Адрес блока ECB.
Эта функция используется для создания канала связи, ожидает пакета от функции SPXEstablishConnection.
Программа-сервер вызывает SPXListenForConnection, передавая ей адрес блока ECB. Этот блок будет использован для образования канала связи.
В блоке ECB необходимо определить значение поля ESRAddress и указать номер сокета. Для каждого сокета можно создать несколько каналов.
После образования канала связи, когда в поле InUse будет записано нулевое значение, поле CCode блока ECB будет содержать код завершения:
00 канал связи создан, ошибок нет;
FFh указанный в ECB сокет не был открыт;
FCh запрос SPXListenForConnection был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
EFh переполнилась внутренняя таблица номеров каналов связи; до тех пор, пока какой-нибудь канал не будет закрыт, вы не сможете образовать новые каналы.
SPXEstablishConnection
На входе:
BX = 11h.
AL = Счетчик повторов попыток создать канал связи.
AH = Флаг включения системы периодической проверки связи.
ES:SI = Адрес блока ECB.
На выходе:
AL = Промежуточный код завершения:
00h - выполняется попытка создать канал;
FFh - указанный в блоке ECB сокет закрыт;
FDh - сбойный пакет: либо счетчик фрагментов не равен 1, либо размер фрагмента не равен 42;
EFh - переполнение локальной таблицы номеров каналов связи.
DX = Присвоенный номер канала.
Функция устанавливает канал связи с программой, вызвавшей функцию SPXListenForConnection.
Для функции необходимо подготовить блок ECB и пакет в формате SPX, состоящий из одного заголовка. В блоке ECB необходимо заполнить поля ESRAddress, Socket, счетчик количества фрагментов (нужен один фрагмент) и указатель на фрагмент размером 42 байта. В заголовке SPX-пакета необходимо заполнить поля DestNetwork, DestNode, DestSocket.
Кроме того, перед вызовом функции SPXListenForConnection программа должна выделить хотя бы один ECB для приема SPX-пакета. Это нужно сделать при помощи функции SPXListenForSequencedPacket
Если по каким-либо причинам канал создать не удалось, в поле CCode будет записан код ошибки:
00h канал связи создан, ошибок нет;
FCh запрос SPXListenForConnection был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
FDh сбойный пакет: либо счетчик фрагментов не равен единице, либо размер фрагмента не равен 42;
FFh указанный в ECB сокет не был открыт;
EFh переполнилась внутренняя таблица номеров каналов связи; до тех пор, пока какой-нибудь канал не будет закрыт, вы не сможете образовать новые каналы;
EDh адресат не отвечает или сообщает, что он не может создать канал; этот код может возникнуть либо как результат неисправности сетевого аппаратного обеспечения, либо если функция SPXEstablishConnection была отменена при помощи функции SPXAbortConnection.
SPXListenForSequencedPacket
На входе:
BX = 17h
ES:SI = Адрес блока ECB.
Функция обеспечивает прием пакетов средствами протокола SPX.Функция обеспечивает прием пакетов средствами протокола SPX. Используемый блок ECB ставится в очередь на приём, а функция возвращает управление вашей программе.
Перед вызовом функции необходимо заполнить в структуре ECB поля ESRAddress, Socket, счетчик фрагментов и адреса и размеры фрагментов. Необходимо также открыть используемый сокет при помощи функции IPXOpenSocket.
После того как пакет будет принят, в поле InUse блока ECB устанавливается нулевое значение, а в поле CCode - код завершения:
00h пакет принят без ошибок;
FCh запрос SPXListenForSequencedPacket был отменен функциями IPXCancelEvent или IPXCloseSocket (ESR не вызывается);
FDh переполнение пакета - принятый пакет имеет длину, которая превосходит размер буферов, указанных в дескрипторах фрагментов;
EDh система периодической проверки связи обнаружила разрыв канала, номер разрушенного канала записан в первых двух байтах поля IPXWorkspace блока ECB;
FFh указанный в ECB сокет не был открыт.
SPXSendSequencedPacket
На входе:
BX = 16h
ES:SI = Адрес блока ECB.
DX = Номер канала связи.
Перед вызовом функции программа должна заполнить поле ESRAddress, счетчик фрагментов и адреса и размеры фрагментов блока ECB, а также бит End-Of-Message в поле ConnControl и поле DataStreamType в заголовке передаваемого пакета.
Если партнер не успевает принимать передаваемые пакеты, они ставятся в очередь на передачу, чем обеспечивается правильная последовательность доставки пакетов.
После завершения передачи пакета поле InUse блока ECB имеет нулевое значение. Если определена программа ESR, она вызывается. В поле CCode находится код завершения:
00h пакет был передан и успешно принят партнером;
FCh указанный в ECB сокет был закрыт, программа ESR не вызывается;
FDh сбойный пакет: либо счетчик фрагментов равен нулю, либо размер первого фрагмента меньше 42 байт, либо размер всего пакета больше 576 байт;
EEh неправильное значение в регистре DX;
EDh либо система периодической проверки связи обнаружила разрыв канала, либо канал был уничтожен функцией SPXAbortConnection (номер разрушенного канала записан в первых двух байтах поля IPXWorkspace блока ECB);
ECh удаленный партнер закрыл канал без подтверждения приема этого пакета, при этом SPX не может гарантировать, что переданный пакет был успешно принят партнером перед тем, как канал был закрыт.
Простая система клиент - сервер
Алгоритм:
Определяем наличие драйвера IPX и SPX, аналогично серверу IPX из предыдущей статьи. Затем открывается сокет для протокола IPX, подготавливается ECB для приема пакета от клиента (да, сначала надо обменяться пакетами по протоколу IPX, чтобы знать сетевые адреса клиента и сервера!). Программа сервер ожидает широковещательного пакета от клиента, клиент посылает широковещательный пакет.
После того, как сервер примет пакет, он копирует адрес клиента из поля ImmAddress структуры ECB и отправляет ответный IPX пакет клиенту, затем клиент копирует адрес сервера из поля ImmAddress структуры ECB, теперь клиент и сервер знают адреса друг друга.
После этого сервер и клиент открывают ещё один сокет, который будет использоваться для протокола SPX (для протокола SPX и IPX необходимо выделять разные сокеты).
Когда сервер и клиент знают адреса друг друга, сокеты для работы с протоколами IPX и SPX открыты, сервер подготавливает структуру ECB для приема пакета SPX от клиента, заполняя необходимые поля, затем вызывается функция SPXListenForSequencedPacket.
Программа - сервер подготавливает ещё один блок ECB для создания канала и вызывает функцию SPXListenForConnection.
Программа - клиент подготавливает блок ECB для отправки запроса на создание канала и вызывает функцию SPXEstablishConnection.
После того, как канал создан, сервер и клиент завершают свою работу (не забываем закрывать сокеты, я использую короткоживущие сокеты).
Сервер:
Код: Выделить всё
.model tiny
.286
code segment
org 100h
start:
;Check IPX
pusha
mov ax, 7A00h
int 2Fh
cmp al, 0FFh
jnz exit_err_ipx
mov word ptr [ipx_entry], di
mov word ptr [ipx_entry+2], es
;Check SPX
mov bx, 10h
xor ax, ax
call dword ptr [ipx_entry]
cmp ax, 0FFh
jnz exit_err_spx
popa
;Open socket
pusha
xor bx, bx
xor al, al
mov dx, 4444h
call dword ptr [ipx_entry]
mov ecbrx.socket, dx
mov ecbtx.socket, dx
mov ipxtx.destsocket, dx
popa
;IPXListenForPacket
pusha
push cs
pop es
mov bx, 4d
mov ecbrx.fragmentcnt, 2d
mov ax, offset ipxrx
mov ecbrx.address1, ax
mov ecbrx.address1+2, es
mov ax, offset rxbuf
mov ecbrx.address2, ax
mov ecbrx.address2+2, es
xor ax, ax
mov si, offset ecbrx.link
call dword ptr [ipx_entry]
popa
wait_rx:
cmp ecbrx.inuse, 0FEh
jnz done_rx
pusha
mov bx, 0Ah
call dword ptr [ipx_entry]
popa
jmp wait_rx
done_rx:
mov ah, 9d
mov dx, offset donerx
int 21h
;Write ImmAdress
push cx
push si
push di
mov si, offset ecbrx.immaddress
mov di, offset ecbtx.immaddress
cld
mov cx, 6d
rep movsb
pop di
pop si
pop cx
;IPXSendPacket
push cs
pop es
pusha
mov bx, 3d
mov ecbtx.fragmentcnt, 2d
mov ipxtx.packettype, 4d
mov ax, offset ipxtx
mov ecbtx.address1, ax
mov ecbtx.address1+2, es
mov ax, offset txbuf
mov ecbtx.address2, ax
mov ecbtx.address2+2, ax
mov si, offset ecbtx.link
xor ax, ax
call dword ptr [ipx_entry]
popa
wait_tx:
cmp ecbtx.immaddress-7, 0FFh
jnz done_tx
pusha
mov bx, 0Ah
call dword ptr [ipx_entry]
popa
jmp wait_tx
done_tx:
mov ah, 9d
mov dx, offset donetx
int 21h
;SPX BLOCK
;Open socket
xor bx, bx
xor ax, ax
mov dx, 4545h
pusha
call dword ptr [ipx_entry]
mov spxsocket, dx
popa
;Ready ECB for receive packet
mov ax, spxsocket
mov ecbspx.socket, ax
mov ecbspx.fragmentcnt, 2d
mov ax, offset spxpack
mov ecbspx.address1, ax
mov ecbspx.address1+2, es
mov ax, offset rxbuf
mov ecbspx.address2, ax
mov ecbspx.address2+2, es
;Fill ImmAddress in ecbspx
mov si, offset ecbtx.immaddress
mov di, offset ecbspx.immaddress
mov cx, 6d
cld
rep movsb
;ListenForSequencedPacket
mov bx, 17h
mov si, offset ecbspx
call dword ptr [ipx_entry]
;Ready SPX header for waiting channel
mov spxconn.packettype, 5d
mov spxconn.transportctrl, 0
mov ax, spxsocket
mov spxconn.destsocket, ax
;Copy Immediate address in SPXconn
mov si, offset ecbspx.immaddress
mov di, offset spxconn.destnode
mov cx, 6d
rep movsb
;Ready ECB
mov ecbconn.socket, ax
mov ecbconn.fragmentcnt, 1d
mov ax, offset spxconn
mov ecbconn.address1, ax
mov ecbconn.address1+2, ax
;Wait request on making channel
mov bx, 12h
mov al, 0
mov ah, 0
mov si, offset ecbconn
pusha
call dword ptr [ipx_entry]
popa
wait_req:
cmp ecbconn.inuse, 0
jz done_ch
pusha
mov bx, 0Ah
call dword ptr [ipx_entry]
popa
jmp wait_req
done_ch:
mov ah, 9d
mov dx, offset doneconn
int 21h
jmp exit
exit_err_spx:
mov ah, 9d
mov dx, offset err_spx
int 21h
jmp exit
exit_err_ipx:
mov ah, 9d
mov dx, offset err_ipx
int 21h
exit:
push 0FFFEh
pop sp
mov ax, 4C00h
int 21h
err_ipx db 'IPX NOT LOADED', 0Ah, 0Dh, 24h
err_spx db 'SPX NOT LOADED', 0Ah, 0Dh, 24h
donetx db 'Packet Send!', 0Ah, 0Dh, 24h
donerx db 'Packet Received!', 0Ah, 0Dh, 24h
doneconn db 'SPX|Connected!', 0Ah, 0Dh, 24h
rxbuf db 512d dup(0)
txbuf db 'Client Demo', 500d dup(0)
mysocket dw ?
spxsocket dw ?
ipx_entry dw 2d dup(0)
IPXtx_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db 4d
DestNetwork db 4d dup(0)
DestNode db 6d dup(0FFh)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
IPXtx_ ends
ECBtx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0FFh)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof ipxtx
Address2 dw 2d dup(0)
Size_2 dw sizeof txbuf
ECBtx_ ends
IPXrx_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db ?
DestNetwork db 4d dup(0)
DestNode db 6d dup(0)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
IPXrx_ ends
ECBrx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof ipxrx
Address2 dw 2d dup(0)
Size_2 dw sizeof rxbuf
ECBrx_ ends
SPXCONN_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db 4d
DestNetwork db 4d dup(0)
DestNode db 6d dup(0FFh)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
ConnControl db ?
DataStrType db ?
SourceConnID dw ?
DestConnID dw ?
SeqNumber dw ?
AckNumber dw ?
AllocNumber dw ?
SPXCONN_ ends
ECBconn_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof spxconn
ECBconn_ ends
SPXpack_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db 4d
DestNetwork db 4d dup(0)
DestNode db 6d dup(0)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
ConnControl db ?
DataStrType db ?
SourceConnID dw ?
DestConnID dw ?
SeqNumber dw ?
AckNumber dw ?
AllocNumber dw ?
SPXpack_ ends
ECBspx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0FFh)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof spxpack
Address2 dw 2d dup(0)
Size_2 dw sizeof rxbuf
ECBspx_ ends
ecbtx ECBtx_ <>
ipxtx IPXtx_ <>
ecbrx ECBrx_ <>
ipxrx IPXrx_ <>
ecbconn ECBconn_ <>
ecbspx ECBspx_ <>
spxconn SPXconn_ <>
spxpack SPXpack_ <>
code ends
end start
Код: Выделить всё
.model tiny
.286
code segment
org 100h
start:
;Check IPX
pusha
mov ax, 7A00h
int 2Fh
cmp al, 0FFh
jnz exit_err_ipx
mov word ptr [ipx_entry], di
mov word ptr [ipx_entry+2], es
;Check SPX
mov bx, 10h
xor ax, ax
call dword ptr [ipx_entry]
cmp ax, 0FFh
jnz exit_err_spx
popa
;Open socket
pusha
xor bx, bx
mov al, 0FFh
mov dx, 4444h
call dword ptr [ipx_entry]
mov ecbtx.socket, dx
mov ecbrx.socket, dx
mov ipxtx.destsocket, dx
popa
;IPXSendPacket
push cs
pop es
pusha
mov bx, 3d
;mov ax, mysocket
;mov ecbtx.socket, ax
mov ecbtx.fragmentcnt, 2d
mov ipxtx.packettype, 4d
mov ax, offset ipxtx
mov ecbtx.address1, ax
mov ecbtx.address1+2, es
mov ax, offset txbuf
mov ecbtx.address2, ax
mov ecbtx.address2+2, ax
mov si, offset ecbtx.link
xor ax, ax
call dword ptr [ipx_entry]
popa
wait_tx:
cmp ecbtx.immaddress-7, 0FFh
jnz done_tx
pusha
mov bx, 0Ah
call dword ptr [ipx_entry]
popa
jmp wait_tx
done_tx:
cmp ecbtx.ccode, 0
mov ah, 9d
mov dx, offset donetx
int 21h
;IPXListenForPacket
pusha
push cs
pop es
mov bx, 4d
mov ecbrx.fragmentcnt, 2d
mov ax, offset ipxrx
mov ecbrx.address1, ax
mov ecbrx.address1+2, es
mov ax, offset rxbuf
mov ecbrx.address2, ax
mov ecbrx.address2+2, es
xor ax, ax
mov si, offset ecbrx.link
call dword ptr [ipx_entry]
popa
wait_rx:
cmp ecbrx.inuse, 0FEh
jnz done_rx
pusha
mov bx, 0Ah
call dword ptr [ipx_entry]
popa
jmp wait_rx
done_rx:
mov ah, 9d
mov dx, offset donerx
int 21h
;SPX block
;Copy server immediate address
push ds
pop es
mov si, offset ecbrx.immaddress
mov di, offset ecbspx.immaddress
mov cx, 6d
rep movsb
sub si, 6d
mov cx, 6d
mov di, offset spxconn.destnode
rep movsb
;Open socket
xor ax, ax
xor bx, bx
mov dx, 4545h
call dword ptr [ipx_entry]
mov ecbspx.socket, dx
mov spxconn.destsocket, dx
mov ecbconn.socket, dx
;SPXListenForSequencedPacket
mov ecbspx.fragmentcnt, 2d
mov ax, offset spxtx
mov ecbspx.address1, ax
mov ecbspx.address1+2, es
mov ax, offset rxbuf
mov ecbspx.address2, ax
mov ecbspx.address2+2, es
mov si, offset ecbspx
pusha
mov bx, 17h
call dword ptr [ipx_entry]
popa
;Ready SPX header
mov spxconn.packettype, 5d
mov spxconn.transportctrl, 0
;Ready ECB for connection
mov ecbconn.fragmentcnt, 1d
mov ax, offset spxconn
mov ecbconn.address1, ax
mov ecbconn.address1+2, es
;Connect
pusha
mov bx, 11h
xor ax, ax
mov si, offset ecbconn
call dword ptr [ipx_entry]
popa
wait_connect:
cmp ecbconn.inuse, 0
jz done_connect
pusha
mov bx, 10d
call dword ptr [ipx_entry]
popa
jmp wait_connect
done_connect:
mov ah, 9d
mov dx, offset doneconn
int 21h
jmp exit
exit_err_spx:
mov ah, 9d
mov dx, offset err_spx
int 21h
jmp exit
exit_err_ipx:
mov ah, 9d
mov dx, offset err_ipx
int 21h
exit:
push 0FFFEh
pop sp
mov ax, 4C00h
int 21h
err_ipx db 'IPX NOT LOADED', 0Ah, 0Dh, 24h
err_spx db 'SPX NOT LOADED', 0Ah, 0Dh, 24h
donetx db 'Packet Send!', 0Ah, 0Dh, 24h
donerx db 'Packet Received!', 0Ah, 0Dh, 24h
doneconn db 'Channel created!', 0Ah, 0Dh, 24h
rxbuf db 512d dup(0)
txbuf db 'Client Demo', 500d dup(0)
mysocket dw ?
ipx_entry dw 2d dup(0)
IPXtx_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db 4d
DestNetwork db 4d dup(0)
DestNode db 6d dup(0FFh)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
IPXtx_ ends
ECBtx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0FFh)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof ipxtx
Address2 dw 2d dup(0)
Size_2 dw sizeof txbuf
ECBtx_ ends
IPXrx_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db ?
DestNetwork db 4d dup(0)
DestNode db 6d dup(0)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
IPXrx_ ends
ECBrx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof ipxrx
Address2 dw 2d dup(0)
Size_2 dw sizeof rxbuf
ECBrx_ ends
ECBconn_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof spxconn
ECBconn_ ends
ECBspx_ struc
Link dw 2d dup(0)
ESRAddress dw 2d dup(0)
InUse db ?
CCode db ?
Socket dw ?
IPXWorkspace db 4d dup(0)
DRVWorkspace db 12d dup(0)
ImmAddress db 6d dup(0)
FragmentCnt dw ?
Address1 dw 2d dup(0)
Size_1 dw sizeof spxtx
Address2 dw 2d dup(0)
Size_2 dw sizeof rxbuf
ECBspx_ ends
SPXrx_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db ?
DestNetwork db 4d dup(0)
DestNode db 6d dup(0)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
ConnControl db ?
DataStrType db ?
SourceConnID dw ?
DestConnID dw ?
SeqNumber dw ?
AckNumber dw ?
AllocNumber dw ?
SPXrx_ ends
SPXconn_ struc
Checksum dw ?
Len dw ?
TransportCtrl db ?
PacketType db ?
DestNetwork db 4d dup(0)
DestNode db 6d dup(0)
DestSocket dw ?
SourceNetwork db 4d dup(0)
SourceNode db 6d dup(0)
SourceSocket dw ?
ConnControl db ?
DataStrType db ?
SourceConnID dw ?
DestConnID dw ?
SeqNumber dw ?
AckNumber dw ?
AllocNumber dw ?
SPXconn_ ends
ecbtx ECBtx_ <>
ipxtx IPXtx_ <>
ecbrx ECBrx_ <>
ipxrx IPXrx_ <>
ecbspx ECBspx_ <>
ecbconn ECBconn_ <>
spxtx SPXrx_ <>
spxconn SPXconn_ <>
code ends
end start
Спасибо за внимание!
С уважением, push0ret!