Hi all, I need some help to continue my current wine work.
In order to implement SO_PROTOCOL_INFO for getsockopt I need to retrieve some information from the socket like its family and protocol.
I have searched for a few days and ended up with a solution I dislike so I had a better idea (at least I hope I did).
Instead of using non-portable SO_DOMAIN and SO_PROTOCOL/SO_PROTOTYPE to retrieve the socket family and protocol or using non-reliable guessing using only the socket type I thought it would be better to ask the server for this information. Using a request just like is used for several other information in ws2_32 (operation which will work on every OS).
So, all I need is a server request that based on the socket fd will return the socket family, type and protocol. I tried to understand how requests work but I failed completely.
Maybe this request can be later improved to return the connection time so we can finally fix SO_CONNECT_TIME option.
The current solution is attached, since I sent the tests separated and they were commited the patch will not apply, it's only for reference. The idea is to remove the functions get_sock_[family|protocol|type] to a single server request.
So, is this a good idea? If yes, how can I create and use the request? If not I'm all ears.
Best wishes and thanks in advance, Bruno
On Aug 29, 2013, at 6:43 PM, Bruno Jesus wrote:
Hi all, I need some help to continue my current wine work.
In order to implement SO_PROTOCOL_INFO for getsockopt I need to retrieve some information from the socket like its family and protocol.
I have searched for a few days and ended up with a solution I dislike so I had a better idea (at least I hope I did).
Instead of using non-portable SO_DOMAIN and SO_PROTOCOL/SO_PROTOTYPE to retrieve the socket family and protocol or using non-reliable guessing using only the socket type I thought it would be better to ask the server for this information. Using a request just like is used for several other information in ws2_32 (operation which will work on every OS).
So, all I need is a server request that based on the socket fd will return the socket family, type and protocol. I tried to understand how requests work but I failed completely.
Maybe this request can be later improved to return the connection time so we can finally fix SO_CONNECT_TIME option.
The current solution is attached, since I sent the tests separated and they were commited the patch will not apply, it's only for reference. The idea is to remove the functions get_sock_[family|protocol|type] to a single server request.
So, is this a good idea?
There's no way I know of to get this information directly on at least Mac OS, so I'd say go for it. (But I can't speak for anyone else on this list, so...)
If yes, how can I create and use the request?
To add a new request to the server, you first add a definition to server/protocol.def . This file is processed by the make_requests tool, which generates a bunch of other files from it. The syntax of the server protocol definition file is somewhat like Objective-C (if you've ever used or seen that). A typical server request definition looks like this:
@REQ(request_name) /* input parameters go here */ int input; obj_handle_t handle; /* don't use Windows types */ @REPLY /* output values go here */ int output; @END
As with all generated files, the files generated by make_requests shouldn't be included in your patch.
After defining a new server call, you define the handler in the server like so:
DECL_HANDLER(request_name) { /* implicit parameters: req, reply */ /* use the 'current' global to refer to the process and thread that made the request */ if (req->handle != ((obj_handle_t)-1)) { reply->output = do_something(req->input, req->handle); } else { set_error(STATUS_UNSUCCESSFUL); /* NTSTATUS is returned to client */ } /* no return value */ }
Then, in the client DLLs, you make server calls like this:
SERVER_START_REQ( request_name ) { /* implicit variables: req, reply */ req->input = 1; req->handle = wine_server_obj_handle( handle ); /* converts Windows HANDLE to a server obj_handle_t */ if (wine_server_call( req ) != STATUS_SUCCESS) { /* SetLastError(), return error code, etc. */ } do_something(reply->output); } SERVER_END_REQ;
There's lots of examples throughout Wine of this in action, especially in lower-level DLLs like ntdll and kernel32; I encourage you to look at them. (That's how I figured all this out, after all.) If you have any more questions (and not just because you were too lazy to even look ;), feel free to ask.
Chip
On Thu, Aug 29, 2013 at 10:38 PM, Charles Davis cdavis5x@gmail.com wrote:
To add a new request to the server, you first add a definition to server/protocol.def . This file is processed by the make_requests tool, which generates a bunch of other files from it. The syntax of the server protocol definition file is somewhat like Objective-C (if you've ever used or seen that). A typical server request definition looks like this:
@REQ(request_name) /* input parameters go here */ int input; obj_handle_t handle; /* don't use Windows types */ @REPLY /* output values go here */ int output; @END
Thanks for the information, before sending the email I tried making the DECL_HANDLER and used with SERVER_START_REQ but I was not aware of the server/protocol.def so it was not working.
There's lots of examples throughout Wine of this in action, especially in lower-level DLLs like ntdll and kernel32; I encourage you to look at them. (That's how I figured all this out, after all.) If you have any more questions (and not just because you were too lazy to even look ;), feel free to ask.
Chip
Thank you again, I guess now I can do it correctly. Basically it's the opposite of the create_socket message. http://source.winehq.org/source/server/protocol.def#L1131
Regards, Bruno