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 23static int counter = 0; 24 25static void 26timer_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 39typedef 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 49static Client 50client_alloc( SysChannel channel ) 51{ 52 Client client = calloc( sizeof(*client), 1 ); 53 54 client->channel = channel; 55 return client; 56} 57 58static void 59client_free( Client client ) 60{ 61 sys_channel_close( client->channel ); 62 client->channel = NULL; 63 free( client ); 64} 65 66static void 67client_append( Client client, const char* str, int len ); 68 69static void 70client_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 103static void 104client_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 151ExitClient: 152 printf( "client %p exiting\n", client ); 153 client_free( client ); 154} 155 156static void 157client_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 176static void 177accept_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 194int 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