Here is some easy to use "kind of" library for connect into any client (internal ones) since it follow the Window messages based connection (it isnt recommended for complex taks), instead of that use IOCP.
But anyway here is for Wnd MSG, you just set the information in the structure and call the procedures with the arguments:
;///////////////////////////////////
; WinSock releated
;///////////////////////////////////
.const
MAX_BUFF_LENGTH equ 4000 ;Do not change
WSABUF Struct
len DWord ? ;len of buffer
buffer DWord ? ;pointer to buffer
WSABUF EndS
InternalClients_Struct Struct
TCPorUDP Dword ? ;Connection Model
Port Dword ? ;Port for connection
IPorName DB 20 Dup(?) ;IP or Host name
hWnd DWord ? ;Handler of WndProc
MSGID Dword ? ;ID for WSAAsynSelect
Sock DWord ? ;Var for socket
SockAddr sockaddr_in <>
SendBuff DB MAX_BUFF_LENGTH Dup(?) ;Buffer for send bytes, dont change this constant
RecvBuff DB MAX_BUFF_LENGTH Dup(?) ;Buffer for recv bytes, dont change this constant
SendBuffSize DWord ? ;If we want to use less bytes for buffer without changing the constant
RecvBuffSize DWord ? ;If we want to use less bytes for buffer without changing the constant
pSendPacket Dword ? ;Variable for hold the pointer to the last packet that couldt been sended caused WSAEWOULDBLOCK
LastLengthPacket Dword ? ;Variable for hold the last length of the packet that couldt been sended caused WSAWOULDBLOCk
ProtocolAddr Dword ? ;Pointer to protocol for handle packets
Connected DWord ? ;Its Connected sock or dont
InternalClients_Struct EndS
V_Sock_CreateSocket Proto :Dword
V_Sock_MakeAddr Proto :Dword, :Dword
.Const
.Data?
.Data
.Code
V_Sock_SetAll Proc uses ecx
Local pWSADATA:WSADATA ;Point to local struct
assume ecx:ptr InternalClients_Struct
Invoke WSAStartup, 202H, Addr pWSADATA
.If (Eax != 0)
RGB 255, 127, 80 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] Error on while loading WSA"), eax
xor eax, eax
.else
mov edx, Dword ptr pWSADATA
and edx, 0FFFFh ;Word
.if (edx == 2) ;Check version high byte
mov edx, Dword ptr pWSADATA
and edx, 0FFFFh ;Word
shr edx, 8
and edx, 0FFh ;Byte
.if (edx == 2) ;Check version low byte
push ecx ;Save struct
invoke V_Sock_CreateSocket, [ecx].TCPorUDP ;Create a socket
.if (eax == NULL)
RGB 255, 64, 64 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] Error while creating Socket"), eax
xor eax, eax
.else
invoke V_Sock_MakeAddr, [ecx].IPorName, [ecx].Port ;Convert IP or HOST name into internet address
.if (eax == NULL)
RGB 255, 64, 64 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] Error while resolving Address"), eax
xor eax, eax
.else
call V_Sock_Connect ;Connect
.if (eax == NULL)
RGB 255, 64, 64 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] Error while trying to connect to port:[%d]"), eax, [ecx].Port
xor eax, eax
.endif
.endif
.endif
.else
RGB 255, 64, 64 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] WSA Version its 2.[%d], please use 2.2"), eax, edx
.endif
.else
RGB 255, 64, 64 ;Coral (orange ligth)
invoke vprint, $CTA0("SockInteral:\] WSA Version its too old, please use 2.2"), eax
.endif
.endif
pop ecx ;Return struct
.if (eax == NULL)
call V_Sock_Close ;Close if something went wrong
xor eax, eax
.endif
Ret
V_Sock_SetAll EndP
V_Sock_Send Proc Uses Ecx pPacket:DWord, PacketLength:DWord
Local MyStruct:DWord
Local BytesSend:DWord
Local ExtraBytes:DWord
Mov MyStruct, Ecx
Mov ExtraBytes, 0
Mov BytesSend, 0
Assume Ecx:Ptr InternalClients_Struct
mov eax, pPacket
mov edx, PacketLength
mov [ecx].pSendPacket, eax ;Save in case that we cant send the packet, caused WSAEWOULDBLOCK
mov [ecx].LastLengthPacket, edx ;Save in case that we cant send the packet, caused WSAEWOULDBLOCK
.If (edx == 0) ;If packet length its 0
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Trying to send a NULL packet"), eax
Xor Eax, Eax
.Elseif ([Ecx].Connected == 0) ;If we arent connected
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] You arent connected to the internal client for send"), eax
Xor Eax, Eax
.Elseif (PacketLength > MAX_BUFF_LENGTH) ;If more than max buffer length
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] The packet exceed the MAX_BUFFER_LENGTH constant"), eax
Xor Eax, Eax
.Else
.Repeat
Mov Eax, PacketLength
Mov Edx, pPacket
Add Edx, ExtraBytes ;Packet + ExtraBytes if they are
Sub Eax, ExtraBytes ;PacketLength - ExtraBytes = NewPacketLength (if there are extra bytes)
Invoke send, [Ecx].Sock, Edx, Eax, NULL
Mov Ecx, MyStruct
Mov BytesSend, Eax
.If (Eax == -1)
Invoke WSAGetLastError
.If (Eax != WSAEWOULDBLOCK) ;If connection is busy
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Connection busy for send, will resend when ready"), eax
mov eax, 2
.Else
mov edx, eax
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Error when sending [%d]"), eax, edx
Xor Eax, Eax
.Endif
.Else
Mov Eax, PacketLength
.If (BytesSend != Eax) ;If not all the bytes where sended
Mov Edx, BytesSend
Add ExtraBytes, Edx
.Else
mov eax, 1
.Endif
.Endif
.Until (ExtraBytes == 0)
.Endif
.if (eax == 1) || (eax == 0) ;If all went OK or a error happend
invoke V_ZeroBuff, Addr InternalPacket, MAX_PACKETSEND_LENGTH ;Clean the packet buffer
.else ;If WSAEWOULDBLOCK then i dont clean the packet buffer
.endif
Assume Ecx:Nothing
Ret
V_Sock_Send EndP
V_Sock_Recv Proc
Local MyStruct:DWord
Local BytesRecv:DWord
Local RecvPacketLength:DWord
Local RecvPacketHeader:Dword
Local localExtraBytes:DWord
.data
ExtraBytes DD ? ;Extra bytes in global mode
.code
Mov localExtraBytes, 0
mov RecvPacketLength, 0
Mov MyStruct, Ecx
Assume Ecx:Ptr InternalClients_Struct
lea edx, [ecx].RecvBuff
add edx, ExtraBytes ;If there are extra bytes
Invoke recv, [Ecx].Sock, edx, [ecx].RecvBuffSize, 0
Mov BytesRecv, Eax
.If (Eax == 0)
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Error no bytes recv"), eax
mov eax, -1
.ElseIf (Eax == -1)
Invoke WSAGetLastError
.If (Eax == WSAEWOULDBLOCK) ;if connection is busy
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Connection busy to recv, we will recv later"), eax
mov eax, 1 ;We will try later to recv
.Else
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Internal error while recv"), eax
mov eax, -1
.EndIf
.Else
Mov Ecx, MyStruct
.If (BytesRecv > 3) ;if less than 3 bytes
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Error, less than 3 bytes recv"), eax
mov eax, -1
.Else
CheckC1orC2:
Mov Edx, localExtraBytes
Movsx eax, Byte Ptr [[Ecx].RecvBuff + Edx]
.If (Al == 0C1H)
Xor Eax, Eax
Mov Edx, localExtraBytes
Movsx eax, Byte Ptr [[Ecx].RecvBuff + Edx + 1]
Mov RecvPacketLength, Eax
Movsx eax, Byte Ptr [[Ecx].RecvBuff + Edx + 2]
Mov RecvPacketHeader, eax
.ElseIf (Al == 0C2H)
Mov Edx, localExtraBytes
Xor Eax, Eax
Xor Ebx, Ebx
Movsx eax, Byte Ptr [[Ecx].RecvBuff + Edx + 1]
Shl Eax, 8
Movsx ebx, Byte Ptr [[Ecx].RecvBuff + Edx + 2]
Or Eax, Ebx
Mov RecvPacketLength, Eax
Movsx eax, Byte Ptr [[Ecx].RecvBuff + Edx + 3]
Mov RecvPacketHeader, eax
.Else
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Invalid packet header"), eax
mov ExtraBytes, 0
mov eax, -1
jmp EndRecv
.EndIf
.If (RecvPacketLength == 0) ;If packet length its 0
RGB 255, 64, 64
invoke vprint, $CTA0("SockInteral:\] Invalid length of packet"), eax
mov ExtraBytes, 0
mov eax, -1
.Else
Mov Ecx, MyStruct
Mov Edx, RecvPacketLength
.If (Edx <= BytesRecv) ;If the byte of packet is less or equal than the recived bytes
Xor Ebx, Ebx
Lea Edx, [Ecx].ProtocolAddr
Lea Eax, [Ecx].RecvBuff
Add Eax, localExtraBytes
Mov ebx, RecvPacketHeader
Push RecvPacketLength
Push Eax ;RecvBuffer
Push Ebx ;PacketHeader
Call Edx ;call Protocol core depending of the struct used
Mov Ecx, MyStruct
Mov Edx, RecvPacketLength
Add localExtraBytes, Edx
Sub BytesRecv, Edx
.If (BytesRecv < 0) ;if still bytes that we havent readed
Jmp CheckC1orC2
CheckLoop:
.Else
mov ExtraBytes, 0 ;I make sure to set this
mov eax, 1
.EndIf
.Else ;If byte packet of length says there still more bytes that the ones we actual recieve
mov edx, BytesRecv
add ExtraBytes, edx ;Save to global counter
xor eax, eax
.Endif
.Endif
.EndIf
.EndIf
EndRecv:
.if (eax == -1) ;If some error has happen
mov ecx, MyStruct
invoke V_ZeroBuff, [ecx].RecvBuff, [ecx].RecvBuffSize ;Clean the buffer
.elseif (eax == 1) ;If we end succesfull reading the packet
mov ecx, MyStruct
invoke V_ZeroBuff, [ecx].RecvBuff, [ecx].RecvBuffSize ;Clean the buffer
.else ;If we expecting to link the next packet comming to the current we dont clean the buffer
.endif
Assume Ecx:Nothing
Ret
V_Sock_Recv EndP
;/////////////////////////////////////////
;Create Socket
;////////////////////////////////////////
V_Sock_CreateSocket Proc Uses Ecx UDPorTCP:Dword
assume ecx:ptr InternalClients_Struct
.If (UDPorTCP == 1) ;UDP
Mov Eax, SOCK_DGRAM
.Else
Mov Eax, SOCK_STREAM
.EndIf
Lea Ecx, [Ecx].Sock
Push Ecx
Invoke socket, AF_INET, Eax, IPPROTO_IP
Pop Ecx
.If (Eax == -1)
mov dword ptr [ecx], eax ;Unvalid Socket
xor eax, eax
.Else
Mov DWord Ptr [Ecx], Eax ;Save socket in struct
.EndIf
Assume Ecx:Nothing
Ret
V_Sock_CreateSocket EndP
;///////////////////////////////////////////////////////
;Connect procedure
;///////////////////////////////////////////////////////
V_Sock_Connect Proc uses ecx
assume ecx:ptr InternalClients_Struct
push ecx
Invoke connect, [Ecx].Sock, addr [Ecx].SockAddr, SizeOf sockaddr_in
pop ecx
.If (Eax == -1)
Invoke WSAGetLastError
.If (Eax != WSAEWOULDBLOCK)
Xor Eax, Eax
.else
push ecx
Invoke WSAAsyncSelect, [Ecx].Sock, [ecx].hWnd, [ecx].MSGID, FD_READ + FD_CLOSE
pop ecx
.If (Eax == -1)
Xor Eax, Eax
.Else
Mov [Ecx].Connected, 1 ;Already connected
.EndIf
.endif
.endif
Assume Ecx:Nothing
Ret
V_Sock_Connect EndP
;/////////////////////////////////////////////////////////
;Custom proc for make an Host address from input arguments
;and save the address in UDP struct
;RETURN VALUES: 1 == SUCCESS, 0 == FAILURE
;/////////////////////////////////////////////////////////
V_Sock_MakeAddr Proc Uses Ecx IPorName:DWord, Port:DWord
Local MyStruct:DWord
assume ecx:ptr InternalClients_Struct
lea ecx, [ecx].SockAddr
Assume Ecx:Ptr sockaddr_in
Push Ecx
Invoke ntohs, Port
Pop Ecx
Mov [Ecx].sin_family, 2
Mov [Ecx].sin_port, Ax
push ecx
Invoke inet_addr, IPorName ;Take by IP
pop ecx
Mov [Ecx].sin_addr, Eax
mov MyStruct, ecx ;Save for now struct in a variable
.If (Eax == -1)
Invoke gethostbyname, IPorName ;Take by Host Name
.If (Eax == 0)
.Else
Assume Eax:Ptr hostent
Mov Ecx, MyStruct
Mov Edx, DWord Ptr [Eax].h_list
Mov Ebx, [Edx] ;EBX = Host name converted
Invoke MemCopy, Ebx, Addr [Ecx].sin_addr, [Eax].h_len ;Save into sin_addr in our struct
.EndIf
.EndIf
Assume Ecx:Nothing
assume eax:Nothing
Ret
V_Sock_MakeAddr EndP
;/////////////////////////////////////////
;Close socket
;////////////////////////////////////////
V_Sock_Close Proc Uses Ecx
Assume Ecx:Ptr InternalClients_Struct
Push Ecx
Invoke shutdown, [Ecx].Sock, NULL
Pop Ecx
Push Ecx
Invoke closesocket, [Ecx].Sock
Pop Ecx
Mov [Ecx].Sock, -1
Mov [Ecx].Connected, 0
Assume Ecx:Nothing
Ret
V_Sock_Close EndP
The code is tested under 5-6 internal clients under UDP some and others in TCP connection with no problems. (I use it on a game emulator)
The procedures like Recv and Send are customed for handle UDP and TCP at the same time.
Also the procedure Recv is made for a custom packet system based on this:
C1 -> Main Header
XX -> Lenght of packet
XX -> Header
XX -> SubHeader
[XX XX XX] -> Extra data
Ignore the Vprint procedure is just to print for window, you can remove if you like. :cheekygreen:
Hope it helps somebody :U