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 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 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 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 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 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 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 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 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