1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 ** GNU General Public License for more details.
11 */
12 #include "sysdeps.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17
18 #define PORT 8000
19 #define MAX_COUNTER 30
20 #define INITIAL_DELAY 1000
21 #define DELAY 5000
22
23 static int counter = 0;
24
25 static void
timer_func(void * _timer)26 timer_func( void* _timer )
27 {
28 SysTimer timer = _timer;
29 SysTime now = sys_time_ms();
30
31 ++counter;
32 printf( "tick %d/%d a %.2fs\n", counter, MAX_COUNTER, now/1000. );
33 if (counter < MAX_COUNTER)
34 sys_timer_set( timer, now + DELAY, timer_func, timer );
35 else
36 sys_timer_destroy( timer );
37 }
38
39 typedef struct {
40 SysChannel channel;
41 char in_buff[ 128 ];
42 int in_pos;
43
44 char out_buff[ 128 ];
45 int out_pos;
46 int out_size;
47 } ClientRec, *Client;
48
49 static Client
client_alloc(SysChannel channel)50 client_alloc( SysChannel channel )
51 {
52 Client client = calloc( sizeof(*client), 1 );
53
54 client->channel = channel;
55 return client;
56 }
57
58 static void
client_free(Client client)59 client_free( Client client )
60 {
61 sys_channel_close( client->channel );
62 client->channel = NULL;
63 free( client );
64 }
65
66 static void
67 client_append( Client client, const char* str, int len );
68
69 static void
client_handle_line(Client client,const char * cmd)70 client_handle_line( Client client, const char* cmd )
71 {
72 char temp[256];
73 int nn, mm = 0;
74
75 for (nn = 0; cmd[nn] != 0; nn++) {
76 int c = cmd[nn];
77 if (c >= 32 && c <= 127)
78 temp[mm++] = c;
79 else if (c == '\n') {
80 strcat( temp+mm, "<LF>" );
81 mm += 4;
82 }
83 else if (c == '\r') {
84 strcat( temp+mm, "<CR>" );
85 mm += 4;
86 }
87 else {
88 sprintf( temp+mm, "\\x%02x", c );
89 mm += strlen( temp+mm );
90 }
91 }
92 temp[mm] = 0;
93 printf( "%p: << %s\n", client, temp );
94
95 if ( !strcmp( cmd, "quit" ) ) {
96 printf( "client %p quitting\n", client );
97 client_free( client );
98 return;
99 }
100 client_append( client, "type 'quit' to quit\n", -1 );
101 }
102
103 static void
client_handler(void * _client,int events)104 client_handler( void* _client, int events )
105 {
106 Client client = _client;
107
108 if (events & SYS_EVENT_READ) {
109 int ret;
110 /* read into buffer, one character at a time */
111 ret = sys_channel_read( client->channel, client->in_buff + client->in_pos, 1 );
112 if (ret != 1) {
113 fprintf(stderr, "client %p could not read byte, result = %d, error: %s\n",
114 client, ret, strerror(errno) );
115 goto ExitClient;
116 }
117 if (client->in_buff[client->in_pos] == '\r' ||
118 client->in_buff[client->in_pos] == '\n' ) {
119 const char* cmd = client->in_buff;
120 client->in_buff[client->in_pos] = 0;
121
122 /* eat leading cr and lf, maybe left-overs from previous line */
123 while (*cmd == '\r' || *cmd =='\n')
124 cmd++;
125
126 client_handle_line( client, cmd );
127 client->in_pos = 0;
128 } else
129 client->in_pos += 1;
130 }
131
132 if (events & SYS_EVENT_WRITE) {
133 int ret;
134 /* write from output buffer, one char at a time */
135 ret = sys_channel_write( client->channel, client->out_buff + client->out_pos, 1 );
136 if (ret != 1) {
137 fprintf(stderr, "client %p could not write byte, result = %d, error: %s\n",
138 client, ret, strerror(errno) );
139 goto ExitClient;
140 }
141 client->out_pos += 1;
142 if (client->out_pos == client->out_size) {
143 client->out_size = 0;
144 client->out_pos = 0;
145 /* we don't need to write */
146 sys_channel_on( client->channel, SYS_EVENT_READ, client_handler, client );
147 }
148 }
149 return;
150
151 ExitClient:
152 printf( "client %p exiting\n", client );
153 client_free( client );
154 }
155
156 static void
client_append(Client client,const char * str,int len)157 client_append( Client client, const char* str, int len )
158 {
159 int avail;
160
161 if (len < 0)
162 len = strlen(str);
163
164 avail = sizeof(client->out_buff) - client->out_size;
165 if (len > avail)
166 len = avail;
167
168 memcpy( client->out_buff + client->out_size, str, len );
169 if (client->out_size == 0) {
170 sys_channel_on( client->channel, SYS_EVENT_READ | SYS_EVENT_WRITE, client_handler, client );
171 }
172 client->out_size += len;
173 }
174
175
176 static void
accept_func(void * _server,int events)177 accept_func( void* _server, int events )
178 {
179 SysChannel server = _server;
180 SysChannel handler;
181 Client client;
182
183 printf( "connection accepted for server channel, getting handler socket\n" );
184 handler = sys_channel_create_tcp_handler( server );
185 printf( "got one. creating client\n" );
186 client = client_alloc( handler );
187
188 events=events;
189 sys_channel_on( handler, SYS_EVENT_READ, client_handler, client );
190 client_append( client, "Welcome !\n", -1 );
191 }
192
193
main(void)194 int main( void )
195 {
196 SysTimer timer;
197 SysChannel server_channel;
198
199 /* initialize event subsystem */
200 sys_main_init();
201
202 /* create timer and register it */
203 timer = sys_timer_create();
204 sys_timer_set( timer, sys_time_ms() + INITIAL_DELAY, timer_func, timer );
205
206 server_channel = sys_channel_create_tcp_server( PORT );
207 printf( "listening on port %d with %p\n", PORT, server_channel );
208
209 sys_channel_on( server_channel, SYS_EVENT_READ, accept_func, server_channel );
210
211 printf("entering event loop\n");
212 sys_main_loop();
213 printf("exiting event loop\n" );
214 return 0;
215 }
216