tcps/tcps.c

$Log$ Revision 1.6 2008/01/31 09:38:15 haraldkipp Added return statement in main to avoid warnings with latest GCC.

Revision 1.5 2005/11/22 09:14:13 haraldkipp Replaced specific device names by generalized macros.

Revision 1.4 2005/04/30 16:42:41 chaac Fixed bug in handling of NUTDEBUG. Added include for cfg/os.h. If NUTDEBUG is defined in NutConf, it will make effect where it is used.

Revision 1.3 2005/04/19 08:55:29 haraldkipp Description updated

Revision 1.2 2003/11/04 17:46:52 haraldkipp Adapted to Ethernut 2

Revision 1.1 2003/08/05 18:59:05 haraldkipp Release 3.3 update

Revision 1.8 2003/02/04 16:24:35 harald Adapted to version 3

Revision 1.7 2002/06/26 17:29:06 harald First pre-release with 2.4 stack

Revision 1.6 2002/06/12 10:59:05 harald *** empty log message ***

Revision 1.5 2002/06/04 19:12:55 harald *** empty log message ***

Revision 1.4 2002/05/08 16:02:32 harald First Imagecraft compilation

Simple TCP server.

Program Ethernut with tcps.hex and enter

00001  telnet x.x.x.x 

on a command prompt, replacing x.x.x.x with the IP address of your ethernut board. Enter help for a list of available commands.

