learn to sockets ammar (also made gui optional)

This commit is contained in:
Ammar Askar 2012-04-12 01:22:58 +05:00
parent 135c924f8d
commit 04046d0b47
4 changed files with 136 additions and 50 deletions

View File

@ -9,34 +9,52 @@ import struct
#Eclipse pyDev error fix
wx=wx
class ServerConnection:
EntityID = 0
class ServerConnection(threading.Thread):
def __init__(self, window, username, password, sessionID, server, port):
threading.Thread.__init__(self)
self.username = username
self.password = password
self.sessionID = sessionID
self.server = server
self.port = port
if(window == None):
self.NoGUI = True
self.window = window
def attemptConnection(self):
def run(self):
self.socket = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
try:
self.socket.connect ( ( self.server, self.port ) )
PacketManager.sendString("\x02", self.username + self.server + ":" + str(self.port), self.socket)
response = PacketManager.readStringFromSocket(self.socket)
serverid = response['string']
PacketManager.sendString("\x02", self.username + ";" + self.server + ":" + str(self.port), self.socket)
if(self.socket.recv(1) == "\x02"):
response = PacketManager.handle02(self.socket)
else:
print "Server responded with a malformed packet"
pass
serverid = response
if(serverid != '-'):
url = "http://session.minecraft.net/game/joinserver.jsp?user=" + self.username + "&sessionId=" + self.sessionID + "&serverId=" + serverid
response = urllib2.urlopen(url).read()
if(response != "OK"):
self.window.connectStatus.SetLabel("Response from sessions.minecraft.net wasn't OK")
if(self.NoGUI == False):
self.window.connectStatus.SetLabel("Response from sessions.minecraft.net wasn't OK")
else:
print "Response from sessions.minecraft.net wasn't OK, it was " + response
return False
PacketManager.sendLoginRequest(self.socket, self.username)
PacketListener(self.window, self.socket).start()
else:
print "Server is in offline mode"
PacketManager.sendLoginRequest(self.socket, self.username)
except Exception, e:
self.window.connectStatus.SetForegroundColour(wx.RED)
self.window.connectStatus.SetLabel("Connection to server failed")
if(self.NoGUI == False):
self.window.connectStatus.SetForegroundColour(wx.RED)
self.window.connectStatus.SetLabel("Connection to server failed")
else:
print "Connection to server failed"
traceback.print_exc()
return False
@ -51,15 +69,24 @@ class PacketListener(threading.Thread):
self.socket.settimeout(60)
while True:
try:
response = self.socket.recv(256)
response = self.socket.recv(1)
except socket.timeout, e:
self.window.connectStatus.SetLabel("Ping timeout")
if(self.NoGUI == False):
self.window.connectStatus.SetLabel("Ping timeout")
else:
print "Ping timeout"
break
print hex(ord(response[0]))
if(response[0] == "\x00"):
PacketManager.handle00(self.socket)
if(response[0] == "\x01"):
PacketManager.handle01(self.socket)
if(response[0] == "\x03"):
PacketManager.handle03(self.socket)
if(response[0] == "\xFF"):
response = response[3:].decode("utf-16be", 'strict')
print response
#DisconMessage = PacketManager.handleFF(self.socket, response)
self.window.connectStatus.SetLabel("Disconnected: " + response)
DisconMessage = PacketManager.handleFF(self.socket, response)
if(self.NoGUI == False):
"Disconnected: " + DisconMessage
else:
self.window.connectStatus.SetLabel("Disconnected: " + DisconMessage)

28
NoGUIstuff.py Normal file
View File

@ -0,0 +1,28 @@
import urllib2, urllib
def loginToMinecraft(username, password):
try:
url = 'https://login.minecraft.net'
header = {'Content-Type' : 'application/x-www-form-urlencoded'}
data = {'user' : username,
'password' : password,
'version' : '13'}
data = urllib.urlencode(data)
req = urllib2.Request(url, data, header)
opener = urllib2.build_opener()
response = opener.open(req)
response = response.read()
print response
except urllib2.URLError:
toReturn = {'Response' : "Can't connect to minecraft.net"}
return toReturn
if(response == "Bad login"):
toReturn = {'Response' : "Incorrect username/password"}
return toReturn
response = response.split(":")
sessionid = response[3]
toReturn = {'Response' : "Good to go!",
'Username' : response[2],
'SessionID' : sessionid
}
return toReturn

View File

