...my very second program/exercise is experiencing a memory leak, every time it spawns a MessageBox.
The code that projects this MessageBox is within a thread procedure, because I want to process & display multiple messages in a multithreaded enviroment:
WinsockGetData proc
local SenderIP: dword
local Sender: sockaddr_in
local SenderLen: dword
invoke WaitForSingleObject, hInBufferMutex, INFINITE
  mov SenderLen, sizeof sockaddr_in
  invoke recvfrom, hSocket, addr InBuffer, sizeof InBuffer, 0, addr Sender, addr SenderLen
  invoke ReleaseMutex, hInBufferMutex
  push Sender.sin_addr
  call inet_ntoa
  mov SenderIP, eax
  invoke MessageBox, 0, addr InBuffer, SenderIP, MB_ICONINFORMATION
invoke ExitThread, 0
WinsockGetData endp
I'm not sure but I think this leak is caused by event objects that do not close after the MessageBox is closed (or maybe this is one of the many different leaks :P). Everytime a MessageBox is created, it creates 2 event objects (I don't know why :P) Some of them, while in a burst, do not close.
- Is there a way to track 'em down and close?
well if you're using releasemutex with the idea that it free's it.. you're wrong
you need to CloseHandle on the mutex to close it
sounds like your events are piling up.....
can you explain what you're trying to do?
The add esp,4 statement, is it associated with push Sender.sin_addr or something else ?
Don't worry about ReleaseMutex, I have read MSDN. This mutex handle is global and it is invalidated when the main program ends.
I also use CloseHandle with the newly created thread. Well, as a general rule, I alaways close handles that are not of use anymore.
The problem arises from MessageBox, I think...
The program is a UDP chat, that displays the messages with message boxes. Say, something similar to the Messenger service, but it does not use mailslots...
As for "add esp, 4", yeah you're right. It's useless. I thought I needed to pop the argument that passed to the procedure. But it's wrong. ExitThread do this, right? I'll correct it to avoid confusion.
Hi Stifado,
You should terminate the procedure with a ret instruction instead of ExitThread. Masm will balance the stack to free the parameter(s) passed to the procedure. Note that the stdcall calling convention should be selected at the top of the source code to enable this feature. Note that the C calling convention handles the stack balancing differently.
Let's assume you pass two parameter to your procedure :
abc PROC x:DWORD,y:DWORD
.
.
ret
abc ENDP
Masm will put a ret 8 instruction at the epilogue code to terminate the procedure.
I have read the "Art of Assembly", so I am considered to know much of the basics. Yes, I know about the calling conventions, and yes, I use the stdcall calling convention because I've read that Win API uses this one...
Using a simple "ret" instead of ExitThread... I have tried this, but doesn't change anything!
Okay, I'll make use of a "ret" instruction instead of ExitThread...
But I don't think calling ExitThread will mess up things because:
"... When this function is called (either explicitly or by returning from a thread procedure), the current thread's stack is deallocated, all pending I/O initiated by the thread is cancelled, and the thread terminates. ..." from MSDN
... ???
Here is a simple demonstration :
.386
.model flat,stdcall
option casemap : none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
test1 PROTO :DWORD,:DWORD
.data
format1 db 'x + y = %d',0
capt db 'Procedure demo',0
.data?
buffer db 100 dup(?)
.code
start:
invoke test1,75,25
invoke wsprintf,ADDR buffer,ADDR format1,eax
invoke MessageBox,0,ADDR buffer,ADDR capt,MB_OK
invoke ExitProcess,0
test1 PROC x:DWORD,y:DWORD
mov eax,x
add eax,y
invoke ExitThread,0
test1 ENDP
END start
Here,
ExitThread will terminate the application, so there will be no access to the continuation of the code, invoke wsprintf etc. Replacing
ExitThread with ret, the procedure will return the control the main module.
QuoteI have read the "Art of Assembly", so I am considered to know much of the basics. Yes, I know about the calling conventions, and yes, I use the stdcall calling convention because I've read that Win API uses this one...
I am trying to be good intended and I am just trying to help you...
edit : sorry, I missed you are talking about multithreading, you can omit the code above.
Hey! I just stated what I have read, just to tell you what I am aware of, so you won't waste your time explaining to me. That 'll speed up things :P For God's sake, no offense meant, and for God's sake, noone can just know everything! Not even me :P
tried debugging your code then?
Well, that's what I'm trying to do... find the bug or in this case the leak...
I'll attach the source code, in case someone would like to help with it in first hand.
[attachment deleted by admin]
I'll quit searching this deadend. If I ever find it, I'll report it :P
.686
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
include \masm32\include\ole32.inc
include \masm32\include\oleaut32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\masm32.inc
include \masm32\include\wsock32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\ole32.lib
includelib \masm32\lib\oleaut32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\masm32.lib
includelib \masm32\Lib\wsock32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include \masm32\macros\macros.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
frmMain equ 101
FormIcon equ 102
txtMessage equ 1002
txtRecipient equ 1003
cmdSend equ 1004
cmdExit equ 1005
lblStatus equ 1006
lblIPAddress equ 1007
SMM_PORT equ 1a02h
OUT_BUFFER_SIZE equ 1024
IN_BUFFER_SIZE equ 1024
WM_SOCKET equ WM_USER + 100
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
Buffer db OUT_BUFFER_SIZE dup (?)
InBuffer db IN_BUFFER_SIZE dup (?)
hSocket SOCKET ?
hInstance HINSTANCE ?
hIcon HICON ?
hDialog HWND ?
hInBufferMutex HANDLE ?
x WSADATA<?>
hStopEvent dd ?
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
SetStatus proc text: dword
invoke SetDlgItemText, hDialog, lblStatus, text
ret
SetStatus endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WinsockSendData proc
local Recipient: sockaddr_in
local MsgSize: dword
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke GetDlgItemText, hDialog, txtRecipient, addr Buffer, sizeof Buffer
.if eax != 0
invoke inet_addr, addr Buffer
.if eax != INADDR_NONE
mov Recipient.sin_addr, eax
invoke htons,SMM_PORT
mov Recipient.sin_port, ax
mov Recipient.sin_family, AF_INET
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke GetDlgItemText, hDialog, txtMessage, addr Buffer, sizeof Buffer
.if eax != 0
mov MsgSize, eax
inc MsgSize
invoke sendto, hSocket, addr Buffer, MsgSize, 0, addr Recipient, sizeof sockaddr_in
.if eax == SOCKET_ERROR
invoke WSAGetLastError
.else
xor eax, eax ; Message sent
.endif
.else
mov eax, 3 ; Message is empty
.endif
.else
mov eax, 2 ; Invalid IPv4 address
.endif
.else
mov eax, 1 ; No IPv4 address specified
.endif
ret
WinsockSendData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; WARNING - This is a thread procedure!
WinsockGetData proc lpParameter: LPVOID
local SenderIP: dword
local Sender: sockaddr_in
local SenderLen: dword
invoke WaitForSingleObject,hStopEvent,INFINITE
invoke RtlZeroMemory,addr InBuffer,sizeof InBuffer
mov SenderLen, sizeof sockaddr_in
invoke recvfrom, hSocket, addr InBuffer, sizeof InBuffer, 0, addr Sender, addr SenderLen
push Sender.sin_addr
call inet_ntoa
add esp,4
mov SenderIP, eax
invoke MessageBox, 0, addr InBuffer, SenderIP, MB_ICONINFORMATION
invoke ResetEvent,hStopEvent
invoke closesocket, hSocket
jmp WinsockGetData
ret
WinsockGetData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
GetLocalIP proc
invoke gethostbyname,0
lea eax, [eax+12]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax]
ret
GetLocalIP endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DialogProc proc hwndDlg: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
local y: sockaddr_in
mov eax,uMsg
.if eax == WM_INITDIALOG
push hwndDlg
pop hDialog
invoke SendMessage, hwndDlg, WM_SETICON, ICON_SMALL, hIcon
invoke SendMessage, hwndDlg, WM_SETICON, ICON_BIG, hIcon
invoke GetLocalIP
invoke inet_ntoa, eax
invoke SetDlgItemText, hwndDlg, lblIPAddress , eax
invoke CreateEvent,NULL,TRUE,FALSE,NULL
mov hStopEvent,eax
invoke CreateThread, 0, 0, addr WinsockGetData, 0, 0, 0
invoke CloseHandle, eax
.elseif eax == WM_CLOSE
QuitProgram:
invoke EndDialog, hwndDlg, 0
.elseif eax == WM_COMMAND
.if word ptr wParam == cmdSend
invoke socket, AF_INET, SOCK_DGRAM, IPPROTO_UDP
.if eax != INVALID_SOCKET
mov hSocket, eax
invoke RtlZeroMemory,addr y,sizeof y
mov y.sin_family, AF_INET
invoke htons,SMM_PORT
mov y.sin_port, ax
mov y.sin_addr, 0
invoke bind, hSocket, addr y, sizeof sockaddr_in
invoke WSAAsyncSelect, hSocket, hwndDlg, WM_SOCKET, FD_READ
invoke WinsockSendData
push eax
.if eax == 0
fn SetStatus, "Message sent"
.elseif eax == 1
fn SetStatus, "No IPv4 address specified"
.elseif eax == 2
fn SetStatus, "Invalid IPv4 address"
.elseif eax == 3
fn SetStatus, "The message is empty"
.else
.if eax == WSAEHOSTUNREACH
fn SetStatus, "Destination unreachable"
.elseif eax == WSAEADDRNOTAVAIL
fn SetStatus, "Address not available"
.else
fn SetStatus, "Unknown error"
.endif
.endif
pop eax
.if eax!=0
invoke closesocket, hSocket
invoke MessageBeep,MB_ICONHAND
.endif
.else
fn MessageBox, 0, "Failed to initialize Winsock!", "SMM - Error", MB_ICONERROR
jmp QuitProgram
.endif
.elseif word ptr wParam == cmdExit
jmp QuitProgram
.endif
.elseif eax == WM_SOCKET
invoke SetEvent,hStopEvent
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DialogProc endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke GetModuleHandle, 0
mov hInstance, eax
invoke LoadIcon, hInstance, FormIcon
mov hIcon, eax
invoke WSAStartup, 0202h, addr x
.if eax==0
invoke DialogBoxParam, hInstance, frmMain, 0, addr DialogProc, 0
invoke WSACleanup
.else
fn MessageBox, 0, "Failed to initialize Winsock!", "SMM - Error", MB_ICONERROR
.endif
exit
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
Thanks for posting, six_L. Let's see...
QuoteSMM_PORT equ 1a02h
Is there something wrong with 9a02h that I should be aware of? :P Unless you play Doom, you can use it. :)
QuoteWM_SOCKET equ WM_USER + 100
I've searched MSDN about WM_USER. That suits better than RegisterWindowMessage. Thanks.
Quote
...
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke GetDlgItemText, hDialog, txtRecipient, addr Buffer, sizeof Buffer
...
Well, in my opinion, using RtlZeroMemory is useless (just a waste of time), because GetDlgItemText reads and the NULL char.
Quoteinvoke htons,SMM_PORT
I have already byte swapped the port that's why I put it on a compiler constant... Is that wrong?
Quote
...
invoke RtlZeroMemory,addr Buffer,sizeof Buffer
invoke GetDlgItemText, hDialog, txtMessage, addr Buffer, sizeof Buffer
...
Later in sendto I specify the bytes to send... Why use RtlZeroMemory? I mean, there's nothing bad about overlapping data...
Quoteinvoke WaitForSingleObject,hStopEvent,INFINITE
Using an event object to synchronize the thread that reads the data from the socket. Ok by me.
Quote
...
invoke RtlZeroMemory,addr InBuffer,sizeof InBuffer
mov SenderLen, sizeof sockaddr_in
invoke recvfrom, hSocket, addr InBuffer, sizeof InBuffer, 0, addr Sender, addr SenderLen
...
Yet another one, (useless) memory clear operation. Ok, to say the truth, if you must pass a structure with a lot of fields to some function, it would be a nice idea to clear it whole first, and then assign the fields you want accordingly. So, the fields that you were to set to zero, will be already zero. But, this is not the case. Actually, recvfrom writes data to the buffer and returns how much bytes has read. Which means that you know what data to discard. Anyway, later the MessageBox function waits for a null terminating string. By the time the data includes this NULL char, there should be no problem at all.
Quote
...
push Sender.sin_addr
call inet_ntoa
add esp,4
...
I can't understand "add esp, 4"... help please.
Quote
...
invoke ResetEvent,hStopEvent
invoke closesocket, hSocket
jmp WinsockGetData
ret
...
"jmp WinsockGetData": I guessed that before debugging it: This one will rebuild the stack frame, again and again... well until the stack overflows... that'll need some time though, so it's acceptable :P
Quote
...
invoke bind, hSocket, addr y, sizeof sockaddr_in
invoke WSAAsyncSelect, hSocket, hwndDlg, WM_SOCKET, FD_READ
  invoke WinsockSendData
  push eax
