Ooops
July 09, 2020, 10:09:39 AM

Author Topic: Segmentation fault  (Read 365 times)

Offline wombats

  • Jr. Member
  • **
  • Posts: 51
Segmentation fault
« on: June 08, 2020, 02:23:15 PM »
Hi,

I'm trying to get an old project of mine to work in BlitzMax NG. It uses this networking code by JoshK. I had to make some changes to get it to compile with the new ENet in NG:

Code: [Select]
Private

Const ENET_PACKET_FLAG_UNSEQUENCED:Int=2
Const SERVERUPDATEFREQUENCY:Int=4*1000*60

Function enet_host_port:Int( peer:Byte Ptr  )
Local ip:Int=(Int Ptr peer)[1]
Local port:Int=(Short Ptr peer)[4]
?LittleEndian
ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
?
Return port
EndFunction

Function enet_host_ip:Int( peer:Byte Ptr  )
Local ip:Int=(Int Ptr peer)[1]
Local port:Int=(Short Ptr peer)[4]
?LittleEndian
ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
?
Return ip
EndFunction

Function enet_peer_port:Int( peer:Byte Ptr  )
Local ip:Int=(Int Ptr peer)[3]
Local port:Int=(Short Ptr peer)[8]
?LittleEndian
ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
?
Return port
EndFunction

Function enet_peer_ip:Int( peer:Byte Ptr  )
Local ip:Int=(Int Ptr peer)[3]
Local port:Int=(Short Ptr peer)[8]
?LittleEndian
ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
?
Return ip
EndFunction

Public

Type TNetworkNode

Field port:Int
Field ip:Int
Field enethost:Byte Ptr
Field enetpeer:Byte Ptr

Method Delete()
Free()
EndMethod

Method Free()
If enethost
enet_host_destroy(enethost)
enethost=Null
EndIf
EndMethod

Method Update()

Local ip:Int,port:Int,client:TClient,ev:ENetEvent=New ENetEvent,id:Byte,packet:TPacket

If Not Self.enethost RuntimeError "Can't update a remote server."
Repeat
If enet_host_service(Self.enethost,ev,0)

Select ev.event

Case ENET_EVENT_TYPE_CONNECT
id=NETWORK_CONNECT

Case ENET_EVENT_TYPE_DISCONNECT
id=NETWORK_DISCONNECT

Case ENET_EVENT_TYPE_RECEIVE
Local size:Int=bmx_enet_packet_size(ev.packet)
Local data:Byte[size]
MemCopy(Varptr id,bmx_enet_packet_data(ev.packet),1)
If size>1
packet=New TPacket
packet._bank.resize(size-1)
MemCopy(packet._bank.buf(),bmx_enet_packet_data(ev.packet)+1,size-1)
EndIf

Default
Continue

EndSelect

EvaluateEvent(id,packet,ev.peer)

Else
Exit
EndIf

If enethost=Null Exit

Forever

EndMethod

Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Abstract

EndType

'Public


Const NETWORK_CONNECT:Int=1
Const NETWORK_DISCONNECT:Int=2
Const NETWORK_PINGREQUEST:Int=3
Const NETWORK_PINGRESPONSE:Int=4
Const NETWORK_JOINREQUEST:Int=5
Const NETWORK_JOINRESPONSE:Int=6
Const NETWORK_CHAT:Int=7
Const NETWORK_LEAVEGAME:Int=8
Const NETWORK_CHANGENAMEREQUEST:Int=9
Const NETWORK_CHANGENAMERESPONSE:Int=10
Const NETWORK_PLAYERJOINED:Int=11
Const NETWORK_PLAYERLEFT:Int=12
Const NETWORK_LEAVEGAMEREQUEST:Int=13
Const NETWORK_LEAVEGAMERESPONSE:Int=14
Const NETWORK_PLAYERCHANGEDNAME:Int=15

Const SEND_RELIABLE:Int=ENET_PACKET_FLAG_RELIABLE
Const SEND_UNSEQUENCED:Int=ENET_PACKET_FLAG_UNSEQUENCED

Type TServer Extends TNetworkNode

Field clients:TList=New TList
Field callback(server:TServer,client:TClient,id:Int,packet:TPacket)
Field bannedips:Int[]
Field clientmap:TMap=New TMap
Field url:String
Field lastrefreshtime:Int

Method Free()
If url
Remove()
url=""
EndIf
Super.Free()
EndMethod

Function EncodeURL:String(t:String)
Local newString:String
Local i:Int,c:String,asciival:Int,hexstr:String,newhexstr:String
For i = 0 To Len(t)
c:String = t[i..i+1]
asciival = Asc(c)
If asciival > 32 And asciival < 123
' handle replacing the special set of chars
c = Replace(c,"'","%27")
c = Replace(c,"%","%25")
c = Replace(c,"<","%3C")
c = Replace(c,">","%3E")
c = Replace(c,"\","%5C")
c = Replace(c,"^","%5E")
c = Replace(c,"[","%5B")
c = Replace(c,"]","%5D")
c = Replace(c,"+","%2B")
c = Replace(c,"$","%24")
c = Replace(c,",","%2C")
c = Replace(c,"@","%40")
c = Replace(c,":","%3A")
c = Replace(c,";","%3B")
c = Replace(c,"/","%2F")
c = Replace(c,"!","%21")
c = Replace(c,"#","%23")
c = Replace(c,"?","%3F")
c = Replace(c,"=","%3D")
c = Replace(c,"&","%26")
newString:+c
Else
hexstr$ = Hex(asciival)
newhexstr$ = "%" + hexstr[Len(hexstr)-2..Len(hexstr)]
newstring:+newhexstr
EndIf
Next

newstring = newstring[..Len(newstring)-3]
Return newstring
EndFunction

Function Create:TServer(port:Int=0,portrange:Int=40)
Local addr:Byte Ptr,server:TServer=New TServer

server.ip=DottedIPToInt(ENET_HOST_ANY)
If portrange<=1
server.port = port
addr=enet_address_create(server.ip,server.port)
server.enethost=enet_host_create(addr,32,0,0,0)
enet_address_destroy(addr)
Else
If port=0 port=7777
For Local n:Int=port To port+portrange-1
addr=enet_address_create(ENET_HOST_ANY,n)
server.enethost=enet_host_create(addr,64,0,0,0)
enet_address_destroy(addr)
If server.enethost
server.port=n
Exit
EndIf
Next
EndIf
If Not server.enethost Return Null
Return server
EndFunction

Method Publish:Int(servername:String="",gamename:String="",url:String="http::www.leadwerks.com/gameservers/gameservers.php")
Local stream:TStream
gamename=EncodeURL(gamename)
servername=EncodeURL(servername)
Self.url=url
stream=OpenStream(url+"?action=addserver&gamename="+gamename+"&servername="+port+"|"+servername)
If Not stream Return False
Self.url=url
While Not stream.Eof()
Local s:String=stream.ReadLine()
If s.Trim()
stream.close()
Return False
EndIf
Wend
stream.close()
lastrefreshtime=MilliSecs()
Return True
EndMethod

Method Remove:Int()
Local stream:TStream
stream=OpenStream(url+"?action=removeserver")
If stream
stream.close()
Return True
Else
Return False
EndIf
EndMethod

Function Query:String[](gamename:String="",url:String="")
Local stream:TStream,s:String,sarr:String[],n:Int

If url="" url="http::www.leadwerks.com/gameservers/gameservers.php"
stream=OpenStream(url+"?action=listservers&gamename="+gamename)
If Not stream Return Null
While Not stream.Eof()
s=ReadLine(stream)
If s.Trim().length>0
sarr=sarr[..sarr.length+1]
sarr[sarr.length-1]=s.Trim()
Local sa:String[]=sarr[sarr.length-1].split("|")
Local name:String=sa[0]
sarr[sarr.length-1]=HostIp(name)+"|"+sarr[sarr.length-1]
EndIf
Wend
stream.close()
Return sarr
EndFunction

Method Refresh:Int()
Local stream:TStream
stream=OpenStream(url+"?action=refreshserver")
If Not stream Return False
stream.close()
Return True
EndMethod

Method FindClientByName:TClient(name:String)
Return TClient(clientmap.valueforkey(name))
EndMethod

Method FindClientByPeer:TClient(peer:Byte Ptr)
Local client:TClient
For client=EachIn clients
If client.enetpeer=peer Return client
Next
EndMethod

Method FindClient:TClient(ip:Int,port:Int)
Local client:TClient
For client=EachIn clients
If client.ip=ip And client.port=port Return client
Next
EndMethod

Method Update()
Rem
If url
Local time:Int=MilliSecs()
If time-lastrefreshtime>serverupdatefrequency
lastrefreshtime=time
Refresh()
EndIf
EndIf
EndRem
Super.Update()
EndMethod

Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr)
Local client:TClient=FindClient(enet_peer_ip(enetpeer),enet_peer_port(enetpeer))
Select id

