Author Topic: IOCP - 64-bit IPv6 Echo Server Stress Test  (Read 254 times)

aw27

  • Member
  • ****
  • Posts: 851
  • Let's Make ASM Great Again!
IOCP - 64-bit IPv6 Echo Server Stress Test
« on: November 21, 2017, 02:02:28 AM »
Input Output Completion Port 64-bit IPv6 Client/Server.

Launch first the Server then the Client (you can launch more than 1 Client). Each Client will launch 64 connecting threads.
This is based on the  Windows 7 SDK IOCP sample.

Server:

Code: [Select]
;\masm32\bin\ml64  -c -Zp8 iocpServer.asm
;\masm32\bin\link /ENTRY:main /SUBSYSTEM:console /MACHINE:X64 iocpServer.obj
OPTION casemap:NONE

include iocpHelper.inc
.data
heapHandle HANDLE ?
SemaphoreObject HANDLE ?

.code

ServerWorkerThread proc CompletionPortID : PTR
LOCAL CompletionPort : HANDLE
LOCAL BytesTransferred : DWORD
LOCAL PerHandleData : LPPER_HANDLE_DATA
LOCAL PerIoData : LPPER_IO_OPERATION_DATA
LOCAL SendBytes : DWORD
LOCAL RecvBytes : DWORD
LOCAL Flags : DWORD

sub rsp, 38h ; maximum 7 parameters + shadow space
and rsp, -16

mov CompletionPort, rcx

