Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

Winsock getsockname

Wichu

Member

I'm attempting to make a script that lets my game communicate with a wireless device via the Winsock API. I'm starting out with existing networking scripts such as those in Blizzard's RMXP Online System, which provide me with most of the Socket class. However, I want to use the getsockname function so I can get the address of the socket the script uses, and I'm having problems implementing it successfully (being inexperienced with integrating Windows API functions). Here is the Winsock getsockname function syntax:
Code:
int getsockname(

  __in     SOCKET s,

  __out    struct sockaddr *name,

  __inout  int *namelen

);
This is what I have so far:
Code:
module Winsock

  Win32API_getsockname = Win32API.new(DLL, "getsockname", "ppl", "l")

  def self.getsockname(*args)

    Win32API_getsockname.call(*args)

  end

end

 

class Socket

  def getsockname

    sockaddr = "\0" * 256

    SocketError.check if (Winsock.getsockname(@fd, sockaddr, 256) == -1)

    sockaddr

  end

end
where Socket#fd is the pointer returned by Winsock::socket in Socket's constructor.

When I run the code, I get error 10014 (WSAEFAULT). Microsoft says this error is caused by sockaddr or namelen being invalid pointers, or due to namelen being too small.

I'm pretty sure it's something to do with how I'm calling the API, but I'm stumped as to what I need to do to fix it. Can anyone help me out?
 

Wichu

Member

Wow, can't believe I missed that. For future reference, this code works:
Code:
module Winsock

  Win32API_getsockname = Win32API.new(DLL, "getsockname", "pp[color=#FF0000]p[/color]", "l")

  def self.getsockname(*args)

    Win32API_getsockname.call(*args)

  end

end

 

class Socket

  def getsockname

    sockaddr = "\0" * 256

    [color=#FF0000]namelen = [256].pack("s")[/color]

    SocketError.check if (Winsock.getsockname(@fd, sockaddr, [color=#FF0000]namelen[/color]) == -1)

    sockaddr[color=#FF0000][0, namelen.unpack("s")[0]][/color]

  end

end
The sockaddr structure should only be 16 bytes, but I don't see any harm in allocating more to stay on the safe side.

Thanks for your help :)

EDIT: OK, now I'm having problems with recvfrom.
Code:
module Winsock

  Win32API_recvfrom = Win32API.new(DLL, "recvfrom", "ppllpp", "l")

  def self.recvfrom(*args)

    Win32API_recvfrom.call(*args)

  end

end

 

class Socket

  def recvfrom(len, flags = 0)

    sockaddr = "\0" * 256

    namelen = [256].pack("s")

    buf = "\0" * len

    SocketError.check if (ret = Winsock.recvfrom(@fd, buf, len, flags, sockaddr, namelen) == -1)

    return [buf, sockaddr]

  end  

end
I just get an WSAEINVAL error every time, despite the standard recv working with the exact same arguments (other than sockaddr and namelen). For example, this works:
Code:
class Socket

  def recvfrom(len, flags = 0)

    sockaddr = "\0" * 256

    namelen = [256].pack("s")

    buf = "\0" * len

    SocketError.check if (ret = Winsock.recv(@fd, buf, len, flags) == -1)

    return [buf, sockaddr]

  end  

end
but obviously without getting the sender's address. WSAEINVAL should mean exactly the same thing for recv and recvfrom, so why does the recv work but recvfrom not?
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top