Case NETWORK_PINGRESPONSE
client.latency=MilliSecs()-packet.ReadInt()

Case NETWORK_LEAVEGAMEREQUEST
If client
Send(client,NETWORK_LEAVEGAMERESPONSE,Null,SEND_RELIABLE)
Local relay:TPacket=New TPacket
relay.WriteLine(client.name)
Broadcast(NETWORK_PLAYERLEFT,relay,SEND_RELIABLE)
clients.remove(client)
If clientmap.valueforkey(client.name)=client clientmap.remove(client.name)
EndIf

Case NETWORK_JOINREQUEST
If client
Disconnect(client,1)
Local relay:TPacket=New TPacket
relay.WriteLine(client.name)
Broadcast(NETWORK_PLAYERLEFT,relay,SEND_RELIABLE)
EndIf
client=TClient.Find(enet_peer_ip(enetpeer),enet_peer_port(enetpeer))
client.enetpeer=enetpeer

If IPBanned(client.ip)
Disconnect(client,0)
Return
Else
client.name=packet.ReadLine()
If Not FindClientByName(client.name)
clientmap.insert(client.name,client)
clients.AddLast(client)
Local responsepacket:TPacket=New TPacket
responsepacket.WriteByte(1)
responsepacket.WriteByte(clients.count()-1)
Local peer:TClient
For peer=EachIn clients
If peer<>client responsepacket.WriteLine(peer.name)
Next
Send(client,NETWORK_JOINRESPONSE,responsepacket,SEND_RELIABLE)
id=NETWORK_PLAYERJOINED

'Tell everyone he joined
responsepacket=New TPacket
responsepacket.WriteLine(client.name)
Broadcast(NETWORK_PLAYERJOINED,responsepacket,SEND_RELIABLE)

Else
packet=New TPacket
packet.WriteByte(0)'no, you can't joint
packet.WriteByte(1)'reason: name already taken
Send(client,NETWORK_JOINRESPONSE,packet,SEND_RELIABLE)
'Disconnect(client,0)
Return
EndIf
EndIf

Case NETWORK_CHANGENAMEREQUEST
Local name:String=packet.ReadLine()
packet=New TPacket
If client
Local oldname:String=client.name
If FindClientByName(name)<>Null And client.name<>name
packet.WriteByte(0)
send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
Return
Else
packet.WriteByte(1)
packet.WriteLine(name)
send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
clientmap.remove(client.name)
client.name=name
clientmap.insert(name,client)
If oldname<>name
packet=New TPacket
packet.WriteLine(oldname)
packet.WriteLine(name)
Broadcast(NETWORK_PLAYERCHANGEDNAME,packet,SEND_RELIABLE)
EndIf
EndIf
Else
If FindClientByName(name)=Null
packet.WriteByte(1)
packet.WriteLine(name)
send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
Return
EndIf
EndIf
Return

Case NETWORK_CONNECT
Return

Case NETWORK_DISCONNECT
If client
clients.remove(client)
If clientmap.valueforkey(client.name)=client clientmap.remove(client.name)
If Not client.enethost client.free()
EndIf

Case NETWORK_PINGREQUEST
If Not client
client=New TClient
client.enetpeer=enetpeer
EndIf
Send(client,NETWORK_PINGRESPONSE,packet)
Return

Case NETWORK_CHAT
Local relay:TPacket=New TPacket
Local count:Int=packet.ReadByte()
relay.WriteLine(client.name)
relay.WriteLine(packet.ReadLine())
If count=0
Broadcast(NETWORK_CHAT,relay,SEND_RELIABLE)
Else
For Local n:Int=1 To count
client=FindClientByName(packet.ReadLine())
If client
Send(client,NETWORK_CHAT,relay,SEND_RELIABLE)
EndIf
Next
EndIf
Return

EndSelect

If callback
If packet packet.seek(0)
callback(Self,client,id,packet)
EndIf
EndMethod

Method Send:Int(client:TClient,id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
Local enetpacket:Byte Ptr
Local result:Int

If Not client.enetpeer RuntimeError "Can't send to local client."

Local data:Byte[]
If packet
If packet._bank.size()=0 packet=Null
EndIf
If packet
data=New Byte[packet._bank.size()+1]
MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
Else
data=New Byte[1]
EndIf
data[0]=id
enetpacket=enet_packet_create(data,data.length,flags)
result=(enet_peer_send(client.enetpeer,channel,enetpacket)=0)
Return result
EndMethod

Method Broadcast:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
Local result:Int=1
For Local client:TClient=EachIn clients
If Not Send(client,id,packet,flags,channel) result=0
Next
Return result
Rem
Local enetpacket:Byte Ptr
Local result:Int

Local data:Byte[]
If packet
If packet._bank.size()=0 packet=Null
EndIf
If packet
data=New Byte[packet._bank.size()+1]
MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
Else
data=New Byte[1]
EndIf
data[0]=id
enetpacket=enet_packet_create(data,data.length,flags)
enet_host_broadcast(Self.enethost,channel,enetpacket)
EndRem
EndMethod

Method Disconnect(client:TClient,force:Int=False)
If client.enetpeer
If force
'enet_peer_reset(client.enetpeer)
Else
enet_peer_disconnect(client.enetpeer,0)
EndIf
clients.remove(client)
If Not client.enethost
client.link.remove()
EndIf
If clientmap.valueforkey(client.name)=client
clientmap.remove(client.name)
EndIf
client.enetpeer=Null
EndIf
EndMethod

Method BanIP(ip:Int)
bannedips=bannedips[..bannedips.length+1]
bannedips[bannedips.length-1]=ip
EndMethod

Method IPBanned:Int(ip:Int)
For Local n:Int=0 To bannedips.length-1
If ip=bannedips[n] Return True
Next
Return False
EndMethod

Method Kick(client:TClient)
BanIP(client.ip)
Disconnect(client)
EndMethod

EndType

Type TClient Extends TNetworkNode

Const maxplayers:Int=64

Global list:TList=New TList

Field name:String
Field link:TLink
Field server:TServer
Field connected:Int
Field joined:Int=0
Field callback(client:TClient,id:Int,packet:TPacket)
Field userdata:Object
Field channels:Int=16
Field latency:Int

Method Free()
If link
link.remove()
link=Null
EndIf
Super.Free()
EndMethod

Function Find:TClient(ip:Int,port:Int)
Local client:TClient
For client=EachIn list
If client.ip=ip And client.port=port Return client
Next
client=New TClient
client.ip=ip
client.port=port
client.link=list.addlast(client)
Return client
EndFunction

Function Create:TClient(port:Int=0,portrange:Int=40)
Const maxpeers:Int=32
Local client:TClient=New TClient
Local addr:Byte Ptr

If portrange<=1
client.ip=DottedIPToInt(ENET_HOST_ANY)
client.port=port
addr=enet_address_create(client.ip,client.port)
client.enethost=enet_host_create(addr,maxpeers,0,0,0)
enet_address_destroy(addr)
If Not client.enethost Return Null
client.link=list.addlast(client)
Else
If port=0 port=7776
For Local n:Int=port To port+portrange-1
addr=enet_address_create(ENET_HOST_ANY,n)
client.enethost=enet_host_create(addr,maxpeers,0,0,0)
enet_address_destroy(addr)
If client.enethost
client.port=port
Exit
EndIf
Next
EndIf

Return client
EndFunction

Method Disconnect(force:Int=False)
Const disconnecttimeout:Int=10000

If Not Self.enethost RuntimeError "Can't update a remote server."
If server
If force
'enet_peer_reset(server.enetpeer)
Else
Send(NETWORK_LEAVEGAMEREQUEST,Null,SEND_RELIABLE)
Local ev:ENetEvent=New ENetEvent
Local start:Int=MilliSecs()
Repeat
If MilliSecs()-start>disconnecttimeout Exit
If enet_host_service(Self.enethost,ev,100)
Select ev.event
Case ENET_EVENT_TYPE_RECEIVE
If ev.packet
Local id:Int,packet:TPacket
Local size:Int=bmx_enet_packet_size(ev.packet)
Local data:Byte[size]
MemCopy(Varptr id,bmx_enet_packet_data(ev.packet),1)
If size>1
packet=New TPacket
packet._bank.resize(size-1)
MemCopy(packet._bank.buf(),bmx_enet_packet_data(ev.packet)+1,size-1)
EndIf
Select id
Case NETWORK_LEAVEGAMERESPONSE
Exit
EndSelect
EndIf
EndSelect
Else
Exit
EndIf
Forever
enet_peer_disconnect(server.enetpeer,0)
EndIf
server=Null
EndIf
joined=False
EndMethod

Method SetName(name:String)
If name.length>16 name=name[..16]
If server
Local packet:TPacket=New TPacket
packet.WriteLine(name)
Send(NETWORK_CHANGENAMEREQUEST,packet,SEND_RELIABLE)
Else
Self.name=name
EndIf
EndMethod

Method Connect:Int(ip:Int,port:Int)
Local addr:Byte Ptr

If ip=0 ip=2130706433
If Not Self.enethost RuntimeError "Remote client cannot connect to server."
If server Disconnect()
server=New TServer
server.ip=ip
server.port=port
addr=enet_address_create(server.ip,server.port)
server.enetpeer=enet_host_connect(enethost,addr,channels,0)
enet_address_destroy(addr)
If server.enetpeer=Null
server=Null
Return 0
EndIf

Rem
Local _callback:Byte Ptr=Null
_callback=callback
Local start:Int=MilliSecs()
Repeat
Update()
If MilliSecs()-start>10000 Or joined=1 Exit
Forever
callback=_callback
EndRem

Return 1
EndMethod

Method Send:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
Local enetpacket:Byte Ptr
Local result:Int

If Not connected Return 0

If Not server RuntimeError "Client is not connected."
Local data:Byte[]
If packet
If packet._bank.size()=0 packet=Null
EndIf
If packet
data=New Byte[packet._bank.size()+1]
MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
Else
data=New Byte[1]
EndIf
data[0]=id
enetpacket=enet_packet_create(data,data.length,flags)
result=(enet_peer_send(server.enetpeer,channel,enetpacket)=0)
Return result
EndMethod

Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr)
Select id
Case NETWORK_CONNECT
Self.connected=True
packet=New TPacket
packet.WriteLine(name)
Send(NETWORK_JOINREQUEST,packet)

