3 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <arpa/inet.h>
27 #include <sys/socket.h>
28 #include <sys/select.h>
29 #include <netinet/in.h>
33 struct sockaddr_in sockname
;
35 /* Client structure */
36 typedef struct client_context
{
37 struct client_context
*next
, *prev
;
44 int mserver_bind (int port
)
46 if ((fd
= socket (AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == -1) {
47 printf ("> cant create socket\n");
51 sockname
.sin_family
= AF_INET
;
52 sockname
.sin_port
= htons (port
);
54 // Create listen socket
55 if (bind (fd
, (struct sockaddr
*) &sockname
, sizeof (sockname
)) == -1) {
56 printf ("bind () - port is used\n");
60 // Create queue for accept
61 if (listen (fd
, 10) == -1) {
62 printf ("ERROR -> listen () == -1\n");
66 client_list
.next
= &client_list
;
67 client_list
.prev
= &client_list
;
72 int mserver_newclient ()
75 struct sockaddr_in clientInfo
;
76 socklen_t addrlen
= sizeof (clientInfo
);
78 if (FD_ISSET (fd
, &myset
)) {
79 printf ("> new client connected\n");
81 client
= accept (fd
, (struct sockaddr
*) &clientInfo
, &addrlen
);
84 // alloc and init context
85 client_t
*ctx
= (client_t
*) malloc (sizeof (client_t
));
92 ctx
->next
= &client_list
;
93 ctx
->prev
= client_list
.prev
;
94 ctx
->prev
->next
= ctx
;
95 ctx
->next
->prev
= ctx
;
104 int mserver_sendtoall (client_t
*me
, char *buf
, unsigned len
)
110 for (c
= client_list
.next
; c
!= &client_list
; c
= c
->next
)
112 send (c
->fd
, buf
, len
, 0);
117 int mserver_handle (client_t
*c
)
119 if (!FD_ISSET (c
->fd
, &myset
))
123 int r
= recv (c
->fd
, str
, 79, 0);
128 printf ("data: %d: %s", c
->fd
, str
);
129 mserver_sendtoall (c
, str
, r
);
131 printf ("client %d is disconnected\n", c
->fd
);
132 /* disconnect socket */
135 /* delete client_t * struct from list */
136 c
->next
->prev
= c
->prev
;
137 c
->prev
->next
= c
->next
;
154 for (c
= client_list
.next
; c
!= &client_list
; c
= c
->next
)
155 FD_SET (c
->fd
, &myset
);
160 int ret
= select (0, &myset
, NULL
, NULL
, &tv
);
163 printf ("select error\n");
165 } else if (ret
== 0) {
166 printf ("select timeout\n");
170 /* check for incoming connections */
171 if (mserver_newclient ())
174 for (c
= client_list
.next
; c
!= &client_list
; c
= c
->next
) {
175 if (mserver_handle (c
) == -1)
182 int main (int argc
, char **argv
)
184 int ret
= mserver_bind (1234);