Can someone tell me why this prog aint receiving all the data properly. It works only if I use MessageBox inside the recv loop.



.386
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\wsock32.inc
includelib \masm32\lib\wsock32.lib
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
include C:\ASM\string.inc

.data

SOCKSET STRUCT
dwCount dword ?
dwSocket dword ?
SOCKSET ENDS

wsadata WSADATA <?>
fdset SOCKSET <?>
timeout timeval <?>
p sockaddr_in <?>
sock dword ?

sockopt dword 1
recbuf byte 1001 dup (0)
stobuf byte 64000 dup (0)
port dword 80, 0
ipaddress byte "216.17.149.78", 0
slcterror1 byte "select error: write", 0
slcterror2 byte "select error: read", 0
nosend byte "couldn't send data", 0
blockerror byte "couldn't set socket mode", 0
noinit byte "couldn't initialise winsock", 0
nosock byte "couldn't create a socket", 0
noconnect byte "couldn't connect to server", 0
closed byte "connection closed", 0
finished byte "FINISHED", 0
filename byte "bleh.txt", 0
bufwrite dword ?

get byte 'GET /index.html', 10, 13
byte 'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*', 10, 13
byte 'Accept-Language: en-gb', 10, 13
byte 'Accept-Encoding: gzip, deflate', 10, 13
byte 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)', 10, 13
byte 'Host: www.rec.com', 10, 13
byte 'Connection: Keep-Alive', 10, 13, 10, 13, 0 ;258 chars

;=========
.code

start:

@@initialise_winsock:
invoke WSAStartup, 101h, addr wsadata
cmp eax, NULL
jne @@noinit

@@setup_socket:
invoke socket, AF_INET, SOCK_STREAM, 0
cmp eax, INVALID_SOCKET
je @@nosock
mov , eax
invoke htons, 80
mov p.sin_port, ax
invoke inet_addr, addr ipaddress
mov p.sin_addr, eax
mov p.sin_family, AF_INET

@@connect_to_server:
invoke connect, , addr p, sizeof p
cmp eax, SOCKET_ERROR
je @@noconnect

@@make_non_blocking:
invoke ioctlsocket, , FIONBIO, addr sockopt
cmp eax, SOCKET_ERROR
je @@blockerror

@@check_for_sock_write:
mov eax,
mov fdset.dwSocket, eax
mov fdset.dwCount, 1
mov timeout.tv_sec, 3
mov timeout.tv_usec, NULL
invoke select, NULL, NULL, addr fdset, NULL, addr timeout
cmp eax, NULL
je @@slcterror1
cmp eax, SOCKET_ERROR
je @@slcterror1

@@send_request_data:
invoke lstrlen, addr get
invoke send, , addr get, eax, NULL
cmp eax, SOCKET_ERROR
je @@no_send

@@check_for_sock_read:
mov eax,
mov fdset.dwSocket, eax
mov fdset.dwCount, 1
mov timeout.tv_sec, 20
mov timeout.tv_usec, NULL
invoke select, NULL, addr fdset, NULL, NULL, addr timeout
cmp eax, NULL
je @@slcterror2
cmp eax, SOCKET_ERROR
je @@slcterror2

@@receive_data_loop:
invoke recv, , addr recbuf, 1000, NULL
cmp eax, SOCKET_ERROR
je @@finish1
cmp eax, NULL
je @@closed
mov , 0
;invoke MessageBox, NULL, addr recbuf, NULL, MB_OK
invoke _strcat, addr stobuf, addr recbuf ; my append-a-string proc
jmp @@receive_data_loop

@@closed:
invoke MessageBox, NULL, addr closed, addr finished, MB_OK
jmp @@finish2

@@finish1:
invoke _strcat, addr stobuf, addr recbuf ; append the collected data to recbuf

@@finish2:
invoke closesocket,
invoke WSACleanup
invoke CreateFile,\
addr filename,\
GENERIC_WRITE,\
FILE_SHARE_READ or\
FILE_SHARE_WRITE,\
NULL,\
CREATE_ALWAYS,\
FILE_ATTRIBUTE_NORMAL,\
NULL

push eax
invoke lstrlen, addr stobuf
mov edx, eax
pop eax

invoke WriteFile,\
eax,\
addr stobuf,\
edx,\
addr bufwrite,\
NULL

invoke MessageBox, NULL, addr stobuf, addr finished, MB_OK
jmp @@exitproc





;==============
@@no_send:
invoke MessageBox, NULL, addr nosend, NULL, MB_OK
jmp @@exitproc

@@blockerror:
invoke MessageBox, NULL, addr blockerror, NULL, MB_OK
jmp @@exitproc