'Self.connected=True
'Self.Join()

Case NETWORK_JOINRESPONSE
joined=packet.ReadByte()
If joined=0 Disconnect()
Case NETWORK_CHANGENAMERESPONSE
If packet.ReadByte()=1
name=packet.ReadLine()
EndIf
Case NETWORK_PINGREQUEST
Send(NETWORK_PINGRESPONSE,packet)
Return
Case NETWORK_PINGRESPONSE
latency=MilliSecs()-packet.ReadInt()
packet.WriteInt(enet_peer_ip(enetpeer))
packet.WriteInt(enet_peer_port(enetpeer))
If enetpeer=pingpeer
enet_peer_disconnect(pingpeer,0)
pingpeer=Null
EndIf
EndSelect
If callback
If packet packet.seek(0)
callback(Self,id,packet)
EndIf
EndMethod

Method Join()
If Not joined
Local packet:TPacket=New TPacket
packet.WriteLine(name)
Send(NETWORK_JOINREQUEST,packet)
EndIf
EndMethod

Function ConvertEvent:Int(ev:EnetEvent,packet:TPacket)
Select ev.event
Case ENET_EVENT_TYPE_CONNECT
Return NETWORK_CONNECT
Case ENET_EVENT_TYPE_DISCONNECT
Return NETWORK_DISCONNECT
Case ENET_EVENT_TYPE_RECEIVE
If ev.packet
Local id:Int
Local size:Int=bmx_enet_packet_size(ev.packet)
Local data:Byte[size]
MemCopy(Varptr id,bmx_enet_packet_data(ev.packet),1)
If size>1
packet._bank.resize(size-1)
MemCopy(packet._bank.buf(),bmx_enet_packet_data(ev.packet)+1,size-1)
EndIf
enet_packet_destroy(ev.packet)
Return id
EndIf
EndSelect
EndFunction

Field pingpeer:Byte Ptr

Method Ping:Int(ip:Int=0,port:Int=0)
Const disconnecttimeout:Int=1000
Local packet:TPacket=New TPacket,addr:Byte Ptr,enetpacket:Byte Ptr,ev:EnetEvent,result:Int,id:Int,start:Int

If server
If server.ip=ip And server.port=port ip=0
EndIf

If Not enethost RuntimeError("Can't ping remote client.")
If ip
If pingpeer
enet_peer_disconnect(pingpeer,0)
pingpeer=Null
EndIf

ev=New EnetEvent
addr=enet_address_create(ip,port)
pingpeer=enet_host_connect(enethost,addr,1,0)
enet_address_destroy(addr)
If pingpeer
start=MilliSecs()
Repeat
If MilliSecs()-start>disconnecttimeout
enet_peer_disconnect(pingpeer,0)
pingpeer=Null
'Print "Connect timeout"
Return 0
EndIf
If enet_host_service(enethost,ev,0)
id=ConvertEvent(ev,packet)
Select id
Case NETWORK_CONNECT
Exit
EndSelect
EndIf
Forever
Local data:Byte[5]
data[0]=NETWORK_PINGREQUEST
start=MilliSecs()
MemCopy(Varptr data[1],Varptr start,4)
enetpacket=enet_packet_create(data,data.length,0)
If enet_peer_send(pingpeer,0,enetpacket)=0
Return 1
Else
enet_peer_disconnect(pingpeer,0)
pingpeer=Null
'Print "can't send packet"
Return 0
EndIf
Else
'Print "Cant connect to peer at "+ip+", "+port
Return 0
EndIf
Else
packet:TPacket=New TPacket
packet.WriteInt(MilliSecs())
Return Send(NETWORK_PINGREQUEST,packet)
EndIf
EndMethod

Method Say:Int(text:String,recipients:String[]=Null)
Local packet:TPacket=New TPacket
If recipients
packet.WriteByte(recipients.length)
packet.WriteLine(text)
For Local n:Int=0 To recipients.length-1
packet.WriteLine(recipients[n])
Next
Else
packet.WriteByte(0)
packet.WriteLine(text)
EndIf
Return Send(NETWORK_CHAT,packet)
EndMethod

EndType


Type TPacket Extends TBankStream

Method New()
_bank=New TBank
EndMethod

EndType


Function CreatePacket:TPacket()
Local packet:TPacket=New TPacket
Return packet
EndFunction

This simple program fails with Segmentation fault (core dumped) on Linux (Ubuntu 20.04, x64).

Code: [Select]
SuperStrict

Import pub.enet

Include "network.bmx"

Global port:Int = 6138

Global server:TServer = TServer.Create(port)
If server
Print "started server"
While True
server.Update()
Wend
EndIf

Does anyone have any ideas?

Offline markcwm

  • Sr. Member
  • ****
  • Posts: 465
