1. to bernie: more on mixedlib.e and other stuff
- Posted by cense <cense at MAIL.RU>
Nov 20, 2000
-
Last edited Nov 21, 2000
Hey there Bernie,
I have more questions about mixedlib.e and the new "AssociatePtr( )" routine
you coded in responce to some of my earlier problems.
I have wrapped the accept( ) function from C. This wrapper seems to work fine
on the surface eg. connections are accepted and i can send and recv through the
socket. The problem im having occurs randomly from the first to the ????
accept( ) attempt on a server using my wrapped accept( ). Mixedlib pops me
back with an error stating:
GETS FUNCTION FAILED !
Member sin_family does not exists
Now i know that this *would* be normal if that member *did NOT* exist all the
time but this error randomly occurs. I use your "AssociatePtr( )" routine just
like you advised but it still messes up consistently but only after a
random number of connections.
Here is the code i have so far for accept( ). I think that im also doing
someting wrong in initializing the sockaddr_in_ptr pointer.
-- include mixedlib.e
global
function accept( int sd )
int status
pointer sockaddr_in_ptr, len_ptr
sequence return_seq
sockaddr_in_ptr = allocate( 16 ) -- the size of a sockaddr_in struct
len_ptr = get_pointer( sizeof( sockaddr_in_ptr ) )
status = c_func( accept_, { sd, sockaddr_in_ptr, len_ptr } )
if ( status > 0 and len_ptr != 0 ) then
AssociatePtr( sockaddr_in_ptr, get_sockaddr_in_seq( ), HIGH )
return_seq = { { Gets( sockaddr_in_ptr, "sin_family" ), -- error here
Gets( sockaddr_in_ptr, "sin_port" ),
Gets( sockaddr_in_ptr, "s_addr" ) }, status }
free( len_ptr )
free( sockaddr_in_ptr )
return return_seq
else
free( len_ptr )
free( sockaddr_in_ptr )
return -1
end if
end function
get_sockaddr_in_seq( ) just returns a "struc" copatiable sequence.
I slightly modified AssociatePtr in how its invoked but not in its function.
One other thing, the s_addr member of sockaddr_in_ptr always returns some
gooffy IP address and the last two dot delimited numbers (after conversion
using inet_ntoa) are always ?.?.17.8 no matter who connects, me or a friend.
I think this all has to do with the way that im initializing sockaddr_in_ptr
but ive tried many different ways and it never seems to make a difference.
Any help on either of these two questions would greatly help. If you need
anymore info that i have not including i will be more than willing to mail it
away.
--
evil, corruption and bad taste
^[cense]
2. Re: to bernie: more on mixedlib.e and other stuff
cense:
Warning I could not test this code.
Because I don't know exactly how the rest of your program is coded
If I understand what you are doing you don't need AssociatePtr
I have tried to show you what to do in general.
I hope this helps.
Bernie
-- include mixedlib.e
-- define the following structures outside of the function
-----------------------------------------------------------------
pointer generic_sockaddr
generic_sockaddr =
struc("sa_family_t:ushort: 1 "& -- identifies format of address
data
"sa_data : char: 256 ",HIGH) -- address buffer varies and can be
-- greater than 14 bytes so use 256
-----------------------------------------------------------------
pointer addr_of_size_ptr -- upon RETURN contains (in bytes) address size
addr_of_size_ptr = struc("length:int:1",HIGH)
-----------------------------------------------------------------
global -- assuming a socket has been established
function accept( int socket , pointer client, pointer client_length)
--
int FD -- file_discriptor
FD = c_func( accept_, { socket, client, client_length} )
if FD < 0 then
return -1 -- error condition
else
return FD -- return FILE DISCRIPTOR use for reading an writing/read
socket
end if
--
end function
constant AF_INET = 2 --
pointer client1, client2
pointer client1_size_ptr1, client2_size_ptr1
-- create the client structures
client1 = dups(generic_sockaddr,HIGH) -- "C" socketaddr &client;
client1_size_ptr = dups(addr_of_size_ptr,HIGH) -- "C" &client_length
Sets(client1,"sa_family_t",AF_INET) -- set the address family FORMAT
-- so "C" knows what format to use
int client1_FD
-- get the file discriptor
client1_FD = accept( socket, client1, client1_size_ptr)
-- Now you can use the client1_FD to do read() or write()
-- To the get the address of the client into a sequence do this:
pointer client1_str_name
sequence client1_seq_name
-- allocate a string buffer
client1_str_name = string(256)
-- copy the address into the buffer this also gets rid of any garbage
-- returned in the structure
strncpy(client1_str_name, loc(client, "sa_data") , client1_size_ptr)
-- You can use this string with any of the string functions in mixedlib.e
-- or convert it to a sequence to use in Euphoria
client1_seq_name = str2seq(client1_str_name)
-- .... talk back and forth
-- When you are DONE communicating with the client be sure to
closeFD(client1_FD)
free(client1)
free(client1_size_ptr)
free(client1_str_name)
3. Re: to bernie: more on mixedlib.e and other stuff
- Posted by cense <cense at MAIL.RU>
Nov 21, 2000
-
Last edited Nov 22, 2000
On Tue, 21 Nov 2000, Bernie wrote:
>> cense:
>> Warning I could not test this code.
>>
>> Because I don't know exactly how the rest of your program is coded
>> If I understand what you are doing you don't need AssociatePtr
>> I have tried to show you what to do in general.
>> I hope this helps.
>> Bernie
Well im still working on that socket wrapper for linux. I have not worked on
it in a while and just discovered this during testing.
>> -- include mixedlib.e
>>
>> -- define the following structures outside of the function
>> -----------------------------------------------------------------
>> pointer generic_sockaddr
>> generic_sockaddr =
>> struc("sa_family_t:ushort: 1 "& -- identifies format of address
>> data
>> "sa_data : char: 256 ",HIGH) -- address buffer varies and can be
>> -- greater than 14 bytes so use 256
>>
>> -----------------------------------------------------------------
>> pointer addr_of_size_ptr -- upon RETURN contains (in bytes) address size
>> addr_of_size_ptr = struc("length:int:1",HIGH)
>>
>> -----------------------------------------------------------------
>>
>> global -- assuming a socket has been established
>> function accept( int socket , pointer client, pointer client_length)
>> --
>> int FD -- file_discriptor
>>
>> FD = c_func( accept_, { socket, client, client_length} )
>>
>> if FD < 0 then
>> return -1 -- error condition
>> else
>> return FD -- return FILE DISCRIPTOR use for reading an writing/read
>> socket
>> end if
>> --
>> end function
>>
>> constant AF_INET = 2 --
>> pointer client1, client2
>> pointer client1_size_ptr1, client2_size_ptr1
>>
>> -- create the client structures
>> client1 = dups(generic_sockaddr,HIGH) -- "C" socketaddr &client;
>> client1_size_ptr = dups(addr_of_size_ptr,HIGH) -- "C" &client_length
>>
>> Sets(client1,"sa_family_t",AF_INET) -- set the address family FORMAT
>> -- so "C" knows what format to use
>> int client1_FD
>> -- get the file discriptor
>> client1_FD = accept( socket, client1, client1_size_ptr)
>> -- Now you can use the client1_FD to do read() or write()
>> -- To the get the address of the client into a sequence do this:
>> pointer client1_str_name
>> sequence client1_seq_name
>>
>> -- allocate a string buffer
>> client1_str_name = string(256)
>> -- copy the address into the buffer this also gets rid of any garbage
>> -- returned in the structure
>> strncpy(client1_str_name, loc(client, "sa_data") , client1_size_ptr)
>> -- You can use this string with any of the string functions in mixedlib.e
>> -- or convert it to a sequence to use in Euphoria
>> client1_seq_name = str2seq(client1_str_name)
>>
>> -- .... talk back and forth
>> -- When you are DONE communicating with the client be sure to
>> closeFD(client1_FD)
>> free(client1)
>> free(client1_size_ptr)
>> free(client1_str_name)
I understand all of your code above just fine. There is one thing that i need
clarrified though. When i look at online C socket tutorials for berkley sockets
i see the author always typecast a sockaddr_in structure to sockaddr and
then pass it to accept( ) instead of just using a sockaddr struct in the first
place
What would be the use of this?
--
evil, corruption and bad taste
^[cense]
4. Re: to bernie: more on mixedlib.e and other stuff
>I understand all of your code above just fine. There is one thing that i
need
>clarrified though. When i look at online C socket tutorials for berkley
sockets
>i see the author always typecast a sockaddr_in structure to sockaddr and
>then pass it to accept( ) instead of just using a sockaddr struct in the
first
>place
>
>What would be the use of this?
cense:
I assume that this is what you are talking about.
struct sockaddr_in client;
int fd;
client_len = sizeof(client);
fd = accept(sock, (struct sockaddr *) &client, &client_len);
The reason for this is that the real accept function prototype
is:
accept(int s, const void* addr, int addrlen)
You will notice that the SECOND parameter is a VOID POINTER.
A void pointer in "C" is a general type of pointer ( or holds a
general address ) that can be assigned any type of pointer
( or address ). The void pointer can NOT be derefernced UNTIL
it is FIRST CAST to ANOTHER type. SO because we are using the
REFERENCE OPERATOR & ( or address operator ) we have to do a CAST
to tell "C" to treat the VOID POINTER as a GENERIC SOCKADDR
STRUCTURE POINTER. That means we can point to ANY SOCKADDR
STRUCTURE TYPE. The sockaddr_in is only one of these types of
structures.
Hope that clears this up for you.
Bernie
could benitialized
to different
5. Re: to bernie: more on mixedlib.e and other stuff
>I understand all of your code above just fine. There is one thing that i
need
>clarrified though. When i look at online C socket tutorials for berkley
sockets
>i see the author always typecast a sockaddr_in structure to sockaddr and
>then pass it to accept( ) instead of just using a sockaddr struct in the
first
>place
>
>What would be the use of this?
cense:
I assume that this is what you are talking about.
struct sockaddr_in client;
int fd;
client_len = sizeof(client);
fd = accept(sock, (struct sockaddr *) &client, &client_len);
The reason for this is that the real accept function prototype
is:
accept(int s, const void* addr, int addrlen)
You will notice that the SECOND parameter is a VOID POINTER.
A void pointer in "C" is a general type of pointer ( or holds a
general address ) that can be assigned any type of pointer
( or address ). The void pointer can NOT be derefernced UNTIL
it is FIRST CAST to ANOTHER type. SO because we are using the
REFERENCE OPERATOR & ( or address operator ) we have to do a CAST
to tell "C" to treat the VOID POINTER as a GENERIC SOCKADDR
STRUCTURE POINTER. That means we can point to ANY SOCKADDR
STRUCTURE TYPE. The sockaddr_in is only one of these types of
structures.
Hope that clears this up for you.
Bernie