summaryrefslogtreecommitdiff
path: root/src/lib/ecore_con/efl_net_server_fd.eo
blob: bbb25a58bfb056cf7af1a8418905a9c26f24b365 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
abstract Efl.Net.Server_Fd (Efl.Loop_Fd, Efl.Net.Server) {
    [[A generic server based on file descriptors.

      @since 1.19
    ]]

    methods {
        socket_activate {
            [[If this method is called, use an already activated socket.

              This method allows a server to use an existing socket
              received from systemd or any similar system.

              It will replace @Efl.Net.Server.serve, thus if this is
              used, this method will return EALREADY.

              Note: The parameter 'address' given to this function is
              only used to validate the next socket available. It
              doesn't search for a socket with the given address. Thus
              the socket to be used is the next unused one : order
              matters if using multiple servers!

              Note: subclasses must validate the socket and return
              EINVAL prior to call the base class with
              Efl.Object.super. They must also emit "serving" when
              ready. For instance stream protocols may need to check
              for listening and if not, try to listen. Usually they
              will also query getsockname() and set
              @Efl.Net.Server.address.

              Errors:

                - EALREADY: There already is a socket, either from
                  previous @.socket_activate or
                  @Efl.Net.Server.serve. Usually represents a
                  programming error.

                - ENOENT: No sockets received from process manager
                  (ie: systemd). Usually this is not a fatal error,
                  just proceed by calling @Efl.Net.Server.serve

                - EINVAL: the socket received is not of the correct
                  family, type or protocol. Usually this means a
                  configuration mismatch between the order of server
                  creation and calls to socket_activate. The
                  systemd.socket entries must match the order in your
                  application.
            ]]
            params {
                address: string; [[The address to validate the next available socket. It cannot be used to search, only for validation.]]
            }
            return: Eina.Error; [[$0 on success, ENOENT if no socket is available or EALREADY if already have a socket]]
        }

        @property family {
            [[The address family (AF_*) family of this socket.

              It will be one of AF_INET (IPv4), AF_INET6 (IPv6),
              AF_UNIX...

              It must be set before the @Efl.Loop_Fd.fd.set is called
              with a valid file descriptor.
            ]]
            get { }
            set @protected { }
            values {
                family: int; [[Socket address family]]
            }
        }

        @property close_on_exec {
            [[Controls Close-on-Exec() using FD_CLOEXEC.

              Child sockets inherit the server's settings by
              default. You can change the behavior using each instance
              @Efl.Io.Closer.close_on_exec.set. Defaults to $true.
            ]]
            get { }
            set {
                return: bool (false); [[$true on success, $false otherwise]]
            }
            values {
                close_on_exec: bool; [[If $true close on exec will be used, $false otherwise]]
            }
        }

        @property reuse_address {
            [[Controls address reuse() using SO_REUSEADDR]]
            get { }
            set {
                return: bool (false); [[$true on success, $false otherwise]]
            }
            values {
                reuse_address: bool; [[If $true the server will reuse the address, $false otherwise]]
            }
        }

        @property reuse_port {
            [[Controls port reuse() using SO_REUSEPORT (since linux 3.9)]]
            get { }
            set {
                return: bool (false); [[$true on success, $false otherwise]]
            }
            values {
                reuse_port: bool; [[If $true the server will reuse the port, $false otherwise]]
            }
        }

        process_incoming_data @protected {
            [[When the socket has data to be read, process it.

              By default this method will call accept() and then
              decide if @.client_add or @.client_reject must be
              executed, however it may be replaced with something
              else, such as in SOCK_DGRAM (UDP) there is no accept(),
              only recvfrom().

              It is called straight from @Efl.Loop_Fd "read" event
              handler and is provided as a method to allow easy
              extending of the class for various purposes.
            ]]
        }

        client_add @protected @pure_virtual {
            [[Accepts a new client, should emit "client,add".

              Remember to create the client object with a callback to
              EFL_IO_CLOSER_EVENT_CLOSED during the construction,
              decrease @Efl.Net.Server.clients_count as well as unref
              the client and remove yourself as parent.

              The new clients should have the server as parent and
              increase the @Efl.Net.Server.clients_count.

              Whenever this function fails, it must close the given
              client file descriptor.
            ]]
            params {
                client_fd: int; [[The file descriptor of the client socket. It comes preconfigured with close_on_exec. On failure, remember to close this socket.]]
            }
        }

        client_reject @protected @pure_virtual {
            [[Rejects a new client, should emit "client,rejected".

              Must always close the client socket when it's done.
            ]]
            params {
                client_fd: int; [[The file descriptor of the client socket. It comes preconfigured with close_on_exec and should be closed once it's not needed anymore]]
            }
        }
    }

    implements {
        Efl.Object.finalize;
        Efl.Object.constructor;
        Efl.Object.destructor;
        Efl.Loop_Fd.fd { set; }
        Efl.Net.Server.address { get; set; }
        Efl.Net.Server.clients_count { get; set; }
        Efl.Net.Server.clients_limit { get; set; }
        Efl.Net.Server.serving { get; set; }
        Efl.Net.Server.serve;
        Efl.Net.Server.client_announce;
    }
}