Re: Segmentation fault
« Reply #1 on: June 08, 2020, 03:36:48 PM »
I made a few changes thanks to the compiler and it runs in Ubuntu, mostly had overload error where there was an extra parameter, also functions with prefix bmx_ were not in pub.enet.
Code: BlitzMax
  1. Private
  2.  
  3. Const ENET_PACKET_FLAG_UNSEQUENCED:Int=2
  4. Const SERVERUPDATEFREQUENCY:Int=4*1000*60
  5.  
  6. Function enet_host_port:Int( peer:Byte Ptr  )
  7.         Local ip:Int=(Int Ptr peer)[1]
  8.         Local port:Int=(Short Ptr peer)[4]
  9.         ?LittleEndian
  10.         ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
  11.         ?
  12.         Return port
  13. EndFunction
  14.  
  15. Function enet_host_ip:Int( peer:Byte Ptr  )
  16.         Local ip:Int=(Int Ptr peer)[1]
  17.         Local port:Int=(Short Ptr peer)[4]
  18.         ?LittleEndian
  19.         ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
  20.         ?
  21.         Return ip
  22. EndFunction
  23.  
  24. Function enet_peer_port:Int( peer:Byte Ptr  )
  25.         Local ip:Int=(Int Ptr peer)[3]
  26.         Local port:Int=(Short Ptr peer)[8]
  27.         ?LittleEndian
  28.         ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
  29.         ?
  30.         Return port
  31. EndFunction
  32.  
  33. Function enet_peer_ip:Int( peer:Byte Ptr  )
  34.         Local ip:Int=(Int Ptr peer)[3]
  35.         Local port:Int=(Short Ptr peer)[8]
  36.         ?LittleEndian
  37.         ip=(ip Shr 24) | (ip Shr 8 & $ff00) | (ip Shl 8 & $ff0000) | (ip Shl 24)
  38.         ?
  39.         Return ip
  40. EndFunction
  41.  
  42. Public
  43.  
  44. Type TNetworkNode
  45.        
  46.         Field port:Int
  47.         Field ip:Int
  48.         Field enethost:Byte Ptr
  49.         Field enetpeer:Byte Ptr
  50.        
  51.         Method Delete()
  52.                 Free()
  53.         EndMethod
  54.        
  55.         Method Free()
  56.                 If enethost
  57.                         enet_host_destroy(enethost)
  58.                         enethost=Null
  59.                 EndIf
  60.         EndMethod
  61.        
  62.         Method Update()
  63.  
  64.                 Local ip:Int,port:Int,client:TClient,ev:ENetEvent=New ENetEvent,id:Byte,packet:TPacket
  65.                
  66.                 If Not Self.enethost RuntimeError "Can't update a remote server."
  67.                 Repeat
  68.                         If enet_host_service(Self.enethost,ev,0)
  69.                                
  70.                                 Select ev.event
  71.                                
  72.                                 Case ENET_EVENT_TYPE_CONNECT
  73.                                         id=NETWORK_CONNECT
  74.                                
  75.                                 Case ENET_EVENT_TYPE_DISCONNECT
  76.                                         id=NETWORK_DISCONNECT
  77.                                
  78.                                 Case ENET_EVENT_TYPE_RECEIVE
  79.                                         Local size:Int=enet_packet_size(ev.packet)
  80.                                         Local data:Byte[size]
  81.                                         MemCopy(Varptr id,enet_packet_data(ev.packet),1)
  82.                                         If size>1
  83.                                                 packet=New TPacket
  84.                                                 packet._bank.resize(size-1)
  85.                                                 MemCopy(packet._bank.buf(),enet_packet_data(ev.packet)+1,size-1)
  86.                                         EndIf
  87.                                
  88.                                 Default
  89.                                         Continue
  90.                                        
  91.                                 EndSelect
  92.                                
  93.                                 EvaluateEvent(id,packet,ev.peer)
  94.                                
  95.                         Else
  96.                                 Exit
  97.                         EndIf
  98.                        
  99.                         If enethost=Null Exit
  100.                        
  101.                 Forever
  102.  
  103.         EndMethod
  104.        
  105.         Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr) Abstract
  106.        
  107. EndType
  108.  
  109. 'Public
  110.  
  111.  
  112. Const NETWORK_CONNECT:Int=1
  113. Const NETWORK_DISCONNECT:Int=2
  114. Const NETWORK_PINGREQUEST:Int=3
  115. Const NETWORK_PINGRESPONSE:Int=4
  116. Const NETWORK_JOINREQUEST:Int=5
  117. Const NETWORK_JOINRESPONSE:Int=6
  118. Const NETWORK_CHAT:Int=7
  119. Const NETWORK_LEAVEGAME:Int=8
  120. Const NETWORK_CHANGENAMEREQUEST:Int=9
  121. Const NETWORK_CHANGENAMERESPONSE:Int=10
  122. Const NETWORK_PLAYERJOINED:Int=11
  123. Const NETWORK_PLAYERLEFT:Int=12
  124. Const NETWORK_LEAVEGAMEREQUEST:Int=13
  125. Const NETWORK_LEAVEGAMERESPONSE:Int=14
  126. Const NETWORK_PLAYERCHANGEDNAME:Int=15
  127.  
  128. Const SEND_RELIABLE:Int=ENET_PACKET_FLAG_RELIABLE
  129. Const SEND_UNSEQUENCED:Int=ENET_PACKET_FLAG_UNSEQUENCED
  130.  
  131. Type TServer Extends TNetworkNode
  132.        
  133.         Field clients:TList=New TList
  134.         Field callback(server:TServer,client:TClient,id:Int,packet:TPacket)
  135.         Field bannedips:Int[]
  136.         Field clientmap:TMap=New TMap
  137.         Field url:String
  138.         Field lastrefreshtime:Int
  139.        
  140.         Method Free()
  141.                 If url
  142.                         Remove()
  143.                         url=""
  144.                 EndIf
  145.                 Super.Free()
  146.         EndMethod
  147.        
  148.         Function EncodeURL:String(t:String)
  149.                 Local newString:String
  150.                 Local i:Int,c:String,asciival:Int,hexstr:String,newhexstr:String
  151.                 For i = 0 To Len(t)
  152.                         c:String = t[i..i+1]
  153.                         asciival = Asc(c)
  154.                         If asciival > 32 And asciival < 123
  155.                                 ' handle replacing the special set of chars
  156.                                 c = Replace(c,"'","%27")
  157.                                 c = Replace(c,"%","%25")
  158.                                 c = Replace(c,"<","%3C")
  159.                                 c = Replace(c,">","%3E")
  160.                                 c = Replace(c,"\","%5C")
  161.                                 c = Replace(c,"^","%5E")
  162.                                 c = Replace(c,"[","%5B")
  163.                                 c = Replace(c,"]","%5D")
  164.                                 c = Replace(c,"+","%2B")
  165.                                 c = Replace(c,"$","%24")
  166.                                 c = Replace(c,",","%2C")
  167.                                 c = Replace(c,"@","%40")
  168.                                 c = Replace(c,":","%3A")
  169.                                 c = Replace(c,";","%3B")
  170.                                 c = Replace(c,"/","%2F")
  171.                                 c = Replace(c,"!","%21")
  172.                                 c = Replace(c,"#","%23")
  173.                                 c = Replace(c,"?","%3F")
  174.                                 c = Replace(c,"=","%3D")
  175.                                 c = Replace(c,"&","%26")
  176.                                 newString:+c
  177.                         Else
  178.                                 hexstr$ = Hex(asciival)
  179.                                 newhexstr$ = "%" + hexstr[Len(hexstr)-2..Len(hexstr)]
  180.                                 newstring:+newhexstr
  181.                         EndIf
  182.                 Next
  183.                
  184.                 newstring = newstring[..Len(newstring)-3]
  185.                 Return newstring
  186.         EndFunction
  187.        
  188.         Function Create:TServer(port:Int=0,portrange:Int=40)
  189.                 Local addr:Byte Ptr,server:TServer=New TServer
  190.  
  191.                 server.ip=DottedIPToInt(ENET_HOST_ANY)
  192.                 If portrange<=1
  193.                         server.port = port
  194.                         addr=enet_address_create(server.ip,server.port)
  195.                         server.enethost=enet_host_create(addr,32,0,0)
  196.                         enet_address_destroy(addr)
  197.                 Else
  198.                         If port=0 port=7777
  199.                         For Local n:Int=port To port+portrange-1
  200.                                 addr=enet_address_create(ENET_HOST_ANY,n)
  201.                                 server.enethost=enet_host_create(addr,64,0,0)
  202.                                 enet_address_destroy(addr)
  203.                                 If server.enethost
  204.                                         server.port=n
  205.                                         Exit
  206.                                 EndIf
  207.                         Next
  208.                 EndIf
  209.                 If Not server.enethost Return Null             
  210.                 Return server
  211.         EndFunction
  212.        
  213.         Method Publish:Int(servername:String="",gamename:String="",url:String="http::www.leadwerks.com/gameservers/gameservers.php")
  214.                 Local stream:TStream
  215.                 gamename=EncodeURL(gamename)
  216.                 servername=EncodeURL(servername)
  217.                 Self.url=url
  218.                 stream=OpenStream(url+"?action=addserver&gamename="+gamename+"&servername="+port+"|"+servername)
  219.                 If Not stream Return False
  220.                 Self.url=url
  221.                 While Not stream.Eof()
  222.                         Local s:String=stream.ReadLine()
  223.                         If s.Trim()
  224.                                 stream.close()
  225.                                 Return False
  226.                         EndIf
  227.                 Wend
  228.                 stream.close()
  229.                 lastrefreshtime=MilliSecs()
  230.                 Return True
  231.         EndMethod
  232.        
  233.         Method Remove:Int()
  234.                 Local stream:TStream
  235.                 stream=OpenStream(url+"?action=removeserver")
  236.                 If stream
  237.                         stream.close()
  238.                         Return True
  239.                 Else
  240.                         Return False
  241.                 EndIf
  242.         EndMethod
  243.        
  244.         Function Query:String[](gamename:String="",url:String="")
  245.                 Local stream:TStream,s:String,sarr:String[],n:Int
  246.                
  247.                 If url="" url="http::www.leadwerks.com/gameservers/gameservers.php"
  248.                 stream=OpenStream(url+"?action=listservers&gamename="+gamename)
  249.                 If Not stream Return Null
  250.                 While Not stream.Eof()
  251.                         s=ReadLine(stream)
  252.                         If s.Trim().length>0
  253.                                 sarr=sarr[..sarr.length+1]
  254.                                 sarr[sarr.length-1]=s.Trim()
  255.                                 Local sa:String[]=sarr[sarr.length-1].split("|")
  256.                                 Local name:String=sa[0]
  257.                                 sarr[sarr.length-1]=HostIp(name)+"|"+sarr[sarr.length-1]
  258.                         EndIf
  259.                 Wend
  260.                 stream.close()
  261.                 Return sarr
  262.         EndFunction
  263.        
  264.         Method Refresh:Int()
  265.                 Local stream:TStream
  266.                 stream=OpenStream(url+"?action=refreshserver")
  267.                 If Not stream Return False
  268.                 stream.close()
  269.                 Return True    
  270.         EndMethod
  271.        
  272.         Method FindClientByName:TClient(name:String)
  273.                 Return TClient(clientmap.valueforkey(name))
  274.         EndMethod
  275.        
  276.         Method FindClientByPeer:TClient(peer:Byte Ptr)
  277.                 Local client:TClient
  278.                 For client=EachIn clients
  279.                         If client.enetpeer=peer Return client
  280.                 Next
  281.         EndMethod
  282.        
  283.         Method FindClient:TClient(ip:Int,port:Int)
  284.                 Local client:TClient
  285.                 For client=EachIn clients
  286.                         If client.ip=ip And client.port=port Return client
  287.                 Next
  288.         EndMethod
  289.        
  290.         Method Update()
  291.                 Rem
  292.                 If url
  293.                         Local time:Int=MilliSecs()
  294.                         If time-lastrefreshtime>serverupdatefrequency
  295.                                 lastrefreshtime=time
  296.                                 Refresh()
  297.                         EndIf
  298.                 EndIf
  299.                 EndRem
  300.                 Super.Update()         
  301.         EndMethod
  302.        
  303.         Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr)
  304.                 Local client:TClient=FindClient(enet_peer_ip(enetpeer),enet_peer_port(enetpeer))
  305.                 Select id
  306.                
  307.                 Case NETWORK_PINGRESPONSE
  308.                         client.latency=MilliSecs()-packet.ReadInt()
  309.                
  310.                 Case NETWORK_LEAVEGAMEREQUEST
  311.                         If client
  312.                                 Send(client,NETWORK_LEAVEGAMERESPONSE,Null,SEND_RELIABLE)
  313.                                 Local relay:TPacket=New TPacket
  314.                                 relay.WriteLine(client.name)
  315.                                 Broadcast(NETWORK_PLAYERLEFT,relay,SEND_RELIABLE)
  316.                                 clients.remove(client)
  317.                                 If clientmap.valueforkey(client.name)=client clientmap.remove(client.name)
  318.                         EndIf
  319.                        
  320.                 Case NETWORK_JOINREQUEST
  321.                         If client
  322.                                 Disconnect(client,1)
  323.                                 Local relay:TPacket=New TPacket
  324.                                 relay.WriteLine(client.name)
  325.                                 Broadcast(NETWORK_PLAYERLEFT,relay,SEND_RELIABLE)
  326.                         EndIf
  327.                         client=TClient.Find(enet_peer_ip(enetpeer),enet_peer_port(enetpeer))
  328.                         client.enetpeer=enetpeer
  329.                        
  330.                         If IPBanned(client.ip)
  331.                                 Disconnect(client,0)
  332.                                 Return
  333.                         Else
  334.                                 client.name=packet.ReadLine()
  335.                                 If Not FindClientByName(client.name)
  336.                                         clientmap.insert(client.name,client)
  337.                                         clients.AddLast(client)
  338.                                         Local responsepacket:TPacket=New TPacket
  339.                                         responsepacket.WriteByte(1)
  340.                                         responsepacket.WriteByte(clients.count()-1)
  341.                                         Local peer:TClient
  342.                                         For peer=EachIn clients
  343.                                                 If peer<>client responsepacket.WriteLine(peer.name)
  344.                                         Next
  345.                                         Send(client,NETWORK_JOINRESPONSE,responsepacket,SEND_RELIABLE)
  346.                                         id=NETWORK_PLAYERJOINED
  347.                                        
  348.                                         'Tell everyone he joined
  349.                                         responsepacket=New TPacket
  350.                                         responsepacket.WriteLine(client.name)
  351.                                         Broadcast(NETWORK_PLAYERJOINED,responsepacket,SEND_RELIABLE)
  352.                                        
  353.                                 Else
  354.                                         packet=New TPacket
  355.                                         packet.WriteByte(0)'no, you can't joint
  356.                                         packet.WriteByte(1)'reason: name already taken
  357.                                         Send(client,NETWORK_JOINRESPONSE,packet,SEND_RELIABLE)
  358.                                         'Disconnect(client,0)
  359.                                         Return
  360.                                 EndIf
  361.                         EndIf
  362.                
  363.                 Case NETWORK_CHANGENAMEREQUEST
  364.                         Local name:String=packet.ReadLine()
  365.                         packet=New TPacket
  366.                         If client
  367.                                 Local oldname:String=client.name
  368.                                 If FindClientByName(name)<>Null And client.name<>name
  369.                                         packet.WriteByte(0)
  370.                                         send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
  371.                                         Return
  372.                                 Else
  373.                                         packet.WriteByte(1)
  374.                                         packet.WriteLine(name)
  375.                                         send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
  376.                                         clientmap.remove(client.name)
  377.                                         client.name=name
  378.                                         clientmap.insert(name,client)
  379.                                         If oldname<>name
  380.                                                 packet=New TPacket
  381.                                                 packet.WriteLine(oldname)
  382.                                                 packet.WriteLine(name)
  383.                                                 Broadcast(NETWORK_PLAYERCHANGEDNAME,packet,SEND_RELIABLE)
  384.                                         EndIf
  385.                                 EndIf
  386.                         Else
  387.                                 If FindClientByName(name)=Null
  388.                                         packet.WriteByte(1)
  389.                                         packet.WriteLine(name)
  390.                                         send(client,NETWORK_CHANGENAMERESPONSE,packet,SEND_RELIABLE)
  391.                                         Return
  392.                                 EndIf
  393.                         EndIf
  394.                         Return
  395.                                                                
  396.                 Case NETWORK_CONNECT
  397.                         Return
  398.                
  399.                 Case NETWORK_DISCONNECT
  400.                         If client
  401.                                 clients.remove(client)
  402.                                 If clientmap.valueforkey(client.name)=client clientmap.remove(client.name)
  403.                                 If Not client.enethost client.free()
  404.                         EndIf
  405.                        
  406.                 Case NETWORK_PINGREQUEST
  407.                         If Not client
  408.                                 client=New TClient
  409.                                 client.enetpeer=enetpeer
  410.                         EndIf
  411.                         Send(client,NETWORK_PINGRESPONSE,packet)
  412.                         Return
  413.                
  414.                 Case NETWORK_CHAT
  415.                         Local relay:TPacket=New TPacket
  416.                         Local count:Int=packet.ReadByte()
  417.                         relay.WriteLine(client.name)
  418.                         relay.WriteLine(packet.ReadLine())
  419.                         If count=0
  420.                                 Broadcast(NETWORK_CHAT,relay,SEND_RELIABLE)
  421.                         Else
  422.                                 For Local n:Int=1 To count
  423.                                         client=FindClientByName(packet.ReadLine())
  424.                                         If client
  425.                                                 Send(client,NETWORK_CHAT,relay,SEND_RELIABLE)
  426.                                         EndIf
  427.                                 Next
  428.                         EndIf
  429.                         Return
  430.                
  431.                 EndSelect
  432.                
  433.                 If callback
  434.                         If packet packet.seek(0)
  435.                         callback(Self,client,id,packet)
  436.                 EndIf
  437.         EndMethod
  438.        
  439.         Method Send:Int(client:TClient,id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
  440.                 Local enetpacket:Byte Ptr
  441.                 Local result:Int
  442.                
  443.                 If Not client.enetpeer RuntimeError "Can't send to local client."
  444.                
  445.                 Local data:Byte[]
  446.                 If packet
  447.                         If packet._bank.size()=0 packet=Null
  448.                 EndIf
  449.                 If packet
  450.                         data=New Byte[packet._bank.size()+1]
  451.                         MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
  452.                 Else
  453.                         data=New Byte[1]
  454.                 EndIf
  455.                 data[0]=id
  456.                 enetpacket=enet_packet_create(data,data.length,flags)
  457.                 result=(enet_peer_send(client.enetpeer,channel,enetpacket)=0)          
  458.                 Return result
  459.         EndMethod
  460.        
  461.         Method Broadcast:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
  462.                 Local result:Int=1
  463.                 For Local client:TClient=EachIn clients
  464.                         If Not Send(client,id,packet,flags,channel) result=0
  465.                 Next
  466.                 Return result
  467.                 Rem
  468.                 Local enetpacket:Byte Ptr
  469.                 Local result:Int
  470.                
  471.                 Local data:Byte[]
  472.                 If packet
  473.                         If packet._bank.size()=0 packet=Null
  474.                 EndIf
  475.                 If packet
  476.                         data=New Byte[packet._bank.size()+1]
  477.                         MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
  478.                 Else
  479.                         data=New Byte[1]
  480.                 EndIf
  481.                 data[0]=id
  482.                 enetpacket=enet_packet_create(data,data.length,flags)
  483.                 enet_host_broadcast(Self.enethost,channel,enetpacket)
  484.                 EndRem
  485.         EndMethod
  486.        
  487.         Method Disconnect(client:TClient,force:Int=False)
  488.                 If client.enetpeer
  489.                         If force
  490.                                 'enet_peer_reset(client.enetpeer)
  491.                         Else
  492.                                 enet_peer_disconnect(client.enetpeer)
  493.                         EndIf
  494.                         clients.remove(client)
  495.                         If Not client.enethost
  496.                                 client.link.remove()
  497.                         EndIf
  498.                         If clientmap.valueforkey(client.name)=client
  499.                                 clientmap.remove(client.name)
  500.                         EndIf
  501.                         client.enetpeer=Null
  502.                 EndIf
  503.         EndMethod
  504.        
  505.         Method BanIP(ip:Int)
  506.                 bannedips=bannedips[..bannedips.length+1]
  507.                 bannedips[bannedips.length-1]=ip
  508.         EndMethod
  509.        
  510.         Method IPBanned:Int(ip:Int)
  511.                 For Local n:Int=0 To bannedips.length-1
  512.                         If ip=bannedips[n] Return True
  513.                 Next
  514.                 Return False
  515.         EndMethod
  516.        
  517.         Method Kick(client:TClient)
  518.                 BanIP(client.ip)
  519.                 Disconnect(client)
  520.         EndMethod
  521.        
  522. EndType
  523.  
  524. Type TClient Extends TNetworkNode
  525.        
  526.         Const maxplayers:Int=64
  527.        
  528.         Global list:TList=New TList
  529.        
  530.         Field name:String
  531.         Field link:TLink
  532.         Field server:TServer
  533.         Field connected:Int
  534.         Field joined:Int=0
  535.         Field callback(client:TClient,id:Int,packet:TPacket)
  536.         Field userdata:Object
  537.         Field channels:Int=16
  538.         Field latency:Int
  539.        
  540.         Method Free()
  541.                 If link
  542.                         link.remove()
  543.                         link=Null
  544.                 EndIf
  545.                 Super.Free()
  546.         EndMethod
  547.        
  548.         Function Find:TClient(ip:Int,port:Int)
  549.                 Local client:TClient
  550.                 For client=EachIn list
  551.                         If client.ip=ip And client.port=port Return client
  552.                 Next
  553.                 client=New TClient
  554.                 client.ip=ip
  555.                 client.port=port
  556.                 client.link=list.addlast(client)
  557.                 Return client
  558.         EndFunction
  559.        
  560.         Function Create:TClient(port:Int=0,portrange:Int=40)
  561.                 Const maxpeers:Int=32
  562.                 Local client:TClient=New TClient
  563.                 Local addr:Byte Ptr
  564.                
  565.                 If portrange<=1
  566.                         client.ip=DottedIPToInt(ENET_HOST_ANY)
  567.                         client.port=port
  568.                         addr=enet_address_create(client.ip,client.port)
  569.                         client.enethost=enet_host_create(addr,maxpeers,0,0)
  570.                         enet_address_destroy(addr)
  571.                         If Not client.enethost Return Null
  572.                         client.link=list.addlast(client)
  573.                 Else
  574.                         If port=0 port=7776
  575.                         For Local n:Int=port To port+portrange-1
  576.                                 addr=enet_address_create(ENET_HOST_ANY,n)
  577.                                 client.enethost=enet_host_create(addr,maxpeers,0,0)
  578.                                 enet_address_destroy(addr)
  579.                                 If client.enethost
  580.                                         client.port=port
  581.                                         Exit
  582.                                 EndIf
  583.                         Next
  584.                 EndIf
  585.                
  586.                 Return client
  587.         EndFunction
  588.        
  589.         Method Disconnect(force:Int=False)
  590.                 Const disconnecttimeout:Int=10000
  591.                
  592.                 If Not Self.enethost RuntimeError "Can't update a remote server."
  593.                 If server
  594.                         If force
  595.                                 'enet_peer_reset(server.enetpeer)
  596.                         Else
  597.                                 Send(NETWORK_LEAVEGAMEREQUEST,Null,SEND_RELIABLE)
  598.                                 Local ev:ENetEvent=New ENetEvent
  599.                                 Local start:Int=MilliSecs()
  600.                                 Repeat
  601.                                         If MilliSecs()-start>disconnecttimeout Exit
  602.                                         If enet_host_service(Self.enethost,ev,100)
  603.                                                 Select ev.event
  604.                                                 Case ENET_EVENT_TYPE_RECEIVE
  605.                                                         If ev.packet
  606.                                                                 Local id:Int,packet:TPacket
  607.                                                                 Local size:Int=enet_packet_size(ev.packet)
  608.                                                                 Local data:Byte[size]
  609.                                                                 MemCopy(Varptr id,enet_packet_data(ev.packet),1)
  610.                                                                 If size>1
  611.                                                                         packet=New TPacket
  612.                                                                         packet._bank.resize(size-1)
  613.                                                                         MemCopy(packet._bank.buf(),enet_packet_data(ev.packet)+1,size-1)
  614.                                                                 EndIf
  615.                                                                 Select id
  616.                                                                 Case NETWORK_LEAVEGAMERESPONSE
  617.                                                                         Exit
  618.                                                                 EndSelect
  619.                                                         EndIf
  620.                                                 EndSelect
  621.                                         Else
  622.                                                 Exit
  623.                                         EndIf
  624.                                 Forever
  625.                                 enet_peer_disconnect(server.enetpeer)
  626.                         EndIf
  627.                         server=Null
  628.                 EndIf
  629.                 joined=False
  630.         EndMethod
  631.        
  632.         Method SetName(name:String)
  633.                 If name.length>16 name=name[..16]
  634.                 If server
  635.                         Local packet:TPacket=New TPacket
  636.                         packet.WriteLine(name)
  637.                         Send(NETWORK_CHANGENAMEREQUEST,packet,SEND_RELIABLE)
  638.                 Else
  639.                         Self.name=name
  640.                 EndIf
  641.         EndMethod
  642.        
  643.         Method Connect:Int(ip:Int,port:Int)
  644.                 Local addr:Byte Ptr
  645.                                
  646.                 If ip=0 ip=2130706433
  647.                 If Not Self.enethost RuntimeError "Remote client cannot connect to server."
  648.                 If server Disconnect()         
  649.                 server=New TServer
  650.                 server.ip=ip
  651.                 server.port=port
  652.                 addr=enet_address_create(server.ip,server.port)
  653.                 server.enetpeer=enet_host_connect(enethost,addr,channels)
  654.                 enet_address_destroy(addr)
  655.                 If server.enetpeer=Null
  656.                         server=Null
  657.                         Return 0
  658.                 EndIf
  659.                
  660.                 Rem
  661.                 Local _callback:Byte Ptr=Null
  662.                 _callback=callback             
  663.                 Local start:Int=MilliSecs()
  664.                 Repeat
  665.                         Update()
  666.                         If MilliSecs()-start>10000 Or joined=1 Exit
  667.                 Forever
  668.                 callback=_callback
  669.                 EndRem
  670.                
  671.                 Return 1
  672.         EndMethod
  673.        
  674.         Method Send:Int(id:Int,packet:TPacket=Null,flags:Int=0,channel:Int=0)
  675.                 Local enetpacket:Byte Ptr
  676.                 Local result:Int
  677.                
  678.                 If Not connected Return 0
  679.                
  680.                 If Not server RuntimeError "Client is not connected."
  681.                 Local data:Byte[]
  682.                 If packet
  683.                         If packet._bank.size()=0 packet=Null
  684.                 EndIf
  685.                 If packet
  686.                         data=New Byte[packet._bank.size()+1]
  687.                         MemCopy(Varptr data[1],packet._bank.buf(),packet._bank.size())
  688.                 Else
  689.                         data=New Byte[1]
  690.                 EndIf
  691.                 data[0]=id
  692.                 enetpacket=enet_packet_create(data,data.length,flags)
  693.                 result=(enet_peer_send(server.enetpeer,channel,enetpacket)=0)          
  694.                 Return result
  695.         EndMethod
  696.        
  697.         Method EvaluateEvent(id:Int,packet:TPacket,enetpeer:Byte Ptr)
  698.                 Select id
  699.                 Case NETWORK_CONNECT
  700.                         Self.connected=True
  701.                         packet=New TPacket
  702.                         packet.WriteLine(name)
  703.                         Send(NETWORK_JOINREQUEST,packet)       
  704.  
  705.                         'Self.connected=True
  706.                         'Self.Join()
  707.                                        
  708.                 Case NETWORK_JOINRESPONSE
  709.                         joined=packet.ReadByte()
  710.                         If joined=0 Disconnect()
  711.                 Case NETWORK_CHANGENAMERESPONSE
  712.                         If packet.ReadByte()=1
  713.                                 name=packet.ReadLine()
  714.                         EndIf
  715.                 Case NETWORK_PINGREQUEST
  716.                         Send(NETWORK_PINGRESPONSE,packet)
  717.                         Return
  718.                 Case NETWORK_PINGRESPONSE
  719.                         latency=MilliSecs()-packet.ReadInt()
  720.                         packet.WriteInt(enet_peer_ip(enetpeer))
  721.                         packet.WriteInt(enet_peer_port(enetpeer))
  722.                         If enetpeer=pingpeer
  723.                                 enet_peer_disconnect(pingpeer)
  724.                                 pingpeer=Null
  725.                         EndIf
  726.                 EndSelect
  727.                 If callback
  728.                         If packet packet.seek(0)
  729.                         callback(Self,id,packet)
  730.                 EndIf
  731.         EndMethod
  732.        
  733.         Method Join()
  734.                 If Not joined
  735.                         Local packet:TPacket=New TPacket
  736.                         packet.WriteLine(name)
  737.                         Send(NETWORK_JOINREQUEST,packet)
  738.                 EndIf
  739.         EndMethod
  740.        
  741.         Function ConvertEvent:Int(ev:EnetEvent,packet:TPacket)
  742.                 Select ev.event
  743.                 Case ENET_EVENT_TYPE_CONNECT
  744.                         Return NETWORK_CONNECT
  745.                 Case ENET_EVENT_TYPE_DISCONNECT
  746.                         Return NETWORK_DISCONNECT
  747.                 Case ENET_EVENT_TYPE_RECEIVE
  748.                         If ev.packet
  749.                                 Local id:Int
  750.                                 Local size:Int=enet_packet_size(ev.packet)
  751.                                 Local data:Byte[size]
  752.                                 MemCopy(Varptr id,enet_packet_data(ev.packet),1)
  753.                                 If size>1
  754.                                         packet._bank.resize(size-1)
  755.                                         MemCopy(packet._bank.buf(),enet_packet_data(ev.packet)+1,size-1)
  756.                                 EndIf
  757.                                 enet_packet_destroy(ev.packet)
  758.                                 Return id
  759.                         EndIf
  760.                 EndSelect
  761.         EndFunction
  762.        
  763.         Field pingpeer:Byte Ptr
  764.        
  765.         Method Ping:Int(ip:Int=0,port:Int=0)
  766.                 Const disconnecttimeout:Int=1000
  767.                 Local packet:TPacket=New TPacket,addr:Byte Ptr,enetpacket:Byte Ptr,ev:EnetEvent,result:Int,id:Int,start:Int
  768.                
  769.                 If server
  770.                         If server.ip=ip And server.port=port ip=0
  771.                 EndIf
  772.                
  773.                 If Not enethost RuntimeError("Can't ping remote client.")
  774.                 If ip
  775.                         If pingpeer
  776.                                 enet_peer_disconnect(pingpeer)
  777.                                 pingpeer=Null
  778.                         EndIf
  779.                        
  780.                         ev=New EnetEvent
  781.                         addr=enet_address_create(ip,port)
  782.                         pingpeer=enet_host_connect(enethost,addr,1)
  783.                         enet_address_destroy(addr)
  784.                         If pingpeer
  785.                                 start=MilliSecs()
  786.                                 Repeat
  787.                                         If MilliSecs()-start>disconnecttimeout
  788.                                                 enet_peer_disconnect(pingpeer)
  789.                                                 pingpeer=Null
  790.                                                 'Print "Connect timeout"
  791.                                                 Return 0
  792.                                         EndIf
  793.                                         If enet_host_service(enethost,ev,0)
  794.                                                 id=ConvertEvent(ev,packet)
  795.                                                 Select id
  796.                                                 Case NETWORK_CONNECT
  797.                                                         Exit
  798.                                                 EndSelect
  799.                                         EndIf
  800.                                 Forever
  801.                                 Local data:Byte[5]
  802.                                 data[0]=NETWORK_PINGREQUEST
  803.                                 start=MilliSecs()
  804.                                 MemCopy(Varptr data[1],Varptr start,4)
  805.                                 enetpacket=enet_packet_create(data,data.length,0)
  806.                                 If enet_peer_send(pingpeer,0,enetpacket)=0
  807.                                         Return 1
  808.                                 Else
  809.                                         enet_peer_disconnect(pingpeer)
  810.                                         pingpeer=Null
  811.                                         'Print "can't send packet"
  812.                                         Return 0
  813.                                 EndIf                          
  814.                         Else
  815.                                 'Print "Cant connect to peer at "+ip+", "+port
  816.                                 Return 0
  817.                         EndIf
  818.                 Else
  819.                         packet:TPacket=New TPacket
  820.                         packet.WriteInt(MilliSecs())
  821.                         Return Send(NETWORK_PINGREQUEST,packet)
  822.                 EndIf
  823.         EndMethod
  824.        
  825.         Method Say:Int(Text:String,recipients:String[]=Null)
  826.                 Local packet:TPacket=New TPacket
  827.                 If recipients
  828.                         packet.WriteByte(recipients.length)
  829.                         packet.WriteLine(Text)
  830.                         For Local n:Int=0 To recipients.length-1
  831.                                 packet.WriteLine(recipients[n])
  832.                         Next
  833.                 Else
  834.                         packet.WriteByte(0)
  835.                         packet.WriteLine(Text)
  836.                 EndIf
  837.                 Return Send(NETWORK_CHAT,packet)               
  838.         EndMethod
  839.        
  840. EndType
  841.  
  842.  
  843. Type TPacket Extends TBankStream
  844.        
  845.         Method New()
  846.                 _bank=New TBank
  847.         EndMethod
  848.        
  849. EndType
  850.  
  851.  
  852. Function CreatePacket:TPacket()
  853.         Local packet:TPacket=New TPacket
  854.         Return packet
  855. EndFunction
  856.  

Offline wombats

  • Jr. Member
  • **
  • Posts: 51
Re: Segmentation fault
« Reply #2 on: June 08, 2020, 03:54:16 PM »
I should have mentioned that I'm using the newest Linux released for NG that includes an updated version of pub.enet that requires the bmx_ prefix changes.

Offline Derron

  • Hero Member
  • *****
  • Posts: 3034
Re: Segmentation fault
« Reply #3 on: June 08, 2020, 05:44:00 PM »
If you built the debug modules with "gdb" option enabled, you could run your application via
gdb -r myapp
(then "r" to run it ... and once it crashed, "bt" to see the backtrace of where it crashed and why)


bye
Ron

Offline markcwm

  • Sr. Member
  • ****
  • Posts: 465
Re: Segmentation fault
« Reply #4 on: June 09, 2020, 04:39:01 PM »
The gdb backtrace output for my NG v0.120 is:
Code: [Select]
(gdb) r
Starting program: /~/bmx-ng-0.120/projects/network_test.debug
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3d6c700 (LWP 26857)]
started server