.if eax == 0
  fn SetStatus, "Message sent"
.elseif eax == 1
fn SetStatus, "No IPv4 address specified"
.elseif eax == 2
fn SetStatus, "Invalid IPv4 address"
.elseif eax == 3
fn SetStatus, "The message is empty"
.else
.if eax == WSAEHOSTUNREACH
fn SetStatus, "Destination unreachable"
.elseif eax == WSAEADDRNOTAVAIL
fn SetStatus, "Address not available"
.else
fn SetStatus, "Unknown error"
.endif
.endif
pop eax
.if eax!=0
invoke closesocket, hSocket
invoke MessageBeep,MB_ICONHAND
.endif
...
First of all, you invoke bind only when the user decides to send something which means that he won't be able to receive data, right?
Also, I can't figure exactly what goes wrong, but If the user sends a message to an address that is invalid, and then sends a message to a valid one, this code will keep creating sockets, thus generating a leak.
After "invoke WinsockSendData" you push eax, because SetStatus messes up eax value which you want to check after this "if" statement. I have corrected this one in my code. By the time SetStatus returns nothing it would be nice to preserve eax. Thanks again.
Can't really say that your program works, but I learned some things from it. Thanks again :)
hey,StifadoÂ
before you use a buffer or Structure, Clearing its maybe a good habit.
if my code can't work, normally i first use some stupid way to make it running, no matter how it's mess.
Quoteadd esp,4
for balancing the stack.
the trouble of your code isn't the memory leak,is the hSocket's trouble. Service's hSocket isn't same client's hSocket.
can you explain what you're trying to do?Quote[server_1]~~Message
    |<--------- [client_2]