00001 /*
00002  * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00086 #include <cfg/os.h>
00087 #include <string.h>
00088 #include <stdio.h>
00089 #include <io.h>
00090 
00091 #include <dev/board.h>
00092 
00093 #include <sys/version.h>
00094 #include <sys/heap.h>
00095 #include <sys/thread.h>
00096 #include <sys/timer.h>
00097 #include <sys/socket.h>
00098 
00099 #include <arpa/inet.h>
00100 #include <pro/dhcp.h>
00101 
00102 #ifdef NUTDEBUG
00103 #include <sys/osdebug.h>
00104 #include <net/netdebug.h>
00105 #endif
00106 
00107 #include <sys/confnet.h>
00108 
00109 static char buff[128];
00110 
00111 /*
00112  * To save RAM, we store large strings in program space. With AVRGCC we
00113  * would be able to use the PSTR() macro and put the text directly in
00114  * the statement that uses it. But ICCAVR doesn't support anything like 
00115  * this. Sigh.
00116  */
00117 #if defined(__IMAGECRAFT__)
00118 #define CC_STRING   "ICCAVR"
00119 #elif defined(__GNUC__)
00120 #define CC_STRING   "AVRGCC"
00121 #else
00122 #define CC_STRING   "Compiler unknown"
00123 #endif
00124 
00125 prog_char vbanner_P[] = "\n\nTCP Server Sample - Nut/OS %s - " CC_STRING "\n";
00126 prog_char banner_P[] = "200 Welcome to tcps. Type help to get help.\r\n";
00127 prog_char help_P[] = "400 List of commands follows\r\n"
00128     "m[emory]\tQueries number of RAM bytes free.\r\n"
00129     "t[hreads]\tLists all created threads.\r\n"
00130     "ti[mers]\tLists all running timers.\r\n" "q[uit]\t\tTerminates connection.\r\n" ".\r\n";
00131 prog_char thread_intro_P[] = "220 List of threads with name,state,prio,stack,mem,timeout follows\r\n";
00132 prog_char timer_intro_P[] = "221 List of timers with ticks left and interval follows\r\n";
00133 prog_char mem_fmt_P[] = "210 %u bytes RAM free\r\n";
00134 
00135 /*
00136  * Process client requests.
00137  */
00138 void ProcessRequests(FILE * stream)
00139 {
00140     int got;
00141     char *cp;
00142 
00143     /*
00144      * Send a welcome banner.
00145      */
00146     fputs_P(banner_P, stream);
00147     for (;;) {
00148 
00149         /*
00150          * Flush output and read a line.
00151          */
00152         fflush(stream);
00153         if (fgets(buff, sizeof(buff), stream) == 0)
00154             break;
00155 
00156         /*
00157          * Chop off EOL.
00158          */
00159         if ((cp = strchr(buff, '\r')) != 0)
00160             *cp = 0;
00161         if ((cp = strchr(buff, '\n')) != 0)
00162             *cp = 0;
00163 
00164         /*
00165          * Ignore blank lines.
00166          */
00167         got = strlen(buff);
00168         if (got == 0)
00169             continue;
00170 
00171         /*
00172          * Memory info.
00173          */
00174         if (strncmp(buff, "memory", got) == 0) {
00175             fprintf_P(stream, mem_fmt_P, (u_int)NutHeapAvailable());
00176             continue;
00177         }
00178 
00179         /*
00180          * List threads.
00181          */
00182         if (strncmp(buff, "threads", got) == 0) {
00183             NUTTHREADINFO *tdp;
00184             NUTTIMERINFO *tnp;
00185 
00186             fputs_P(thread_intro_P, stream);
00187             for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
00188                 fputs(tdp->td_name, stream);
00189                 switch (tdp->td_state) {
00190                 case TDS_TERM:
00191                     fputs("\tTerm\t", stream);
00192                     break;
00193                 case TDS_RUNNING:
00194                     fputs("\tRun\t", stream);
00195                     break;
00196                 case TDS_READY:
00197                     fputs("\tReady\t", stream);
00198                     break;
00199                 case TDS_SLEEP:
00200                     fputs("\tSleep\t", stream);
00201                     break;
00202                 }
00203                 fprintf(stream, "%u\t%u", tdp->td_priority, (u_int) tdp->td_sp - (u_int) tdp->td_memory);
00204                 if (*((u_long *) tdp->td_memory) != DEADBEEF)
00205                     fputs("\tCorrupted\t", stream);
00206                 else
00207                     fputs("\tOK\t", stream);
00208 
00209                 if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0)
00210                     fprintf(stream, "%lu\r\n", tnp->tn_ticks_left);
00211                 else
00212                     fputs("None\r\n", stream);
00213             }
00214             fputs(".\r\n", stream);
00215             continue;
00216         }
00217 
00218         /*
00219          * List timers.
00220          */
00221         if (strncmp("timers", buff, got) == 0) {
00222             NUTTIMERINFO *tnp;
00223 
00224             fputs_P(timer_intro_P, stream);
00225             for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00226                 fprintf(stream, "%lu\t", tnp->tn_ticks_left);
00227                 if (tnp->tn_ticks)
00228                     fprintf(stream, "%lu\r\n", tnp->tn_ticks);
00229                 else
00230                     fputs("Oneshot\r\n", stream);
00231             }
00232             fputs(".\r\n", stream);
00233             continue;
00234         }
00235 
00236         /*
00237          * Quit connection.
00238          */
00239         if (strncmp("quit", buff, got) == 0) {
00240             break;
00241         }
00242 
00243         /*
00244          * Display help text on any unknown command.
00245          */
00246         fputs_P(help_P, stream);
00247     }
00248 }
00249 
00250 /*
00251  * Main application routine. 
00252  *
00253  * Nut/OS automatically calls this entry after initialization.
00254  */
00255 int main(void)
00256 {
00257     TCPSOCKET *sock;
00258     FILE *stream;
00259     u_long baud = 115200;
00260     u_char mac[6] = { 0x00, 0x06, 0x98, 0x00, 0x00, 0x55 };
00261 
00262     /*
00263      * Register all devices used in our application.
00264      */
00265     NutRegisterDevice(&DEV_DEBUG, 0, 0);
00266     NutRegisterDevice(&DEV_ETHER, 0x8300, 5);
00267 
00268     /*
00269      * Assign stdout to the UART device.
00270      */
00271     freopen(DEV_DEBUG_NAME, "w", stdout);
00272     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00273     printf_P(vbanner_P, NutVersionString());
00274 #ifdef NUTDEBUG
00275     NutTraceTcp(stdout, 1);
00276     NutTraceOs(stdout, 0);
00277     NutTraceHeap(stdout, 0);
00278     NutTracePPP(stdout, 0);
00279 #endif
00280 
00281     NutNetLoadConfig(DEV_ETHER_NAME);
00282     memcpy(confnet.cdn_mac, mac, 6);
00283     NutNetSaveConfig();
00284 
00285     /*
00286      * Setup the ethernet device. Try DHCP first. If this is
00287      * the first time boot with empty EEPROM and no DHCP server
00288      * was found, use hardcoded values.
00289      */
00290     printf("Configure eth0...");
00291     if (NutDhcpIfConfig("eth0", 0, 60000)) {
00292         printf("initial boot...");
00293         if (NutDhcpIfConfig("eth0", mac, 60000)) {
00294             u_long ip_addr = inet_addr("192.168.192.100");
00295             u_long ip_mask = inet_addr("255.255.255.0");
00296 
00297             printf("no DHCP...");
00298             NutNetIfConfig("eth0", mac, ip_addr, ip_mask);
00299             /* If not in a local network, we must also call 
00300                NutIpRouteAdd() to configure the routing. */
00301         }
00302     }
00303     puts("OK");
00304     printf("IP: %s\n", inet_ntoa(confnet.cdn_ip_addr));
00305 
00306     /*
00307      * Now loop endless for connections.
00308      */
00309     for (;;) {
00310         /*
00311          * Create a socket.
00312          */
00313         if ((sock = NutTcpCreateSocket()) != 0) {
00314             /*
00315              * Listen on port 23. If we return, we got a client.
00316              */
00317             printf("Waiting for a telnet client...");
00318             if (NutTcpAccept(sock, 23) == 0) {
00319                 puts("connected");
00320 
00321                 /*
00322                  * Open a stream and associate it with the socket, so 
00323                  * we can use standard I/O. Note, that socket streams
00324                  * currently do support text mode.
00325                  */
00326                 if ((stream = _fdopen((int) sock, "r+b")) != 0) {
00327                     /*
00328                      * Process client requests.
00329                      */
00330                     ProcessRequests(stream);
00331                     puts("Disconnected");
00332 
00333                     /*
00334                      * Close the stream.
00335                      */
00336                     fclose(stream);
00337                 } else
00338                     puts("Assigning a stream failed");
00339             } else
00340                 puts("failed");
00341 
00342             /*
00343              * Close our socket.
00344              */
00345             NutTcpCloseSocket(sock);
00346         }
00347     }
00348     return 0;
00349 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/