Thread 1 "network_test.de" received signal SIGSEGV, Segmentation fault.
bbObjectFree (o=0x7ffff7e4a1b0) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/blitz_object.c:71
71 clas->dtor( o );
(gdb) bt
#0  bbObjectFree (o=0x7ffff7e4a1b0) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/blitz_object.c:71
#1  0x0000000000734b0e in GC_invoke_finalizers () at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/finalize.c:1281
#2  0x0000000000734d1c in GC_notify_or_invoke_finalizers () at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/finalize.c:1360
#3  0x00000000007360c7 in GC_generic_malloc (lb=16, k=0) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/malloc.c:247
#4  0x000000000073683f in GC_malloc_kind_global (k=0, lb=<optimized out>) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/malloc.c:327
#5  GC_malloc_kind (k=0, lb=<optimized out>) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/malloc.c:333
#6  GC_malloc_atomic (lb=<optimized out>) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/bdwgc/malloc.c:340
#7  0x00000000007226fb in bbGCAllocObject (sz=<optimized out>, clas=clas@entry=0x9f9ca0 <pub_enet_ENetEvent>, flags=3)
    at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/blitz_gc.c:102
#8  0x0000000000718cd8 in bbObjectAtomicNew (clas=0x9f9ca0 <pub_enet_ENetEvent>) at /~/bmx-ng-0.120/mod/brl.mod/blitz.mod/blitz_object.c:47
#9  0x0000000000408ff0 in __m_network_test_TNetworkNode_Update (o=<optimized out>)
    at /~/bmx-ng-0.120/projects/.bmx/network_test.bmx.gui.debug.linux.x64.c:492