[client_1]----->[server_2]~~Message
the responsibility for recv msg and show msg belong to server's thread (main thread)
the responsibility for send msg belong to client's thread(child thread)
is it right?
Quoteif my code can't work, normally i first use some stupid way to make it running, no matter how it's mess.
And what does this supposed to mean? I've never heard of this "stupid" way to develop logic programs. I don't think it's possible to first write the code and then think of it... that sounds stupid, indeed :P
Quote
Quote
add esp,4
for balancing the stack
Balancing what? Ehm, so what's the value that should be popped of the stack? Where it came from? I mean...
WinsockGetData proc lpParameter: LPVOID
local SenderIP: dword
local Sender: sockaddr_in
local SenderLen: dword
invoke WaitForSingleObject,hStopEvent,INFINITE
invoke RtlZeroMemory,addr InBuffer,sizeof InBuffer
    mov SenderLen, sizeof sockaddr_in
    invoke recvfrom, hSocket, addr InBuffer, sizeof InBuffer, 0, addr Sender, addr SenderLen
push Sender.sin_addr
call inet_ntoa
add esp,4
mov SenderIP, eax
    invoke MessageBox, 0, addr InBuffer, SenderIP, MB_ICONINFORMATION
invoke ResetEvent,hStopEvent
invoke closesocket, hSocket
jmp WinsockGetData
ret
WinsockGetData endp
  (or substitute this with ENTER) This adds a dword on the stack.
