Hi guys!

I'm having some design problems with my code. I'm currently writing a file-transfer application in masm.

What I would need some help with is the receiving part of the code.

I need to receive a binary file and then write it to disk, most likely with WriteFile API


Is there any examples online? Searched and searched for hours but havn't found anything useful.

Regards,
n1mda
Posted on 2008-12-12 16:17:16 by n1mda
I think there was Iczelion's zip-download app.
There is also MadWizard's tutorial on networking:  http://www.madwizard.org/programming/tutorials/netasm/
It's actually easy - you initialize winsock, create a socket (connection) to the server, send some header, and start reading from the socket, finally closing the socket.
Posted on 2008-12-12 17:13:30 by Ultrano
Unless you want to do it 'the hard way', check the TransmitFile api function :) Only drawback is that you'll need to emit your data to a 'file to be sent' before making the call, but on the plus side, you can specify overlapped (asynchronous) operation without the need to implement your own IOCP.

Posted on 2008-12-12 20:23:42 by Homer
Thank you for answers guys!

The thing is, I know how to transfer a file. I just don't know how to receive it on the other end.

I guess I would use recv as usual, but I'm not sure about the buffers etc.

ReadSocket PROC

LOCAL mHandle:DWORD
LOCAL mPointer:DWORD
invoke ioctlsocket, hSocket, FIONREAD, addr sizetoread
.if eax != SOCKET_ERROR
invoke GlobalAlloc, GHND, sizetoread
mov mHandle, eax
invoke GlobalLock, eax
mov mPointer, eax
invoke recv, hSocket, mPointer, sizetoread, 0

invoke CreateFile, addr lpszDiskFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
mov hFile, eax
invoke WriteFile, hFile, addr mPointer, sizeof mPointer, addr fwritten, 0
invoke CloseHandle, hFile

invoke GlobalUnlock, mPointer
invoke GlobalFree, mHandle
.endif
ret
ReadSocket ENDP


I'm not sure about this part:
invoke WriteFile, hFile, addr mPointer, sizeof mPointer, addr fwritten, 0
since I don't know if sizeof mPointer is right, or weather I have to write mPointer to the file.

Regards,
n1mda
Posted on 2008-12-13 05:25:23 by n1mda
#1 - create the file before you start receiving... if something goes wrong, you can delete the file.

#2- don't bother peeking to see how much data is available using FIONREAD - theres no reason to , and its slow.


#3- If you dont mind using a blocking socket, just call recv (with a fixed size) in a loop until it returns NULL, or -1.
NULL means the socket has closed, you got all the data.
-1 means SOCKET_ERROR, you can call WSAGetLastError to find out why.
Anything else means #bytes you received - it can vary, depends on a few things, but it will be your fixed size, or less.

When recv has returned a nonzero value, write the data out to the file, and loop for more.
When it returns zero, you're done with the file, you can close the filehandle and return success.
When it returns -1, something is wrong, you can close the filehandle and return failure.

If your question is really about how to call WriteFile, just refer to the Win32 api helpfile, or rephrase your question.
Posted on 2008-12-13 06:57:44 by Homer
Just to nitpick: recv() returns 0, not NULL. 0 is an integer value (ie., count of bytes received), NULL means a pointer.
Posted on 2008-12-13 07:53:07 by f0dder
Thank you for your great explanation Homer! But this is driving me mad. I'm pretty sure I do exactly as you said but it won't work. The file is created, but the buffer is never written to it. I currentl use netcat to just send random messages.

ReadSocket PROC
invoke CreateFile, addr lpszDiskFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
.if eax == INVALID_HANDLE_VALUE
invoke ExitProcess, 0
.endif
mov hFile, eax

_recvloop:
;invoke RtlZeroMemory, addr buff_sock, 512
invoke recv, hSocket, buff_sock, 4096, 0
mov bytes_recieved, eax
.if eax<=0
;invoke MessageBox, 0, addr szErr, addr szErr, MB_OK
invoke CloseHandle, hFile
invoke closesocket, hSocket
invoke WSACleanup
invoke ExitProcess, 0
.else
invoke WriteFile, hFile, buff_sock, bytes_recieved, addr fwritten, 0
;invoke MessageBox, 0, buff_sock, 0, MB_OK
jmp _recvloop
.endif
invoke CloseHandle, hFile

ret
ReadSocket ENDP
Posted on 2008-12-13 09:13:33 by n1mda
Try adding a few lines of code to debug what's going on, especially after the recv call - I find messageboxes to be the most simple way to spew some debug to the screen , when I am not using ObjAsm32 on top of masm (which has excellent debug support).
It's much simpler than tracing it in a debugger, anyway.
Posted on 2008-12-13 11:43:07 by Homer
The ".if eax<=0"  line is wrong. MASM registers by default are treated as unsigned DWORDs by the ".if" statement. (so a "ja" instruction is generated, instead of "jg")
Other than that, your ReadSocket looks correct. Just put some debug-trace "PrintDec bytes_recieved".

