Properly receive connections for epollecho, still WIP

Not currently handling EAGAIN on the socket we're reading data from
This commit is contained in:
R. Tyler Croy 2013-03-24 18:11:48 -07:00
parent 6f7d8d3cd0
commit 1836864f53
2 changed files with 37 additions and 28 deletions

View File

@ -49,9 +49,8 @@ package Epoll is
end record;
pragma Convention (C_Pass_By_Copy, Event_Type);
type Event_Array_Type is array (Positive range <>) of aliased Event_Type;
type Event_Array_Type is array (Integer range <>) of aliased Event_Type;
pragma Convention (C, Event_Array_Type);
--for Event_Array_Type'Component_Size use Event_Type'Size;
function Create (Size : Interfaces.C.int) return Epoll_Fd_Type;

View File

@ -9,8 +9,7 @@ with Epoll;
procedure Main is
Event : aliased Epoll.Event_Type;
Events : Epoll.Event_Array_Type;
First_Event : aliased Epoll.Event_Type := Events (Events'First);
Events : Epoll.Event_Array_Type (1 .. 10);
ServerSock : GNAT.Sockets.Socket_Type;
ServerAddr : GNAT.Sockets.Sock_Addr_Type;
@ -36,6 +35,10 @@ procedure Main is
begin
while true loop
Ada.Streams.Read (Channel.All, Data, Offset);
if Offset < 0 then
Put_Line ("Wat!");
end if;
exit when Offset = 0;
Put (Character'Val (Data (1)));
end loop;
@ -43,6 +46,21 @@ procedure Main is
GNAT.Sockets.Close_Socket (S);
end Read_Data;
procedure Make_Non_Blocking (S : in GNAT.Sockets.Socket_Type) is
Socket_Request : GNAT.Sockets.Request_Type :=
GNAT.Sockets.Request_Type'(Name => Non_Blocking_IO,
Enabled => True);
begin
Control_Socket (Socket => S,
Request => Socket_Request);
end Make_Non_Blocking;
procedure Error_Exit (Message : In String) is
begin
Ada.Text_IO.Put_Line (Message);
Ada.Command_Line.Set_Exit_Status (1);
end Error_Exit;
begin
Put_Line ("Starting epoll-based echo server...");
ServerAddr.Addr := Inet_Addr (Listen_Addr);
@ -50,16 +68,16 @@ begin
Create_Socket (ServerSock);
Set_Socket_Option (ServerSock, Socket_Level, (Reuse_Address, True));
Bind_Socket (ServerSock, ServerAddr);
Make_Non_Blocking (ServerSock);
Put_Line (".. bound to socket");
Listen_Socket (ServerSock);
Put_Line (".. listening for connections");
Put_Line (".. listening for connections on" & Image (ServerSock));
EpollFD := Epoll.Create (Events'Last);
EpollFD := Epoll.Create (Events'Last + 1);
if EpollFD = -1 then
Put_Line ("Failed to create epoll(7) file descriptor");
Ada.Command_Line.Set_Exit_Status (1);
Error_Exit ("Failed to create epoll(7) file descriptor");
return;
end if;
@ -69,38 +87,34 @@ begin
Retval := Epoll.Control (EpollFD, Epoll.Epoll_Ctl_Add, To_C (ServerSock), Event'Access);
if Retval = -1 then
Put_Line ("Epoll.Control call failed, not sure why");
Ada.Command_Line.Set_Exit_Status (1);
Error_Exit ("Epoll.Control call failed, not sure why");
return;
end if;
loop
Put_Line ("Waiting..");
Num_FDs := Epoll.Wait (EpollFD, First_Event'Access, 10, -1);
-- Reset the Num_FDs before we wait again
Num_FDs := 0;
Num_FDs := Epoll.Wait (EpollFD, Events (Events'First)'Access, 10, -1);
Put_Line ("Activity on" & Num_FDs'Img & " sockets");
if Num_FDs = -1 then
Put_Line ("Failure on Epoll.Wait, exiting");
Ada.Command_Line.Set_Exit_Status (1);
Error_Exit ("Failure on Epoll.Wait, exiting");
return;
end if;
for I in 0 .. Num_FDs loop
Put_Line ("Activity on" & Num_FDs'Img & " sockets");
for I in 1 .. Num_FDs loop
declare
Index : constant Integer := Integer (I);
Polled_Event : Epoll.Event_Type := Events (Index);
ClientSock : GNAT.Sockets.Socket_Type;
Socket_Request : GNAT.Sockets.Request_Type :=
GNAT.Sockets.Request_Type'(Name => Non_Blocking_IO,
Enabled => True);
begin
Put_Line ("Socket with activity" & Image (Polled_Event.Data.FD));
Put_Line ("Socket (" & Index'Img & ") with data:" & Image (Polled_Event.Data.FD));
if Polled_Event.Data.FD = ServerSock then
Put_Line ("Polled_Event is new connection, let's accept");
Accept_Socket (ServerSock, ClientSock, ServerAddr);
Control_Socket (Socket => ClientSock,
Request => Socket_Request);
Make_Non_Blocking (ClientSock);
Event.Events := Epoll.Epoll_In_And_Et;
Event.Data.FD := ClientSock;
@ -112,15 +126,11 @@ begin
To_C (ClientSock),
Event'Access);
if Retval = -1 then
Put_Line ("Failed to add accepted socket to epollfd");
Ada.Command_Line.Set_Exit_Status (1);
Error_Exit ("Failed to add accepted socket to epollfd");
return;
end if;
else
Put ("Received data on socket: ");
Put (Image (Polled_Event.Data.FD));
Put (To_C (Polled_Event.Data.FD)'Img);
New_Line;
Put_Line ("Received data on socket: " & Image (Polled_Event.Data.FD));
Read_Data (Polled_Event.Data.FD);
end if;
end;