• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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