@whileLoop:
mov rcx, CompletionPort
lea rdx, BytesTransferred
lea r8, PerHandleData
lea r9, PerIoData
mov DWORD PTR [rsp+20h], INFINITE
call GetQueuedCompletionStatus
cmp eax, 0
jnz @F
errMacro err11
@@:
cmp BytesTransferred, 0
jnz @F1
mov r8, PerHandleData
mov rcx, (PER_HANDLE_DATA PTR [r8]).Socket
call closesocket
cmp eax, SOCKET_ERROR
jnz @F
errMacro err12, 1
@@:
mov rcx, heapHandle
mov edx,0
mov r8, PerHandleData
call HeapFree
mov rcx, heapHandle
mov edx,0
mov r8, PerIoData
call HeapFree
jmp @whileLoop
@F1:
mov r10, PerIoData
cmp (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV,0
jnz @F
mov eax, BytesTransferred
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV, eax
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND,0
jmp @F2
@@:
mov eax, BytesTransferred
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND, eax
@F2:
mov eax, (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV
cmp eax, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
jbe @F3
mov r10, PerIoData
lea rdi, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov al, 0
mov rcx,  sizeof OVERLAPPED
cld
rep stosb
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
add rax, rcx
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax

mov ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV
sub ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, ecx
mov r11, PerHandleData
mov rcx, (PER_HANDLE_DATA PTR [r11]).Socket
lea rdx, (PER_IO_OPERATION_DATA PTR [r10]).DataBuf
mov r8, 1
lea r9, SendBytes
mov DWORD PTR [rsp+20h], 0
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov [rsp+28h], rax
mov QWORD PTR [rsp+30h],0
call WSASend
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
errMacro err13, 1
@@:
jmp @whileLoop
@F3:
mov r10, PerIoData
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV, 0
mov Flags,0
lea rdi, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov al, 0
mov rcx,  sizeof OVERLAPPED
cld
rep stosb
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, DATA_BUFSIZE
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax

mov r11, PerHandleData
mov rcx, (PER_HANDLE_DATA PTR [r11]).Socket
lea rdx, (PER_IO_OPERATION_DATA PTR [r10]).DataBuf
mov r8, 1
lea r9, RecvBytes
lea rax, Flags
mov [rsp+20h], rax
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov [rsp+28h], rax
mov QWORD PTR [rsp+30h],0
call WSARecv
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
errMacro err9, 1
@@:
jmp @whileLoop
@exit1:
mov rcx, 0
call ExitThread
ServerWorkerThread endp

main proc uses rdi r12
LOCAL wsadata:WSADATA
LOCAL CompletionPort : HANDLE
LOCAL SystemInfo : SYSTEM_INFO
LOCAL ThreadId : DWORD
LOCAL Listen : SOCKET
LOCAL Accept : SOCKET
LOCAL InternetAddr : SOCKADDR_IN6
LOCAL PerHandleData : LPPER_HANDLE_DATA
LOCAL PerIoData : LPPER_IO_OPERATION_DATA
LOCAL RecvBytes : DWORD
LOCAL Flags : DWORD


sub rsp, 38h ; maximum 7 parameters + shadow space
and rsp, -16

mov cx, 202h
lea rdx, wsadata
call WSAStartup
cmp eax,0
jz @F
lea rcx, err1
mov edx, eax
call printf
jmp @exit2
@@:
mov rcx, NULL
mov edx, 1
mov r8d, 1
mov r9, NULL

call CreateSemaphoreA
cmp rax, 0
jnz @F
errMacro err21
@@:
mov SemaphoreObject, rax

mov rcx, INVALID_HANDLE_VALUE
mov rdx, NULL
mov r8, 0
mov r9, 0
call CreateIoCompletionPort
cmp rax, 0
jnz @F
errMacro err2
@@:
mov CompletionPort, rax

lea rcx, SystemInfo
call GetSystemInfo

lea rax, SystemInfo
mov r12d, (SYSTEM_INFO PTR [rax]).dwNumberOfProcessors
shl r12d, 1

mov ebx, 0
@loop1start:
cmp ebx, r12d
jae @loop1exit
mov rcx,NULL
mov rdx,0
lea r8, ServerWorkerThread
mov r9, CompletionPort
mov dword ptr [rsp+20h], 0
lea rax, ThreadId
mov [rsp+28h], rax
call CreateThread
cmp rax, 0
jnz @F
errMacro err3
@@:
mov rcx, rax
call CloseHandle
inc ebx
jmp @loop1start
@loop1exit:

mov rcx, AF_INET6
mov rdx, SOCK_STREAM
mov r8, 0
mov r9, NULL
mov DWORD PTR [rsp+20h], 0
mov DWORD PTR [rsp+28h], WSA_FLAG_OVERLAPPED
call WSASocketA
cmp rax, INVALID_HANDLE_VALUE ;INVALID_SOCKET
jnz @F
errMacro err4, 1
@@:
mov Listen, rax
lea rdi, InternetAddr
mov al,0
mov rcx, sizeof InternetAddr
cld
rep stosb

mov InternetAddr.sin6_family, AF_INET6
mov cx, PORT
call htons
mov InternetAddr.sin6_port, ax
; no need to fill in6addr_any because InternetAddr.sin6_addr already filled with zeros
mov rcx, Listen
lea rdx, InternetAddr
mov r8d, sizeof InternetAddr
call bind
cmp eax, SOCKET_ERROR
jnz @F
errMacro err5, 1
@@:
mov rcx, Listen
mov edx, SOMAXCONN
call listen
cmp eax, SOCKET_ERROR
jnz @F
errMacro err6, 1
@@:
call GetProcessHeap
cmp rax, 0
jnz @F
errMacro err10
@@:
mov heapHandle, rax

@loop2start:
mov rcx, Listen
mov rdx, NULL
mov r8, NULL
mov r9, NULL
mov dword ptr [rsp+20h], 0
call WSAAccept
cmp eax, SOCKET_ERROR
jnz @F
errMacro err7, 1
@@:
mov Accept, rax
mov rcx, heapHandle
mov edx, HEAP_ZERO_MEMORY
mov r8, sizeof PER_HANDLE_DATA
call HeapAlloc
cmp rax,0
jnz @F
errMacro err8
@@:
mov PerHandleData, rax
lea rcx, msg2
mov rdx, Accept
call printf

mov r8, PerHandleData
mov rax, Accept
mov (PER_HANDLE_DATA PTR [r8]).Socket, rax

mov rcx, Accept
mov rdx, CompletionPort
mov r8, PerHandleData
mov r9,0
call CreateIoCompletionPort
cmp rax, 0
jnz @F
errMacro err2
@@:
mov rcx, heapHandle
mov edx, HEAP_ZERO_MEMORY
mov r8, sizeof PER_IO_OPERATION_DATA
call HeapAlloc

cmp rax,0
jnz @F
errMacro err8
@@:
mov PerIoData, rax

mov r10, PerIoData
lea rdi, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov al, 0
mov rcx,  sizeof OVERLAPPED
cld
rep stosb
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND,0
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV,0
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, DATA_BUFSIZE
lea r9, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, r9

mov Flags,0

mov rcx, Accept
lea rdx, (PER_IO_OPERATION_DATA PTR [r10]).DataBuf
mov r8, 1
lea r9, RecvBytes
lea rax, Flags
mov [rsp+20h], rax
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Overlapped
mov [rsp+28h], rax
mov QWORD PTR [rsp+30h],0
call WSARecv
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
errMacro err9, 1
@@:
jmp @loop2start

@exit1:
mov rcx, SemaphoreObject
call CloseHandle
call WSACleanup
@exit2:
mov ecx, 0
call ExitProcess
main endp

end

Client:

Code: [Select]
;\masm32\bin\ml64  -c -Zp8 iocpClient.asm
;\masm32\bin\link /ENTRY:main /SUBSYSTEM:console /MACHINE:X64 iocpClient.obj

OPTION casemap:NONE

include iocpHelper.inc

.data
g_ThreadInfo THREADINFO <>
g_hCleanupEvent WSAEVENT ?
g_Options OPTIONS <>
heapHandle HANDLE ?
SemaphoreObject HANDLE ?

.code

SendBuffer proc uses rdi r12 nThreadNum:sdword, outbuf:PTR
LOCAL nTotalSend : SDWORD
LOCAL bufp : PTR

sub rsp, 20h
and rsp, -16

mov nThreadNum, ecx
mov outbuf, rdx
mov bufp, rdx
mov nTotalSend,0

mov r12d, g_Options.nBufSize
@loopStart:
cmp r12d, nTotalSend
jbe @loopEnd
mov ecx, nThreadNum
lea rdi, g_ThreadInfo.sd
lea rdi, [rdi+rcx*sizeof SOCKET]
mov rcx, [rdi]
mov rdx, bufp
mov r8d, g_Options.nBufSize
sub r8d, nTotalSend
mov r9d, 0
call send
cmp eax, SOCKET_ERROR
jnz @F
errMacro err19,1
@@:
cmp eax, 0
jnz @F
msgPrint msg3, nThreadNum
jmp @exit1
@@:
add nTotalSend, eax
add bufp, rax
jmp @loopStart
@loopEnd:
mov eax, 1
ret
@exit1:
mov eax, 0
ret
SendBuffer endp

RecvBuffer proc uses rdi r12 nThreadNum:sdword, inbuf:PTR
LOCAL nTotalRecv : SDWORD
LOCAL bufp : PTR

sub rsp, 20h
and rsp, -16

mov nThreadNum, ecx
mov inbuf, rdx
mov bufp, rdx
mov nTotalRecv,0

mov r12d, g_Options.nBufSize
@loopStart:
cmp r12d, nTotalRecv
jbe @loopEnd
mov ecx, nThreadNum
lea rdi, g_ThreadInfo.sd
lea rdi, [rdi+rcx*sizeof SOCKET]
mov rcx, [rdi]
mov rdx, bufp
mov r8d, g_Options.nBufSize
sub r8d, nTotalRecv
mov r9d, 0
call recv
cmp eax, SOCKET_ERROR
jnz @F
errMacro err20,1
@@:
cmp eax, 0
jnz @F
msgPrint msg3, nThreadNum
jmp @exit1
@@:
add nTotalRecv, eax
add bufp, rax
jmp @loopStart
@loopEnd:
mov eax, 1
ret
@exit1:
mov eax, 0
ret
RecvBuffer endp

EchoThread proc uses rbx rsi rdi r12 lpParameter : PTR
LOCAL inbuf : PTR
LOCAL outbuf : PTR
LOCAL nThreadNum : SDWORD

sub rsp, 20h
and rsp, -16

mov lpParameter, rcx
mov inbuf,0
mov outbuf,0
mov eax, SDWORD PTR [rcx]
mov nThreadNum, eax

msgPrint msg1, nThreadNum

mov rcx, heapHandle
mov edx, HEAP_ZERO_MEMORY
mov r8d, g_Options.nBufSize
call HeapAlloc
cmp rax,0
jnz @F
errMacro err8
@@:
mov inbuf, rax
mov rcx, heapHandle
mov edx, HEAP_ZERO_MEMORY
mov r8d, g_Options.nBufSize
call HeapAlloc
cmp rax,0
jnz @F
errMacro err8
@@:
mov outbuf, rax

mov rdi, outbuf
mov al, BYTE PTR nThreadNum
mov ecx,  g_Options.nBufSize
cld
rep stosb
@loopStart:
mov ecx, nThreadNum
mov rdx, outbuf
call SendBuffer
cmp eax, 0
je @loopEnd
mov ecx, nThreadNum
mov rdx, inbuf
call RecvBuffer
cmp eax,0
je @loopEnd
mov rsi, inbuf
mov rax, qword ptr [rsi]
mov rdi, outbuf
mov rbx, qword ptr [rdi]
cmp rax, rbx
jnz @err
mov eax, g_Options.nBufSize
sub eax, 8
add rsi, rax
add rdi, rax
mov rax, qword ptr [rsi]
mov rbx, qword ptr [rdi]
cmp rax, rbx
jnz @err
msgPrint msg4, nThreadNum
jmp @loopStart
@err:
msgPrint msg5, nThreadNum
@loopEnd:

@exit1:
cmp inbuf,0
jz @F
mov rcx, heapHandle
mov edx,0
mov r8, inbuf
call HeapFree
@@:
cmp outbuf,0
jz @F
mov rcx, heapHandle
mov edx,0
mov r8, outbuf
call HeapFree
@@:
mov rcx, 0
call ExitThread
EchoThread endp

CreateConnectedSocket proc uses rdi r12 nThreadNum : dword
LOCAL hints : addrinfo
LOCAL addr_srv : PTR addrinfo

sub rsp, 20h
and rsp, -16

mov nThreadNum, ecx

lea rdi, hints
mov al, 0
mov rcx,  sizeof addrinfo
cld
rep stosb
      mov hints.ai_flags, 0
mov hints.ai_family, AF_INET6
mov hints.ai_socktype, SOCK_STREAM
mov hints.ai_protocol, IPPROTO_TCP
lea rcx, g_Options.szHostname
lea rdx, g_Options.port
lea r8, hints
lea r9, addr_srv
call getaddrinfo
cmp eax, 0
jz @F
mov r12d, eax
msgPrint err15, r12d
jmp @exit1
@@:
mov r12, addr_srv
mov ecx, (addrinfo PTR [r12]).ai_family
mov edx, (addrinfo PTR [r12]).ai_socktype
mov r8d, (addrinfo PTR [r12]).ai_protocol
call socket
mov ecx, nThreadNum
lea rdi, g_ThreadInfo.sd
lea rdi, [rdi+rcx*sizeof SOCKET]
mov [rdi], rax
cmp rax, INVALID_SOCKET
jnz @F
errMacro err16, 1
@@:
mov rcx, [rdi]
mov rdx, (addrinfo PTR [r12]).ai_addr
mov r8, (addrinfo PTR [r12]).ai_addrlen
call connect
cmp eax, SOCKET_ERROR
jnz @F
errMacro err17, 1
@@:
mov rcx, r12
call freeaddrinfo
mov eax, 1
ret
@exit1:
mov eax, 0
ret
CreateConnectedSocket endp

main proc uses rbx rsi rdi r12
LOCAL nThreadNum[MAXTHREADS] : SDWORD
LOCAL wsadata : WSADATA
LOCAL bInitError : DWORD
LOCAL ThreadId : DWORD

sub rsp, 30h
and rsp, -16

mov ebx, 0
mov rsi, offset g_ThreadInfo.sd
mov rdi, offset g_ThreadInfo.hThread
lea r11, nThreadNum
@forLoop1Start:
cmp ebx, MAXTHREADS
jae @forLoop1End
mov rax, INVALID_SOCKET
mov [rsi], rax
mov [rdi], rax
mov DWORD PTR [r11], 0
add r11, sizeof SDWORD
add rsi, 8
add rdi, 8
inc ebx
@forLoop1End:

mov g_hCleanupEvent, WSA_INVALID_EVENT

mov cx, 202h
lea rdx, wsadata
call WSAStartup
cmp eax,0
jz @F
mov r12d, eax
msgPrint err1, r12d
jmp @exit2
@@:
call WSACreateEvent
cmp rax, WSA_INVALID_EVENT
jnz @F
errMacro err14, 1
@@:
mov g_hCleanupEvent, rax

mov rcx, NULL
mov edx, 1
mov r8d, 1
mov r9, NULL
call CreateSemaphoreA
cmp rax, 0
jnz @F
errMacro err21
@@:
mov SemaphoreObject, rax

call GetProcessHeap
cmp rax, 0
jnz @F
errMacro err10
@@:
mov heapHandle, rax

mov ebx,0
mov r12, 0
mov bInitError, 0
@forLoop2Start:
cmp ebx, g_Options.nTotalThreads

jae @forLoop2End
mov ecx, ebx
call CreateConnectedSocket
cmp eax, 1
jnz @F
lea r11, nThreadNum
add r11, r12
mov DWORD PTR [r11], ebx
mov rcx,NULL
mov rdx,0
lea r8, EchoThread
mov r9, r11
mov dword ptr [rsp+20h], 0
lea rax, ThreadId
mov [rsp+28h], rax
call CreateThread

cmp rax, NULL
jnz @F
call GetLastError
mov r12d, eax
msgPrint err18, r12d
jmp @forLoop2End
@@:
lea rdi, g_ThreadInfo.hThread
add rdi, r12
mov [rdi], rax
inc ebx
add r12, sizeof SDWORD
mov rcx, 1000
call Sleep ; let's give some time here
jmp @forLoop2Start
@forLoop2End:
mov ecx, g_Options.nTotalThreads
mov rdx, offset g_ThreadInfo.hThread
mov r8d, TRUE
mov r9d, INFINITE
call WaitForMultipleObjects
mov ecx, 1

lea rdx, g_hCleanupEvent
mov r8d, TRUE
mov r9d, WSA_INFINITE
mov DWORD PTR [rsp+20h], FALSE
call WSAWaitForMultipleEvents ; crash
mov rcx, g_hCleanupEvent
call WSACloseEvent
@exit1:
mov rcx, SemaphoreObject
call CloseHandle
call WSACleanup
@exit2:
mov ecx, 0
call ExitProcess
main endp

end


six_L

  • Member
  • **
  • Posts: 95
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #1 on: November 23, 2017, 04:08:38 AM »
Hi, aw27,
Great Stuff for IOCP.

aw27

  • Member
  • ****
  • Posts: 851
  • Let's Make ASM Great Again!
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #2 on: November 23, 2017, 04:29:37 AM »
Hi, aw27,
Great Stuff for IOCP.
Thank you six_L.  :t

six_L

  • Member
  • **
  • Posts: 95
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #3 on: December 07, 2017, 05:30:39 AM »
hello, aw27
i translated your codes into the uasm64 styles,but using invaild address  had happended on 1-WSARecv.
i can't find where were the errors.
Quote
UASM v2.46, Dec  4 2017, Masm-compatible assembler.
Portions Copyright (c) 1992-2002 Sybase, Inc. All Rights Reserved.
Source code is available under the Sybase Open Watcom Public License.

iocpS_2.asm: 361 lines, 3 passes, 164 ms, 0 warnings, 0 errors
Microsoft (R) Incremental Linker Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.
Code: [Select]
option casemap:none
option frame:auto
option win64:3

include \UASM64\include\windows.inc

includelib \UASM64\Lib\msvcrt.lib
includelib \UASM64\Lib\kernel32.lib
includelib \UASM64\Lib\user32.lib
includelib \UASM64\Lib\ws2_32.lib

PORT EQU 5150
DATA_BUFSIZE EQU 8192
MAXTHREADS EQU 64
WAIT_OBJECT_0 EQU 0

SOCKADDR_IN6 STRUCT
sin6_family WORD ?
sin6_port WORD ?
sin6_flowinfo   DWORD ?
sin6_addr BYTE 16 DUP (?)
sin6_scope_id   DWORD ?
SOCKADDR_IN6 ENDS

LPPER_HANDLE_DATA TYPEDEF PTR PER_HANDLE_DATA
PER_HANDLE_DATA STRUCT
Socket SOCKET ?
PER_HANDLE_DATA ENDS

LPPER_IO_OPERATION_DATA TYPEDEF PTR PER_IO_OPERATION_DATA
PER_IO_OPERATION_DATA STRUCT
Overlapped OVERLAPPED <>
DataBuf WSABUF <>
Buffer SBYTE DATA_BUFSIZE dup (?)
BytesSEND DWORD ?
BytesRECV DWORD ?
PER_IO_OPERATION_DATA ENDS

THREADINFO STRUCT
hThread HANDLE MAXTHREADS dup (?)
sd SOCKET MAXTHREADS dup (?)
THREADINFO ENDS

OPTIONS STRUCT
szHostname db "localhost",0
port db "5150",0
nTotalThreads SDWORD 64
nBufSize SDWORD 4096
OPTIONS ENDS

sockaddr STRUCT
sa_family WORD ?
sa_data SBYTE 14 DUP (?)
sockaddr ENDS

addrinfo STRUCT
ai_flags SDWORD ?
ai_family SDWORD ?
ai_socktype SDWORD ?
ai_protocol SDWORD ?
ai_addrlen QWORD ?
ai_canonname LPVOID ?
ai_addr LPVOID ?
ai_next LPVOID ?
addrinfo ENDS

printf PROTO :PTR, :VARARG

.data
;extern in6addr_any:oword
msg2 db "Socket %d got connected",10,0

.data?
heapHandle HANDLE ?
SemaphoreObject HANDLE ?

.code

ErrorMessage Proc USES rsi rdi lpCaption:QWORD,nFlag:BOOL
Local lpErrorMessage:QWORD

invoke WaitForSingleObject,SemaphoreObject,1000
cmp eax, WAIT_OBJECT_0
jnz @1

.if nFlag==TRUE
call WSAGetLastError
.else
call GetLastError
.endif
mov edi,Eax
lea rsi,lpErrorMessage
invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, NULL, edi, LANG_NEUTRAL,rsi,0,NULL
invoke printf,CStr("%s:%s",13,10),lpCaption,lpErrorMessage
@1:
invoke ReleaseSemaphore,SemaphoreObject,1,NULL
invoke LocalFree, lpErrorMessage
ret   

ErrorMessage EndP

ServerWorkerThread proc CompletionPortID : PTR
LOCAL CompletionPort : HANDLE
LOCAL BytesTransferred : DWORD
LOCAL PerHandleData : LPPER_HANDLE_DATA
LOCAL PerIoData : LPPER_IO_OPERATION_DATA
LOCAL SendBytes : DWORD
LOCAL RecvBytes : DWORD
LOCAL Flags : DWORD

mov rcx,CompletionPortID
mov CompletionPort, rcx

@whileLoop:
invoke GetQueuedCompletionStatus,CompletionPort,addr BytesTransferred,addr PerHandleData,PerIoData,INFINITE
cmp eax, 0
jnz @F
invoke ErrorMessage,CStr("GetQueuedCompletionStatus"),FALSE
;jmp @exit1

@@:
cmp BytesTransferred, 0
jnz @F1
mov r8, PerHandleData
invoke closesocket,(PER_HANDLE_DATA PTR [r8]).Socket
cmp eax, SOCKET_ERROR
jnz @F
invoke ErrorMessage,CStr("closesocket"),TRUE
;jmp @exit1
@@:
invoke HeapFree,heapHandle,0,PerHandleData
invoke HeapFree,heapHandle,0,PerIoData
jmp @whileLoop
@F1:
mov r10, PerIoData
cmp (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV,0
jnz @F
mov eax, BytesTransferred
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV, eax
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND,0
jmp @F2
@@:
mov eax, BytesTransferred
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND, eax
@F2:
mov eax, (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV
cmp eax, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
jbe @F3
mov r10, PerIoData
invoke RtlZeroMemory,ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped, sizeof OVERLAPPED

lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
add rax, rcx
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax

mov ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV
sub ecx, (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, ecx
mov r11, PerHandleData
invoke WSASend,(PER_HANDLE_DATA PTR [r11]).Socket,addr (PER_IO_OPERATION_DATA PTR [r10]).DataBuf,\
1,addr SendBytes,0,addr (PER_IO_OPERATION_DATA PTR [r10]).Overlapped,0
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
invoke ErrorMessage,CStr("WSASend"),TRUE
;jmp @exit1
@@:
jmp @whileLoop
@F3:
mov r10, PerIoData
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV, 0
mov Flags,0
invoke RtlZeroMemory,ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped, sizeof OVERLAPPED

mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, DATA_BUFSIZE
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax

mov r11, PerHandleData
invoke WSARecv,(PER_HANDLE_DATA PTR [r11]).Socket,addr (PER_IO_OPERATION_DATA PTR [r10]).DataBuf,\
1,addr RecvBytes,addr Flags,addr (PER_IO_OPERATION_DATA PTR [r10]).Overlapped,0 
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
invoke ErrorMessage,CStr("1-WSARecv"),TRUE
;jmp @exit1
@@:
jmp @whileLoop
@exit1:
invoke ExitThread,NULL
ServerWorkerThread endp

main proc uses rdi r12
LOCAL wsadata:WSADATA
LOCAL CompletionPort : HANDLE
LOCAL SystemInfo : SYSTEM_INFO
LOCAL ThreadId : DWORD
LOCAL Listen : SOCKET
LOCAL Accept : SOCKET
LOCAL InternetAddr : SOCKADDR_IN6
LOCAL PerHandleData : LPPER_HANDLE_DATA
LOCAL PerIoData : LPPER_IO_OPERATION_DATA
LOCAL RecvBytes : DWORD
LOCAL Flags : DWORD

invoke WSAStartup,0202h,ADDR wsadata
cmp eax,0
jz @F
invoke ErrorMessage,CStr("WSAStartup"),TRUE
jmp @exit2
@@:
invoke CreateSemaphoreA, NULL,1,1,NULL
cmp rax, 0
jnz @F
invoke ErrorMessage,CStr("CreateSemaphoreA"),FALSE
;jmp @exit1
@@:
mov SemaphoreObject, rax

invoke CreateIoCompletionPort,INVALID_HANDLE_VALUE,NULL,NULL,NULL
cmp rax, 0
jnz @F
invoke ErrorMessage,CStr("CreateIoCompletionPort"),FALSE
;jmp @exit1
@@:
mov CompletionPort, rax

invoke GetSystemInfo,addr SystemInfo

lea rax, SystemInfo
mov r12d, (SYSTEM_INFO PTR [rax]).dwNumberOfProcessors
shl r12d, 1

mov ebx, 0
@loop1start:
cmp ebx, r12d
jae @loop1exit
invoke CreateThread,NULL,NULL,addr ServerWorkerThread,CompletionPort,0,addr ThreadId
cmp rax, 0
jnz @F
invoke ErrorMessage,CStr("CreateThread"),FALSE
;jmp @exit1
@@:
invoke CloseHandle,rax
inc ebx
jmp @loop1start
@loop1exit:

invoke WSASocket,AF_INET6,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED
cmp rax, INVALID_HANDLE_VALUE ;INVALID_SOCKET
jnz @F
invoke ErrorMessage,CStr("WSASocket"),TRUE
;jmp @exit1
@@:
mov Listen, rax
invoke RtlZeroMemory,ADDR InternetAddr, sizeof InternetAddr

mov InternetAddr.sin6_family, AF_INET6
invoke htons,PORT
mov InternetAddr.sin6_port, ax
; no need to fill in6addr_any because InternetAddr.sin6_addr already filled with zeros

invoke bind,Listen,ADDR InternetAddr,sizeof InternetAddr
cmp eax, SOCKET_ERROR
jnz @F
invoke ErrorMessage,CStr("bind"),TRUE
;jmp @exit1
@@:
invoke listen,Listen,SOMAXCONN
cmp eax, SOCKET_ERROR
jnz @F
invoke ErrorMessage,CStr("listen"),TRUE
;jmp @exit1
@@:
invoke GetProcessHeap
cmp rax, 0
jnz @F
invoke ErrorMessage,CStr("GetProcessHeap"),FALSE
;jmp @exit1
@@:
mov heapHandle, rax

@loop2start:
invoke WSAAccept,Listen,NULL,NULL,NULL,0
cmp eax, SOCKET_ERROR
jnz @F
invoke ErrorMessage,CStr("WSAAccept"),TRUE
;jmp @exit1
@@:
mov Accept, rax
invoke HeapAlloc,heapHandle,HEAP_ZERO_MEMORY,sizeof PER_HANDLE_DATA
cmp rax,0
jnz @F
invoke ErrorMessage,CStr("HeapAlloc"),FALSE
;jmp @exit1
@@:
mov PerHandleData, rax
invoke printf,ADDR msg2,Accept

mov r8, PerHandleData
mov rax, Accept
mov (PER_HANDLE_DATA PTR [r8]).Socket, rax

invoke CreateIoCompletionPort,Accept,CompletionPort,PerHandleData,0
cmp rax, 0
jnz @F
invoke ErrorMessage,CStr("CreateIoCompletionPort"),FALSE
;jmp @exit1
@@:
invoke HeapAlloc,heapHandle,HEAP_ZERO_MEMORY,sizeof PER_IO_OPERATION_DATA
cmp rax,0
jnz @F
invoke ErrorMessage,CStr("HeapAlloc"),FALSE
;jmp @exit1
@@:
mov PerIoData, rax

mov r10, PerIoData
invoke RtlZeroMemory,ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped, sizeof OVERLAPPED

mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND,0
mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV,0
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, DATA_BUFSIZE
lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax
mov Flags,0
invoke WSARecv,Accept,ADDR (PER_IO_OPERATION_DATA PTR [r10]).DataBuf,1,ADDR RecvBytes,ADDR Flags,\
ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped,0
cmp eax, SOCKET_ERROR
jnz @F
call WSAGetLastError
cmp eax, ERROR_IO_PENDING
jz @F
invoke ErrorMessage,CStr("2-WSARecv"),TRUE
;jmp @exit1
@@:
jmp @loop2start

@exit1:
invoke CloseHandle,SemaphoreObject
invoke WSACleanup
@exit2:
invoke ExitProcess,NULL
main endp

end
Quote
    \UASM64\bin\uasm64 -c -win64 %name%.asm
    \UASM64\bin\Link /ENTRY:main /SUBSYSTEM:console /MACHINE:X64 %name%.obj

aw27

  • Member
  • ****
  • Posts: 851
  • Let's Make ASM Great Again!
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #4 on: December 07, 2017, 06:01:55 AM »
A fast look shows that at least this is not according to the original:
invoke GetQueuedCompletionStatus,CompletionPort,addr BytesTransferred,addr PerHandleData,PerIoData,INFINITE

should be addr PerIoData.

Debugging is indeed hard.  :(

six_L

  • Member
  • **
  • Posts: 95
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #5 on: December 07, 2017, 01:15:11 PM »
HI,AW27
thanks you respone.
the error still there.
Quote
   mov PerIoData, rax   
   ;INT 3
   mov r10, PerIoData
   invoke RtlZeroMemory,ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped, sizeof OVERLAPPED

   mov (PER_IO_OPERATION_DATA PTR [r10]).BytesSEND,0
   mov (PER_IO_OPERATION_DATA PTR [r10]).BytesRECV,0
   mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.len, DATA_BUFSIZE
   lea rax, (PER_IO_OPERATION_DATA PTR [r10]).Buffer
   mov (PER_IO_OPERATION_DATA PTR [r10]).DataBuf.buf, rax
   mov Flags,0

   invoke WSARecv,Accept,ADDR (PER_IO_OPERATION_DATA PTR [r10]).DataBuf,1,ADDR RecvBytes,ADDR Flags,\
      ADDR (PER_IO_OPERATION_DATA PTR [r10]).Overlapped,0
   cmp eax, SOCKET_ERROR
   jnz @F
   call WSAGetLastError
   cmp eax, ERROR_IO_PENDING
   jz @F
   invoke ErrorMessage,CStr("2-WSARecv"),TRUE
now all is OK.
option fieldalign:16
;option frame:auto

« Last Edit: December 07, 2017, 04:52:26 PM by six_L »

aw27

  • Member
  • ****
  • Posts: 851
  • Let's Make ASM Great Again!
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #6 on: December 07, 2017, 06:11:35 PM »
option fieldalign:8 should be OK as well.
I am not sure why option frame:auto causes problems, may be you have to check with the UASM team.

six_L

  • Member
  • **
  • Posts: 95
Re: IOCP - 64-bit IPv6 Echo Server Stress Test
« Reply #7 on: December 07, 2017, 06:20:12 PM »
Quote
option fieldalign:8 should be OK as well.
it's OK.