#10 0x0000000000408702 in __m_network_test_TServer_Update (o=<optimized out>)
    at /~/bmx-ng-0.120/projects/.bmx/network_test.bmx.gui.debug.linux.x64.c:1840
#11 0x0000000000417c34 in _bb_main () at /~/bmx-ng-0.120/projects/.bmx/network_test.bmx.gui.debug.linux.x64.c:6011
#12 0x0000000000712b43 in __bb_brl_appstub_appstub () at /~/bmx-ng-0.120/mod/brl.mod/appstub.mod/.bmx/appstub.bmx.debug.linux.x64.c:8
#13 0x00000000004082ff in main ()
(gdb)

I dropped pub.enet into NG v0.93 and got a segfault as well, this is my gdb backtrace:
Code: [Select]
(gdb) r
Starting program: /~/bmx-ng/network_test.debug
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff74e6700 (LWP 30241)]
started server

Thread 1 "network_test.de" received signal SIGSEGV, Segmentation fault.
0x000000000046d6e3 in bbObjectFree (o=0x9beb20)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/blitz_object.c:77
77 clas->dtor( o );
(gdb) bt
#0  0x000000000046d6e3 in bbObjectFree (o=0x9beb20)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/blitz_object.c:77
#1  0x0000000000485865 in GC_invoke_finalizers ()
    at /~/bmx-ng/mod/brl.mod/blitz.mod/bdwgc/finalize.c:1192