@@slcterror1:
invoke MessageBox, NULL, addr slcterror1, NULL, MB_OK
jmp @@exitproc

@@slcterror2:
invoke MessageBox, NULL, addr slcterror2, NULL, MB_OK
jmp @@exitproc

@@nosock:
invoke MessageBox, NULL, addr nosock, NULL, MB_OK
jmp @@exitproc

@@noinit:
invoke MessageBox, NULL, addr noinit, NULL, MB_OK
jmp @@exitproc

@@noconnect:
invoke MessageBox, NULL, addr noconnect, NULL, MB_OK

@@exitproc:
invoke ExitProcess, 1

end start
Posted on 2001-09-12 20:06:02 by nin


@@make_non_blocking:
invoke ioctlsocket, [sock], FIONBIO, addr sockopt
cmp eax, SOCKET_ERROR
je @@blockerror


Removing the above code seems to fix the problem. I assume that the required settings have already taken place and this is optional. If anyone would like to further explain, please do so.
Posted on 2001-09-13 14:31:20 by PuffCool
PuffCool: I don't think that's the solution as removing that code makes select useless..
However I tried to assemble your code but of course I didn't had the string.inc, so I just changed all your strcat functions to the lstrcat windows API. Then it ran fine and showed the finish messagebox with full content and no crashes.. So I think there's a bug in your string.inc

Thomas
Posted on 2001-09-13 14:43:31 by Thomas
Problem is PuffCool I need the socket to be non-blocking mode! I did what u did Thomas (using lstrcat) but it didnt collect all the data. Compare the data collected and put into the bleh.txt file with the source from the actual website that IE gives you!
Posted on 2001-09-13 14:53:15 by nin
Thomas

When you ran the application after assembling, did you take a look at the text file that was created? When I used the source as provided, the text file was incomplete, whereas when I took out the selected code, the file was complete. I'm not saying what I did is a proper solution, but just thought i'd bring it to attention.

I am also curious to the solution, however I tried to have the application download an exe file with no success. If anyone knows the proper way, I would gladly appreciate any help.
Posted on 2001-09-13 15:00:10 by PuffCool
The reason why it wont deal with an exe file is cos an exe file is in binary which will contain any of the characters from 0-255. This means that at some point lstrcat will encounter a null byte and stop appending at that point rather than going through the rest of the string. I appreciate you brought the non-blocking (ioctlsocket) to attention but this function has to be there to make the socket a non-blocking socket. I'm just wondering why the text file generated is incomplete when I use a non-blocking mode socket??
Posted on 2001-09-13 15:14:52 by nin
Puffcool: I just had a quick look and overlooked that (sorry for that), thanks

I solved the problem, I guess. Right now, you wait for the socket to have data available (@@check_for_sock_read), but this doesn't mean ALL data is available. It just means, at least one byte is available.. Your code assumes it can just keep on reading until it returns 0 but this isn't true.. It can occur that no data is available at some point. In that case, recv will fail with WSAEWOULDBLOCK, because you are in non-blocking mode, recv fails instead of blocking (i.e. waiting for more data).
Your error is that on any error, you just quit. Instead, first check if you have a WSAEWOULDBLOCK error, and if it is, call select again to wait for more data.. Here is the working code:


.....
@@receive_data_loop:
invoke recv, [sock], addr recbuf, 1000, NULL
cmp eax, SOCKET_ERROR
je @@error ;<<<<<<<<< MODIFIED!!!
.....

; ADDED!!!:
@@error:
invoke WSAGetLastError
.IF eax==WSAEWOULDBLOCK
jmp @@check_for_sock_read
.ENDIF
int 3 ;breakpoint, some other error occured
....


The int 3 is just a breakpoint.. If you reach that point some other error has occurred..

By making these changes I got the full html file in the output file so I think this will do.

Thomas
Posted on 2001-09-14 17:28:47 by Thomas
ahhh thx m8. Now I can move on LOL :). One last question. Sometimes when I try this on a site such as google.com/search?q=art (216.239.39.100) the data in the messagebox is fine but the file output doesnt have all the newline characters in it. Why?
Posted on 2001-09-14 17:54:01 by nin
I think this can only have to do with the way of displaying.. As WriteFile and MessageBox use exactly the same data it has to be this.
Maybe there's a LF of the CRLF missing somewhere, or something else a messagebox displays different than your text editor..
I wouldn't worry about it,

Thomas
Posted on 2001-09-15 04:00:24 by Thomas
unix / linux servers i think use ,13 at the end of a line.
windows uses ,13,10

the message box can probably interpret both but Notepad.exe cant. have a search for TextPad on google. its free and can interpret both types of new line.


hope ive helped ;)
skud.
Posted on 2001-10-02 14:15:33 by skud