@ -7,13 +7,6 @@ def sendString( packetid, string, socket):
socket.send(packetid)
socket.send(length)
socket.send(string.encode('utf-16be','strict'))
def readStringFromSocket(socket):
response = socket.recv(256)
packetid = response[0]
response = response[3:]
response = response.decode("utf-16be")
return {'packetid' : packetid, 'string' : response}
def sendLoginRequest(socket, username):
socket.send("\x01")
@ -27,37 +20,53 @@ def sendLoginRequest(socket, username):
socket.send(struct.pack('!b', 0))
socket.send(struct.pack('!B', 1))
socket.send(struct.pack('!B', 0))
def ReceiveLoginRequest(socket):
response = socket.recv(256)
packetid = response[0]
if(packetid != "\x01"):
return ""
response = response[1:]
def handle00(socket):
print "Sending keep alive response"
socket.send("\x00")
socket.send(struct.pack('!i', 0))
KAid = struct.unpack('!i', socket.recv(4))[0]
print "Sending keep alive response " + str(KAid)
socket.send("\x00" + struct.pack('!i', KAid))
def handle01(socket):
Eid = struct.unpack('!i', socket.recv(4))[0]
length = struct.unpack('!h', socket.recv(2))[0] * 2
socket.recv(length)
length = struct.unpack('!h', socket.recv(2))[0] * 2
socket.recv(length)
mode = struct.unpack('!i', socket.recv(4))[0]
dimension = struct.unpack('!i', socket.recv(4))[0]
difficulty = struct.unpack('!b', socket.recv(1))[0]
socket.recv(1)
maxplayers = struct.unpack('!B', socket.recv(1))[0]
toReturn = {'EntityID' : Eid,
'Mode' : mode,
'Dimension' : dimension,
'Difficulty' : difficulty,
'MaxPlayers' : maxplayers
}
print toReturn
return toReturn
def handle02(socket):
length = struct.unpack('!h', socket.recv(2))[0] * 2
message = socket.recv(length)
message = message.decode('utf-16be', 'strict')
return message
def handle03(socket):
length = struct.unpack('!h', socket.recv(2))[0]
message = socket.recv(length)
message = message.decode('utf-16be','strict')
print message
return message
def handleFF(socket, response):
response = response[3:]
print "Length: " + str(response.__len__())
print response
response = socket.recv(2)
length = struct.unpack('!h', response)[0] * 2
response = socket.recv(length)
response = response.decode("utf-16be", 'strict')
print response
return response
def handleIncomingPacket(socket):
response = socket.recv(256)
if not response:
handleIncomingPacket(socket)
packetid = response[0]
print str(ord(packetid))
if(packetid == "\x00"):
handle00(socket, response)
elif(packetid == "\xFF"):
handleFF(socket, response)

View File

@ -5,6 +5,7 @@ import socket
import sys
import PacketManager
import NetworkManager
import NoGUIstuff
import time
import threading
import thread
@ -104,7 +105,7 @@ class Window(wx.Frame):
host = StuffEnteredIntoBox
port = 25565
self.connection = NetworkManager.ServerConnection(self, self.username, self.password, self.sessionID, host, port)
thread.start_new_thread(self.connection.attemptConnection, ())
self.connection.start()
def OnButtonClick(self, event):
if(self.entry.GetValue() == ""):
@ -204,9 +205,30 @@ class KeepConnectionAlive(threading.Thread):
popup.ShowModal()
if __name__ == "__main__":
app = wx.App(0)
Window(None, title='pyCraft')
app.MainLoop()
if (len(sys.argv) > 1):
if(sys.argv[1] == "nogui"):
user = raw_input("Enter your username: ")
passwd = getpass.getpass("Enter your password: ")
derp = NoGUIstuff.loginToMinecraft(user, passwd)
if(derp['Response'] == "Incorrect username/password" or derp['Response'] == "Can't connect to minecraft.net"):
print derp['Response']
sys.exit()
sessionid = derp['SessionID']
print "Logged in as " + derp['Username'] + "! Your session id is: " + sessionid
stuff = raw_input("Enter host and port if any: ")
if ':' in stuff:
StuffEnteredIntoBox = stuff.split(":")
host = stuff[0]
port = stuff[1]
else:
host = stuff
port = 25565
connection = NetworkManager.ServerConnection(None, derp['Username'], passwd, sessionid, host, port)
connection.start()
else:
app = wx.App(0)
Window(None, title='pyCraft')
app.MainLoop()
"""
url = 'https://login.minecraft.net'