#2  0x0000000000485b03 in GC_notify_or_invoke_finalizers ()
    at /~/bmx-ng/mod/brl.mod/blitz.mod/bdwgc/finalize.c:1267
#3  0x0000000000486da7 in GC_generic_malloc (lb=16, k=0)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/bdwgc/malloc.c:177
#4  0x0000000000487268 in GC_malloc_atomic (lb=<optimized out>)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/bdwgc/malloc.c:249
#5  0x0000000000476398 in bbGCAllocObject (sz=<optimized out>,
    clas=clas@entry=0x6b32c0 <pub_enet_ENetEvent>, flags=3)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/blitz_gc.c:81
#6  0x000000000046d805 in bbObjectAtomicNew (
    clas=0x6b32c0 <pub_enet_ENetEvent>)
    at /~/bmx-ng/mod/brl.mod/blitz.mod/blitz_object.c:45
#7  0x00000000004042b2 in __m_network_test_TNetworkNode_Update (
    o=<optimized out>) at /~/bmx-ng/network.bmx:64
#8  0x0000000000403a33 in __m_network_test_TServer_Update (o=<optimized out>)
    at /~/bmx-ng/network.bmx:300
#9  0x0000000000412dfd in _bb_main () at /~/bmx-ng/network_test.bmx:18
#10 0x0000000000468c93 in __bb_brl_appstub_appstub ()
---Type <return> to continue, or q <return> to quit---
4.c:8
#11 0x000000000040365f in main (argc=1, argv=0x7fffffffdf88) at /~/bmx-ng/mod/brl.mod/appstub.mod/appstub.linux.c:18
(gdb)

