Reputation: 1
I have just coded in python a very basic IRC bot that connects to a IRC channel and prints what the server returns.
import socket
import time
SERVER = "irc.example.com"
CHANNEL = "#mychannel"
BOTNICK = "mybot"
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ircsock.connect((SERVER, 6667))
ircsock.sendall(bytes("USER "+BOTNICK+" "+BOTNICK+" "+BOTNICK+" :"+BOTNICK+"\r\n", "UTF-8"))
ircsock.sendall(bytes("NICK " + BOTNICK + "\r\n", "UTF-8"))
time.sleep(1)
ircsock.sendall(bytes("JOIN " + CHANNEL + "\r\n", "UTF-8"))
while 1:
text = ircsock.recv(2048).decode("UTF-8")
print(text)
if text.find("PING") != -1 :
print("---- PING ---\n")
ircsock.send(bytes("PONG " + "\r\n", "UTF-8"))
I was wondering, in which order does this code execute ? What I don’t understand is that when I look at the packets I capture with Wireshark, I have for example a packet where the data is :
:irc.hackerzvoice.net NOTICE Auth :*** Looking up your hostname...
This packet is sent to me by the server, before I send the JOIN request, so before the while 1 loop, but, when I execute the script in my shell, it actually prints ":irc.hackerzvoice.net NOTICE Auth :*** Looking up your hostname...", how is it possible ?
Should not only the data I receive after the JOIN request (when I enter the while 1 loop) be printed by my script ? Is the data I receive before the while 1 loop, captured (how ?), stored somewhere and then printed ?
Upvotes: 0
Views: 448
Reputation: 87
I recommend using Trio mini framework. I have an example code of just enough code to handle the irc connection. It works as a proxy server with username user and password pass on port 12345. Check it out at https://github.com/ashburry-chat-irc/trio_ircproxy
All you need is trio_ircproxy.py and an irc client that you can configure to use a proxy server with. Proxy IP will be 127.0.0.1 on port 12345.
Just a warning, I've been committing code without testing so there could be some errors preventing the code from running. Just leave a comment on the GitHub page somewhere if you cannot fix the errors yourself. If someone needs to run the code I will get it operational as long as I am not exhausted because when I am exhausted I cannot code properly. I feel okay right now though, but I am not going to work on the code until tonight unless someone gives me a message saying the code doesn't work.
oh yeah, you will need to pip install trio and pip install cryptocode first.
Upvotes: 0
Reputation: 58929
The operating system receives data from the network card, figures out which program they belong to, and if the program isn't currently calling recv
, it stores the data until it is. When your program calls recv
, it gets the stored data first before it waits for any new data.
If it didn't work this way, it would be basically impossible to write a socket program that actually worked, because you'd lose data all the time. Imagine if a message came in while your program was still processing the last message, before it got to the next recv
call!
If you don't call recv
for a long time, the operating system will refuse to store more data than a certain amount of data, and it will tell the server it's not ready to receive more data, and the server won't send it, and the server's operating system will store some data, and when that's full it will tell the server program that you're not ready to receive (i.e. send
will fail). The server program will store even more data. That's the last line of defense - when that reaches a certain size the server program will just disconnect you. This is the "SendQ exceeded" error in IRC. Each of these intermediate storage spaces is called a "buffer" or "queue" ("send queue" = "SendQ").
IRC servers will disconnect you, but if you're writing your own server that doesn't disconnect people when this happens, it's possible to have a deadlock scenario where both sides are calling send
to happen, and send
is waiting for the other side to be ready to receive more data, but it won't happen because they won't call recv
until send
returns. That's something to be aware of when writing network programs.
Upvotes: 0
Reputation: 12205
That happens because of how IRC servers work. They launch the hostname lookup as soon as you connect, and they send a message to the client about that. The actual hostname lookup should be asynchronous so that your connection is not blocked if the server does not receive a DNS response but that is another matter.
As already mentioned in comments, everything the server sends back is held in a buffer in the order it was received. Your code only starts reading the buffer (server responses) after sending user, nick and join but it does not mean the server only starts sending messages after that.
Upvotes: 3