[li]l
ocal SenderIP: dword
local Sender: sockaddr_in
local SenderLen: dword[/li]Â Â This one leaves 24B on the stack.
[li]
invoke WaitForSingleObject,hStopEvent,INFINITE[/li]Â Â This one doesn't leave garbage on the stack.
[li]
invoke RtlZeroMemory,addr InBuffer,sizeof InBuffer[/li]  I can't see anything left on the stack while debuging...
[li]
invoke recvfrom, hSocket, addr InBuffer, sizeof InBuffer, 0, addr Sender, addr SenderLen[/li]Â Â Nope.
[li]
push Sender.sin_addr
call inet_ntoa[/li]Â Â Nah.
[li]
invoke MessageBox, 0, addr InBuffer, SenderIP, MB_ICONINFORMATION[/li]Â Â It's an API call after all. It uses stdcall. Or not?
[/list]
Maybe it's something that I'm not aware of...? Please, explain. Need to know.
Quotethe trouble of your code isn't the memory leak,is the hSocket's trouble. Service's hSocket isn't same client's hSocket.
Well, I don't have any experience in Winsock *API* programming... what do you mean "Service's hSocket isn't same client's hSocket."?
Quotecan you explain what you're trying to do?
Merely a simple UDP messagebox-driven chat program. Basically to exercise on API calls.
Quotethe responsibility for recv msg and show msg belong to server's thread (main thread)
Am I writting incomprehensible code? :( Everytime the socket is ready to read data, it spawns a thread that will read the data and display the MessageBox.
Quotethe responsibility for send msg belong to client's thread(child thread)
Actually, the main thread is the one that sends the data...
Quoteis it right?
Definately, no :P
Don't be rude to other members - particularly when they're trying to help. Understand that many members do not have English as their first language, so it's sometimes difficult to get their point across - don't mock them.
Unfortunately, six_L is getting mixed up with tcp socket details, while you're using udp.
As for your code - I can't seem to see anything wrong. The stack's balanced, there's nothing weird going on, resources appear to be cleared up.. Each time you receive a new message, a new thread is created which will increase the memory usage a little, but it's cleaned up again afterwards -- this even coming from program manager, which has a habit of over-estimating memory usage. Also keep in mind that reclamation is done lazily, so the usage won't necessarily drop immediately - try minimizing the window and watch the memory suddenly get reclaimed.
Indeed Tedd, if you display a string in an edit control, windows uses a chunk of allocated memory outside of program space to hold the working copy of that string. If you then remove that edit control, the memory "used" is still marked by TaskMgr as "taken" but in reality, it is free to be overwritten at any time, like a GlobalAlloc chunk which is "freed." Perhaps something along these lines is what is happening here -- windows is allocating temporary memory which TaskMgr is assuming is all taken, but in reality it is just cached temporary memory.
I could try tracing through the calls to determine if this is the case, but it is a lot of work... and why should we help anyone who is not on their best behavior? It is interesting, how much more helpful people can be when you are nice to them.
Hey, I don't remember been rude to anyone here. My native language is not English too (as you should have guessed already). So, maybe the way I express my thoughts is kinda wierd, thus this misunderstadning. I always try to enrich my speech with the sense of humour, and that's why you may find some of my expressions grin... I'm not trying to project that image, of a smart ass. (Not sure about this sentence, syntactically :P)
Now,Tedd. You said that six_L has mixed TCP sockets in this discussion... I can't say that for sure, because I don't know much about sockets but, I beleive you.
Also, I beleive that he hasn't got any bad intesnsion by having a look at my code, and posting it back (changing it to the way he thought that it would be right). So, I've learned about WM_USER message...
While I was looking at his code, I found some things that I thought he might be interested in hearing. I don't think proposals are bad...
...while on the other hand posts like:
Quote
Posted by: evlncrn8
tried debugging your code then?
C' mon! You gotta be kiddin' me, right?
BUT, as far as I remember, I didn't hesitate to answer back, and of course, not in a bad way.
Quote
Each time you receive a new message, a new thread is created which will increase the memory usage a little, but it's cleaned up again afterwards -- this even coming from program manager, which has a habit of over-estimating memory usage. Also keep in mind that reclamation is done lazily, so the usage won't necessarily drop immediately - try minimizing the window and watch the memory suddenly get reclaimed.
That explains (fairly) everything. Though, I have tried minimizing the window, nothing happened. But I guess when the time comes (a need for memory), the "system" will "set it free" (those resources). Thanks for the information.
Hey there, Mark Jones. That was supposed to be braininess? :clap:
hey,Stifado
if udp_1.exe can't work, let me know.
server UDP port: 8889
msg limit: 1024 Bytes
...
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ServerRecvData proc hRecvSocket
local @dwRecv,@dwStructSize
local RecvSin:sockaddr_in
mov @dwStructSize,sizeof sockaddr_in
invoke RtlZeroMemory,addr RecvBuf,sizeof RecvBuf
invoke RtlZeroMemory,addr RecvSin,sizeof RecvSin
invoke recvfrom,hRecvSocket,addr RecvBuf,sizeof RecvBuf,0,addr RecvSin,addr @dwStructSize
.if eax == SOCKET_ERROR
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: server Recv failed!")
.else
invoke inet_ntoa,dword ptr [RecvSin.sin_addr]
invoke Add2Recv,addr RecvBuf,EAX
.endif
ret
ServerRecvData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ClientSendData proc
invoke RtlZeroMemory,addr SendBuf,sizeof SendBuf
invoke GetDlgItemText, hMain, ID_SENDMSG, offset SendBuf, sizeof SendBuf
    .if eax != 0
invoke socket, AF_INET, SOCK_DGRAM, IPPROTO_UDP
.if eax != INVALID_SOCKET
mov hClientSocket, eax
invoke WSAAsyncSelect,hClientSocket,hMain,WM_SOCKET,FD_WRITE
.else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Client socket failed!")
.endif
    .else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Message is empty!")
    .endif
ret
ClientSendData endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ClientThread proc
invoke GetDlgItemText, hMain, ID_SENDIP, offset szTargetIP, sizeof szTargetIP
.if eax!=0
invoke GetDlgItemText, hMain, ID_SENDPORT, offset szPort, sizeof szPort
.if eax!=0
invoke atodw,offset szPort
invoke htons, eax
mov UdpSendAddr.sin_port, ax
mov UdpSendAddr.sin_family, AF_INET
invoke inet_addr, offset szTargetIP
.if (eax != INADDR_NONE) && (eax != 0)
mov UdpSendAddr.sin_addr, eax
invoke ClientSendData
.else
invoke gethostbyname, offset szTargetIP
.if eax != 0
mov eax, dword ptr [eax+12]
mov eax, dword ptr [eax]
mov eax, dword ptr [eax]
mov UdpSendAddr.sin_addr, eax
invoke ClientSendData
.else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Invalid IPv4 address!")
.endif
.endif
.else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: No Port specified!")
.endif
.else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: No IPv4 address specified!")
.endif
ret
ClientThread endp
...
.if uMsg == WM_CREATE
...
invoke socket,AF_INET,SOCK_DGRAM,0
.if eax!=0
mov hServerSocket,eax
invoke WSAAsyncSelect,hServerSocket,hWnd,WM_SOCKET,FD_READ
invoke RtlZeroMemory,addr UdpRecvAddr,sizeof UdpRecvAddr
invoke htons,UDP_PORT
mov UdpRecvAddr.sin_port,ax
mov UdpRecvAddr.sin_family,AF_INET
mov UdpRecvAddr.sin_addr,INADDR_ANY
invoke bind,hServerSocket,addr UdpRecvAddr,sizeof UdpRecvAddr
.if eax == SOCKET_ERROR
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Failed on bind !")
jmp @Exit
.endif
.else
invoke MessageBeep,MB_ICONHAND
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Failed on socket!!")
.endif
...
.elseif uMsg==WM_COMMAND
mov eax,wParam
.if eax==ID_SEND
invoke CreateThread, 0, 0, addr ClientThread, 0, 0, 0
invoke CloseHandle, eax
...
.elseif uMsg == WM_SOCKET
mov eax,lParam
.if ax == FD_READ ; for server
invoke ServerRecvData,wParam
.elseif ax == FD_WRITE ; for client
invoke lstrlen,addr SendBuf
invoke sendto, wParam, addr SendBuf, eax, 0, addr UdpSendAddr, sizeof sockaddr_in
.if eax == SOCKET_ERROR
invoke MessageBeep,MB_ICONHAND
invoke WSAGetLastError
.if eax == WSAEHOSTUNREACH
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Destination unreachable!")
.elseif eax == WSAEADDRNOTAVAIL
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Address not available!")
.else
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("Error: Unknown!")
.endif
.else
invoke inet_ntoa,dword ptr [UdpSendAddr.sin_addr]
invoke Add2Send,addr SendBuf,EAX
invoke SendMessage, hWndStat, SB_SETTEXT, 1, S("OK: Message sent!")
.endif
invoke closesocket,wParam
.endif
the attachment is exe
[attachment deleted by admin]