18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sysdeps.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h>
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  PORT          8000
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_COUNTER   30
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  INITIAL_DELAY 1000
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DELAY         5000
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int  counter = 0;
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttimer_func( void*  _timer )
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTimer  timer = _timer;
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTime   now   = sys_time_ms();
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ++counter;
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "tick %d/%d a %.2fs\n", counter, MAX_COUNTER, now/1000. );
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (counter < MAX_COUNTER)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_timer_set( timer, now + DELAY, timer_func, timer );
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_timer_destroy( timer );
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel   channel;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char         in_buff[ 128 ];
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          in_pos;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char         out_buff[ 128 ];
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          out_pos;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          out_size;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ClientRec, *Client;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic Client
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_alloc( SysChannel  channel )
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Client  client = calloc( sizeof(*client), 1 );
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->channel = channel;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return client;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_free( Client  client )
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_close( client->channel );
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->channel = NULL;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( client );
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_append( Client  client, const char*  str, int len );
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_handle_line( Client  client, const char*  cmd )
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char temp[256];
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn, mm = 0;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; cmd[nn] != 0; nn++) {
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = cmd[nn];
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 32 && c <= 127)
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            temp[mm++] = c;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '\n') {
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            strcat( temp+mm, "<LF>" );
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mm += 4;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else if (c == '\r') {
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            strcat( temp+mm, "<CR>" );
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mm += 4;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sprintf( temp+mm, "\\x%02x", c );
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            mm += strlen( temp+mm );
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    temp[mm] = 0;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "%p: << %s\n", client, temp );
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !strcmp( cmd, "quit" ) ) {
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        printf( "client %p quitting\n", client );
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client_free( client );
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client_append( client, "type 'quit' to quit\n", -1 );
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_handler( void* _client, int  events )
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Client  client = _client;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (events & SYS_EVENT_READ) {
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  ret;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* read into buffer, one character at a time */
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = sys_channel_read( client->channel, client->in_buff + client->in_pos, 1 );
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret != 1) {
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fprintf(stderr, "client %p could not read byte, result = %d, error: %s\n",
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    client, ret, strerror(errno) );
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto ExitClient;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->in_buff[client->in_pos] == '\r' ||
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->in_buff[client->in_pos] == '\n' ) {
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            const char*  cmd = client->in_buff;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->in_buff[client->in_pos] = 0;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* eat leading cr and lf, maybe left-overs from previous line */
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (*cmd == '\r' || *cmd =='\n')
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cmd++;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client_handle_line( client, cmd );
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->in_pos = 0;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->in_pos += 1;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (events & SYS_EVENT_WRITE) {
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  ret;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* write from output buffer, one char at a time */
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = sys_channel_write( client->channel, client->out_buff + client->out_pos, 1 );
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret != 1) {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            fprintf(stderr, "client %p could not write byte, result = %d, error: %s\n",
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    client, ret, strerror(errno) );
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goto ExitClient;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->out_pos += 1;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->out_pos == client->out_size) {
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->out_size = 0;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->out_pos  = 0;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* we don't need to write */
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sys_channel_on( client->channel, SYS_EVENT_READ, client_handler, client );
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExitClient:
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "client %p exiting\n", client );
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client_free( client );
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectclient_append( Client  client, const char*  str, int len )
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  avail;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 0)
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = strlen(str);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    avail = sizeof(client->out_buff) - client->out_size;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len > avail)
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = avail;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy( client->out_buff + client->out_size, str, len );
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client->out_size == 0) {
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_channel_on( client->channel, SYS_EVENT_READ | SYS_EVENT_WRITE, client_handler, client );
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->out_size += len;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectaccept_func( void*  _server, int  events )
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  server  = _server;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  handler;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Client      client;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "connection accepted for server channel, getting handler socket\n" );
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    handler = sys_channel_create_tcp_handler( server );
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "got one. creating client\n" );
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client  = client_alloc( handler );
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    events=events;
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_on( handler, SYS_EVENT_READ, client_handler, client );
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client_append( client, "Welcome !\n", -1 );
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  main( void )
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysTimer    timer;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SysChannel  server_channel;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* initialize event subsystem */
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_main_init();
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* create timer and register it */
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    timer = sys_timer_create();
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_timer_set( timer, sys_time_ms() + INITIAL_DELAY, timer_func, timer );
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    server_channel = sys_channel_create_tcp_server( PORT );
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf( "listening on port %d with %p\n", PORT, server_channel );
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_on( server_channel, SYS_EVENT_READ, accept_func, server_channel );
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("entering event loop\n");
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_main_loop();
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("exiting event loop\n" );
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
216