| /* Copyright (C) 2007-2008 The Android Open Source Project |
| ** |
| ** This software is licensed under the terms of the GNU General Public |
| ** License version 2, as published by the Free Software Foundation, and |
| ** may be copied, distributed, and modified under those terms. |
| ** |
| ** This program is distributed in the hope that it will be useful, |
| ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
| ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| ** GNU General Public License for more details. |
| */ |
| #include "sysdeps.h" |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #define PORT 8000 |
| #define MAX_COUNTER 30 |
| #define INITIAL_DELAY 1000 |
| #define DELAY 5000 |
| |
| static int counter = 0; |
| |
| static void |
| timer_func( void* _timer ) |
| { |
| SysTimer timer = _timer; |
| SysTime now = sys_time_ms(); |
| |
| ++counter; |
| printf( "tick %d/%d a %.2fs\n", counter, MAX_COUNTER, now/1000. ); |
| if (counter < MAX_COUNTER) |
| sys_timer_set( timer, now + DELAY, timer_func, timer ); |
| else |
| sys_timer_destroy( timer ); |
| } |
| |
| typedef struct { |
| SysChannel channel; |
| char in_buff[ 128 ]; |
| int in_pos; |
| |
| char out_buff[ 128 ]; |
| int out_pos; |
| int out_size; |
| } ClientRec, *Client; |
| |
| static Client |
| client_alloc( SysChannel channel ) |
| { |
| Client client = calloc( sizeof(*client), 1 ); |
| |
| client->channel = channel; |
| return client; |
| } |
| |
| static void |
| client_free( Client client ) |
| { |
| sys_channel_close( client->channel ); |
| client->channel = NULL; |
| free( client ); |
| } |
| |
| static void |
| client_append( Client client, const char* str, int len ); |
| |
| static void |
| client_handle_line( Client client, const char* cmd ) |
| { |
| char temp[256]; |
| int nn, mm = 0; |
| |
| for (nn = 0; cmd[nn] != 0; nn++) { |
| int c = cmd[nn]; |
| if (c >= 32 && c <= 127) |
| temp[mm++] = c; |
| else if (c == '\n') { |
| strcat( temp+mm, "<LF>" ); |
| mm += 4; |
| } |
| else if (c == '\r') { |
| strcat( temp+mm, "<CR>" ); |
| mm += 4; |
| } |
| else { |
| sprintf( temp+mm, "\\x%02x", c ); |
| mm += strlen( temp+mm ); |
| } |
| } |
| temp[mm] = 0; |
| printf( "%p: << %s\n", client, temp ); |
| |
| if ( !strcmp( cmd, "quit" ) ) { |
| printf( "client %p quitting\n", client ); |
| client_free( client ); |
| return; |
| } |
| client_append( client, "type 'quit' to quit\n", -1 ); |
| } |
| |
| static void |
| client_handler( void* _client, int events ) |
| { |
| Client client = _client; |
| |
| if (events & SYS_EVENT_READ) { |
| int ret; |
| /* read into buffer, one character at a time */ |
| ret = sys_channel_read( client->channel, client->in_buff + client->in_pos, 1 ); |
| if (ret != 1) { |
| fprintf(stderr, "client %p could not read byte, result = %d, error: %s\n", |
| client, ret, strerror(errno) ); |
| goto ExitClient; |
| } |
| if (client->in_buff[client->in_pos] == '\r' || |
| client->in_buff[client->in_pos] == '\n' ) { |
| const char* cmd = client->in_buff; |
| client->in_buff[client->in_pos] = 0; |
| |
| /* eat leading cr and lf, maybe left-overs from previous line */ |
| while (*cmd == '\r' || *cmd =='\n') |
| cmd++; |
| |
| client_handle_line( client, cmd ); |
| client->in_pos = 0; |
| } else |
| client->in_pos += 1; |
| } |
| |
| if (events & SYS_EVENT_WRITE) { |
| int ret; |
| /* write from output buffer, one char at a time */ |
| ret = sys_channel_write( client->channel, client->out_buff + client->out_pos, 1 ); |
| if (ret != 1) { |
| fprintf(stderr, "client %p could not write byte, result = %d, error: %s\n", |
| client, ret, strerror(errno) ); |
| goto ExitClient; |
| } |
| client->out_pos += 1; |
| if (client->out_pos == client->out_size) { |
| client->out_size = 0; |
| client->out_pos = 0; |
| /* we don't need to write */ |
| sys_channel_on( client->channel, SYS_EVENT_READ, client_handler, client ); |
| } |
| } |
| return; |
| |
| ExitClient: |
| printf( "client %p exiting\n", client ); |
| client_free( client ); |
| } |
| |
| static void |
| client_append( Client client, const char* str, int len ) |
| { |
| int avail; |
| |
| if (len < 0) |
| len = strlen(str); |
| |
| avail = sizeof(client->out_buff) - client->out_size; |
| if (len > avail) |
| len = avail; |
| |
| memcpy( client->out_buff + client->out_size, str, len ); |
| if (client->out_size == 0) { |
| sys_channel_on( client->channel, SYS_EVENT_READ | SYS_EVENT_WRITE, client_handler, client ); |
| } |
| client->out_size += len; |
| } |
| |
| |
| static void |
| accept_func( void* _server, int events ) |
| { |
| SysChannel server = _server; |
| SysChannel handler; |
| Client client; |
| |
| printf( "connection accepted for server channel, getting handler socket\n" ); |
| handler = sys_channel_create_tcp_handler( server ); |
| printf( "got one. creating client\n" ); |
| client = client_alloc( handler ); |
| |
| events=events; |
| sys_channel_on( handler, SYS_EVENT_READ, client_handler, client ); |
| client_append( client, "Welcome !\n", -1 ); |
| } |
| |
| |
| int main( void ) |
| { |
| SysTimer timer; |
| SysChannel server_channel; |
| |
| /* initialize event subsystem */ |
| sys_main_init(); |
| |
| /* create timer and register it */ |
| timer = sys_timer_create(); |
| sys_timer_set( timer, sys_time_ms() + INITIAL_DELAY, timer_func, timer ); |
| |
| server_channel = sys_channel_create_tcp_server( PORT ); |
| printf( "listening on port %d with %p\n", PORT, server_channel ); |
| |
| sys_channel_on( server_channel, SYS_EVENT_READ, accept_func, server_channel ); |
| |
| printf("entering event loop\n"); |
| sys_main_loop(); |
| printf("exiting event loop\n" ); |
| return 0; |
| } |