News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

CMP Part of a String of Bytes?

Started by asmftw, August 19, 2007, 06:02:00 PM

Previous topic - Next topic

asmftw

Hello, I am coding an IRC client for part of an application.

The problem is, I need to send PONG "X" when the client recieves PING "X" from the server.

For example, i recieve:
PING :irc.efnet.ca

I need to send back PONG :irc.efnet.ca

but the ":irc.efnet.ca" part changes in every server I join.

So I need to code something like this:

IF Message contains the word "PING ",
Get the whole message
Replace PONG with PING
move the new message "PING :"X" into send buffer


How could I do it?

Jimg

Assuming Message is the buffer containing the received line, and PING is the first word of the message:
   .if dword ptr Message == "GNIP"
      mov dword ptr Message,"GNOP"
   .endif

asmftw

#2
Quote from: Jimg on August 19, 2007, 06:51:22 PM
Assuming Message is the buffer containing the received line, and PING is the first word of the message:
   .if dword ptr Message == "GNIP"
      mov dword ptr Message,"GNOP"
   .endif


Yes that should work, but it is not working for some reason :/

I dont think what is appearing in Buffer is correct because I attached it with Olly and I only see things that are 3 or 4 bytes long. I attached WPE to debug the winsocks connections and I see everything that should be there though.

Is my Recv command correct?

ircloop:
push 1000
call Sleep ;sleep for 1 second.
mov buffer,0 ;clear buffer
push offset available_data
push FIONREAD
push [sock]
call ioctlsocket    ;Get read length
    .if eax==SOCKET_ERROR
    invoke WSAGetLastError
    invoke MessageBox,NULL,TEXT("SOCKET_ERROR while getting read length"), addr err_title, MB_OK
    .endif
cmp eax,0                 ;if read length = 0 then check again.
jnz ircloop
        invoke GlobalAlloc,GHND,available_data
        mov hMemory,eax
        invoke GlobalLock,eax
        mov buffer,eax

push 0
push available_data
push buffer
push [sock]
call recv

    .if eax==SOCKET_ERROR
    invoke WSAGetLastError
    invoke MessageBox,NULL,TEXT("SOCKET_ERROR during recv"), addr err_title, MB_OK
    .endif
   
      mov actual_data_read,eax ;size of data read
cmp eax,0
jz ircloop

HandlePing:
cmp word PTR [buffer],'IP'       ;is a ping?
      jne NoPing
...

~Paul~

Not sure if this is of any help but this is a tutorial i made in C++ in regards to winsock and stuff ;)

http://ultimatecode.net/showthread.php?p=94#post94

It might help with ASM i know i find ASM and C++ very similar  :cheekygreen:

Tedd

If you're planning on writing a full irc client you're going to need a general strategy for handling messages, not some different way for every different one. Read the RFC and notice how the messages are structured, then you can use the first part to identify the message type and separate its components.
Also note that you won't necessarily receive a full message 'line' in one call to recv, so you'll need to buffer data as it comes in and then parse it into lines before acting on a message.
No snowflake in an avalanche feels responsible.

Jimg

If buffer contains the address of the message, I think the line:
cmp word PTR [buffer],'IP'
should be something like:
mov esi,buffer
cmp word ptr [esi],'IP'


asmftw

#6
Quote from: Jimg on August 20, 2007, 12:50:51 PM
If buffer contains the address of the message, I think the line:
cmp word PTR [buffer],'IP'
should be something like:
mov esi,buffer
cmp word ptr [esi],'IP'



HA! thats what I thought at first it would be but I forgot about it. Thank you very much! :)
@Tedd, it will not be a full blown IRC client. It only needs to be very basic. But thanks for the heads up, you just made me realize some things that I have to change.

I've run into a new problem though, I am trying to make it read up to CRLF so I get single messages only but I get some error called "WSAECONNABORTED" which means there is no space on the socket's queue but I don't see how there isn't.

Here's my function to recieve a line from the server:


recvdata proc ;Revieves data from the socket.
RecvLine:
     mov ReturnBuffer,0 ;clear buffer

GetLine: ;recv until crlf

push offset available_data
push FIONREAD
push [sock]
call ioctlsocket    ;Get read length
cmp eax,0                 ;if read length = 0 then check again.
jnz HaveNoData

invoke recv,sock,ByteBuffer,1,0 ;Receive 1 byte of data.
cmp eax,0 ;error?
je Exit ;if so, exit

      mov esi,ByteBuffer
cmp byte ptr [esi],10          ;arrived CRLF? (CRLF = 10,13)
je HaveLine ;then return

invoke lstrcat,\ ;append byte to buffer
ReturnBuffer,\ ;pointer
ByteBuffer ;the byte

jmp GetLine ;receive next byte

HaveLine: ;we have a line and can..
ret ;...return

HaveNoData:
ret

;  OLD METHOD:
;    invoke ioctlsocket, sock, FIONREAD, addr available_data ;get read length
;    .if eax==NULL
;        invoke GlobalAlloc, GHND, available_data
;        mov hMemory,eax
;        invoke GlobalLock, eax
;        mov ReturnBuffer,eax
;        invoke recv, sock, ReturnBuffer, available_data, 0 ;recv some data
;        mov actual_data_read, eax
;        ;.....
;        ;<use the data in buffer>
;        ;....
;        invoke GlobalUnlock, ReturnBuffer
;        invoke GlobalFree, hMemory
;    .endif
;    ret
recvdata endp

Tedd

Hmm... a few things..

Receiving 1 byte at a time is a terrible idea :bdg If you don't eat up the data fast enough, the socket's buffers will overflow and the connection will abort.
"ByteBuffer" is the value IN ByteBuffer, what you want is "ADDR ByteBuffer" to say save the data there. As it is, you're saying store the data at 0 (or whatever happens to be left in ByteBuffer at the time), which will just cause recv to fail, so you're not receiving the data, leading to overflow and connection aborted :P [Unless ByteBuffer happens to actually be a pointer to a memory block you've allocated, but then why on earth are you only receiving one byte at a time :dazzled:]
CR,LF = 13,10 ::)
By trying to read until you find a newline, you're assuming that you will necessarily receive a whole line at once - this is not always the case! (As I mentioned earlier.)

So, what you really should do is create a bigger buffer (not just one byte!!) and receive a large chunk into that - it doesn't necessarily need to be all the available data at once, but if you don't eat it up fast enough you're going to lose your connection. Yes this will mean you have a bit more work to do by the fact that you'll end up receiving more than one line at some point and so have to take the tail from the buffer and save it for later processing, but that's the fun of programming and problem solving :bdg That said, you 'may' be able to get away with chewing one byte at a time, but I wouldn't recommend it at all; and since you'll have to store them in sequence anyway, you may as well receive them all at once (and deal with the - oh no so complicated - tail that starts the next line.)
No snowflake in an avalanche feels responsible.

asmftw

Ooh thanks for pointing that out, I didn't think it mattered how fast I received the buffer.

I'm starting to think that I don't need to recieve lines until CRLF though because I can make the command functions handle them since I only need PRIVMSG and a few other simple things like that.