I'm going to ask Derron to let us know what he thinks, cause I can't follow it.

Online col

  • Sr. Member
  • ****
  • Posts: 444
Re: Segmentation fault
« Reply #5 on: June 09, 2020, 05:26:13 PM »
Does the seg fault appear when building a 32bit version, (I'm thinking of pointer sizes with maybe a 64bit pointer stored in a 32bit integer).

Or

maybe a pointer manually deleted previous to the GC deleting an object and trying to delete again.
To be is to be perceived.

https://github.com/davecamp

Offline markcwm

  • Sr. Member
  • ****
  • Posts: 465
Re: Segmentation fault
« Reply #6 on: June 09, 2020, 08:11:13 PM »
Yes, it also segfaults in 32bit. Here's the Win x86 backtrace for v0.120:
Code: [Select]
(gdb) r
Starting program: C:\bmx-ng-0.120\projects\network_test.debug.exe
[New Thread 1500.0x5bc]
warning: `C:\Windows\SYSTEM32\ntdll.dll': Shared library architecture i386:x86-6
4 is not compatible with target architecture i386.
warning: `C:\Windows\SYSTEM32\wow64.dll': Shared library architecture i386:x86-6
4 is not compatible with target architecture i386.
warning: `C:\Windows\SYSTEM32\wow64win.dll': Shared library architecture i386:x8
6-64 is not compatible with target architecture i386.
warning: `C:\Windows\SYSTEM32\wow64cpu.dll': Shared library architecture i386:x8
6-64 is not compatible with target architecture i386.
warning: Could not load shared library symbols for WOW64_IMAGE_SECTION.
Do you need "set solib-search-path" or "set sysroot"?
warning: Could not load shared library symbols for WOW64_IMAGE_SECTION.
Do you need "set solib-search-path" or "set sysroot"?
warning: Could not load shared library symbols for NOT_AN_IMAGE.
Do you need "set solib-search-path" or "set sysroot"?
warning: Could not load shared library symbols for NOT_AN_IMAGE.
Do you need "set solib-search-path" or "set sysroot"?
[New Thread 1500.0x9f0]

Program received signal SIGSEGV, Segmentation fault.
0x0000002b in ?? ()
(gdb) bt
#0  0x0000002b in ?? ()
(gdb)

The Win x64 backtrace yields more information:
Code: [Select]
(gdb) r
Starting program: C:\bmx-ng-0.120\projects\network_test.debug.exe
[New Thread 3008.0x584]
[New Thread 3008.0xbac]

Program received signal SIGSEGV, Segmentation fault.
0x00000000004369bd in ?? ()
(gdb) bt
#0  0x00000000004369bd in ?? ()
#1  0x00000000004022bc in ?? ()
#2  0x0000000000401837 in ?? ()
#3  0x000000000040fe12 in ?? ()
#4  0x000000000046ca7e in ?? ()
#5  0x000000000049c562 in ?? ()
#6  0x00000000004013c7 in ?? ()
#7  0x00000000004014cb in ?? ()
#8  0x00000000770159cd in KERNEL32!BaseThreadInitThunk ()
   from C:\Windows\system32\kernel32.dll
#9  0x000000007724a561 in ntdll!RtlUserThreadStart ()
   from C:\Windows\SYSTEM32\ntdll.dll
#10 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb)

Offline Derron

  • Hero Member
  • *****
  • Posts: 3034
Re: Segmentation fault
« Reply #7 on: June 09, 2020, 09:15:40 PM »
The error sounds - as col wrote - as if something cleaned up something which normally would be cleaned up by the GC ... so GC fails and you get the segfault.

Code: [Select]
#7  0x00000000004042b2 in __m_network_test_TNetworkNode_Update (
    o=<optimized out>) at /~/bmx-ng/network.bmx:64

Something there maybe


bye
Ron

Offline wombats

  • Jr. Member
  • **
  • Posts: 51
Re: Segmentation fault
« Reply #8 on: June 10, 2020, 07:39:01 AM »
Thanks for your replies and looking into it.

If I comment out If enet_host_service(Self.enethost,ev,0), it doesn't crash on macOS or give a Segmentation fault on Ubuntu, so I wonder what's going on with that function.

Offline Derron

  • Hero Member
  • *****
  • Posts: 3034
Re: Segmentation fault
« Reply #9 on: June 10, 2020, 08:56:36 AM »
You could "debugstop" there ... and check out what "self.enethost" and "ev" contain - both are "Byte Ptr" and maybe they do no longer contain valid data behind that memory address.

Or maybe you send the wrong "ev" (there is "Type ENetEvent" - and surely some raw enet event in C).


bye
Ron

Offline markcwm

  • Sr. Member
  • ****
  • Posts: 465
Re: Segmentation fault
« Reply #10 on: June 10, 2020, 11:08:28 AM »
Setting timeout to 1 fixes it: enet_host_service(Self.enethost,ev,1).

Edit: actually no, timeout just delays the segfault.

Edit: The older pub.enet works with v0.120 but conflicts with brl.gnet.

Offline wombats

  • Jr. Member
  • **
  • Posts: 51
Re: Segmentation fault
« Reply #11 on: June 11, 2020, 03:53:27 AM »
You could "debugstop" there ... and check out what "self.enethost" and "ev" contain - both are "Byte Ptr" and maybe they do no longer contain valid data behind that memory address.

Or maybe you send the wrong "ev" (there is "Type ENetEvent" - and surely some raw enet event in C).


bye
Ron
"self.enethost" and "ev" both appear to be valid.

This code worked perfectly ten years ago, so I'm wondering if some change in BlitzMax NG is making that command crash.

Setting the timeout value to something higher like 500 or 1000 seems to let it run without crashing (but I don't know for how long), though I wonder what impact that would have on speed.

Offline Derron

  • Hero Member
  • *****
  • Posts: 3034
Re: Segmentation fault
« Reply #12 on: June 11, 2020, 01:33:17 PM »
The enet library was updated a while ago - and maybe Brucey missed a bug sneaking in.


bye
Ron

Offline markcwm

  • Sr. Member
  • ****
  • Posts: 465
Re: Segmentation fault
« Reply #13 on: June 11, 2020, 09:07:48 PM »
Well, while you're wait for Brucey to fix this bug with the new zpl-c enet, it seems you can copy over and use the brl.gnet and pub.enet modules from v0.93, although I only tested the code here by wombats.

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal