I am writing a basic irc client (masm), right now it connects and I send the USER/NICK info, that works, then it sends me a ping, I am writing to recv the ping and pong it back, I should recv "PING 4444444444444" 444's being the ping ID or w/e. and what I do is check if the first 4 letters are PING, then pong back that ID.. but I recv more than PING..

 

rcvloop:
invoke recv, sckMain, addr buffer, sizeof buffer, 0
invoke MessageBox, 0, addr buffer, addr App, 0

invoke midstr, addr buffer, addr pongbuff, 0, 4
invoke lstrcmpi, addr pingbuff, addr ping
.if EAX==0
invoke midstr, addr buffer, addr pingcode, 5, 128
invoke lstrcat, addr pongbuff, addr pong
invoke lstrcat, addr pongbuff, addr pingcode
invoke send, sckMain, addr pongbuff, sizeof pongbuff, 0
invoke MessageBox, 0, addr pongbuff, addr App, 0
jmp TheEnd
.endif
jmp rcvloop

the second invoke (msgbox) shows "notice: hostname found.. cached" followed by 2 other lines then a blank line THEN the ping line, which should be alone.
Posted on 2003-06-20 23:50:20 by KewLexX
Why do you expect it to be alone? IRC commands, as in many other protocols, are separated by CRLF, and you should tokenize up your packets in that fashion, whether they come alone or several together.
Posted on 2003-06-21 00:20:07 by comrade
How do I tokenize? Also I am using a recv loop to recv data, Is their another way? using Messages?
Posted on 2003-06-21 14:51:06 by KewLexX
He means to scan all data that comes in on the wire for a CRLF, and when you find one, to consider all the data up to that point to be your packet. Pluck it out of the data stream and then parse it.

Also I am using a recv loop to recv data, Is their another way? using Messages?


There are many different ways. Check Thomas's winsock tutorial.
Posted on 2003-06-21 14:57:17 by iblis
What is wrong with this? I am using a tokenizer dll I found online.


.data
tOke db 0Dh,0Ah ;CRLF

rcvloop:
invoke RtlZeroMemory, addr buffer, 1024
invoke recv, sckMain, addr buffer, sizeof buffer, 0
invoke TokenizeString, addr buffer, addr tOke
mov handle, EAX
.if EAX
invoke GetCurrentToken, EAX
.while EAX
invoke MessageBox, 0, EAX, addr App, 0
cmp EAX, offset authX
je AuthX
invoke GetNextToken, handle
.endw
invoke KillTokenHandle, handle
.endif
AuthX:

AuthX sends out the info to auth (USER and NICK info)..
Posted on 2003-06-21 17:43:34 by KewLexX
Maybe token has to be null-terminated?
Posted on 2003-06-21 19:55:43 by comrade
Tried, same thing, these are the messages I guess, in order: (a blank line means its in a separate msgbox)
NOTICE AUTH: *** Looking up your hostname
NOTICE AUTH: *** Checking Ident

NOTICE AUTH: *** Looking up your hostname

NOTICE AUTH: *** Checking Ident

NOTICE AUTH: *** Couldn't look up your hostname

and then
ERROR: Closing Link: cK-pLayer1 by Slim.ny.us.gamesnet.net (ping timeout)

followed by an inifinite empty msgbox

The code looks for a msg starting with PING and then pongs it back..

 

.386
.model flat, stdcall

include /masm32/include/win32.inc ;shell32 user32 kernel32 wsock32 advapi32
include toke.inc
includelib toke.lib

.data
App db "basic irc cLient, gui later on",0
irc_server db "216.179.62.108",0 ;Gamesnet
HostInfo hostent <>
Err db "Error", 0

;iDent host HOST:PORT/0 :FIRST LAST
AuthInfo db "USER boner keke keke:4005/0 :Jansen Guim",0Dh,0Ah,0
NickInfo db "NICK cK-pLayer1",0Dh,0Ah,0
pong db "PONG ", 0
ping db "PING",0
authX db "NOTICE AUTH :*** Checking Ident",0
tOke db 0Dh,0Ah,0

.data?
sckMain dd ?
wsaData WSADATA <?>
buffer db 1024 dup(?)
bHost dd ?
sckInfo sockaddr_in <?>
pongbuff db 128 dup(?)
pingbuff db 128 dup(?)
pingcode db 128 dup(?)
handle dd ?

.code
start:
invoke WSAStartup, 101h, offset wsaData
retry:
mainsocket_listen:
invoke socket, PF_INET, SOCK_STREAM, 0
cmp EAX, INVALID_SOCKET
jz retry
mov sckMain, EAX

mov sckInfo.sin_family, PF_INET
invoke htons, 6667
mov sckInfo.sin_port, AX
invoke inet_addr, addr irc_server
;mov [sckInfo.sin_addr.S_un.S_addr], eax
mov sckInfo.sin_addr, EAX

invoke bind, sckMain, addr sckInfo, sizeof sckInfo
connect_lbl:
invoke connect,sckMain, addr sckInfo, sizeof sckInfo
test EAX, EAX
jz done
invoke MessageBox, 0, addr Err, addr App, 0
jmp TheEnd
done:
invoke Sleep, 400
invoke send, sckMain, addr NickInfo, sizeof NickInfo, 0
invoke send, sckMain, addr AuthInfo, sizeof AuthInfo, 0
;invoke Sleep, 200
;invoke send, sckMain, addr pong, sizeof pong, 0
rcvloop:
invoke RtlZeroMemory, addr buffer, 1024
invoke recv, sckMain, addr buffer, sizeof buffer, 0
invoke MessageBox, 0, addr buffer, addr App, 0
;Check if pong, if so, pong it back
invoke midstr, addr buffer, addr pingbuff, 0, 4
invoke lstrcmpi, addr pingbuff, addr ping
.if EAX==0
invoke midstr, addr buffer, addr pingcode, 5, 128
invoke lstrcat, addr pongbuff, addr pong
invoke lstrcat, addr pongbuff, addr pingcode
invoke send, sckMain, addr pongbuff, sizeof pongbuff, 0
invoke MessageBox, 0, addr pongbuff, addr App, 0
jmp rcvloop
.endif
invoke TokenizeString, addr buffer, addr tOke
mov handle, EAX
.if EAX
invoke GetCurrentToken, EAX
.while EAX
invoke MessageBox, 0, EAX, addr App, 0
cmp EAX, offset authX
je AuthX
invoke GetNextToken, handle
.endw
invoke KillTokenHandle, handle
.endif
AuthX:
invoke send, sckMain, addr NickInfo, sizeof NickInfo, 0
invoke send, sckMain, addr AuthInfo, sizeof AuthInfo, 0
jmp rcvloop

TheEnd:
invoke closesocket, sckMain
invoke WSACleanup
invoke ExitProcess, 0
end start



Can someone please help getting it to work, I jsut want it to connect, I can implement the JOIN/QUIT/NICK commands later on. thanks
Posted on 2003-06-21 21:28:46 by KewLexX
This part:
cmp EAX, offset authX


You need to check actual contents of string, use strcmp.
Posted on 2003-06-21 21:54:42 by comrade
My IRC client didn't tokenize anything.
I simply used http-style parsing to set flags which trigger events.
For example, one such flag might be called INeedToEmitAPong (its TRUE!)
Posted on 2003-06-21 22:47:20 by Homer
Ok I tried strcmp, same problem. Does anyone have ANY example of just using winsock API to connect to an IRC server? I can do the other commands like whois/nick/join/quit..etc.

ANY example? JUST to connect to a server? or anyone know what's wrong with my code? please help.. I've been trying to figure out what's wrong for 2 days..
Posted on 2003-06-22 13:28:31 by KewLexX
I am reading the source for ldirc.asm or something, I found it on this board, it compiles but crashes shortly after running. Anyone know whats wrong with it? (XP)
Posted on 2003-06-23 15:57:14 by KewLexX
HAH, I am finally getting another message, now it finds my hostname, 1 question tho,

This is the info I need to send:
USER boner keke host_name:local_port/0 :Jansen followed by a CrLf

How do I find my hostname and localport?

also what is this:
Nick db 'hitchhikr'
db 31-9 dup (0)

what is 31-9 for?
Posted on 2003-06-23 16:09:46 by KewLexX
In crude pseudo-code terms:

---
send() the 'user' and 'nick' stuff...

start recv()ing byte by byte and store it in a buffer in a loop until you hit a carraige return...

say esi is your pointer to the buffer, then all you need to do is mov byte ptr ,'O' to change 'ping' into 'pong', and send the buffer right back.
---

i hope this isn't too hard for you, if you need some code to start off, just post or tell me......

hope this helped!
Posted on 2003-06-23 18:06:17 by Drocon
I never thought of that, awsome :) anway:
I got it to connect, it connects fine now but lets say I want it to join a channel right when it connects, I dont think I can just do a send("JOIN #CHAN") right when it connects because it will be sending me the motd and whatnot, how do I check if motd is done (for any server) and then join when it can?
Posted on 2003-06-23 18:14:20 by KewLexX

I never thought of that, awsome :) anway:
I got it to connect, it connects fine now but lets say I want it to join a channel right when it connects, I dont think I can just do a send("JOIN #CHAN") right when it connects because it will be sending me the motd and whatnot, how do I check if motd is done (for any server) and then join when it can?


as far as i know, you don't need to wait for any motd, since it's not like telnet where you have to wait for your client to display what it has received, and then allow you to input something. just directly send() the join chan cmd, or if you want to be on the safe side, do a invoke Sleep,100
Posted on 2003-06-23 18:57:46 by Drocon
Ok, how would I split up the string, like this is an example:

The user types /join #channel, right now I can check if the command pressed is /join, but how do I get the #channel part separate from /join, know what I mean? so I can send "JOIN " followed by the #channel
Posted on 2003-06-23 19:15:49 by KewLexX
You need to set up a system for parsing user commands and a system for translating those commands to the appropriate IRC message. Example, your commands could be of the format: /command arg1 arg2 arg3... etc. Using the space character as a delimeter, you could scan the string for spaces, replace the spaces with null, and then save the offsets of the spaces as a pointer, and store each pointer in an array. Then you would pass that array to another procedure which would handle the commands, arguments, and rebuild a string to send to the server. It's similar to the setup of C's int main( int argc, char ** argv ); argc is the number of arguments, and argv is a pointer to an array of string pointers.

Once you've identified the command and any arguments, validated them, you can begin to build the string to send to the server.

The answer should be evident. If it's not then maybe you should work on a smaller project and tackle writing an IRC client sometime later once you have the basics down.
Posted on 2003-06-24 01:27:39 by iblis
badabing badaboom
Posted on 2003-06-24 02:18:45 by Homer
Ok, I am working on that now, I started a separate project to learn/practice string manipulation and whatnot, this is waht I have, I replaced the " " with a null, but now how do I say them on an array?

 

.386
.model flat,stdcall
option casemap:none

include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

.data
string db "this string has a lot of spaces. can you say 15", 0

.data?

.code
startp:

mov esi, offset string
goop:
cmp byte ptr [esi],' '
je found
cmp byte ptr [esi], 0 ;terminating 0
je NoMore
inc esi
jmp goop
found:
;If a space is found
;replace it with a 0h
mov byte ptr [esi], 0h
inc
;invoke MessageBox, 0, esi, addr string, 0
inc esi
jmp goop
NoMore:

invoke ExitProcess, 0
end startp

Posted on 2003-06-24 14:37:58 by KewLexX
uh, off the top of my head:





.data
string BYTE '/join #moo',0
chan BYTE 256 dup(0)

.code

mov esi,offset string
mov edi,offset chan

@@:
lodsb
inc esi
cmp al,' '
jne @B
@@:
lodsb
test al,al
jz @F
stosb
inc esi
inc edi
jmp @B
@@:
;okay! now chan = channel name :)



dunno if it works, but it basically checks to see if it has reached a space, and keeps on incrementing, and then copies everything from the space to the null terminator...

hope this helped!
Posted on 2003-06-24 15:24:03 by Drocon