Hi,
I have an issue tracking completion keys upon returning from GetQueuedCompletionStatus.
My application is receiving first connection with a unique context which is just a memory allocated upon accept. This one is associated to the main socket. This socket is used for commands for send pm, initial ping. And such other small size commands.
The first connection will be that the user is joined to the conversation and so that it will be added to the listview. The lparam of LVM_INSERTITEM will contain this completion key (The main one). The worker threads will notify the GUI main thread about a new user joined via SendNotifyMessage with a custom message. When the main thread receives this message it will initiate a first ping request to the client so it will instruct it to create a new socket for ping and connect it.
On Initial ping command the client will create a new socket and connect it to my application then send a ping data. Upon receiving this ping data at this point my application got 2 completion keys for the same user. Here i run into an issue that i can no longer track this current ping data belongs to which user. As the ping completion key returns different completion key from GetQueuedCompletionStatus than the main one. I can not use LVM_FINDITEM since this ping completion key is not added in listview lparam but the main one is added instead. Now how would i keep a list of completion keys for each user?
Each socket created will have it's own completion key.
My completion key is below. I define OvIn and OvOut as extended overlapped structures inside this CONTEXT_KEY structure
CONTEXT_KEY struct
LastTimeDataSent dd
PingSentTimeMs dd ?
PongReceivedTimeMs dd ?
LastTimePingedMs dd ?
OvIn PER_IO_DATA <>
OvOut PER_IO_DATA <>
chInBuf LPDWORD
TotalBytesReceived DWORD ?
TotalBytesSent DWORD ?
CONTEXT_KEY ends
PER_IO_DATA STRUCT
ov OVERLAPPED <>
socket SOCKET ?
BytesTransferred DWORD ?
ClientAddr sockaddr_in <>
ClientAddrResolved db 32 dup(?)
wsaBuf WSABUF <>
SizeOfClientAddr dd ?
dwFlags DWORD ?
OP_CODE dd ?
Buffer db 1000h dup(?)
CSECTION CRITICAL_SECTION <>
PER_IO_DATA ends
These memory allocations won't be de allocated until the user is disconnected.
I have thought about adding a random unique key per data that is used for main and ping in each send from client so upon receivng these data my application will loop through the listview and grab each user connection key of the main socket then compare it with the ping socket connection key and if they match then this is the user that pinged, but i think this is a poor idea.
I would appreciated any help in this matter.
Probably, most people here will not bother to solve your IO Completion Ports school assignment.
:badgrin:
Quote from: aw27 on November 13, 2017, 05:26:18 PM
Probably, most people here will not bother to solve your IO Completion Ports school assignment.
:badgrin:
First this isn't a school assignment.
Why would you bother posting nonsense? this isn't a spam or joke section.
No? :shock:
> Here i run into an issue that i can no longer track this current ping data belongs to which user.
Hi Frank,
Welcome to the Forum. Can't you allocate an array of QWORDs and access the key via an index?
mov eax, maxusers*8 ; 8=QWORD
mov ebx, alloc(eax)
mov eax, index ; e.g. 3
mov [ebx+8*eax], edx ; store key A
mov [ebx+8*eax+4], edx ; store key B
...
mov edx, [ebx+8*eax] ; retrieve keyA
mov edx, [ebx+8*eax+4] ; retrieve keyB
jj2007 thank you for your welcome message.
The issue is not about where to store the context keys. I can allocate an array and store them there.
But the main issue is that when a ping is issued from server to client it is first issued with the main context which uses different address than the one that will receive the ping. So 1 context send and other context receive. At the point where the ping arrives there is no way for me to tell that this current data belongs to this specific main context. Since each return from GetQueuedCompletionStatus pulls different context key and so the ping can arrive in out of sequence order. I can not rely on list view count. Since on multiple users the ping of first user can arrive before the last one and so on. So the only solution i think is to provide a unique connection ID which will be used in all further communications (All contexts will carry this ID). This way it will be easy to tell which user this is. I think i will stick with just 1 socket and 1 context per user for all communications and just use multiple Per io data instead. Allocate each one at start of new operation and de allocate it once all the packets have been processed.
Quote from: Frank on November 14, 2017, 05:33:15 AMSo 1 context send and other context receive.
OK, got it. This is one of my underdeveloped areas :redface:
So, no way to send a ping and wait for a response from
this client?
Quote from: jj2007 on November 14, 2017, 08:27:30 AM
OK, got it. This is one of my underdeveloped areas :redface:
So, no way to send a ping and wait for a response from this client?
Don't be sad JJ ;). Actually PING is a wrong term here, the term is just CONNECTION and we are very likely talking about TCP connections. I never heard about IOCP for ICMP, which although not impossible would require RAW SOCKETS, which are highly restricted since Windows Vista.
Anyway, I don't see a single line of code in this question, all I see is a badly formulated problem which looks unreal like a school assignment.
@aw27:
Probably you are right. In the "code" above there are only structures defined. :eusa_snooty:
@Frank:
Maybe you can upload some code to prove that aw27 is wrong? :bgrin:
Quote from: aw27 on November 14, 2017, 09:44:07 PM
Quote from: jj2007 on November 14, 2017, 08:27:30 AM
OK, got it. This is one of my underdeveloped areas :redface:
So, no way to send a ping and wait for a response from this client?
Don't be sad JJ ;). Actually PING is a wrong term here, the term is just CONNECTION and we are very likely talking about TCP connections. I never heard about IOCP for ICMP, which although not impossible would require RAW SOCKETS, which are highly restricted since Windows Vista.
Anyway, I don't see a single line of code in this question, all I see is a badly formulated problem which looks unreal like a school assignment.
I never mentioned ICMP protocol. This is just a normal small data share over TCP each x seconds to avoid lose of close notification. Since i noticed the client will lose close notification in case if the server is closed if long time elapsed without data share.
Quote from: felipe on November 15, 2017, 12:02:00 PM
@aw27:
Probably you are right. In the "code" above there are only structures defined. :eusa_snooty:
@Frank:
Maybe you can upload some code to prove that aw27 is wrong? :bgrin:
Server code:
Connection accepting:
AcceptConnection proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED
invoke AddConnectionSlot,pContextKey,pOverlapped
.if EAX != NULL
MOV EDI,EAX ;pContextKey
MOV [ESI].PER_IO_DATA.OP_CODE,OP_ACCEPTING
invoke AcceptExFunc,[Listen],[ESI].PER_IO_DATA.socket,addr [ESI].PER_IO_DATA.Buffer,NULL,sizeof PER_IO_DATA.ClientAddr*2,\
sizeof PER_IO_DATA.ClientAddr*2,addr [ESI].PER_IO_DATA.BytesTransferred,addr [ESI].PER_IO_DATA.ov
invoke CreateIoCompletionPort, [ESI].PER_IO_DATA.socket, [CompletionPort], EDI, NULL
.endif
ret
AcceptConnection endp
AddConnectionSlot is just used for allocation user context using HeapAlloc.
AddConnectionSlot proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED
invoke HeapAlloc,[HeapH],HEAP_ZERO_MEMORY ,sizeof CONTEXT_KEY
MOV pContextKey, EAX
MOV EDX,pContextKey
LEA EBX,[EAX].CONTEXT_KEY.OvIn
MOV pOverlapped,EBX
MOV EAX,pOverlapped
MOV [EAX].PER_IO_DATA.pPContextKey,EDX
invoke HeapAlloc,[HeapH],HEAP_ZERO_MEMORY ,sizeof InitialReadBuffSIze
MOV EDX,pContextKey
MOV [EDX].CONTEXT_KEY.SizeOfOverAllRecvBuffer,InitialReadBuffSIze
MOV [EDX].CONTEXT_KEY.chInBuf,EAX
MOV ESI,EDX
MOV EAX,sizeof PER_IO_DATA.ClientAddr
MOV [ESI].PER_IO_DATA.SizeOfClientAddr,EAX
[ESI].CONTEXT_KEY.SizeOfClientAddr
invoke WSASocket,AF_INET,SOCK_STREAM,NULL,NULL,NULL,WSA_FLAG_OVERLAPPED
MOV EBX,EAX
MOV EAX,pContextKey
LEA EDX,[EAX].CONTEXT_KEY.OvIn
MOV [EDX].PER_IO_DATA.socket,EBX
LEA EDX,[EAX].CONTEXT_KEY.OvOut
MOV [EDX].PER_IO_DATA.socket,EBX
MOV ESI,pOverlapped
ret
AddConnectionSlot endp
Listen function:
Listen_Function proc pServer:PFASTSERVER
local pContextKey:PCONTEXT_KEY
local pOverlapped:POVERLAPPED
LOCAL numBytes:DWORD
invoke WSAStartup,0202h,addr wsd
invoke WSASocket,AF_INET,SOCK_STREAM,NULL,NULL,NULL,WSA_FLAG_OVERLAPPED
MOV ESI,EAX
invoke WSAIoctl,ESI,SIO_GET_EXTENSION_FUNCTION_POINTER,addr WSAID_ACCEPTEX,sizeof WSAID_ACCEPTEX,addr AcceptExPtr\
,sizeof AcceptExPtr,addr numBytes,NULL,NULL
invoke closesocket,ESI
invoke CreateIoCompletionPort,INVALID_HANDLE_VALUE,NULL,NULL,NULL
MOV [CompletionPort],EAX
mov edx, pServer
mov [edx].FASTSERVER.hIOCompletionPort, eax
MOV [CompletionPortAccept],EAX
MOV ESI,NumberOfConcurrentThreads
.while ESI != NULL
invoke CreateThread,NULL,NULL,addr IOWorkerThreads,pServer,NULL,NULL
invoke CloseHandle,EAX
DEC ESI
INC NumberOfThreadsCreated
.endw
invoke WSASocket,AF_INET,SOCK_STREAM,NULL,NULL,NULL,WSA_FLAG_OVERLAPPED
MOV [Listen],EAX
invoke CreateIoCompletionPort, [Listen], [CompletionPort], NULL, NULL
invoke htons,Port
MOV InternetAddr.sin_port, AX
MOV InternetAddr.sin_family, AF_INET
MOV InternetAddr.sin_addr, INADDR_ANY
invoke bind, Listen, addr InternetAddr, SizeOf InternetAddr
invoke listen,Listen,SOMAXCONN
invoke CreateEvent,NULL,FALSE,FALSE,NULL
MOV [hEventObject],EAX
invoke WSAEventSelect,[Listen],[hEventObject],FD_ACCEPT
MOV EDI,EAX
ACCEPT:
invoke WSAWaitForMultipleEvents,1,addr hEventObject,FALSE,WSA_INFINITE,FALSE
invoke AcceptConnection,pContextKey,pOverlapped
JMP ACCEPT
ret
Listen_Function endp
The IO Worker thread pool function
IOWorkerThreads proc pServer:PFASTSERVER
local hIOCompletionPort:HANDLE
local BytesTransferred:DWORD
local pContextKey: PTR DWORD
local pOverlapped:PTR DWORD
mov edx, pServer
mov ecx, [edx].FASTSERVER.hIOCompletionPort
mov hIOCompletionPort, ecx
START:
MOV pContextKey,NULL
MOV [BytesTransferred],NULL
MOV pOverlapped,NULL
invoke GetQueuedCompletionStatus, hIOCompletionPort, addr BytesTransferred,addr pContextKey, addr pOverlapped, INFINITE
.if EAX == FALSE
.if [pOverlapped] == NULL
invoke GetLastError
.if EAX == WAIT_TIMEOUT
JMP START
.else
RET
ret
.endif
.else
.if pOverlapped != NULL
invoke Cleanup,pContextKey,pOverlapped,DC_BY_IO
JMP START
.endif
.endif
.elseif EAX == TRUE
.if [BytesTransferred] == NULL
MOV EDX,pOverlapped
.if [EDX].PER_IO_DATA.OP_CODE == OP_READ
invoke Cleanup,pContextKey,pOverlapped,DC_BY_IO
JMP START
.endif
.endif
.endif
MOV EDX,pOverlapped
Switch [EDX].PER_IO_DATA.OP_CODE
Case OP_ACCEPTING
MOV ESI,pOverlapped
MOV EDI,pContextKey
MOV EAX,sizeof PER_IO_DATA.ClientAddr
MOV [ESI].PER_IO_DATA.SizeOfClientAddr,EAX
invoke setsockopt,[ESI].PER_IO_DATA.socket,SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, addr [Listen],4
invoke getpeername,[ESI].PER_IO_DATA.socket,addr [ESI].PER_IO_DATA.ClientAddr,addr [ESI].PER_IO_DATA.SizeOfClientAddr
MOV ECX,DWORD PTR [ESI].PER_IO_DATA.ClientAddr.sin_addr
invoke inet_ntoa, ECX
LEA EDI,[ESI].PER_IO_DATA.ClientAddrResolved
MOV ESI,EAX ;Buffer of dotted ip address
invoke lstrlen,ESI
MOV ECX,EAX
REP MOVSB
invoke InitialIORead,pContextKey,pOverlapped
Case OP_READ
invoke ProcessReadIO,pContextKey,pOverlapped,[BytesTransferred]
CASE OP_WRITE
MOV EDX,pContextKey
MOV EBX,pOverlapped
MOV ECX,BytesTransferred
ADD [EDX].CONTEXT_KEY.TotalBytesSent,ECX
MOV ECX,[EDX].CONTEXT_KEY.TotalBytesSent
.if ECX < [EBX].PER_IO_DATA.Buffer.PACKET_INFO.PACKET_SIZE
invoke ProcessWriteIO,pContextKey,pOverlapped,[BytesTransferred]
.elseif ECX == [EBX].PER_IO_DATA.Buffer.PACKET_INFO.PACKET_SIZE
MOV [EDX].CONTEXT_KEY.TotalBytesSent,0 ;Reset sent size
invoke IOWriteDone,pContextKey,pOverlapped,[BytesTransferred]
.endif
Case OP_CLOSE
invoke Cleanup,pContextKey,pOverlapped,DC_BY_IO
Default
Endsw
JMP START
ret
IOWorkerThreads endp
Cleanup procedure
Cleanup Proc USES ESI EDI pContextKey:DWORD,pOverlapped:DWORD,COMMAND:DWORD
MOV EDI, pContextKey
MOV ESI,pOverlapped
.if pContextKey != NULL
.if [ESI].PER_IO_DATA.socket != SOCKET_ERROR ;Not closed by right click Disconnect command
invoke SendNotifyMessage, MainTabContentDialogHandle, LV_CMD_REMOVE_USER,pContextKey,pOverlapped
invoke closesocket,[ESI].PER_IO_DATA.socket
MOV [ESI].PER_IO_DATA.socket,SOCKET_ERROR
.endif
MOV ESI,[EDI].CONTEXT_KEY.chInBuf
invoke HeapFree,[HeapH],NULL,ESI
invoke HeapFree,[HeapH],NULL,EDI
.endif
ret
Cleanup endp
Proccess IO Read (WSARecv)
ProcessReadIO proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED,BytesTransferred:DWORD
MOV EDX,pContextKey
MOV EBX, pOverlapped
MOV ECX,[BytesTransferred]
LEA ESI,[EBX].PER_IO_DATA.Buffer
MOV EDI,[EDX].CONTEXT_KEY.chInBuf
ADD EDI,[EDX].CONTEXT_KEY.TotalBytesReceived
REP MOVSB
MOV EBX,[BytesTransferred]
ADD [EDX].CONTEXT_KEY.TotalBytesReceived,EBX
MOV EDX,pContextKey
MOV EBX,pOverlapped
MOV EDX,pContextKey
MOV EDI,[EDX].CONTEXT_KEY.chInBuf ;Dynamic buffer...
.if DWORD PTR [EDI].PACKET_INFO.DATA_START == DATA_START ;ID
MOV EDX,pContextKey
MOV ECX,[EDX].CONTEXT_KEY.TotalBytesReceived
MOV ESI, [EDI].PACKET_INFO.PACKET_SIZE
.if ESI == ECX
;Finished receving all data... parse it and act depend on what command is...
MOV [EDX].CONTEXT_KEY.TotalBytesReceived,0
SWITCH [EDI].PACKET_INFO.MAIN_COMMAND
CASE CMD_ADDNEW
invoke SendMessage,MainTabContentDialogHandle,LV_CMD_ADD_USER,pContextKey,pOverlapped
CASE CMD_PONG
invoke GetTickCount
MOV EDX,pContextKey
MOV [EDX].CONTEXT_KEY.PongReceivedTimeMs,EAX
invoke SendNotifyMessage,MainTabContentDialogHandle,LV_MESSAGE_CALCULATE_PING,pContextKey,pOverlapped
Default
ENDSW
.else
.endif
MOV EDX,pContextKey
LEA EDX,[EDX].CONTEXT_KEY.OvIn
mov [edx].PER_IO_DATA.wsaBuf.len, sizeof PER_IO_DATA.Buffer
lea ecx, [edx].PER_IO_DATA.Buffer
mov [edx].PER_IO_DATA.wsaBuf.buf, ecx
MOV [edx].PER_IO_DATA.BytesTransferred,NULL
MOV [edx].PER_IO_DATA.OP_CODE,OP_READ
invoke WSARecv, [edx].PER_IO_DATA.socket, addr [EDX].PER_IO_DATA.wsaBuf, 1,
addr [edx].PER_IO_DATA.BytesTransferred, addr [EDX].PER_IO_DATA.dwFlags,
addr [EDX].PER_IO_DATA.ov, NULL
.else
invoke Cleanup,pContextKey,pOverlapped,DC_BY_IO
.endif
ret
ProcessReadIO endp
Process IO Write (WSASend)
ProcessWriteIO proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED,BytesTransferred:DWORD
MOV EDX,pOverlapped
mov [edx].PER_IO_DATA.OP_CODE,OP_WRITE
MOV ECX,[EDX].PER_IO_DATA.Buffer.PACKET_INFO.PACKET_SIZE
mov [edx].PER_IO_DATA.wsaBuf.len, ECX
lea ecx, [EDX].PER_IO_DATA.Buffer
mov [edx].PER_IO_DATA.wsaBuf.buf, ECX
invoke WSASend, [edx].PER_IO_DATA.socket, addr [edx].PER_IO_DATA.wsaBuf, 1,
addr [edx].PER_IO_DATA.BytesTransferred, NULL,
addr [edx].PER_IO_DATA.ov, NULL
ret
ProcessWriteIO endp
InitialIORead (First WSARecv to let data arrive)
InitialIORead proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED
mov edx, pOverlapped
mov [edx].PER_IO_DATA.OP_CODE,OP_READ
mov [edx].PER_IO_DATA.wsaBuf.len, sizeof PER_IO_DATA.Buffer
lea ecx, [edx].PER_IO_DATA.Buffer
mov [edx].PER_IO_DATA.wsaBuf.buf, ecx
invoke WSARecv, [edx].PER_IO_DATA.socket, addr [edx].PER_IO_DATA.wsaBuf, 1,
addr [edx].PER_IO_DATA.BytesTransferred, addr [edx].PER_IO_DATA.dwFlags,
addr [edx].PER_IO_DATA.ov, NULL
ret
InitialIORead endp
SendCommand Procedure:
SendCommand Proc USES ESI EDI EAX hWnd:HWND, pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED,COMMAND:DWORD,SUB_COMMAND:DWORD
LOCAL Buffer:DWORD
LOCAL CaptionLen:DWORD
LOCAL TextLen:DWORD
MOV ESI,pContextKey
MOV EDI,pOverlapped
invoke AddCommandToBuffer,addr [ESI].CONTEXT_KEY.OvOut.Buffer,sizeof PER_IO_DATA.Buffer,COMMAND,SUB_COMMAND
MOV Buffer,EAX
SWITCH COMMAND
CASE CMD_CLOSE_CONNECTION
MOV [ESI].CONTEXT_KEY.OvOut.Buffer.PACKET_INFO.PACKET_SIZE,Sizeof PACKET_INFO
MOV [ESI].CONTEXT_KEY.OvOut.OP_CODE,OP_WRITE
MOV [ESI].CONTEXT_KEY.OvIn.OP_CODE,OP_CLOSE
CASE CMD_INITIAL_PING
MOV [ESI].CONTEXT_KEY.OvOut.Buffer.PACKET_INFO.PACKET_SIZE,Sizeof PACKET_INFO
MOV [ESI].CONTEXT_KEY.OvOut.OP_CODE,OP_WRITE
CASE CMD_PING
MOV [ESI].CONTEXT_KEY.OvOut.Buffer.PACKET_INFO.PACKET_SIZE,Sizeof PACKET_INFO
MOV [ESI].CONTEXT_KEY.OvOut.OP_CODE,OP_WRITE
DEFAULT
ENDSW
invoke PostQueuedCompletionStatus,[CompletionPort],NULL,ESI,addr [ESI].CONTEXT_KEY.OvOut
ret
SendCommand endp
Client:
Main proc pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED,pServer:PFASTSERVER
LOCAL NetworkEvents:WSANETWORKEVENTS
LOCAL pContextKeyPing:PCONTEXT_KEY
invoke HeapCreate, NULL,4,NULL
MOV [HeapH],EAX
invoke WSAStartup,0202h,addr wsd
invoke InitializeContext
MOV pContextKey, EAX
LEA EBX,[EAX].CONTEXT_KEY.OvOut
MOV pOverlapped,EBX
invoke CreateSocket
.if EAX != SOCKET_ERROR
MOV ESI,pServer
MOV EDI,pContextKey
MOV MainSocket,EAX
MOV [EDI].CONTEXT_KEY.OvIn.socket,EAX
MOV [EDI].CONTEXT_KEY.OvOut.socket,EAX
invoke CreateIoCompletionPort,INVALID_HANDLE_VALUE,NULL,NULL,NULL
MOV [ESI].FASTSERVER.hIOCompletionPort,EAX
MOV [CompletionPort],EAX
invoke CreateEvent,NULL,TRUE,FALSE,NULL
MOV MainSocketEvents,EAX
MOV [EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent,EAX
invoke CreateEvent,NULL,TRUE,FALSE,NULL
MOV [EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent,EAX
invoke CreateEvent,NULL,TRUE,FALSE,NULL
MOV [EDI].CONTEXT_KEY.OvIn.hCommandsEvent,EAX
MOV [EDI].CONTEXT_KEY.OvOut.hCommandsEvent,EAX
invoke InitializeIOWorkerThreads,pServer
invoke InitializeSocket,pContextKey,pOverlapped,pServer
MOV EDI,pContextKey
MOV [EDI].CONTEXT_KEY.OvOut.OP_CODE,OP_CONNECTING
.repeat
invoke ConnectSocket,pContextKey,pOverlapped
invoke WaitForSocketConnection,[EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent,1000
.until EAX == WAIT_OBJECT_0
invoke ResetEvent,[EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent
invoke RetrievePCInfo,addr [EDI].CONTEXT_KEY.OvOut.Buffer,addr [EDI].CONTEXT_KEY.OvOut.BufferSize ;Get Serial of harddrive to issue a ban on the specific PC
invoke InitialIORead,pContextKey,addr [EDI].CONTEXT_KEY.OvIn
invoke ProcessWriteIO,pContextKey,addr [EDI].CONTEXT_KEY.OvOut,NULL
.while TRUE
invoke WaitForSocketDisconnectionAndCommands,addr [EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent,20000 ;Wait for the main socket for commands or DC
.if EAX != WAIT_TIMEOUT
MOV EDI,pContextKey
LEA EDX,[EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent
MOV EDX,[EDX+EAX*4]
SWITCH EDX
CASE [EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent
SWITCH [EDI].CONTEXT_KEY.OvIn.OP_CODE
CASE OP_DISCONNECTED_BY_NETWORK
MOV EDI,pContextKey
invoke closesocket,[EDI].CONTEXT_KEY.OvIn.socket
MOV [EDI].CONTEXT_KEY.TotalBytesReceived,0
invoke CreateSocket
invoke InitializeSocket,pContextKey,pOverlapped,pServer
MOV [EDI].CONTEXT_KEY.OvIn.OP_CODE,NULL
MOV [EDI].CONTEXT_KEY.OvOut.OP_CODE, OP_RECONNECT
.repeat
invoke ConnectSocket,pContextKey,pOverlapped
invoke WaitForSocketConnection,[EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent,1000
.until EAX == WAIT_OBJECT_0
MOV EDI,pContextKey
invoke ResetEvent,[EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent
invoke ResetEvent,[EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent
invoke ResetEvent,[EDI].CONTEXT_KEY.OvIn.hCommandsEvent
invoke RetrievePCInfo,addr [EDI].CONTEXT_KEY.OvOut.Buffer,addr [EDI].CONTEXT_KEY.OvOut.BufferSize
invoke InitialIORead,pContextKey,addr [EDI].CONTEXT_KEY.OvIn
invoke ProcessWriteIO,pContextKey,addr [EDI].CONTEXT_KEY.OvOut,NULL
CASE OP_DISCONNECTED_BY_COMMAND
MOV EDI,pContextKey
invoke closesocket,[EDI].CONTEXT_KEY.OvIn.socket
invoke CloseHandle,[EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent
invoke CloseHandle,[EDI].CONTEXT_KEY.OvOut.hSocketStatusEvent
invoke CloseHandle,[EDI].CONTEXT_KEY.OvIn.hCommandsEvent
MOV [EDI].CONTEXT_KEY.OvIn.OP_CODE,OP_SHUTDOWN
.repeat
invoke PostQueuedCompletionStatus,[CompletionPort],NULL,EDI,addr [EDI].CONTEXT_KEY.OvIn
DEC NumberOfThreadsCreated
.until NumberOfThreadsCreated == 0
invoke CloseHandle,pServer.FASTSERVER.hIOCompletionPort
.break
DEFAULT
ENDSW
DEFAULT
ENDSW
.elseif EAX == WAIT_TIMEOUT
MOV EDI,pContextKey
invoke GetTickCount
LEA EDX,[EDI].CONTEXT_KEY.OvIn.Buffer
MOV ECX,[EDX].PACKET_INFO.SUB_COMMAND
SUB EAX,ECX
.if EAX > 60000
MOV [EDI].CONTEXT_KEY.OvIn.OP_CODE, OP_DISCONNECTED_BY_NETWORK
invoke SetEvent,[EDI].CONTEXT_KEY.OvIn.hSocketStatusEvent
.endif
.else
.break
.endif
.endw
ret
Main endp
WaitForSocketDisconnectionAndCommands proc Events:LPHANDLE,WaitTime:DWORD
invoke WaitForMultipleObjects,2,Events,FALSE,WaitTime
ret
WaitForSocketDisconnectionAndCommands endp
InitializeContext
InitializeContext proc
invoke HeapAlloc,[HeapH],HEAP_ZERO_MEMORY ,sizeof CONTEXT_KEY
MOV [EAX].CONTEXT_KEY.OvIn.BufferSize,sizeof PER_IO_DATA.Buffer
MOV [EAX].CONTEXT_KEY.OvOut.BufferSize,sizeof PER_IO_DATA.Buffer
ret
InitializeContext endp
Socket Initialization
InitializeSocket Proc USES ESI EDI pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED,pServer:PFASTSERVER
LOCAL numBytes:DWORD
MOV EDI,pContextKey
MOV ESI,pServer
MOV EDI,pContextKey
MOV InternetAddr.sin_addr, 0
invoke htons,0
MOV InternetAddr.sin_port, AX
MOV InternetAddr.sin_family, AF_INET
invoke bind,[EDI].CONTEXT_KEY.OvOut.socket,addr InternetAddr,sizeof InternetAddr
.if ConnectExPtr == NULL
invoke WSAIoctl,[EDI].CONTEXT_KEY.OvOut.socket,SIO_GET_EXTENSION_FUNCTION_POINTER,addr WSAID_CONNECTEX,sizeof WSAID_CONNECTEX,addr ConnectExPtr\
,sizeof ConnectExPtr,addr numBytes,NULL,NULL
.endif
invoke CreateIoCompletionPort,[EDI].CONTEXT_KEY.OvOut.socket, [ESI].FASTSERVER.hIOCompletionPort, pContextKey, NULL
ret
InitializeSocket endp
Socket Connection:
ConnectSocket Proc USES ESI EDI pContextKey:PCONTEXT_KEY,pOverlapped:POVERLAPPED
MOV EDI,pContextKey
invoke inet_addr,addr RemoteIPAddress
MOV InternetAddr.sin_addr, EAX
invoke htons,Port
MOV InternetAddr.sin_port, AX
invoke ConnectExFunc,[EDI].CONTEXT_KEY.OvOut.socket,addr InternetAddr,sizeof InternetAddr,NULL,NULL,NULL,addr [EDI].CONTEXT_KEY.OvOut
invoke GetLastError
.if EAX != ERROR_IO_PENDING
MOV EAX,SOCKET_ERROR
.endif
ret
ConnectSocket endp
Thanks for sharing your work frank, i guess you are telling the true. :t
Welcome to the forum. :redface:
:P
This is a careless code dump.
When I post examples or code it is always complete and ready to be built, even when I don't leave attachments.
For me this subject is closed.
Hi Frank,
this article will probably help you ::) https://www.codeproject.com/Articles/10330/A-simple-IOCP-Server-Client-Class
Quote from: aw27 on November 18, 2017, 12:35:00 AM
This is a careless code dump.
When I post examples or code it is always complete and ready to be built, even when I don't leave attachments.
For me this subject is closed.
lol. Have you seen somebody post his whole project just for a question?
Take a look at stack overflow.
This isn't a code bank so why the hell would i need to post whole project just because small area doesn't work properly?
That is some bullshit there.
Quote from: LiaoMi on November 18, 2017, 01:13:30 AM
Hi Frank,
this article will probably help you ::) https://www.codeproject.com/Articles/10330/A-simple-IOCP-Server-Client-Class
Thank you Liao. Will take a look on it.
Quote from: Frank on November 18, 2017, 05:50:31 AM
lol. Have you seen somebody post his whole project just for a question?
Take a look at stack overflow.
This isn't a code bank so why the hell would i need to post whole project just because small area doesn't work properly?
That is some bullshit there.
Look for someone to fix at Stackoverflow then. The code is a complete nonsense.
Follow the advice and follow simple tutorials to learn the basics.
Quote from: Frank on November 18, 2017, 05:50:31 AMwhy the hell would i need to post whole project just because small area doesn't work properly?
This is forum tradition, Frank: Members want to build the code, insert int 3 in strategic places, and see what's wrong in the debugger. And in general, members are very helpful in chasing bugs. I understand that you don't want to reveal all your secrets, so strip it down to the basics if you can. But just staring at pieces of code will not trigger any response. Really, it's not against you - the request to post "buildable" code is driven purely by practical considerations.
:icon14:
Quote from: Frank on November 18, 2017, 05:51:42 AM
Quote from: LiaoMi on November 18, 2017, 01:13:30 AM
Hi Frank,
this article will probably help you ::) https://www.codeproject.com/Articles/10330/A-simple-IOCP-Server-Client-Class
Thank you Liao. Will take a look on it.
you can see another implementation in ObjAsm, files containing the engine
NetCom.asm
NetCom.inc
NetComConnection.inc
NetComConnectionPool.inc
NetComEngine.inc
NetComFile.inc
NetComIOMsgPool.inc
NetComIOSockJobPool.inc
NetComProtocol.inc
:idea:
Quote from: aw27 on November 18, 2017, 06:14:51 AM
Quote from: Frank on November 18, 2017, 05:50:31 AM
lol. Have you seen somebody post his whole project just for a question?
Take a look at stack overflow.
This isn't a code bank so why the hell would i need to post whole project just because small area doesn't work properly?
That is some bullshit there.
Look for someone to fix at Stackoverflow then. The code is a complete nonsense.
Follow the advice and follow simple tutorials to learn the basics.
You started raging by making false assumption that my code is a school assignment. When i showed all of my relevant code and proved it wasn't you then started to talk nonsense. You need to learn the morals.
Quote from: jj2007 on November 18, 2017, 07:05:10 AM
Quote from: Frank on November 18, 2017, 05:50:31 AMwhy the hell would i need to post whole project just because small area doesn't work properly?
This is forum tradition, Frank: Members want to build the code, insert int 3 in strategic places, and see what's wrong in the debugger. And in general, members are very helpful in chasing bugs. I understand that you don't want to reveal all your secrets, so strip it down to the basics if you can. But just staring at pieces of code will not trigger any response. Really, it's not against you - the request to post "buildable" code is driven purely by practical considerations.
:icon14:
There is no secrets. It is just not a simple task to remove the irrelevant code for gui and other stuff and still get the application to function the same.
Frank,
The request for an example that is at least buildable is reasonable as for anyone to be able to answer your questions or help you out, they must have something to work on. If its a big project that you are working on, see if you can pull out the part that is not working and put it in a test framework that at least runs so it can be tested and worked on.
There is a reason why we can be a bit wary of some of the questions, years ago we used to get these kids from India who would dump their school projects in the forum and post an email address to post the answer back to so we have blocked any conduct like that. To prevent sneak attacks we shoot first and answer questions later so don't be offended as this situation clearly does not apply to you.
Its the usual case around here, miracles are done regularly but the impossible takes longer. :P