preserving state in driver process between callbacks to emulator
Jacob Vorreuter
jacob.vorreuter@REDACTED
Tue Jun 1 02:22:23 CEST 2010
As my linked-in driver adventure continues, I'm at a point where I'm wondering if there's a way to maintain state between callbacks to the emulator. I'm writing an http proxy driver and I would like to be able to read the http headers from the client socket, return the host header to the Erlang emulator, receive back the ip and port of the backend server to connect to and then proxy the previously collected headers as well as the request body to the backend server. My question is how to store the header data so that it's available on subsequent calls to the driver.
Is there a structure that persists between calls from the emulator? I started structuring my driver as follows:
static void process(ErlDrvData handle, ErlIOVec *ev) {
basic_drv_t* driver_data = (basic_drv_t*) handle;
ErlDrvBinary* data = ev->binv[1];
int cmd = data->orig_bytes[0];
if(cmd == 1) {
// read client fd from orig_bytes
int clientfd = ...
// read headers from client socket
char *headers = ...
// read host header
char *host = ...
// send host back to emulator to determine appropriate backend server
ErlDrvTermData spec[] = {
ERL_DRV_ATOM, driver_mk_atom("host"),
ERL_DRV_STRING, (ErlDrvTermData)host, strlen(host),
ERL_DRV_TUPLE, 2
};
driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
} else if(cmd == 2) {
// read backend host and port from orig_bytes
// connect to backend server
// proxy *headers data from above to backend server
ErlDrvTermData spec[] = {ERL_DRV_ATOM, driver_mk_atom("ok")};
driver_output_term(driver_data->port, spec, sizeof(spec) / sizeof(spec[0]));
}
}
And the Erlang code is something like this:
proxy_client_request(Fd) when is_integer(Fd) ->
Port = open_port({spawn, 'basic_drv'}, [binary]),
Cmd1 = 1,
port_command(Port, <<Cmd1:8/integer, Fd:32/unsigned-integer>>),
receive
{host, Host} ->
{ServerHost, ServerPort} = lookup_backend(Host),
Cmd2 = 2,
HostSize = size(ServerHost),
port_command(Port, <<Cmd2:8/integer, Fd:32/unsigned-integer, ServerPort:32/unsigned-integer, HostSize:8/integer, ServerHost/binary>>),
receive ok -> ok end
after 5000 ->
{error, timeout}
end,
port_close(Port).
Does is make sense what I'm trying to do? Any insight?
Thanks, Jake
More information about the erlang-questions
mailing list