Ever since I saw VKDebug, I never returned to MessageBox - it's the ultimate way to debug-trace on the fly :D
Posted on 2008-12-13 12:06:29 by Ultrano
...and who says "in asm, everything is a DWORD"? ;) - type information is useful.

Change to

.if sdword ptr eax<=0


Tada, signed comparison.
Posted on 2008-12-13 12:15:08 by f0dder
This is amazing. I don't see why it shouldn't work, but yet... it doesn't.

Can it have anything to do with that I'm usin async sockets with WSAWaitForMultipleEvents?

When FD_READ is called, i invoke ReadSocket

ReadSocket PROC
invoke CreateFile, addr lpszDiskFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
.if eax == INVALID_HANDLE_VALUE
invoke MessageBox, 0, addr szErr, addr szErr, MB_OK
invoke ExitProcess, 0
.endif
mov hFile, eax

_recvloop:
;invoke RtlZeroMemory, addr buff_sock, 512 ; note that this is commented
invoke recv, hSocket, buff_sock, 4096, 0
mov bytes_recieved, eax
invoke MessageBox, 0, addr szTemp, 0, MB_OK
.if sdword ptr eax<=0
invoke MessageBox, 0, addr szErr, addr szErr, MB_OK
invoke CloseHandle, hFile
invoke closesocket, hSocket
invoke WSACleanup
invoke ExitProcess, 0
.else
invoke WriteFile, hFile, buff_sock, bytes_recieved, addr fwritten, 0
invoke MessageBox, 0, buff_sock, 0, MB_OK
jmp _recvloop
.endif
invoke CloseHandle, hFile

ret
ReadSocket ENDP
Posted on 2008-12-13 13:22:12 by n1mda
:D
Yes, I think it's definitely because of async. Try downloading in a blocking way.
Right now you're creating and resetting the file to size=0 on every received packet.
Posted on 2008-12-13 13:41:39 by Ultrano
Well I set the socket back to blocking-mode within ReadSocket with:
		invoke WSAEventSelect, hSocket, hEvent, 0
invoke ioctlsocket, hSocket, FIONBIO, 0


Still doesn't work :(
Posted on 2008-12-13 14:16:35 by n1mda

Just to nitpick: recv() returns 0, not NULL. 0 is an integer value (ie., count of bytes received), NULL means a pointer.


:lol: NULL "is" zero in ASM and I really hope it is the same in other languages like C, Pascal and etc.
Posted on 2008-12-13 15:27:48 by XCHG

Well I set the socket back to blocking-mode within ReadSocket with:
		invoke WSAEventSelect, hSocket, hEvent, 0
invoke ioctlsocket, hSocket, FIONBIO, 0


Still doesn't work :(


I think it will help if I or somebody else wrote an example code for you?
Posted on 2008-12-13 15:28:47 by XCHG
Hah, well that's not really the way I want to do it  ;)

Trial and error is the best, but if someone has a working example I could take a look ;)
Posted on 2008-12-13 15:47:51 by n1mda


Just to nitpick: recv() returns 0, not NULL. 0 is an integer value (ie., count of bytes received), NULL means a pointer.


:lol: NULL "is" zero in ASM and I really hope it is the same in other languages like C, Pascal and etc.
It might all compile down to "0", but there's different semantic value between "NULL" and "0". Using NULL when you mean 0 is brainrot.
Posted on 2008-12-14 02:29:33 by f0dder
I don't think the cpu actually cares about semantics, hehe.
Yeah I know, NULL and ZERO are not the same semantically, but they are the same numerically.
Arguing about semantics is like .. um.. arguing about semantics.
Posted on 2008-12-14 04:30:17 by Homer
The CPU doesn't care, but then again it isn't the CPU that reads source code - it's humans. Especially when working in a control-freak language like assembly, you ought to program precisely. Writing NULL when you mean 0 is pointless, it muddles up the source, and it takes longer to write. Why do it?
Posted on 2008-12-14 09:46:37 by f0dder
I got it to work. Sort of.

It doesn't loop for data, but recieves 4096 bytes if FD_READ is called. If it's less then 4096 bytes is sent it simply writes whatever bytes that was recieved.

SocketGetFile PROC
invoke CreateFile, addr lpszDiskFile, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
.if eax == INVALID_HANDLE_VALUE
invoke ExitProcess, 0
.endif
mov hFile, eax

invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MEMSIZE
mov hMemory, eax
invoke GlobalLock, hMemory
mov pMemory, eax

invoke recv, hSocket, pMemory, 4096, 0
invoke WriteFile, hFile, pMemory, eax, addr fwritten, NULL
.if eax == 0
invoke ExitProcess, 0
.endif
invoke CloseHandle, hFile
invoke GlobalUnlock, pMemory
invoke GlobalFree, hMemory

ret
SocketGetFile ENDP
Posted on 2008-12-18 11:24:38 by n1mda