pppc/pppc.c

PPP client. Similar to the TCP server sample, but uses PPP over RS232.

The default settings in this sample may be used to connect to a RAS server of a Windows PC. When adding a similar modem script, it will also work with a Linux PC nearly out of the box. At least you need to change the PPPUSER and PPPPASS.

Bug:
This sample works with ICCAVR (6.28 tested) only with debugging enabled.
Bug:
Not working with ATmega103. Debug output needs to be removed.
00001 /*
00002  * Copyright (C) 2003-2006 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 
00076 #include <cfg/arch.h>
00077 
00078 /*
00079  * PPP user and password.
00080  */
00081 #define PPPUSER     "me"
00082 #define PPPPASS     "secret"
00083 
00084 /*
00085  * The Nut/OS modem chat utility works similar to the the UNIX
00086  * chat script. This one is used to connect to a Windows PC
00087  * using a direct cable.
00088  */
00089 #define PPPCHAT     "TIMEOUT 2 '' CLIENT\\c CLIENTSERVER"
00090 
00091 /*
00092  * A very simple modem script.
00093  */
00094 //#define PPPCHAT     "'' AT OK ATD555 CONNECT"
00095 
00096 
00097 /*
00098  * PPP device settings.
00099  */
00100 #if defined(__AVR__)
00101 #define PPPDEV      devAhdlc0   /* Use HDLC driver. */
00102 //#define PPPDEV      devUart0    /* Use standard UART driver. */
00103 #else
00104 #warning "Works on ATmega128 only."
00105 #endif
00106 #define PPPCOM      "uart0"     /* Physical device name. */
00107 #define PPPSPEED    115200      /* Baudrate. */
00108 #define PPPRXTO     1000        /* Character receive timeout. */
00109 
00110 
00111 /*
00112  * Server input buffer size.
00113  */
00114 #define RXBUFFSIZE  256
00115 
00116 #include <cfg/os.h>
00117 #include <dev/debug.h>
00118 //#include <dev/hd44780.h>
00119 #include <dev/ahdlcavr.h>
00120 //#include <dev/uartavr.h>
00121 #include <dev/ppp.h>
00122 #include <dev/chat.h>
00123 
00124 #include <sys/version.h>
00125 #include <sys/heap.h>
00126 #include <sys/thread.h>
00127 #include <sys/socket.h>
00128 
00129 #include <sys/timer.h>
00130 
00131 #include <arpa/inet.h>
00132 #include <netdb.h>
00133 #include <net/if_var.h>
00134 #include <net/route.h>
00135 
00136 #ifdef NUTDEBUG
00137 #include <net/netdebug.h>
00138 #endif
00139 
00140 #include <stdlib.h>
00141 #include <string.h>
00142 #include <stdio.h>
00143 #include <io.h>
00144 #include <fcntl.h>
00145 
00146 #if defined(__IMAGECRAFT__)
00147 #define CC_STRING   "ICCAVR"
00148 #elif defined(__GNUC__)
00149 #define CC_STRING   "AVRGCC"
00150 #else
00151 #define CC_STRING   "Compiler unknown"
00152 #endif
00153 
00154 /*
00155  * Debug output device settings.
00156  */
00157 #ifdef __AVR_ENHANCED__
00158 #define DBGDEV      devDebug1   /* Use debug driver. */
00159 //#define DBGDEV      devUart1    /* Use standard UART driver. */
00160 #define DBGCOM      "uart1"     /* Device name. */
00161 #define DBGSPEED    115200      /* Baudrate. */
00162 #endif
00163 
00164 prog_char vbanner_P[] = "\n\nPPP Client Sample - Nut/OS %s - " CC_STRING "\n";
00165 prog_char banner_P[] = "200 Welcome to tcps. Type help to get help.\r\n";
00166 prog_char help_P[] = "400 List of commands follows\r\n"
00167     "m[emory]\tQueries number of RAM bytes free.\r\n"
00168     "t[hreads]\tLists all created threads.\r\n"
00169     "ti[mers]\tLists all running timers.\r\n" "q[uit]\t\tTerminates connection.\r\n" ".\r\n";
00170 prog_char thread_intro_P[] = "220 List of threads with name,state,prio,stack,mem,timeout follows\r\n";
00171 prog_char timer_intro_P[] = "221 List of timers with ticks left and interval follows\r\n";
00172 prog_char mem_fmt_P[] = "210 %u bytes RAM free\r\n";
00173 
00174 
00175 /*
00176  * Process client requests.
00177  */
00178 void ProcessRequests(FILE * stream)
00179 {
00180     int got;
00181     char *cp;
00182     char *buff;
00183 
00184     /*
00185      * We allocate the input buffer from heap memory.
00186      */
00187     buff = malloc(RXBUFFSIZE);
00188 
00189     /*
00190      * Send a welcome banner.
00191      */
00192     fputs_P(banner_P, stream);
00193     for (;;) {
00194 
00195         /*
00196          * Flush output and read a line.
00197          */
00198         fflush(stream);
00199         if (fgets(buff, RXBUFFSIZE, stream) == 0)
00200             break;
00201 
00202         /*
00203          * Chop off EOL.
00204          */
00205         if ((cp = strchr(buff, '\r')) != 0)
00206             *cp = 0;
00207         if ((cp = strchr(buff, '\n')) != 0)
00208             *cp = 0;
00209 
00210         /*
00211          * Ignore blank lines.
00212          */
00213         got = strlen(buff);
00214         if (got == 0)
00215             continue;
00216 
00217         /*
00218          * Memory info.
00219          */
00220         if (strncmp(buff, "memory", got) == 0) {
00221             fprintf_P(stream, mem_fmt_P, NutHeapAvailable());
00222             continue;
00223         }
00224 
00225         /*
00226          * List threads.
00227          */
00228         if (strncmp(buff, "threads", got) == 0) {
00229             NUTTHREADINFO *tdp;
00230             NUTTIMERINFO *tnp;
00231 
00232             fputs_P(thread_intro_P, stream);
00233             for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
00234                 fputs(tdp->td_name, stream);
00235                 switch (tdp->td_state) {
00236                 case TDS_TERM:
00237                     fputs("\tTerm\t", stream);
00238                     break;
00239                 case TDS_RUNNING:
00240                     fputs("\tRun\t", stream);
00241                     break;
00242                 case TDS_READY:
00243                     fputs("\tReady\t", stream);
00244                     break;
00245                 case TDS_SLEEP:
00246                     fputs("\tSleep\t", stream);
00247                     break;
00248                 }
00249                 fprintf(stream, "%u\t%u", tdp->td_priority, (u_short) tdp->td_sp - (u_short) tdp->td_memory);
00250                 if (*((u_long *) tdp->td_memory) != DEADBEEF)
00251                     fputs("\tCorrupted\t", stream);
00252                 else
00253                     fputs("\tOK\t", stream);
00254 
00255                 if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0)
00256                     fprintf(stream, "%lu\r\n", tnp->tn_ticks_left);
00257                 else
00258                     fputs("None\r\n", stream);
00259             }
00260             fputs(".\r\n", stream);
00261             continue;
00262         }
00263 
00264         /*
00265          * List timers.
00266          */
00267         if (strncmp("timers", buff, got) == 0) {
00268             NUTTIMERINFO *tnp;
00269 
00270             fputs_P(timer_intro_P, stream);
00271             for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00272                 fprintf(stream, "%lu\t", tnp->tn_ticks_left);
00273                 if (tnp->tn_ticks)
00274                     fprintf(stream, "%lu\r\n", tnp->tn_ticks);
00275                 else
00276                     fputs("Oneshot\r\n", stream);
00277             }
00278             fputs(".\r\n", stream);
00279             continue;
00280         }
00281 
00282         /*
00283          * Quit connection.
00284          */
00285         if (strncmp("quit", buff, got) == 0) {
00286             break;
00287         }
00288 
00289         /*
00290          * Display help text on any unknown command.
00291          */
00292         fputs_P(help_P, stream);
00293     }
00294 }
00295 
00296 /*
00297  * PPP client application entry.
00298  */
00299 int main(void)
00300 {
00301     int pppcom;
00302     PPPDCB *dcb;
00303     u_long lctl;
00304     int rc;
00305 
00306     /*
00307      * Register our devices.
00308      */
00309 #ifdef __AVR_ENHANCED__
00310     NutRegisterDevice(&DBGDEV, 0, 0);
00311 #endif
00312 #ifdef PPPDEV
00313     NutRegisterDevice(&PPPDEV, 0, 0);
00314     NutRegisterDevice(&devPpp, 0, 0);
00315 #endif
00316 
00317     /*
00318      * Open debug device for standard output.
00319      */
00320     if(freopen("uart1", "w", stdout) == 0) {
00321         for(;;);
00322     }
00323 
00324     /*
00325      * Set debug output speed.
00326      */
00327 #ifdef __AVR_ENHANCED__
00328     lctl = DBGSPEED;
00329     _ioctl(_fileno(stdout), UART_SETSPEED, &lctl);
00330 #endif
00331 
00332     /*
00333      * Display banner including compiler info and Nut/OS version.
00334      */
00335     printf_P(vbanner_P, NutVersionString());
00336 
00337     /*
00338      * Open PPP device. Specify physical device, user and password.
00339      */
00340     printf("Open uart...");
00341     if ((pppcom = _open("ppp:" PPPCOM "/" PPPUSER "/" PPPPASS, _O_RDWR | _O_BINARY)) == -1) {
00342         printf("Failed to open " PPPCOM "\n");
00343         for (;;);
00344     }
00345     puts("done");
00346 
00347 #ifdef PPPDEV
00348     /*
00349      * Set PPP line speed.
00350      */
00351     lctl = PPPSPEED;
00352     _ioctl(pppcom, UART_SETSPEED, &lctl);
00353 
00354     /*
00355      * The PPP driver doesn't set any receive timeout, but
00356      * may require it.
00357      */
00358     lctl = PPPRXTO;
00359     _ioctl(pppcom, UART_SETREADTIMEOUT, &lctl);
00360 
00361 #ifdef NUTDEBUG
00362     /*
00363      * Optionally enable PPP trace.
00364      */
00365     NutTracePPP(stdout, 1);
00366 #endif
00367 
00368     /*
00369      * This delay may be removed. It is quite helpful during development.
00370      */
00371     NutSleep(5000);
00372 
00373     /*
00374      * PPP connection loop.
00375      */
00376     for (;;) {
00377         /*
00378          * Connect using a chat script. We may also set any
00379          * required hardware handshake line at this stage.
00380          */
00381         printf("Connecting...");
00382         if ((rc = NutChat(pppcom, PPPCHAT)) != 0) {
00383             printf("no connect, reason = %d\n", rc);
00384             continue;
00385         }
00386         puts("done");
00387 
00388         /*
00389          * We are connected, configure our PPP network interface.
00390          * This will initiate the PPP configuration negotiation
00391          * and authentication with the server.
00392          */
00393         printf("Configure PPP...");
00394         rc = NutNetIfConfig("ppp", 0, 0, 0);
00395         if (rc != 0) {
00396             puts("failed");
00397             /*
00398              * Optionally toggle DTR to hang up the modem.
00399              */
00400             continue;
00401         }
00402         puts("done");
00403 
00404         /*
00405          * Set name server and default route. Actually the PPP interface
00406          * should do this, but the current release doesn't.
00407          */
00408         dcb = devPpp.dev_dcb;
00409         NutDnsConfig2(0, 0, dcb->dcb_ip_dns1, dcb->dcb_ip_dns2);
00410         NutIpRouteAdd(0, 0, dcb->dcb_remote_ip, &devPpp);
00411 
00412         /*
00413          * Display our IP settings.
00414          */
00415         printf("     Local IP: %s\n", inet_ntoa(dcb->dcb_local_ip));
00416         printf("    Remote IP: %s\n", inet_ntoa(dcb->dcb_remote_ip));
00417         printf("  Primary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns1));
00418         printf("Secondary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns2));
00419 
00420         /*
00421          * Client connection loop.
00422          */
00423         for (;;) {
00424             TCPSOCKET *sock;
00425             FILE *stream;
00426 
00427             /*
00428              * Create a socket.
00429              */
00430             if ((sock = NutTcpCreateSocket()) != 0) {
00431 
00432                 /*
00433                  * Listen on port 23. If we return, we got a client.
00434                  */
00435                 printf("Waiting for a client...");
00436                 if (NutTcpAccept(sock, 23) == 0) {
00437                     puts("connected");
00438 
00439                     /*
00440                      * Open a stream and associate it with the socket, so
00441                      * we can use standard I/O. Note, that socket streams
00442                      * currently do support text mode.
00443                      */
00444                     if ((stream = _fdopen((int) sock, "r+b")) != 0) {
00445                         /*
00446                          * Process client requests.
00447                          */
00448                         ProcessRequests(stream);
00449                         puts("\nDisconnected");
00450 
00451                         /*
00452                          * Close the stream.
00453                          */
00454                         fclose(stream);
00455                     } else {
00456                         puts("Assigning a stream failed");
00457                     }
00458                 } else {
00459                     puts("failed");
00460                 }
00461 
00462                 /*
00463                  * Close our socket.
00464                  */
00465                 NutTcpCloseSocket(sock);
00466             }
00467             NutSleep(1000);
00468             printf("%u bytes free\n", NutHeapAvailable());
00469         }
00470     }
00471 #endif /* PPPDEV */
00472 }

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