New developer version 0.6.8; added select () function; added demonstrating example...
[ZeXOS.git] / apps / telnetd / net.c
blob7ed92dbd9effdc41d0ce8c042cd9eb2d6f5a44b1
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/socket.h>
28 #include <netdb.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include "client.h"
32 #include "console.h"
34 struct sockaddr_in sockName; // "Jmeno" portu
35 struct sockaddr_in clientInfo; // Klient, ktere se pripojil
36 int mainSocket; // Soket
37 socklen_t addrlen; // Velikost adresy vzdaleneho pocitace
38 char *buffer; // Buffer
39 int client_count; // Pocet pripojenych clientu
41 client_t client_list;
44 int client_send (client_t *c, char *data, unsigned len)
46 int ret;
47 if ((ret = send (c->fd, data, len, 0)) == -1) {
48 printf ("ERROR -> send () = -1\n");
49 return -1;
52 return ret;
55 int clients_send (char *data, unsigned len)
57 client_t *c;
58 for (c = client_list.next; c != &client_list; c = c->next)
59 client_send (c, data, len);
61 return 1;
64 int client_recv (client_t *c, char *data, unsigned len)
66 memset (data, 0, len);
68 int ret = recv (c->fd, data, len, 0);
70 if (ret > 0)
71 data[ret] = '\0';
73 return ret;
76 client_t *client_connected (int fd)
78 client_t *c;
79 for (c = client_list.next; c != &client_list; c = c->next)
80 if (c->fd == fd)
81 return 0;
83 // alloc and init context
84 client_t *ctx = (client_t *) malloc (sizeof (client_t));
86 if (!ctx)
87 return 0;
89 ctx->fd = fd;
90 ctx->state = CLIENT_STATE_CONNECTED;
91 ctx->buf_len = 0;
93 ctx->next = &client_list;
94 ctx->prev = client_list.prev;
95 ctx->prev->next = ctx;
96 ctx->next->prev = ctx;
98 return ctx;
101 int client_handle (client_t *c)
103 if (c->state == CLIENT_STATE_CONNECTED)
104 return console_motd (c);
105 if (c->state == CLIENT_STATE_LOGIN)
106 return console_login (c);
107 if (c->state == CLIENT_STATE_READY)
108 return console_handler (c);
109 if (c->state == CLIENT_STATE_DONE) {
110 /* disconnect socket */
111 close (c->fd);
113 /* delete client_t * struct from list */
114 c->next->prev = c->prev;
115 c->prev->next = c->next;
117 free (c);
118 return 0;
121 return 0;
124 int init (int port)
126 if ((mainSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
127 printf ("Cant create socket\n");
128 return -1;
131 // set mainSocket to non-blocking mode
132 int oldFlag = fcntl (mainSocket, F_GETFL, 0);
133 if (fcntl (mainSocket, F_SETFL, oldFlag | O_NONBLOCK) == -1) {
134 printf ("Cant set socket to nonblocking mode\n");
135 return 0;
138 // 1) Family of protocols
139 sockName.sin_family = AF_INET;
140 // 2) Set number of listen port
141 sockName.sin_port = htons (port);
142 // 3) Listen IP address
143 sockName.sin_addr.s_addr = INADDR_ANY;
145 // Bind on our socket
146 if (bind (mainSocket, (struct sockaddr *) &sockName, sizeof (sockName)) == -1) {
147 printf ("bind () - port is used\n");
148 return -1;
151 // Create queue for accept
152 if (listen (mainSocket, 10) == -1) {
153 printf ("ERROR -> listen () == -1\n");
154 return -1;
157 addrlen = sizeof (clientInfo);
159 printf ("> telnetd is running !\n> listen on port: %d\n", port);
161 client_list.next = &client_list;
162 client_list.prev = &client_list;
164 client_count = 0;
166 return console_init ();
169 int loop ()
171 // "client" is new socket;
172 int client = accept (mainSocket, (struct sockaddr *) &clientInfo, &addrlen);
174 if (client > 0) {
175 printf ("> New client connected !\n");
177 // socket client will be in non-blocking mode
178 int oldFlag = fcntl (client, F_GETFL, 0);
179 if (fcntl (client, F_SETFL, oldFlag | O_NONBLOCK) == -1) {
180 printf ("Cant set socket to nonblocking mode\n");
181 return 0;
184 client_t *c = client_connected (client);
186 if (!c)
187 close (client);
189 usleep (80);
192 client_count = 0;
194 client_t *c;
195 for (c = client_list.next; c != &client_list; c = c->next) {
196 if (!c)
197 continue;
199 client_count ++;
200 if (!client_handle (c))
201 break;
204 return 1;